将数组数据传递给 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];
}
我正在尝试将 "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];
}