WebGL2中除R8外的纹理数据格式无法正常工作求助
WebGL2 3D纹理非R8格式采样全0问题排查与解决
问题现象
在Windows10 64位Chrome v104+环境下,使用TypeScript编写WebGL2代码处理单通道3D纹理时,仅R8格式能正常工作,其余格式均出现采样值全0的情况:
- 切换
R8UI格式(使用usampler3D)时,采样返回全0; R16UI、R32F等格式(对应传入Uint8Array/Float32Array)同样采样全0;- 无着色器编译错误、WebGL运行时控制台报错或错误返回值。
核心问题排查与修复方案
1. 整数纹理必须禁用线性过滤
WebGL2中,整数格式纹理(如R8UI、R16UI)不支持线性过滤,当前代码仅设置了TEXTURE_MIN_FILTER为NEAREST,但未显式设置TEXTURE_MAG_FILTER,部分浏览器会默认使用线性过滤,导致整数纹理采样失效。
修改setDataTexture中的纹理参数设置:
// 补充设置MAG_FILTER为NEAREST,整数纹理不支持LINEAR gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); // 新增这一行
2. 确保数据类型与纹理格式严格匹配
R16UI格式需要传入Uint16Array类型数据,而非Uint8Array;R32F格式需要传入Float32Array类型数据;- 错误的数据类型会导致纹理数据上传失败,最终采样全0。
示例修正(R16UI):
// R16UI 正确数据类型 const data = new Uint16Array(W*H*N); // 改用Uint16Array internal_format = sys.gl.R16UI; setDataTexture(W,H,N, data, internal_format);
3. 验证纹理uniform的绑定与采样器类型匹配
确保着色器中的采样器类型与纹理格式严格对应:
- 浮点格式(R8、R32F)使用
sampler3D; - 无符号整数格式(R8UI、R16UI)使用
usampler3D; - 有符号整数格式(R16I)使用
isampler3D。
同时,检查uniform的纹理单元绑定是否正确:
// 确保uniform变量绑定到正确的纹理单元(以R8UI为例) const volumeLoc = gl.getUniformLocation(program, "volume"); gl.uniform1i(volumeLoc, 0); // 对应TEXTURE0
4. 确认采样坐标在有效范围内
着色器中的采样坐标pos必须处于[0.0, 1.0]区间内,超出范围的坐标会触发CLAMP_TO_EDGE(但整数纹理边界值可能为0)。可以在着色器中添加调试输出验证坐标:
// 片段着色器中添加调试,输出坐标是否正常 if (pos.x < 0.0 || pos.x > 1.0 || pos.y < 0.0 || pos.y > 1.0 || pos.z < 0.0 || pos.z > 1.0) { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 坐标越界输出红色 return; }
5. 补充WebGL错误检查(辅助排查)
虽然当前无控制台报错,但添加错误检查可以定位潜在问题:
// 在texSubImage3D后添加错误检查 gl.texSubImage3D(gl.TEXTURE_3D, 0, 0,0,0, X,Y,Z, fmt, typ, data); const err = gl.getError(); if (err !== gl.NO_ERROR) { console.error(`WebGL error after texSubImage3D: ${err}`); }
完整修正后的代码片段
setDataTexture 修正版
setDataTexture(X: number, Y: number, Z: number, data: any, internal_format: GLenum) { const gl = this.gl; const params: Record<GLenum, any> = {}; params[gl.R8] = ["R8", gl.RED, gl.UNSIGNED_BYTE]; params[gl.R8UI] = ["R8UI", gl.RED_INTEGER, gl.UNSIGNED_BYTE]; params[gl.R16UI] = ["R16UI", gl.RED_INTEGER, gl.UNSIGNED_SHORT]; params[gl.R16I] = ["R16I", gl.RED_INTEGER, gl.SHORT]; params[gl.R32F] = ["R32F", gl.RED, gl.FLOAT]; gl.activeTexture(gl.TEXTURE0); if (this.dataTex !== null) { gl.deleteTexture(this.dataTex); this.dataTex = null; } if (!params[internal_format]) { console.log(`Unknown internal format ${internal_format}`); return; } const [str, fmt, typ] = params[internal_format]; this.dataTex = gl.createTexture(); gl.bindTexture(gl.TEXTURE_3D, this.dataTex); gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1); gl.texStorage3D(gl.TEXTURE_3D, 1, internal_format, X,Y,Z); // 统一设置过滤模式,整数纹理必须用NEAREST const filter = (internal_format === gl.R8UI || internal_format === gl.R16UI || internal_format === gl.R16I) ? gl.NEAREST : gl.NEAREST; // 浮点格式可按需切换为LINEAR gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MIN_FILTER, filter); gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_MAG_FILTER, filter); gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_R, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_3D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); gl.texSubImage3D(gl.TEXTURE_3D, 0, 0,0,0, X,Y,Z, fmt, typ, data); // 检查错误 const err = gl.getError(); if (err !== gl.NO_ERROR) { console.error(`WebGL error: ${err}`); } }
R16UI 主程序示例
// R16UI 正确使用方式 const data = new Uint16Array(W*H*N); // 初始化数据,比如填充非零值 data.fill(0xFFFF); internal_format = sys.gl.R16UI; setDataTexture(W,H,N, data, internal_format);
R8UI 片段着色器调试版
#version 300 es precision highp int; precision highp float; uniform highp usampler3D volume; uniform vec2 resolution; out vec4 fragColor; void main() { vec3 pos = vec3(gl_FragCoord.x / resolution.x, gl_FragCoord.y / resolution.y, 0.5); // 替换为你的实际坐标计算逻辑 // 检查坐标范围 if (pos.x < 0.0 || pos.x > 1.0 || pos.y < 0.0 || pos.y > 1.0 || pos.z < 0.0 || pos.z > 1.0) { fragColor = vec4(1.0, 0.0, 0.0, 1.0); return; } uint val_ = texture(volume, pos).r; fragColor = val_ > 0u ? vec4(0.5, 0.5, 0.5, 1.0) : vec4(0.0, 0.0, 0.0, 1.0); }
内容的提问来源于stack exchange,提问作者Mean_Virus_3460
相关产品推荐
相关产品推荐

