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

如何在Three.js中传递超过255的像素分割ID至自定义着色器?

解决分割ID超过255无法传递的方案

方案1:使用高精度单通道纹理

直接替换纹理存储格式为16位无符号整数或32位浮点数,能支持更大范围的分割ID,步骤如下:

16位无符号整数(支持最大65535的ID)

  1. 修改纹理数据填充逻辑:

    // 单通道16位,数组长度等于像素总数
    var imageData = new Uint16Array(persDatas[threshold].length);
    for (var x = 0; x < persDatas[threshold].length; x++) {
        var segID = persDatas[threshold][x]; // 直接存储原始ID,确保≤65535
        imageData[x] = segID;
    }
    // 创建指定格式的DataTexture
    var texture = new THREE.DataTexture(
        imageData,
        4104,
        1856,
        THREE.RedFormat, // 单通道存储
        THREE.UnsignedShortType // 16位无符号整数类型
    );
    texture.needsUpdate = true;
    persTextures[threshold] = texture;
    uniforms.persTexture.value = texture;
    
  2. 修改着色器采样逻辑:
    采样得到的是0-1的浮点数,乘以65535还原原始ID:

    float segID = texture(persTexture, vPosition.xy).r * 65535.0;
    

32位浮点数(支持超大范围ID)

若ID超过65535,可改用Float32格式:

var imageData = new Float32Array(persDatas[threshold].length);
for (var x = 0; x < persDatas[threshold].length; x++) {
    imageData[x] = persDatas[threshold][x]; // 直接存储原始ID
}
var texture = new THREE.DataTexture(
    imageData,
    4104,
    1856,
    THREE.RedFormat,
    THREE.FloatType
);

着色器中直接读取即可:

float segID = texture(persTexture, vPosition.xy).r;

方案2:多通道拆分编码(兼容Uint8纹理)

如果必须保留Uint8格式,可将ID拆分为高8位和低8位,分别存入R、G通道,组合后支持最大65535的ID:

  1. 修改数据填充逻辑:

    var imageData = new Uint8Array(4 * persDatas[threshold].length);
    for (var x = 0; x < persDatas[threshold].length; x++) {
        var segID = persDatas[threshold][x];
        // 拆分高8位和低8位
        var lowByte = segID & 0xFF;
        var highByte = (segID >> 8) & 0xFF;
        imageData[x * 4] = lowByte;
        imageData[x * 4 + 1] = highByte;
        imageData[x * 4 + 2] = 0;
        imageData[x * 4 + 3] = 255;
    }
    var texture = new THREE.DataTexture(imageData, 4104, 1856);
    texture.needsUpdate = true;
    persTextures[threshold] = texture;
    uniforms.persTexture.value = texture;
    
  2. 修改着色器采样逻辑:
    合并两个通道的值还原原始ID:

    vec4 color = texture(persTexture, vPosition.xy);
    float segID = color.r * 255.0 + color.g * 255.0 * 256.0;
    

方案3:使用存储缓冲区(适合特定场景)

若分割ID与顶点一一对应而非屏幕像素,可考虑用BufferAttribute存储ID数组,通过顶点缓冲区传递。但对于屏幕空间每个像素对应ID的场景,纹理仍是更高效的选择。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 00:05:33