【发布时间】:2014-11-25 18:00:24
【问题描述】:
我正在尝试使用 LibGDX 制作一款复古风格的小游戏,我想让玩家选择几个角色的颜色,所以我考虑加载 png 索引图像,然后以编程方式更新调色板。 ..我错了^^U
调色板似乎已成为过去,而且似乎获得类似结果的最佳选择是使用着色器。
这是一张解释我现在正在尝试的图片:
我的意图是使用 2 张图片。其中之一,pixel_guy.png 是一个只有 6 种颜色的 png 图像(这些颜色是它的原始调色板)。另一张图片colortable.png 是一个 6x6 像素的 png,其中包含 6 个调色板,每个调色板有 6 种颜色(每行是一个不同的调色板)。 colortable.png 第一行像素的颜色将与pixel_guy.png 中使用的颜色匹配,这将是第一个/原始调色板,其他行将是调色板 2 到 6。我试图实现的是使用colortable 的第一个调色板用于索引 pixelguy 颜色,然后通过向着色器发送一个数字(从 2 到 6)来更改调色板。
经过一番研究,我找到了一个post in gamedev stackexchange,显然这是我要找的,所以我尝试测试它。
我创建了顶点着色器和片段着色器并加载了我的纹理(我想要交换其调色板的纹理,以及包含多个调色板的纹理),但输出是一个意想不到的白色图像。
我的顶点着色器:
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord0;
uniform mat4 u_projTrans;
varying vec4 v_color;
varying vec2 v_texCoords;
void main() {
v_color = a_color;
v_texCoords = a_texCoord0;
gl_Position = u_projTrans * a_position;
}
我的片段着色器:
// Fragment shader
// Thanks to Zack The Human https://gamedev.stackexchange.com/questions/43294/creating-a-retro-style-palette-swapping-effect-in-opengl/
uniform sampler2D texture; // Texture to which we'll apply our shader? (should its name be u_texture?)
uniform sampler2D colorTable; // Color table with 6x6 pixels (6 palettes of 6 colors each)
uniform float paletteIndex; // Index that tells the shader which palette to use (passed here from Java)
void main()
{
vec2 pos = gl_TexCoord[0].xy;
vec4 color = texture2D(texture, pos);
vec2 index = vec2(color.r + paletteIndex, 0);
vec4 indexedColor = texture2D(colorTable, index);
gl_FragColor = indexedColor;
}
我用来进行纹理绑定并将调色板编号传递给着色器的代码:
package com.test.shaderstest;
import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShaderProgram;
public class ShadersTestMain extends ApplicationAdapter {
SpriteBatch batch;
Texture imgPixelGuy;
Texture colorTable;
private ShaderProgram shader;
private String shaderVertIndexPalette, shaderFragIndexPalette;
@Override
public void create () {
batch = new SpriteBatch();
imgPixelGuy = new Texture("pixel_guy.png"); // Texture to which we'll apply our shader
colorTable = new Texture("colortable.png"); // Color table with 6x6 pixels (6 palettes of 6 colors each)
shaderVertIndexPalette = Gdx.files.internal("shaders/indexpalette.vert").readString();
shaderFragIndexPalette = Gdx.files.internal("shaders/indexpalette.frag").readString();
ShaderProgram.pedantic = false; // important since we aren't using some uniforms and attributes that SpriteBatch expects
shader = new ShaderProgram(shaderVertIndexPalette, shaderFragIndexPalette);
if(!shader.isCompiled()) {
System.out.println("Problem compiling shader :(");
}
else{
batch.setShader(shader);
System.out.println("Shader applied :)");
}
shader.begin();
shader.setUniformi("colorTable", 1); // Set an uniform called "colorTable" with index 1
shader.setUniformf("paletteIndex", 2.0f); // Set a float uniform called "paletteIndex" with a value 2.0f, to select the 2nd palette
shader.end();
colorTable.bind(1); // We bind the texture colorTable to the uniform with index 1 called "colorTable"
}
@Override
public void render () {
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(imgPixelGuy, 0, 0); // Draw the image with the shader applied
batch.end();
}
}
我不知道这是否是将浮点值传递给片段制服的正确方法。也不确定我尝试使用的代码 sn-p 是如何工作的。
编辑:我尝试了 TenFour04 建议的更改,它们完美地工作:)
这是预处理的精灵
我已经用更改更新了存储库,(Java 代码here,片段着色器here),如果有人感兴趣,可以在这里下载:https://bitbucket.org/hcito/libgdxshadertest
编辑 2: 我刚刚将 TenFour04 建议的最后一个优化添加到存储库中(将调色板索引传递给 R 通道中调用 sprite.setColor() 方法的每个精灵),并且再次完美运行:)
【问题讨论】:
-
为什么这会导致投票失败?
-
不知道:/我知道我的英语不是很好,而且我有点笨拙,但我真的在努力做到最好^^U 非常感谢帮助我,Tenfour :) (顺便说一句,我需要 5 点的声望来支持你的答案^^U)
标签: android opengl-es libgdx shader fragment-shader