我有2个着色器程序-一个用于渲染带有纹理的精灵,第二个用于渲染多边形。我已经启用了混合和Z缓冲区,如下所示:
GLES20.glEnable(GLES20.GL_BLEND);
GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA);
GLES20.glEnable( GLES20.GL_DEPTH_TEST );
GLES20.glDepthFunc( GLES20.GL_LEQUAL );
GLES20.glDepthMask( true );
GLES20.glDepthRangef(0, maxZDepth); //maxZDepth = 100f;
我的渲染包括2个渲染调用(glDrawElements):一个用于精灵,一个紧随其后用于具有足够着色器程序的多边形...将对象数据(顶点等)发送到着色器的顺序是从对象的最低位开始排序的Z值最高,我还必须将这样的指令添加到我的精灵的着色器中:
if(gl_FragColor.a == 0.0)
discard;
现在,混合和Z缓冲区可以正常工作,但一次只能在一个着色器的范围内。由第一个着色器绘制的对象的混合似乎与第二个着色器无关……这是一个示例:
此处的精灵比其下方的棕色多边形具有更高的Z值,这就是为什么它在多边形上绘制但混合失败的原因,并且您可以看到精灵周围显示的灰色背景(由glClearColor创建)...
有人知道这个问题有好的解决方案吗?我考虑过将2个着色器程序合并为一个,然后我希望可以解决这个问题只有1个渲染调用,但我宁愿为精灵和多边形保留2个单独的着色器程序...
根据简短的评论讨论,问题是:
深度缓冲区每个像素仅保留一个深度。部分透明的像素组合了来自不同深度的两种颜色。但是只能分配一个深度。最后就是较近像素的深度。
在理想的世界中,如果您绘制的东西远且不透明,则绘制的东西远近且透明,然后在中间的物体又不透明,则最终输出将是介于中间的物体和接近的物体的混合。实际发生的是透明的事物将其深度设置为深度缓冲区。当您在物体之间绘制物体时,将不会输出任何像素,因为它比深度缓冲区中最近的物体更远。因此,您最终会把遥远的事物与临近的事物混合在一起,好像从未画过中间的事物一样。
有很多解决方案,取决于您要达到的严格精度,多少几何(至少部分是透明的)和多少时间。
首先,如果您有任何绝对不透明的几何图形,则可以首先以最有效的顺序绘制所有几何图形。
最明显的解决方案是对透明几何图形进行排序并从背面渲染。那很棒,除了不能仅通过回到最前面就可以正确绘制所有几何图形(例如参见相互重叠),而且在最幼稚的实现中,GL状态更改最终可能会变得非常昂贵,而不是用一个着色器绘制50,000个三角形,然后每秒切换并绘制50,000,您就为99,999个开关绘制了三角形,开关,绘制,开关,绘制等。
如果可以接受附加透明性,那么您可以按任何旧顺序填充透明材料,而无需写入深度缓冲区。
英伟达(Nvidia)提出的一些东西正在利用多重采样的优势,但可能会稍微提高一点。想象更像是为每个像素组合了8x8或16x16像素样本。在那种情况下,绘制透明度不是通过从帧缓冲区读取,混合并再次写出来实现的,而是如果透明度为50%,则只需在每个单元格中仅写入例如一半的样本。您随机选择一半。当您增加像元大小时,可以提高质量,从而获得与订单无关的透明性。
假设您的多边形始终是不透明的,并且所有子图形都可能是部分透明的,那么,就像我现在正在做的那样,首先绘制多边形,然后以从前到后的顺序绘制子图形。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句