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

时间:2012-03-10 02:25:45

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

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

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

禁用深度缓冲区消除了这个问题,但是会产生一个明显的问题:如果三角形是不透明的,那么如果在之后渲染,它仍然会在它后面渲染三角形。

例如,我试图渲染一棵松树,它基本上是一些堆叠在一起的锥体,它们具有透明的底座。下图显示了启用深度缓冲区时出现的问题:

Depth Buffer Enabled

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

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

Depth Buffer Disabled

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

任何想法如何解决这个问题,并正确渲染松树?

P.S。我正在使用着色器渲染所有内容。

3 个答案:

答案 0 :(得分:5)

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

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

您还需要启用z-buffer。

[编辑]哎呀我意识到当你使用着色器时我不相信那些功能。在着色器情况下,如果alpha值接近于零,则要在片段着色器中使用discard函数。

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

答案 1 :(得分:0)

您需要实施两遍算法。

第一遍只渲染背面,而第二遍只渲染正面。

这样您就不需要对三角形进行排序,但是根据您的几何体是否凸起,可能会出现一些瑕疵。

答案 2 :(得分:-2)

我可能错了,但这是因为当你在3d中渲染时,你没有使用Directx的默认设置渲染三角形的背面,当Z被移除时 - 它按顺序绘制它们,其上的Z不会绘制三角形的背面了。 即使启用Z,也可以显示三角形的两侧,但我认为可能有一个正常启用的原因..例如速度..

Device->SetRenderState(D3DRS_CULLMODE, Value);

值可以等于

D3DCULL_NONE - Shows both sides of triangle
D3DCULL_CW - Culls Front side of triangle
D3DCULL_CCW - Default state