当我设置glStencilFunc( GL_NEVER, . . . )
有效地禁用所有绘图,然后运行我的 [shader-bound] 程序时,与让片段着色器运行相比,我没有得到任何性能提升。我认为模板测试发生在片段程序之前。不是这样吗,或者至少不能保证?将片段着色器替换为仅将常量写入 gl_FragColor 的片段着色器确实会导致更高的 FPS。
4 回答
实际上两者兼而有之。如您在此OpenGL ES 2.0 管道图中所见,每个片段操作应该在片段程序之后发生。但是,许多现代显卡都有一个早期的 z 测试,只要您不写入片段着色器中的深度,就会更早地丢弃片段。
这是AMD/ATI 的一篇关于此类测试的论文。我记得读过规范允许早期测试,只要在着色器产生与之后执行相同的结果之前执行它们,这就是为什么您不想修改深度或丢弃着色器中的片段的原因。OpenGL 论坛上的这个线程有一些有趣的讨论。
除了片段深度修改之外,还有一些其他的事情可以阻止深度/模板测试在片段着色器之前发生。如果启用了 z 写入,则任何在着色器中中止片段的方法都会执行此操作,例如 alpha-test 或discard
着色器指令。
如果 GPU 想要在与 z/stencil 写入相同的操作中进行 stencil/z 测试,它必须等到片段着色器执行之后,才能知道允许片段写入 z-buffer。不过,这可能因不同的卡而异。至少应该很容易判断这是否是您当前的问题。
看看 DX10 管道的以下大纲,它表示模板测试在像素着色器之前运行:
在 DX11 中也是如此:
http://4.bp.blogspot.com/_2YU3pmPHKN4/S1KhDSPmotI/AAAAAAAAAcw/d38b4oA_DxM/s1600-h/DX11.JPG
我不知道这是否是 OpenGL 规范中规定的,但在运行片段程序之前不进行模板测试对实现是有害的。
正如您在此处看到的: http ://www.opengl.org/wiki/Stencil_Test Stencil 测试在 fragmentShader 之后运行。我知道这对性能不利。