我正在尝试理清如何使用片段着色器实现调色板交换(查看此帖https://gamedev.stackexchange.com/questions/43294/creating-a-retro-style-palette-swapping-effect-in-opengl)我是新手来开放gl所以如果有人能解释我的问题,我会很高兴。
以下是我尝试重现的代码段:
http://www.opengl.org/wiki/Common_Mistakes#Paletted_textures
我设置了Open GL环境,这样我就可以创建窗口,加载纹理,着色器并渲染我映射到窗口角落的单个方块(当我调整窗口图像的大小时也会被拉伸)。
我使用顶点着色器将坐标从屏幕空间转换为纹理空间,因此我的纹理也被拉伸
attribute vec2 position;
varying vec2 texcoord;
void main()
{
gl_Position = vec4(position, 0.0, 1.0);
texcoord = position * vec2(0.5) + vec2(0.5);
}
片段着色器是
uniform float fade_factor;
uniform sampler2D textures[2];
varying vec2 texcoord;
void main()
{
vec4 index = texture2D(textures[0], texcoord);
vec4 texel = texture2D(textures[1], index.xy);
gl_FragColor = texel;
}
textures[0]
是索引纹理(我试图着色的那个)
每个像素的颜色值为(0,0,0,255),(1,0,0,255),(2,0,0,255)......(8,0,0,255) - 总共8种颜色,这就是它看起来几乎是黑色的原因。我想使用存储在“红色通道”中的值对我的颜色进行编码。
textures[1]
是颜色表(9x1像素,每个像素都有唯一的颜色,放大到90x10张贴)
因此,您可以从片段着色器摘录中看到,我想从第一个纹理中读取索引值,例如(5,0,0,255),然后从存储在点(x = 5)的像素中查找实际颜色值,y = 0)在第二个纹理中。与在wiki中写的相同。
但是我得到的不是画图像:
实际上,如果我明确设置X点,如vec2(1,0),vec2(2,0),vec2(4,0)或vec2(8,0),我看到我无法访问第二个纹理的像素。但是当我使用vec2(0.1,0)或vec2(0.7,0)时,我可以获得颜色。猜测是因为纹理空间从我的9x1像素归一化到(0,0) - >(1,1)。但是,如何“禁用”该功能并简单地加载我的调色板纹理,以便我可以问“给我存储在(x,y)的像素的颜色值,请”?
答案 0 :(得分:2)
每个像素的颜色值为(0,0,0,255),(1,0,0,255),(2,0,0,255)......(8,0,0,255)
错误。每个像素的颜色值为:(0,0,0,1),(0.00392,0,0,1),(0.00784,0,0,1)...(0.0313,0,0,1)。 / p>
除非您使用整数或浮动纹理(并且您不是),否则您的颜色将存储为标准化浮点值。所以当您从着色器中获取它时,您认为“255”实际上只是“1.0”。
处理此问题的正确方法是首先将规范化值转换回非规范化形式。这是通过将值乘以255来完成的。然后通过除以调色板纹理的宽度(-1)将它们转换为纹理坐标。此外,您的调色板纹理不应该是2D:
#version 330 //Always include a version.
uniform float fade_factor;
uniform sampler2D palattedTexture;
uniform sampler1D palette;
in vec2 texcoord;
layout(location = 0) out vec4 outColor;
void main()
{
float paletteIndex = texture(palattedTexture, texcoord).r * 255.0;
outColor = texture(palette, paletteIndex / (textureSize(palette).x - 1));
gl_FragColor = texel;
}
以上代码是为GLSL 3.30编写的。如果您使用的是早期版本,请相应地进行翻译。
此外,您不应该使用RGBA纹理作为调色板纹理。它只是一个频道,因此请使用GL_LUMINANCE
或GL_R8
。