libgdx - 交叉淡化两个精灵

时间:2014-07-11 04:10:51

标签: libgdx

我有两个精灵,我想从一个淡入淡出另一个:

Sprite sprite1, sprite2;
float alpha = 1;
...

public void render(float delta) {
   alpha -= 0.01f;
   if (alpha<0) alpha = 0;

   sprite1.setAlpha(alpha);
   sprite2.setAlpha(1-alpha);
   sprite1.draw(batch);
   sprite2.draw(batch);
}

但是当我这样做时,混合不正确,组合的图像在alpha为0.5的地方几乎完全透明。我在这里制作了一个问题的视频:http://vimeo.com/100472883 - 精灵1是尖锐的云图像,精灵2是模糊的云图像,我从一个到另一个淡入淡出,然后回来。

如果我在绘制精灵之前使用batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_CONSTANT_ALPHA);,图像的alpha看起来很好,但它会弄乱两个精灵的颜色。

1 个答案:

答案 0 :(得分:1)

我不认为他们“几乎完全”透明,而只是部分透明。如果你有两个50%透明物体在彼此前面,你仍然可以看到它们对。如果您正在进行全屏交叉淡入淡出,那么您正确执行此操作的方法是在另一个精灵后面以100%alpha绘制两个精灵中的一个,并且仅修改前面精灵的alpha。但是,当两个精灵都有alpha通道时,它并不容易。

一种方法是使用多纹理,这实际上并不是SpriteBatch的设计方式。如果使用SpriteBatch进行多纹理处理,则需要确保两个精灵都与其各自纹理的相同TextureRegion对齐,或者您可以将它们放在相同的纹理中并使用着色器中的已知偏移来分隔它们。然后,您可以使用自定义着色器在绘制之前在着色器中混合两个精灵。

如果您的精灵将保持单色,这将变得更加容易。您可以将两个精灵组合成一个精灵,方法是将一个精灵的颜色和alpha放在图像的R和G通道中,将另一个精灵的颜色和alpha放在B和A通道中。然后使用带有片段着色器的自定义着色器,如下所示:

String fragmentShader = "#ifdef GL_ES\n" //
            + "#define LOWP lowp\n" //
            + "precision mediump float;\n" //
            + "#else\n" //
            + "#define LOWP \n" //
            + "#endif\n" //
            + "varying LOWP vec4 v_color;\n" //
            + "varying vec2 v_texCoords;\n" //
            + "uniform sampler2D u_texture;\n" //
            + "uniform float u_crossfade;\n" //
            + "void main()\n"//
            + "{\n" //
            + "  vec4 texture = texture2D(u_texture, v_texCoords);\n" //
            + "  float sprite1Alpha = (1 - u_crossfade) * texture.g * v_color.a;\n" //
            + "  float sprite2Alpha = u_crossfade * texture.a * v_color.a;\n" //
            + "  gl_FragColor = v_color * vec4(vec3(sprite1Alpha*texture.r + sprite2Alpha*texture.b), sprite1Alpha + sprite2Alpha);\n" //
        + "}";

这应该使用blendfunc GL_ONE,GL_ONE_MINUS_SRC_ALPHA绘制,因为它预先乘以alpha。您需要在customShader.setUniformf("u_crossfade", crossfadeBlendValue);spriteBatch.begin()之间致电end()。这意味着如果每个精灵需要不同的交叉淡化,你一次只能批量处理一个精灵。

如果您不打算通过使用精灵色调的R分量来表示混合值,则可以解决这个问题。然后着色器将成为

String fragmentShader = "#ifdef GL_ES\n" //
            + "#define LOWP lowp\n" //
            + "precision mediump float;\n" //
            + "#else\n" //
            + "#define LOWP \n" //
            + "#endif\n" //
            + "varying LOWP vec4 v_color;\n" //
            + "varying vec2 v_texCoords;\n" //
            + "uniform sampler2D u_texture;\n" //
            + "void main()\n"//
            + "{\n" //
            + "  vec4 texture = texture2D(u_texture, v_texCoords);\n" //
            + "  float sprite1Alpha = (1 - v_color.r) * texture.g * v_color.a;\n" //
            + "  float sprite2Alpha = v_color.r * texture.a * v_color.a;\n" //
            + "  gl_FragColor = vec4(vec3(sprite1Alpha*texture.r + sprite2Alpha*texture.b), sprite1Alpha + sprite2Alpha);\n" //
        + "}";