c++ - 如何在另一个网格后面渲染一个网格,比如蒙版?

标签 c++ opengl-es opengl-es-2.0 shader

我希望当网格 A(角色)位于网格 B(一堵墙)后面时,它仍会被渲染,但颜色为纯灰色。

我开始使用 opengles 2.0,但我仍然不确定是否要着手进行此操作。据我了解,深度缓冲区允许网格决定在它们包含的片段中可以看到谁,还有各种混合功能可能涉及到这一点,最后模板缓冲区看起来也有这个理想的功能。

那么有没有办法根据失败的深度测试通过着色器输出不同的颜色呢?有没有办法通过混合来做到这一点?还是我必须以某种方式使用模板缓冲区?

这种技术叫什么以供将来引用?我在很多视频游戏中都看到过它。

最佳答案

这可以使用模板缓冲区来完成。模板缓冲区为每个像素提供一些额外的位,可用作位掩码或计数器。在您的情况下,您将配置模板测试单元以在角色的深度测试失败时设置特定的位掩码(因为它被井阻挡)。然后,您切换模板测试模式操作以通过该特定位掩码的模板测试,并渲染一个完整的视口(viewport)、所需颜色的纯色四边形,并禁用深度测试和深度写入。

代码

我强烈建议您深入阅读模板测试单元的文档。这是一个非常强大的机制,经常被忽视。您的特定问题将通过以下方式解决。我建议您使用此示例代码,将其与模板测试函数引用并行阅读 glStencilFunc , glStencilOp .

您必须将模板缓冲区添加到帧缓冲区的像素格式中——具体操作方式取决于平台。例如,如果您正在使用 GLUT,那么您将添加 |GLUT_STENCILglutInitDisplayMode 的格式位掩码;在 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();

    /* ... */
}

关于c++ - 如何在另一个网格后面渲染一个网格,比如蒙版?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18801153/

相关文章:

java - 释放分配给Java中对象的内存

c++ - 我不明白 placement new 的工作原理以及如何释放内存

c++ - 为什么不能在 dtor 中使用 uncaught_exception?

android - OpenGL ES 3.0 中的多重采样 FBO

iphone - 在 openGL 中检测 3D 对象的触摸位置

Android模拟器OpenGL远平面距离

c++ - 使用带有 cmake 的 OpenGL ES 2.0 生成 iOS 静态库

C++:如何强制派生类设置基成员变量?

java - OpenGL ES 2.0 翻译(移动对象)

c++ - Opengl-es 2.0中渲染三角形的问题