我目前正在研究多線程安全渲染系統,我想知道如何正確更新遊戲世界中的下一步,而前一場景是目前呈現。目前我正在使用LWJGL Opengl與Java綁定。這裏是僞代碼爲我的遊戲循環,因爲它是目前設置了(這也許只是一個基本的循環,大多數人都熟悉):在渲染前一幀時提前更新場景
//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的建議,我已經改變了我gameloop以下幾點:
//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
所以用這個到目前爲止,我已經得到了在性能顯著的改善。可能有一些我不能看到的競爭條件問題,但總體來說我很滿意這種改進。
我更新了我的原始問題,並根據您的評論進行了更改。 – heinz 2012-07-13 01:12:21