You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebGL2片段着色器读取3D纹理值异常求助

问题分析与解决思路

你遇到的核心问题是整数纹理的采样方式错误,以及没有正确将原始整数数据映射到0-1的浮点范围。让我一步步拆解:

1. 整数纹理不能用texture()函数采样

你创建的是gl.R16I格式的整数纹理,但在片段着色器里用了普通的texture()函数——这个函数是为浮点纹理设计的,会自动对纹理值做归一化处理,但对于整数纹理,它的行为不符合预期,导致你拿到的不是真实的整数数值,而是异常的浮点值。

针对整数纹理,你需要用texelFetch()函数直接获取纹理单元的整数数据(需要传入纹理坐标的整数位置),或者用textureFetch()支持归一化坐标采样整数纹理(GLSL 300 ES版本支持)。

2. 原始数据的范围映射

你的纹理数据是Int16Array,范围是**-32768到32767**。要把这个范围映射到0-1的浮点区间,需要做线性转换:

float normalizedValue = (float(textureValue.r) + 32768.0) / 65535.0;

这样就能把最小的-32768转成0,最大的32767转成1,中间值按比例映射。

修正后的片段着色器

下面是调整后的代码,我保留了你的颜色判断逻辑,同时修复了采样和数据转换的问题:

#version 300 es
precision highp float;
precision highp int;
precision highp sampler3D;

uniform isampler3D in_texture; // 注意这里要用isampler3D,对应整数纹理
in vec3 v_texcoord;
out vec4 color;

void main() {
    // 用textureFetch支持归一化坐标采样整数纹理,返回整数类型结果
    ivec4 textureValue = textureFetch(in_texture, v_texcoord, 0);
    float floatValue = float(textureValue.r);
    
    // 映射到0-1范围(如果需要后续使用归一化值的话)
    // float normalized = (floatValue + 32768.0) / 65535.0;
    
    // 基于真实数值的颜色判断逻辑
    if(floatValue == 0.0){
        color = vec4(1.0,0.0,0.0,1.0);
    } else if(floatValue > 0.0){
        color = vec4(0.0,1.0,0.0,1.0);
    } else if(floatValue < 0.0){
        color = vec4(0.0,0.0,1.0,1.0);
    } else {
        color = vec4(0.5,0.5,0.5,1.0);
    }
}

注意几个关键点:

  • 采样器类型改成isampler3D(i代表integer),对应整数纹理格式
  • 使用textureFetch()采样整数纹理,确保拿到原始整数数据
  • 把整数转换成float后,再做数值判断

额外检查点

  • 确保你的v_texcoord是正确的归一化坐标(0到1之间),如果是纹理像素的整数坐标,替换为texelFetch(in_texture, ivec3(v_texcoord), 0)
  • 你的JavaScript纹理创建代码是正确的:gl.R16I、gl.RED_INTEGER、gl.SHORT的搭配符合整数纹理要求,过滤方式用NEAREST也是整数纹理的正确选择(线性过滤对整数纹理通常不支持)

这样修改后,你应该能正确获取到纹理的数值,并且看到预期的颜色分布了。

内容的提问来源于stack exchange,提问作者Dexylon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:23:37