这可以使用模板缓冲区来完成。模板缓冲区为每个像素提供了一些额外的位,这些位可以用作位掩码或计数器。在您的情况下,您将配置模板测试单元以在字符的深度测试失败时设置特定的位掩码(因为它被井挡住了)。然后切换模板测试模式操作以通过此特定位掩码的模板测试,并以所需颜色渲染完整的视口、实心四边形,同时禁用深度测试和深度写入。
代码
我强烈建议您深入了解模板测试单元的文档。这是一个非常强大的机制,但经常被忽视。您的特定问题将通过以下方式解决。我建议您使用此示例代码,将其与模板测试功能参考glStencilFunc、glStencilOp 并行阅读。
您必须将模板缓冲区添加到帧缓冲区的像素格式中——具体操作方式取决于平台。例如,如果您使用 GLUT,那么您需要将 |GLUT_STENCIL 添加到 glutInitDisplayMode 的格式位掩码中;在 iOS 上,你会在 GLKView 上设置一个属性;等等。一旦你添加了一个模板缓冲区,你应该通过在每个绘图的初始 glClear 调用中添加 |GL_STENCIL_BUFFER_BIT 来清除它以及其他渲染缓冲区。
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();
/* ... */
}