我希望这样当网格 A(角色)在网格 B(一堵墙)后面时,它仍然会被渲染,但是是纯灰色的。
我开始使用opengles 2.0,但我仍然不确定是否要解决这个问题。据我了解,深度缓冲区允许网格物体在它们包含的片段中看到谁,还有可能涉及到的各种混合功能,最后模板缓冲区看起来也具有这种理想的功能。
那么有没有办法根据失败的深度测试通过着色器输出不同的颜色呢?有没有办法通过混合来做到这一点?或者我必须如何使用模板缓冲区?
什么是这项技术以供将来参考?我已经看到它在很多视频游戏中使用过。
我希望这样当网格 A(角色)在网格 B(一堵墙)后面时,它仍然会被渲染,但是是纯灰色的。
我开始使用opengles 2.0,但我仍然不确定是否要解决这个问题。据我了解,深度缓冲区允许网格物体在它们包含的片段中看到谁,还有可能涉及到的各种混合功能,最后模板缓冲区看起来也具有这种理想的功能。
那么有没有办法根据失败的深度测试通过着色器输出不同的颜色呢?有没有办法通过混合来做到这一点?或者我必须如何使用模板缓冲区?
什么是这项技术以供将来参考?我已经看到它在很多视频游戏中使用过。
这可以使用模板缓冲区来完成。模板缓冲区为每个像素提供了一些额外的位,这些位可以用作位掩码或计数器。在您的情况下,您将配置模板测试单元以在字符的深度测试失败时设置特定的位掩码(因为它被井挡住了)。然后切换模板测试模式操作以通过此特定位掩码的模板测试,并以所需颜色渲染完整的视口、实心四边形,同时禁用深度测试和深度写入。
我强烈建议您深入研究模板测试单元的文档。这是一个非常强大的机制,但经常被忽视。您的特定问题将通过以下方式解决。我建议您使用此示例代码,将其与模板测试函数引用并行阅读glStencilFunc,glStencilOp。
您必须将模板缓冲区添加到帧缓冲区的像素格式中——具体操作方式取决于平台。例如,如果您使用 GLUT,那么您将添加|GLUT_STENCIL
到格式位掩码glutInitDisplayMode
; 在 iOS 上,你会在你的GLKView
;上设置一个属性。等等一旦你添加了一个模板缓冲区,你应该通过添加到每个绘图|GL_STENCIL_BUFFER_BIT
的初始调用来清除它以及你的其他渲染缓冲区。glClear
GLint const silouhette_stencil_mask = 0x1;
void display()
{
/* ... */
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glDepthFunc(GL_LESS);
glDisable(GL_STENCIL_TEST);
/* The following two are not necessary according to specification.
* But drivers can be buggy and this makes sure we don't run into
* issues caused by not wanting to change the stencil buffer, but
* it happening anyway due to a buggy driver.
*/
glStencilFunc(GL_NEVER, 0, 0);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
draw_the_wall();
glEnable(GL_STENCIL_TEST);
glStencilFunc(GL_ALWAYS, silouhette_stencil_mask, 0xffffffff);
glStencilOp(GL_KEEP, GL_REPLACE, GL_KEEP);
draw_the_character();
glStencilFunc(GL_EQUAL, silouhette_stencil_mask, 0xffffffff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDisable(GL_DEPTH_TEST);
glDepthMask(GL_FALSE);
draw_full_viewport_solid_color();
/* ... */
}