我在场景中渲染了一个objectA,如下所示。场景也有许多其他对象。
void Draw()
{
if( glIsList( displayListID ) )
{
glPushAttrib( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_ENABLE_BIT );
glEnable( GL_BLEND );
glEnable( GL_DEPTH_TEST );
//glDepthMask( GL_FALSE );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
glEnable( GL_LINE_SMOOTH );
glEnable( GL_POINT_SMOOTH );
glEnable( GL_POLYGON_SMOOTH );
glMatrixMode( GL_MODELVIEW );
color.setAlpha(alpha); // set alpha transparent of this objectA
glCallList( displayListID );
//glDepthMask( GL_TRUE );
glDisable( GL_BLEND );
glPopAttrib();
}
}
现在问题就在于此,
如图所示,我评论了两行 // glDepthMask(GL_FALSE); // glDepthMask(GL_TRUE);
场景正确地渲染objectA和其他对象。然而, objectA alpha的修改不再起作用(即color.setAlpha(alpha))。
如果我取消注释上面两行,那么alpha修改就会恢复正常。但是,深度渲染不正确。换句话说,有时,objectA应该在其他对象后面,但看起来objectA在所有对象的前面。
如何解决此问题?
谢谢
答案 0 :(得分:62)
glDepthMask( GL_TRUE )
glDepthMask( GL_FALSE )
BLEND_MODE
你为什么这样做?
您需要担心2个缓冲区:深度缓冲区和颜色缓冲区。这些缓冲区实际上只是大的2d数组,每个数组都是屏幕的宽度x高度。
颜色缓冲区自然会保留每个像素的最终颜色。每个屏幕像素的颜色缓冲区中有一个条目。 深度缓冲区,就像颜色缓冲区一样,每个屏幕像素有一个条目,但它用于不同的东西。 深度缓冲区中的条目衡量每个彩色像素的“接近程度”。
如果渲染1个距离相机很远的三角形,它会为“想要”覆盖在屏幕上的每个像素生成一组颜色和深度值。然后说你渲染另一个更接近的多边形,它还会为深度和颜色缓冲区生成一组值。现在,在像素着色时存在一种“竞争”,其中“更远的”片段(大的深度缓冲器值)被丢弃,并且仅保留最接近的片段。最接近的片段最终会为您拥有的像素着色。 (当两个多边形几乎重叠时,Z-fighting can occur)
首先使用深度蒙版渲染场景中的对象。这意味着您呈现的每个形状,当其像素变为彩色时,深度缓冲区将通过比赛的“赢家”进行更新。
然后,你3)glDepthMask( GL_FALSE )
转动关闭深度缓冲区进行书写,4)打开混合,5)渲染半透明形状从最远到最近。看起来很奇怪,是吗?
当您关闭深度蒙版并渲染半透明形状时,OpenGL仍然会读取深度缓冲区以确定要丢弃的片段(即,如果您的半透明形状位于已渲染的实体后面)形状,然后你扔掉半透明的形状的碎片)。但它不会写入深度缓冲区,所以如果半透明的形状真的非常接近 eye (比如半透明的挡风玻璃),那些挡风玻璃碎片不要阻止实际上远离被绘制的其他碎片。这一点非常重要,因为如果你的挡风玻璃正好位于你面前并且你将它渲染成半透明,和你让挡风玻璃碎片更新深度缓冲区,那么除了挡风玻璃之外你不会在场景中看到任何其他东西。即使它背后有形状,因为OpenGL会认为“嘿,由于这些深度缓冲读数,挡风玻璃是用户应该看到的唯一东西,所以我不会费心去除这个挡风玻璃以外的任何东西。”关闭深度掩码是一种“欺骗”OpenGL“不知道”的方式,有非常接近但半透明的碎片。
答案 1 :(得分:3)
一种可能的解决方案:始终将glDepthMask
设置为GL_TRUE
并首先绘制所有非透明对象(以任何顺序,就像您现在所做的那样),然后绘制所有(半)透明物体从后到前排序。
在某些情况下,如果您不关心绘制(半)透明对象的顺序,并且您只希望其他不透明对象“透过”,则可以跳过排序(半) )透明物体。
答案 2 :(得分:0)
如果从后到前对半透明的对象进行排序,则不必翻转深度缓冲区。
我渲染这样的半透明对象:
丢弃多边形时,会出现丢弃bobobobo提到的片段的问题。但是在这种情况下,禁用深度缓冲区在所有情况下都不会产生正确的结果。乍一看可能看起来不错,但是如果仔细看,您会发现混合顺序不正确:
这种情况在数学上没有解决方案,因为一个多边形必须先于另一个多边形栅格化。 要解决此问题,您(或美术师)必须在3D编辑器(例如Blender)中的交点处分割多边形。因此,您可以将相交的对象分割为2个或更多,并通过排序算法对其进行适当排序。 比半透明的部分将以正确的顺序呈现:
请注意,第二个屏幕截图中已启用深度缓冲区写入!
如果禁用深度缓冲区,您自然会得到相同的结果,但不需要它。 实际上,如果未禁用深度缓冲区写入,则更容易看到此类重叠问题。这就是我不想禁用它的原因。