我在场景中渲染了一个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();
}
}
Run Code Online (Sandbox Code Playgroud)
现在问题在于
如图所示,我注释掉了两行// glDepthMask(GL_FALSE); // glDepthMask(GL_TRUE);
场景正确地渲染objectA和其他对象.但是,objectA alpha的修改不再起作用(即color.setAlpha(alpha)).
如果我取消注释上面两行,那么alpha修改就会恢复正常.但是,深度渲染不正确.换句话说,有时,objectA应该在其他对象后面,但看起来objectA在所有对象的前面.
我该如何解决这个问题?
谢谢
bob*_*obo 67
glDepthMask( GL_TRUE )glDepthMask( GL_FALSE )BLEND_MODE你为什么这么做?
您需要担心2个缓冲区:深度缓冲区和颜色缓冲区.这些缓冲区实际上只是大的2d数组,每个数组都是屏幕的宽度x高度.
该颜色缓冲区自然是要保持每个像素的最终颜色.每个屏幕像素的颜色缓冲区中有一个条目.在深度缓冲,就像在每个屏幕像素一个条目颜色缓冲区,但它被用于不同的东西.深度缓冲区中的条目是每个彩色像素"真实接近"的度量.
如果渲染1个距离相机很远的三角形,它会为"想要"覆盖在屏幕上的每个像素生成一组颜色和深度值.然后说你渲染另一个更接近的多边形,它还会为深度和颜色缓冲区生成一组值.现在,在像素着色时存在一种"竞争",其中"更远的"片段(大的深度缓冲器值)被丢弃,并且仅保留最接近的片段.最接近的片段最终会为您拥有的像素着色.(当两个多边形几乎重叠时,可以发生Z战斗)
首先使用深度蒙版渲染场景中的对象.这意味着您呈现的每个形状,当其像素变为彩色时,深度缓冲区将通过比赛的"赢家"进行更新.
然后,3)glDepthMask( GL_FALSE )变为关断用于写入的深度缓冲,4)打开混合,5)呈现来自最远半透明形状最接近.看起来很奇怪,是吧?
当您关闭深度蒙版并渲染半透明形状时,OpenGL仍将读取深度缓冲区以确定要丢弃的片段(即,如果您的半透明形状位于已经渲染的实体形状后面,那么您将抛出半透明形状的碎片).但它不会写入深度缓冲区,因此如果半透明形状真的非常接近眼睛(比如半透明挡风玻璃),那些挡风玻璃碎片不会阻止其他碎片实际上远离被拉伸.这一点很重要,因为如果你的挡风玻璃是正确的在你的面前,你使它半透明,和你让挡风玻璃碎片来更新深度缓冲然后你会看到没有别的场景,除了挡风玻璃,即使有它背后的形状,因为OpenGL的人都会认为"嘿,那挡风玻璃是用户应该看到的唯一的事,因这些深度缓冲读数,所以我不会费心去除比这个挡风玻璃更远的东西." 关闭深度掩码是一种"欺骗"OpenGL进入"不知道"的方式,有非常接近但半透明的碎片.