在libgdx中的纹理灰度化

6

有没有一种方法可以将libgdx的Texture转换为灰度图像?到目前为止,我已经复制了我想要转换为灰度的图像,并且手动进行了操作,但我认为这不是最好的解决方案,因为我的游戏使用了越来越多的图像,并且它使用了大量的磁盘空间。

3个回答

10

我觉得我应该分享这个东西,供那些想要使用复制/粘贴代码的人使用。

import com.badlogic.gdx.graphics.glutils.ShaderProgram;

public class GrayscaleShader {
    static String vertexShader = "attribute vec4 a_position;\n" +
            "attribute vec4 a_color;\n" +
            "attribute vec2 a_texCoord0;\n" +
            "\n" +
            "uniform mat4 u_projTrans;\n" +
            "\n" +
            "varying vec4 v_color;\n" +
            "varying vec2 v_texCoords;\n" +
            "\n" +
            "void main() {\n" +
            "    v_color = a_color;\n" +
            "    v_texCoords = a_texCoord0;\n" +
            "    gl_Position = u_projTrans * a_position;\n" +
            "}";

    static String fragmentShader = "#ifdef GL_ES\n" +
            "    precision mediump float;\n" +
            "#endif\n" +
            "\n" +
            "varying vec4 v_color;\n" +
            "varying vec2 v_texCoords;\n" +
            "uniform sampler2D u_texture;\n" +
            "\n" +
            "void main() {\n" +
            "  vec4 c = v_color * texture2D(u_texture, v_texCoords);\n" +
            "  float grey = (c.r + c.g + c.b) / 3.0;\n" +
            "  gl_FragColor = vec4(grey, grey, grey, c.a);\n" +
            "}";

    public static ShaderProgram grayscaleShader = new ShaderProgram(vertexShader,
            fragmentShader);
}

要使用它,请调用

spriteBatch.setShader(GrayscaleShader.grayscaleShader)

完成黑白渲染后,别忘了调用它。

spriteBatch.setShader(null);

1
如果你想要一个可维护性和易读性的噩梦,那么就将着色器放在同一个文件中,并加载它们(并使用一些好用的着色器工具)。但是,我建议你将着色器放在单独的文件中。 - Oliver Dixon
2
@iLoveUnicorns 同意。但对于想要快速解决方案进行测试的人来说,这并不是一个复制/粘贴选项。这并不会阻止他们这样做,只是朝着正确的方向迈出了一步。 - Will Calderwood

7
您应该能够编写一个GLSL着色器,以灰度渲染纹理。这需要OpenGL 2.x,并且不会真正“转换”纹理,而只是将其呈现为灰度到显示器上。
要了解关于着色器的详细教程,包括灰度着色器,请查看:https://github.com/mattdesl/lwjgl-basics/wiki/ShaderLesson3 (Libgdx实际上并没有定义GLSL着色器API,它是从OpenGL传递过来的,因此大多数在Web上找到的常规OpenGL教程或代码都可以使用。)
对于更直接的hack,只需取Libgdx SpriteBatch着色器并更改片段着色器,使其平均rgb分量。(您可以定义自己的ShaderProgram并将其提供给SpriteBatch使用。)将片段着色器的主体更改为以下内容(未经测试,可能无法编译):
+ "  vec4 c = v_color * texture2D(u_texture, v_texCoords);\n" //
+ "  float grey = (c.r + c.g + c.b) / 3.0;\n" //
+ "  gl_FragColor = vec4(grey, grey, grey, c.a);\n" //

2
您可以在GLES中仅加载亮度纹理或亮度和透明度纹理(请参见glTexImage2D)。在libgdx中,您可以在实例化Texture时指定PixFormat.Intensity(亮度)或LuminanceAlpha(亮度和透明度),这将生成一个灰度纹理。

您仍然需要加载两个纹理(一个彩色,一个灰度),但它们可以使用相同的源,并且仅使用每像素1个字节的亮度。

更有效的解决方案是根据P.T.的建议实现着色器,但仅适用于GLES 2。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接