【问题标题】:How do use OpenGL to draw decals in a specific ordering?如何使用 OpenGL 以特定顺序绘制贴花?
【发布时间】:2012-06-11 13:42:45
【问题描述】:

为了绘制贴花,我目前正在使用glPolygonOffset(-1,-1),当我通过伪造贴花的 zbuffer 值来绘制贴花时,这让我摆脱了一些丑陋的 z-fighting 工件,就好像贴花的多边形是离相机更近。我还认为我可以使用 glPolygonOffset 和各种参数来相对于彼此订购贴花,但这似乎会根据相机角度进行调整,因此当我移动相机时,整个贴花最终会相互交换顺序周围。

我使用过的另一种方法在本文档中:"Making Decals"

  1. 禁用深度缓冲区以进行写入,然后渲染 A。
  2. 为写入启用深度缓冲区,并渲染 B。
  3. 禁用用于写入的颜色缓冲区,然后重新渲染 A。
  4. 启用颜色缓冲区以进行写入。

这是我的尝试,但我真的不明白如何扩展它以相对于彼此按顺序绘制贴花,因为贴花是在启用深度缓冲区以进行写入时绘制的,我不只是获得更多的 z 战斗?

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
glEnable(GL_BLEND);

//Render a red solid quad on the color mask
glDepthMask(false);
glColor3f (1.0f, 0.0f, 0.0f);
glBegin (GL_QUADS);
    glVertex2f(-1,-1);
    glVertex2f(-1,1);
    glVertex2f(1,1);
    glVertex2f(1,-1);
glEnd ();

//Render the coincident decal, a transparent square works fine for now
glDepthMask(true);
glColor4f(0.0f, 1.0f, 0.0f, 0.5f);
glTranslatef(0, 1, 0.0f);
glScalef(0.5f, 0.5f, 0.5f);
glBegin (GL_QUADS);
    glVertex2f(-1,-1);
    glVertex2f(-1,1);
    glVertex2f(1,1);
    glVertex2f(1,-1);
glEnd ();

//Render the red quad again but only on the depth buffer
glColorMask(false, false, false, false);
glLoadIdentity();
glColor3f(1.0f, 0.0f, 0.0f);
glBegin (GL_QUADS);
    glVertex2f(-1,-1);
    glVertex2f(-1,1);
    glVertex2f(1,1);
    glVertex2f(1,-1);
glEnd ();
glColorMask(true, true, true, true);

这似乎在大多数游戏中都会完成,所以我确信我缺少更好的解决方案。但是,我进行了很多搜索,但无法提供任何教程来在 openGL 中订购这样的贴花。也许我只是使用了错误的搜索词?这个过程还有别的名字吗?

【问题讨论】:

    标签: c opengl 3d


    【解决方案1】:

    按照您的建议使用 glPolygonOffset 并从前到后渲染事物可能会比其他选项提供更好的性能,因为它应该充分利用 GPU 中的“早期 Z”优化。

    您可能想尝试将更大的数字传递给glPolygonOffset,例如,(-4, -4) 用于第一个贴花,(-8, -8) 用于第二个贴花等——这不是一门精确的科学;)

    当然,在您的 glPolygonOffset 变得如此之大之前,您可以以这种方式绘制的贴花数量是有限的,您的贴花会出现在它们不应该出现的东西前面。

    关于相机角度问题:glPolygonOffsetfactor 参数应该为高角度多边形添加额外的软糖。

    您可以尝试的另一种方法是:

    • 正常渲染所有常规几何体
    • 禁用深度写入(但保持启用深度测试)
    • glPolygonOffset(-1, -1)
    • 从后到前绘制所有贴花

    还有另一种可能更有效的方法:

    • 在帧开始时将模板缓冲区清除为 0(同时清除其他缓冲区)
    • 正常渲染所有常规几何体
    • 禁用深度写入(但保持启用深度测试)
    • glPolygonOffset(-1, -1)
    • glStencilFunc(GL_NOTEQUAL, 1, 1), glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE)
    • 从前到后绘制所有贴花

    【讨论】:

    • 关于您列出的第一个(4点)方法:不会在此处启用贴花之间的z-fighting深度测试结果,并且本质上使渲染顺序无关紧要?还是我误解了深度测试的工作原理?
    • 我无法通过使用更大的值来获得 glPolygon 偏移量,我不知道它使用什么样的方程来处理高角度的多边形,但我不认为它真的意味着以这种方式堆叠。在考虑了您发布的那个(4 点)方法之后,我认为它有可能发挥作用。我会尝试一下并在此处发布结果。
    • @Lockyer 深度测试和深度写入是单独启用的。如果你只启用了深度测试,被遮挡的像素仍然会被丢弃(这是我们想要的),但不会更新 z 缓冲区,因此你不会与以后的贴花发生 z-fighting
    • @Lockyer glPolygonOffset 应该是“可堆叠的”:参见例如idevgames.com/forums/thread-5474.html。您的 GPU/驱动程序可能有一个狡猾的实现
    • 感谢 dave 的详细说明,我想我明白它现在在做什么,并且它在我的测试中运行良好。是的,堆叠glPolygonOffset 对我不起作用,这很奇怪,我在 ATI Radeon HD 4670 上运行。但是我认为无论如何你的(4 点)方法更灵活。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多