我想在iPad2上编写一个简单的GLSL片段着色器,并且我遇到了一个奇怪的问题,OpenGL似乎代表了一个8位“红色”值,作为纹理上传的一部分,像素值已被转换为浮点数。我想要做的是传入一个包含大量8位表索引和实际像素值的32bpp表的纹理。iOS中的片段着色器中奇怪的GLSL浮点颜色值
我的纹理数据看起来是这样的:
// Lookup table stored in a texture
const uint32_t pixel_lut_num = 7;
uint32_t pixel_lut[pixel_lut_num] = {
// 0 -> 3 = w1 -> w4 (w4 is pure white)
0xFFA0A0A0,
0xFFF0F0F0,
0xFFFAFAFA,
0xFFFFFFFF,
// 4 = red
0xFFFF0000,
// 5 = green
0xFF00FF00,
// 6 = blue
0xFF0000FF
};
uint8_t indexes[4*4] = {
0, 1, 2, 3,
4, 4, 4, 4,
5, 5, 5, 5,
6, 6, 6, 6
};
然后每个纹理被绑定和纹理数据被上传,像这样:
GLuint texIndexesName;
glGenTextures(1, &texIndexesName);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texIndexesName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED_EXT, width, height, 0, GL_RED_EXT, GL_UNSIGNED_BYTE, indexes);
GLuint texLutName;
glGenTextures(1, &texLutName);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texLutName);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pixel_lut_num, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, pixel_lut);
我相信纹理设置和均匀值按预期工作,因为片段着色器主要与以下代码一起工作:
varying highp vec2 coordinate;
uniform sampler2D indexes;
uniform sampler2D lut;
void main()
{
// normalize to (RED * 42.5) then lookup in lut
highp float val = texture2D(indexes, coordinate.xy).r;
highp float normalized = val * 42.5;
highp vec2 lookupCoord = vec2(normalized, 0.0);
gl_FragColor = texture2D(lut, lookupCoord);
}
上面的代码需要8位索引,并在lut中查找32bpp BGRA像素值。我不明白的部分是在OpenGL中定义了这个42.5值。我通过反复试验发现了这个比例值,并且我已经确认每个像素的输出颜色是正确的(意味着每个查找表查找的索引是正确的)与42.5值。但是,OpenGL究竟如何提供这个值呢?
查看此OpenGL man page,我发现在将8位“索引”值转换为OpenGL内部使用的浮点值时似乎使用了两个颜色常量GL_c_SCALE和GL_c_BIAS。这些常量在哪里定义,我如何在运行时或编译时查询这些值? “索引”表的实际浮点值是否是真正的问题?我不知道为什么texture2D(indexes,...)调用返回这个时髦的值,有没有其他方法可以获得适用于iOS的索引的int或float值?我试着看一维纹理,但他们似乎并不支持。
啊,它是(255 /(pixel_lut_num_1))= 42.5。非常感谢。我不知道为什么我以前没有看到。重新使用缩小过滤器,你是说GL_NEAREST是更好的选择吗? – MoDJ
@MoDJ:是的。只要您不想在LUT中的相邻条目之间进行混合,那么使用GL_NEAREST是最好和最有效的选择。请注意,“缩小”和“放大”之间的距离在访问LUT时没有任何意义,并且GL在这里所做的选择将取决于您用于相邻片段的索引,因此用于缩小和放大的不同滤镜不是“这里真的是个好主意。 – derhass
我几乎可以理解你在这里描述的像素居中逻辑。我测试了我的表格,它的确从0.1428(又名0.0 + 1.0/7.0)的颜色索引0变为1。所以,我看到你说的1/2像素界限是0.1428/2(又名0.0 + 1.0/2 * 7.0)。所以,你说的中心纹理坐标在lut中查找应该是0 = 0.0714,1 =(2 * 0.0714)+ 0.0714等等。所以,我看到你如何得到“补偿”来补充,但你是如何得出“比例”公式的? 255范围被分成两倍的段,但你是如何计算“规模”的? – MoDJ