由于我最近尝试开发了一个RGSS3在不同平台上的移植程序(基于mruby和SDL)
初期在优化不佳的时候,总是会出现拖慢的情况,于是就加了一个跳帧的功能。
不过我一直在想的是,要不要去设计一个逻辑和渲染分线程的的结构呢?
(因为就算是在逻辑渲染内计算跳帧也不能避免渲染方面对于逻辑的拖累)
于是今天做了一个小实验。
全局结构
首先定义一个sprite结构体,它表示我们要渲染的一个对象。
然后是render_command结构体,顾名思义,它存储"渲染指令",和上述sprite的关系是,sprite可以生成render_command。
在这里,作为简单的示例,render_command只储存了渲染对象的坐标,而prepared字段则表示这个render_command是否是"完整"的(不过我觉得加了互斥锁以后这个没什么用处了)。
然后我们设一个float来储存当前逻辑线程所计算出的fps
再设一个全局的render_command,用于暂时储存逻辑线程产生的渲染指令。
之所以设为全局变量,是为了方便能被两个线程都访问到。
逻辑线程的代码
在逻辑线程里,我们设一个sprite。逻辑主循环部分,除了计算fps,就是移动这个sprite。
然后额外的部分就是,根据这个sprite的状态,生成render_command,并且在互斥锁的保护下把这个render_command放到我们之前定义的全局变量当中。
很简单。最后我们Sleep 16毫秒(近似于1秒钟除以60的值),那么logical_fps的期望值就是60左右。
渲染线程的代码
在渲染线程里,除了glut做的一些初始化工作以外,就是渲染线程的主循环了。
除了计算渲染的fps(以及在适当的时机在标题栏显示帧率)之外,就是渲染部分,然后就是窗口的消息处理,可以说是非常简单的结构。
其中渲染部分,访问用互斥锁保护的全局render_command,确保它完整的情况下,根据render_command的值进行渲染。
结果
可以看到渲染fps不会拖累到逻辑(当然这个计算值是不准确的,因为很多时候都并没有真正渲染东西,这是由于render_command_buffer还没有prepared的缘故,有兴趣大家可以自己去计算正确的渲染fps值。
拓展
这只是一个小试验,如果我们要以这个思路进行游戏引擎的开发,我的想法是:
- 设计一个Node类。
- 把全局的render_command_buffer设计成一个队列。
- 给Node类设计一个方法visit,能够根据Node的状态产生渲染指令并添加到上述的队列,并按顺序访问子Node的visit方法。
- 渲染线程按照队列进行渲染。
这样就可以实现一个树形的、生成渲染指令的流程。我们在逻辑渲染的主循环内只要调用顶Node的visit方法,就可以产生当前的渲染指令队列,非常方便。
(以后我也许会尝试以这个结构编写一个完整的2D渲染引擎吧)
完整上述示例程序下载(含exe)
链接: https://pan.baidu.com/s/1ijc7aAy9ddJ_v-mSf7ufOQ 提取码: eg8q
暂无关于此日志的评论。