如何在片段着色器中应用我自己的颜色图?
How to apply my own colormap in the fragment shader?
我有一个给定的图像 img(16 位灰度图像,其值范围从 0 到 65535)和一个颜色图 colormap_file,它是 8位RGB 256*256像素图像。
因此,多亏了这样一个颜色图,我能够为 valueImage 中的所有像素分配一个 (R, G, B) 三元组。
目前,它是通过这个函数在纯 Python 中完成的:
def transcodeThroughColormap(img, colormap_file):
colormap = np.array(Image.open(colormap_file))
flat_colormap = colormap.flatten()
idx = img
i = np.floor(idx / 256)
j = idx - (i * 256)
R = flat_colormap[(3 * (i * 256 + j)).astype('int')]
G = flat_colormap[(3 * (i * 256 + j) + 1).astype('int')]
B = flat_colormap[(3 * (i * 256 + j) + 2).astype('int')]
rgbArray = np.zeros(shape=(img.shape[0], img.shape[1], 3))
rgbArray[..., 0] = R
rgbArray[..., 1] = G
rgbArray[..., 2] = B
return rgbArray
但是,我想在我的片段着色器中应用这样的颜色图。
因此,我想知道我是否必须在我的片段着色器中使用两个 sampler2D,但我不知道如何获得与 Python 中相同的结果。
我通过了从 OpenGL 论坛得到的答案:
一个选项:
uniform usampler2D image_tex;
uniform sampler2D color_map;
in vec2 texcoord;
void main()
{
uint value = texture(image_tex, texcoords).x;
uvec2 uv = uvec2(value / 0x100, value % 0x100);
vec4 color = texelFetch(color_map, uv, 0);
gl_FragColor = color;
}
注意图片纹理需要是无符号整数类型,即GL_R16UI。放大和缩小过滤器需要 GL_NEAREST(线性插值对整数值没有意义)。
如果图像纹理中的值表示连续范围并且颜色图是连续的,那么您可以对图像纹理使用归一化格式(即 GL_R16)并使用一维纹理颜色图(但是不能保证支持 65536 的大小,因此您可能需要对颜色图进行下采样)。例如
uniform sampler2D image_tex;
uniform sampler1D color_map;
in vec2 texcoord;
void main()
{
float value = texture(image_tex, texcoords).x;
vec4 color = texture(color_map, value);
gl_FragColor = color;
}
或者您可以为颜色图使用缓冲纹理(保证支持 65536 大小),这样就无需将值拆分为行和列。例如
uniform sampler2D image_tex;
uniform samplerBuffer color_map;
in vec2 texcoord;
void main()
{
float value = texture(image_tex, texcoords).x;
int idx = int(round(value * 0xFFFF));
vec4 color = texelFetch(color_map, idx, 0);
gl_FragColor = color;
}
我有一个给定的图像 img(16 位灰度图像,其值范围从 0 到 65535)和一个颜色图 colormap_file,它是 8位RGB 256*256像素图像。
因此,多亏了这样一个颜色图,我能够为 valueImage 中的所有像素分配一个 (R, G, B) 三元组。
目前,它是通过这个函数在纯 Python 中完成的:
def transcodeThroughColormap(img, colormap_file):
colormap = np.array(Image.open(colormap_file))
flat_colormap = colormap.flatten()
idx = img
i = np.floor(idx / 256)
j = idx - (i * 256)
R = flat_colormap[(3 * (i * 256 + j)).astype('int')]
G = flat_colormap[(3 * (i * 256 + j) + 1).astype('int')]
B = flat_colormap[(3 * (i * 256 + j) + 2).astype('int')]
rgbArray = np.zeros(shape=(img.shape[0], img.shape[1], 3))
rgbArray[..., 0] = R
rgbArray[..., 1] = G
rgbArray[..., 2] = B
return rgbArray
但是,我想在我的片段着色器中应用这样的颜色图。
因此,我想知道我是否必须在我的片段着色器中使用两个 sampler2D,但我不知道如何获得与 Python 中相同的结果。
我通过了从 OpenGL 论坛得到的答案: 一个选项:
uniform usampler2D image_tex;
uniform sampler2D color_map;
in vec2 texcoord;
void main()
{
uint value = texture(image_tex, texcoords).x;
uvec2 uv = uvec2(value / 0x100, value % 0x100);
vec4 color = texelFetch(color_map, uv, 0);
gl_FragColor = color;
}
注意图片纹理需要是无符号整数类型,即GL_R16UI。放大和缩小过滤器需要 GL_NEAREST(线性插值对整数值没有意义)。
如果图像纹理中的值表示连续范围并且颜色图是连续的,那么您可以对图像纹理使用归一化格式(即 GL_R16)并使用一维纹理颜色图(但是不能保证支持 65536 的大小,因此您可能需要对颜色图进行下采样)。例如
uniform sampler2D image_tex;
uniform sampler1D color_map;
in vec2 texcoord;
void main()
{
float value = texture(image_tex, texcoords).x;
vec4 color = texture(color_map, value);
gl_FragColor = color;
}
或者您可以为颜色图使用缓冲纹理(保证支持 65536 大小),这样就无需将值拆分为行和列。例如
uniform sampler2D image_tex;
uniform samplerBuffer color_map;
in vec2 texcoord;
void main()
{
float value = texture(image_tex, texcoords).x;
int idx = int(round(value * 0xFFFF));
vec4 color = texelFetch(color_map, idx, 0);
gl_FragColor = color;
}