c++ - 使用 OpenGL 中具有 Alpha 的纹理渲染 3D 模型

标签 c++ opengl shader alpha-transparency depth-buffer

因此,当应用于 3D 模型的某些纹理具有 Alpha channel 时,我试图找出在 OpenGL 中渲染 3D 模型的最佳方法。

当我启用深度缓冲区并开始绘制 3D 模型中的所有三角形时,如果它绘制的三角形位于模型中另一个三角形前面,则当它到达时,它不会渲染后面的三角形它。问题是当前面的三角形具有 Alpha 透明度时,应该能够看到它后面的三角形,但后面的三角形仍然没有渲染。

禁用深度缓冲区可以消除该问题,但会产生一个明显的问题,即如果三角形不透明,那么如果在之后渲染,它仍然会将其后面的三角形渲染在顶部。

例如,我正在尝试渲染一棵松树,它基本上是一些相互堆叠的圆锥体,具有透明的底座。下图为启用深度缓冲时出现的问题:

Depth Buffer Enabled

您可以看到如何仍然可以看到透明三角形的轮廓。

下图显示了禁用深度缓冲区时的样子。

Depth Buffer Disabled

在这里您可以看到树背面的一些三角形是如何渲染在树的其余部分前面的。

有什么想法可以解决这个问题并正确渲染松树吗?

附注我正在使用着色器来渲染所有内容。

最佳答案

如果您没有使用任何部分透明度(一切都是 0 或 255),您可以 glEnable(GL_ALPHA_TEST) 这应该会对您有所帮助。问题是,如果您首先渲染顶部圆锥体,它会将整个四边形存入 z 缓冲区(甚至是透明部分),因此下面的较低分支在绘制时会被 z 拒绝。如果像素未通过 alpha 测试(使用 glAlphaFunc 设置),则启用 alpha 测试不会将像素写入 z 缓冲区。

如果您想使用部分透明度,则需要从后到前或在您的情况下从下到上对渲染对象的顺序进行排序。

您还需要启用 z 缓冲区。

[编辑]哎呀,我意识到当您使用着色器时,我认为这些功能不起作用。在着色器情况下,如果 alpha 值接近于零,您希望在片段着色器中使用丢弃函数。

if(color.a < 0.01) {
   discard;
} else {
   outcolor = color;
}

关于c++ - 使用 OpenGL 中具有 Alpha 的纹理渲染 3D 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9643415/

相关文章:

c++ - OpenGL:GL_FRAMEBUFFER_UNSUPPORTED 在帧缓冲区附件的特定组合上

actionscript-3 - 将着色器过滤器应用于 BitmapData 对象会忽略传递的矩形 - 如何正确应用着色器过滤器?

c++ - 在 C++ 中将新的头文件包含到标准库中

c++ - 为什么我需要在使用它的循环的每次迭代中清除 stringstream 变量

c++ - 我修改了 gtest/gmock,所以模拟非虚函数真的很容易

c++ - Qt、声子和多媒体编解码器 : how to bundle them?

c++ - 如何在 GLSL 中使用 4x4 矩阵作为顶点属性?

opengl - 如何在 GLSL 中实现 2D raycasting 光效

unity-game-engine - 如何在unity3d中制作具有自定义属性的轮廓着色器

matrix - glsl 向量*矩阵与 hlsl 不同