我正在尝试通过在片段着色器中应用窗口调平,从 WebGL2 中的 16 位数组缓冲区渲染灰度图像。我生成的纹理如下:
let typedArray = new Int16Array(data);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.R16I,
w, h,
0,
gl.RED_INTEGER,
gl.SHORT,
typedArray);
并尝试使用以下片段着色器中的数据:
let fragmentShaderSource = `#version 300 es
precision highp float;
precision highp int;
precision highp isampler2D;
// our texture
uniform isampler2D u_image;
uniform highp float u_windowWidth;
uniform highp float u_windowCenter;
in vec2 v_texCoord;
out vec4 outColor;
void main() {
highp float f = float(texture(u_image, v_texCoord).r);
f = (f - (u_windowCenter - 0.5)) / max(u_windowWidth - 1.0, 1.0) + 0.5;
f = min(max(f, 0.0), 1.0);
outColor = vec4(vec3(f), 1.0);
}
`;
但这只会呈现黑屏。实际上,经过一些调试,我发现所有像素texture(u_image, v_texCoord)
的值为零,并且(alpha)字段的值非常大(2^29 ~ 2^30)。我试过改变着色器的精度,但结果是一样的。rgb
a
为了缩小问题范围,我尝试了一种不同的方法,将 16 位整数拆分为gl.RGBA4
,每个 RGBA 通道中包含 4 位:
let typedArray = new Uint16Array(data);
gl.texImage2D(
gl.TEXTURE_2D,
0,
gl.RGBA4,
w, h,
0,
gl.RGBA,
gl.UNSIGNED_SHORT_4_4_4_4,
typedArray);
并将 RGBA 值组合回片段着色器中的 16 位整数。
let fragmentShaderSource = `#version 300 es
precision highp float;
precision highp int;
precision highp sampler2D;
// our texture
uniform sampler2D u_image;
uniform highp float u_windowWidth;
uniform highp float u_windowCenter;
in vec2 v_texCoord;
out vec4 outColor;
void main() {
highp vec4 rgba_map = texture(u_image, v_texCoord);
// Combining rgba4 back into int16
highp f = rgba_map.r * 65536.0 + rgba_map.g * 4096.0 + rgba_map.b * 256.0 + rgba_map.a * 16.0;
// signed value
if (f > 32768.0) {
f = 65536.0 - f;
}
f = (f - (u_windowCenter - 0.5)) / max(u_windowWidth - 1.0, 1.0) + 0.5;
f = min(max(f, 0.0), 1.0);
outColor = vec4(vec3(f), 1.0);
}
`;
这个版本很好地呈现了预期的图像,尽管由于转换,结果有点嘈杂。我也尝试过其他一些格式,浮点类型的很好,整数类型的格式都不起作用。所以我认为程序的其他部分都很好。我想知道我的程序有什么问题。