我尝试使用OPENGL ES 3.0在Android手机上实现延迟渲染。我已经让它工作正常,但只是非常缓慢,这相当于失败了整点。真正放慢速度的是对着色器的多次调用。简而言之,这就是我的代码所做的事情:
几何通行证:
渲染场景 - 输出位置,正常和颜色到屏幕外缓冲区。
每盏灯:
a)模板通行证:
在当前灯光位置渲染球体,根据灯光强度调整大小。将这些像素标记为受当前光线的影响。没有实际输出。
b)光通:
再次渲染球体,这次使用几何体传递中的数据将光照方程应用于上一步中标记的像素。将其添加到屏幕外缓冲区
Blit to screen
这会重新启动导致瓶颈的每个灯光的着色器。例如,对于25个灯,上述步骤以大约5 fps运行。相反,我做:Geometry Pass / Stencil Pass - 绘制25个灯/ Light Pass - 绘制25个灯,它以大约30 fps的速度运行。那么,是否有人知道如何避免重新初始化着色器?或者,事实上,只是解释一下占用时间的是什么?是否有帮助甚至是可能的(如果这听起来很糟糕,我很抱歉)让着色器“打开”#39;并覆盖以前的数据而不是做任何花费这么多时间重新启动着色器的数据?或者,无论如何,我应该在移动设备上将其作为一种多灯的方法。
答案 0 :(得分:0)
好吧,我通过使用整数纹理作为模板贴图解决了必须为每个灯光交换着色器的问题,其中设置了某个位来表示每个灯光。 (因此,限制为32个灯。)这意味着步骤2a(上面)可以循环,然后单个更改着色器,并循环步骤2b。然而,(ahahaha!)事实证明,这并没有真正加快速度,因为它毕竟不是交换着色器而是改变了写入目的地。也就是说,多次调用glDrawBuffers
。因为我在模板创建循环中有两个这样的调用 - 一个在绘制球体时计算哪些像素受影响,一个绘制到用作模板贴图的整数纹理。我终于意识到,当我使用混合(每个写入一个颜色,其中一个单位是打开的)时,如果我在像素计算阶段写入是无关紧要的,只要它全部为零。摆脱对glDrawBuffers
的不必要的调用将FPS从单个数字提升到二十几岁。
总之,这种延迟渲染方法肯定比正向渲染快,但仅限于32灯。
我想说我编写代码只是为了看看这是否是一种可行的方法,并且可以进行许多小的优化。顺便说一句,因为我只限于4个绘制缓冲区,所以我不得不抓住位置图,而是从gl_FragCoord.xyz
恢复。我没有适当的基准测试工具,所以我有兴趣听到任何能告诉我这种情况有什么不同的人的速度。