将数组数据传递给 threeJS 中的着色器

pass array data to shader in threeJS

我正在尝试将 "volume._data" 传递到 threeJS 中的片段着色器。 它是一个 Float32Array,最多可以包含:512x512x512x4 个元素。

  var mat = new THREE.ShaderMaterial({
        uniforms: {
            color: {type: 'f', value: 1.0},
            ijk: {type: '??', value: volume._data},
            dimensions: {type: 'vec3', value: volume._dimensions},
            ijktoras: {type: 'mat4', value: volume._RASToIJK}
        },
        vertexShader: document.
                      getElementById('vertShader').text,
        fragmentShader: document.
                      getElementById('fragShader').text
    });

问题是我不知道给它什么类型。或者是传递 2D 纹理的最佳选择?

我担心纹理太大而无法传递给着色器。

是否有任何解决方法可以将这些信息传递给着色器?

我的总体目标是,在片段着色器中,将屏幕像素位置映射到对象世界的坐标。然后将这个世界坐标映射到我的 volume._data (ijk space) 以在屏幕上显示特定的颜色。

谢谢, 尼古拉斯

查看 https://github.com/mrdoob/three.js/wiki/Uniforms-types 数组,例如:

"uFloatArray3" : { type: "fv",  value: [ 0.1, 0.2, 0.3, 0.4, 0.5, 0.6 ] }, // float array (vec3)

"uVec4Array" : { type: "v4v", value: [ new THREE.Vector4( 0.1, 0.2, 0.3, 0.4 ), 
                                   new THREE.Vector4( 0.4, 0.5, 0.6, 0.7 ) ] }, // Vector4 array

您始终可以将该数据打包成一个直线数组并使用定界符。

就您所做的而言,最好传入 3 个纹理,每个 512x512 并访问 RGBA 以获得您的 4 个值。它不会太慢,在你尝试之前不要太担心优化。

这当然取决于您如何将数据填充到缓冲区中。更快的方法是通过 canvas 使用像素数组,如下所述:https://hacks.mozilla.org/2011/12/faster-canvas-pixel-manipulation-with-typed-arrays/

Flux 提供的答案是正确的。对于在座的那些尝试将体积着色器放在一起的人来说,以下内容可能会有用。

您可以使用一维数组来表示 3d space 并使用以下方法通过其 x,y,z 坐标检索正确的数组项。

x,y,z 坐标应位于本地 space(而不是世界),原点位于 0,0,0。您需要知道每个二维部分的宽度和高度。

假设体素体积为 3x3x3

uniform float[] Voxels;
uniform int Width = 3;
uniform int Height = 3;

float getValueAtVoxel(x,y,z) {
    int voxel = (Width * Height * z) + (y * Width) + x;

    if (voxel < 0 || voxel >= Voxels.length) {
        return 0.0;
    }

    return Voxels[voxel];
}