How can I use RGB Voxel data to visualize the volume in Three.js?

I’m trying to render the volume with RGB voxel information, but it is not working properly.
What should I do in order to render the correct RGB value in the scene? The below code in the scene only gives a red colored cube, not the color that I set.

const dims = new Vector3(400,400,400 * 3);
// array that holds r,g,b values for each voxel
const voxelArray = new Uint8Array(dims.x * dims.y * dims.z * 3);

 for (var x = 0; x < dims.x; x++) {
      for (var y = 0; y < dims.y; y++) {
        for (var z = 0; z < dims.z; z++) {
          var index = (x + y * dims.x + z * dims.x * dims.y) * 3;
          voxelArray[index] = 30; // Red component
          voxelArray[index + 1] = 120; // Green component
          voxelArray[index + 2] = 170; // Blue component
        }
      }
    }
const texture = new THREE.Data3DTexture(
      voxelArray,
      dims.x,
      dims.y,
      dims.z,
    );
    texture.format = THREE.RGBAFormat;
    texture.type = THREE.UnsignedByteType;
    texture.minFilter = THREE.LinearFilter;
    texture.magFilter = THREE.LinearFilter;


 const uniforms = {
      volume: { type: 't', value: texture },
      resolution: {
        type: 'v3',
        value: new THREE.Vector3(resolution.x, resolution.y, resolution.z),
      },
    };

const material = new THREE.ShaderMaterial({
      uniforms: uniforms,
    });

    const geometry = new THREE.BoxGeometry(resolution.x, resolution.y, resolution.z);
    const mesh = new THREE.Mesh(geometry, material);

Your THREE.ShaderMaterial needs both a vertexShader and fragmentShader plugged into it as properties, that’s why the ShaderMaterial is red, see the code example here

A simple example of how your fragment shader would look would be…

uniform sampler3D volumeTexture;
uniform vec3 resolution;
varying vec3 vPosition;

void main() {
  // calculate the voxel position in the texture
  vec3 voxelPosition = vPosition / resolution;

  // sample the texture to get the voxel color
  vec4 voxelColor = texture(volumeTexture, voxelPosition);

  // output the voxel color
  gl_FragColor = voxelColor;
}
 
1 Like

Thank you. I think that I have to study more on glsl to set it to work. Do you know some references that I can look up for the vertexShader and fragmentShader examples?

by the way, I did some work on vertexShader and fragmentShader as follows

 var vertexShader = `
    	in vec2 inUv;
    	out vec2 outUv;

    	void main() {
    		outUv = inUv;
    		gl_Position = vec4( (inUv - 0.5)*2.0, 0.0, 1.0 );
    }
    `;

    // Fragment Shader
    var fragmentShader = `
      precision highp sampler3D;
    		precision highp sampler2D;
    		precision highp float;
    		precision highp int;

    		uniform sampler3D volume;
    		uniform float uZCoord;

    		in vec2 vUv;
    		out vec4 outColor;

    		void main() {
    			vec3 color = texture(volume, vec3(${resolution.x}, ${resolution.y},${resolution.z})).rgb;
    			outColor = vec4(color, 1.);
    	}
    `;
const material = new THREE.ShaderMaterial({
      uniforms: {
        volume: { value: texture },
      },
      vertexShader,
      fragmentShader,
    });

But, it gives me an error “outColor : must explicitly specify all locations when using multiple framgment outputs”. Do you have any idea…?