我目前正在开发一个多线程安全渲染系统,我想知道您对如何在当前渲染前一个场景时正确更新游戏世界的下一步的想法。目前我正在使用带有 Java 的 LWJGL Opengl 绑定。这是我当前设置的游戏循环的伪代码(这可能只是大多数人熟悉的基本循环):
//DrawingLayers are wrappers for in game entities and has an update
//and render method
game-loop:
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.update(deltaTime) //update position/color/size for entity
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
swapBuffers() //blocks until scene is fully rendered
goto game-loop
我的问题在于该swapBuffers()
方法,因为它在渲染场景之前一直阻塞,这意味着在此过程中我无法执行任何更新。我对如何解决这个问题的想法是:
拥有我用于更新实体状态的所有 DrawingLayers 的副本,并将另一个副本作为渲染线程的参考。并且在渲染帧时,在之前启动一个线程swapBuffers()
以更新未使用的副本。
我对这种方法持谨慎态度,因为我相信在每一帧之前创建副本会比我想要的更慢系统。
我的方法有意义吗?如果没有,你们对如何做到这一点有什么建议吗?我对彻底重组持开放态度。
更新:根据 datenwolf 的建议,我将游戏循环更改为以下内容:
//DrawingLayers are wrappers for in game entities and has an update
//and render method
//A future for the pre-processing task
Future preProcess = null
game-loop:
//Update: checks if we have a preprocessed update to wait for
//and waits for it to complete
if(preProcess != null):
preProcess.get()
preProcess = null
addInputEventsToInputStack()
removeCompletedDrawingLayers()
foreach layer in DrawingLayerQueue :
layer.render() //performs OpenGL calls
if(layer.isCompleted):
addToCompletedDrawingLayersList()
//UPDATE: the following just calls all the update methods for the layers
// in a new thread
preProcess = executorService.submit(new UpdateRunnable())
swapBuffers() //blocks until scene is fully rendered
goto game-loop
到目前为止,我的性能有了显着提高。可能有一些我看不到的比赛条件问题,但总的来说我对这种改进感到满意。