在一个着色器中使用ZBuffer和alpha混合在2D

时间:2015-08-06 11:19:10

标签: android opengl-es opengl-es-2.0

我有一些精灵表,在场景中我必须渲染来自不同纹理的多张图片。精灵表上的每个对象可以具有不同的Z值(它可以在其他对象之下或之上)。来自不同纹理的对象的Z值经常重叠,我也使用alpha混合来实现透明度。

所有这些因素迫使我按照Z值对所有发送的对象进行排序(最先绘制最远的对象)。这里出现了问题。每个纹理执行1次渲染调用,可以一次正确地对一个纹理中的对象进行排序和绘制。在第一个纹理中的某些对象取决于它们的Z值之前,可能会绘制第二个纹理中的对象。在这种情况下,我无法在绘制之前对对象进行正确排序因为绘图需要的不仅仅是纹理量渲染调用,这是我猜不可接受的。

到目前为止,我想到的唯一解决方案是创建一个片段着色器(根据传递的变化改变采样器):

public static final String fs_Image =
        "precision mediump float;" +
        "varying vec2 v_texCoord;" +
        "varying float v_texInd;" +
        "uniform sampler2D u_tex0;" +
        "uniform sampler2D u_tex1;" +
        "void main() {" +
        "   if(v_texInd == 0.0)" +
        "       gl_FragColor = texture2D( u_tex0, v_texCoord );" +
        "   else" +
        "       gl_FragColor = texture2D( u_tex1, v_texCoord );" +
        "   if(gl_FragColor.a == 0.0)" +
        "       discard;" +
        "}";

我不太喜欢这个解决方案,但它使我能够在1次渲染调用中绘制所有对象。如果有超过2个纹理我怀疑这可能是有效的解决方案。

另一种选择是为不同的精灵表中的所有对象创建Z值约束,然后来自不同纹理的z值不会重叠,我可以在几次渲染调用中正确地对多个纹理中的对象进行排序和绘制。

我想知道哪种方法更好?或者也许有更好的解决方案?我将非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

正如您所做的那样,首先,对您的对象进行z排序。 然后,假设您的像素可以来自4种不同的纹理,并且您需要一次渲染渲染:

  • 向片段着色器添加vec4制服,并使用其组件乘以纹理查找产生的每个vec4
  • 将纹理索引附加到每个对象
  • 在绘制对象之前,绑定均匀,例如将所有值设置为0.0f,除了与要使用的纹理对应的值,设置为1.0f

frag shader会是这样的:

precision mediump float;

varying vec2 v_texCoord;

uniform vec4 u_SelectedTexture;

uniform sampler2D u_tex0;
uniform sampler2D u_tex1;
uniform sampler2D u_tex2;
uniform sampler2D u_tex3;

void main() {
   glFragColor = texture2D(u_tex0, v_texCoord) * uSelectedTexture.x
       + texture2D(u_tex1, v_texCoord) * uSelectedTexture.y +
       texture2D(u_tex2, v_texCoord) * uSelectedTexture.z +
       texture2D(u_tex3, v_texCoord) * uSelectedTexture.w;
}

u_SelectedTexture是我建议你添加的制服。

在渲染管道中,如果你想使用u_tex1,你应该使用像绘图之前的东西:

glUniform4f(uniformLocation, 0.0f, 1.0f, 0.0f, 0.0f);

这些是非依赖性纹理读取,不会显着影响您的渲染时间。

希望它能回答你的问题。

问候!