Java 在仍然渲染前一帧的情况下提前更新场景
我目前正在开发一个多线程安全渲染系统,我想知道您对如何在当前渲染前一个场景时正确更新游戏世界的下一步的想法。目前,我正在将LWJGL Opengl绑定与Java一起使用。以下是我目前设置的游戏循环的伪代码(这可能只是大多数人熟悉的基本循环): 我的问题在于Java 在仍然渲染前一帧的情况下提前更新场景,java,multithreading,opengl,lwjgl,Java,Multithreading,Opengl,Lwjgl,我目前正在开发一个多线程安全渲染系统,我想知道您对如何在当前渲染前一个场景时正确更新游戏世界的下一步的想法。目前,我正在将LWJGL Opengl绑定与Java一起使用。以下是我目前设置的游戏循环的伪代码(这可能只是大多数人熟悉的基本循环): 我的问题在于swapBuffers()方法,因为它在渲染场景之前一直处于阻塞状态,这意味着在渲染过程中我无法执行任何更新。我的想法是: 有一份用于更新实体状态的所有DrawingLayers的副本,另一份副本作为渲染线程的参考。在渲染帧时,在swapBuf
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
到目前为止,我在性能上有了显著的提高。可能有一些比赛条件的问题,我看不到,但总的来说,我对这一改善感到高兴
在swapBuffers()方法中,在渲染场景之前,它会一直阻塞
通过完成渲染,缓冲区交换的阻塞只是部分的。由于等待回程,它通常也会阻塞。但是,OpenGL向您保证,在任何图形命令返回后,可以安全地修改它访问的缓冲区,而不会影响任何挂起的渲染操作。需要实现对所有数据进行复制或写时复制映射
或者简而言之:只需修改缓冲区中的数据。一旦绘图调用(glDrawArrays、glDrawElements)返回,就可以安全地执行此操作。我已使用根据您的评论所做的更改更新了我的原始问题。
//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