Cant't read Data3DTexture inside shader

I was a little too hasty with my joy. I took a Data3DTexture from an example from three.js. I pass this on to my webgl2 shader. the shader works but the screen is black. I tried to find help in the documentation for Data3DTexture on the three.js site but I can’t find a solution there. I suspect that I have to read a Data3DTexture differently and that’s where the problem lies. can anyone confirm this and know how to correct it in the shader?
I think it’s probably a simple thing, but I don’t see it

import * as THREE from "../lib/three/build/three.module.js";
import { OrbitControls } from '../lib/three/examples/jsm/controls/OrbitControls.js';
import { RenderPass } from '../lib/three/examples/jsm/postprocessing/RenderPass.js'; 
import { ShaderPass } from '../lib/three/examples/jsm/postprocessing/ShaderPass.js';
import { EffectComposer } from '../lib/three/examples/jsm/postprocessing/EffectComposer.js'; 
import WebGL from '../lib/three/examples/jsm/WebGL.js';
import { ImprovedNoise } from '../lib/three/examples/jsm/math/ImprovedNoise.js';


function main() {
	new Main();
}

class Main {
	constructor(){
		this.init();
		this.animate();	
	}
	
		
	init(){

	   if (!WebGL.isWebGL2Available()) {
        return false;
      }
	
		const canvas = document.createElement('canvas');
		const context = canvas.getContext('webgl2');
		
		this.renderer = new THREE.WebGLRenderer({ 
			canvas: canvas,
			context: context,
			antialias: true 
		});
		
		this.renderer.setPixelRatio( window.devicePixelRatio ); 
		this.renderer.shadowMap.enabled = true; 
		this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
		this.renderer.autoClear = false;
		
		this.container = document.getElementById('container');
		this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
		this.container.appendChild( this.renderer.domElement );

		this.aspect = this.container.clientWidth / this.container.clientHeight; 
		this.scene = new THREE.Scene();
		this.scene.background = new THREE.Color( 0x000000 );
		
		this.camera = new THREE.PerspectiveCamera( 60, this.aspect, .1, 10000 );
		this.camera.position.set(0, 100, 0);
	
		this.controls = new OrbitControls( this.camera, this.renderer.domElement );
		this.controls.enableZoom = true;
		this.controls.enabled = true;
		this.controls.target.set(0, 0, 0);
	
		this.composer = new EffectComposer(this.renderer);
		const renderPass = new RenderPass(this.scene, this.camera);
		this.composer.addPass(renderPass);

	//-------------------------------------------------------------------------------------------------

		// Texture
		const size = 128;
		const data = new Uint8Array( size * size * size );
		let i = 0;
		
		const perlin = new ImprovedNoise();
		const vector = new THREE.Vector3();
		
		for ( let z = 0; z < size; z ++ ) {
			for ( let y = 0; y < size; y ++ ) {
				for ( let x = 0; x < size; x ++ ) {
					vector.set( x, y, z ).divideScalar( size );
					const d = perlin.noise( vector.x * 6.5, vector.y * 6.5, vector.z * 6.5 );
					data[ i ++ ] = d * 128 + 128;
				}
			}
		} 
		
		this.texture = new THREE.Data3DTexture( data, size, size, size );
		this.texture.format = THREE.RedFormat;
		this.texture.minFilter = THREE.LinearFilter;
		this.texture.magFilter = THREE.LinearFilter;
		this.texture.unpackAlignment = 1;
		this.texture.needsUpdate = true;


		const VS =`

			in vec2 uv;
			out vec2 vUv;

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

		const FS =`
			precision highp sampler3D;
			precision highp float; 
			precision highp int; 	
							
			uniform sampler3D tDiffuse;
			uniform float uZCoord;
			
			in vec2 vUv;
			out vec4 outColor;
			
			void main() {
			
				vec3 color = texture(tDiffuse, vec3(vUv, uZCoord)).rgb;
				
				//color = vec3(0.1, 0.5, 1.);	//just for test, work fine!
				outColor = vec4(color, 1.);

		}`;


		const shaderMaterial = new THREE.RawShaderMaterial({ 
			glslVersion: THREE.GLSL3,
			uniforms: {
				tDiffuse: { value: this.texture},
				uZCoord: { value: 0 },
			},
			vertexShader: VS, 	
			fragmentShader: FS, 
		});

		this.composer.addPass(new ShaderPass(shaderMaterial));
	
	}//end init	
	
	
	animate(){
		requestAnimationFrame( this.animate.bind(this) );  
		this.render();
	}//end animate
	
	
	render(){
		this.controls.update();
		this.renderer.render(this.scene, this.camera); 
		this.composer.render();
	}//end render
}//end class
	
main();

I think this should be vec3(vUv.x, vUv.y, uZCoord)

Unfortunately no difference. The program runs but the screen is black. By the way, your example helped me a lot to understand webgl2 shader. My goal is to create a 3D texture with a shader that can then be used by another shader. Your example here:

is the best I’ve found about “THREE.WebGL3DRenderTarget”. WebGL3DRenderTarget creates a Data3DTexture. That’s great. Now I just need to know how to use a Data3DTexture in a shader. The topic has been on my mind for a whole week and every small step is a great joy for me, and a hard fight :sweat_smile:. Now this last step is missing and i will finally have my peace with it.

1 Like

solved :partying_face:, I found out what I had to correct on the Data3DTexture by comparing it with a 2DdataTexture.

import * as THREE from "../lib/three/build/three.module.js";
import { OrbitControls } from '../lib/three/examples/jsm/controls/OrbitControls.js';
import { RenderPass } from '../lib/three/examples/jsm/postprocessing/RenderPass.js'; 
import { ShaderPass } from '../lib/three/examples/jsm/postprocessing/ShaderPass.js';
import { EffectComposer } from '../lib/three/examples/jsm/postprocessing/EffectComposer.js'; 
import WebGL from '../lib/three/examples/jsm/WebGL.js';
import { ImprovedNoise } from '../lib/three/examples/jsm/math/ImprovedNoise.js';


function main() {
	new Main();
}

class Main {
	constructor(){
		this.init();
		this.animate();	
	}
	
		
	init(){

	   if (!WebGL.isWebGL2Available()) {
        return false;
      }
	
		const canvas = document.createElement('canvas');
		const context = canvas.getContext('webgl2');
		
		this.renderer = new THREE.WebGLRenderer({ 
			canvas: canvas,
			context: context,
			antialias: true 
		});
		
		this.renderer.setPixelRatio( window.devicePixelRatio ); 
		this.renderer.shadowMap.enabled = true; 
		this.renderer.shadowMap.type = THREE.PCFSoftShadowMap;
		this.renderer.autoClear = false;
		
		this.container = document.getElementById('container');
		this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
		this.container.appendChild( this.renderer.domElement );

		this.aspect = this.container.clientWidth / this.container.clientHeight; 
		this.scene = new THREE.Scene();
		this.scene.background = new THREE.Color( 0x000000 );
		
		this.camera = new THREE.PerspectiveCamera( 60, this.aspect, .1, 10000 );
		this.camera.position.set(0, 100, 0);
	
		this.controls = new OrbitControls( this.camera, this.renderer.domElement );
		this.controls.enableZoom = true;
		this.controls.enabled = true;
		this.controls.target.set(0, 0, 0);

		this.composer = new EffectComposer(this.renderer);
		const renderPass = new RenderPass(this.scene, this.camera);
		this.composer.addPass(renderPass);

		//-------------------------------------------------------------------------------------------------

		const size = 16;

		//Texture	2D
		const data2D = [];
		for (let y = 0; y < size; y++) {
  			for (let x = 0; x < size; x++) {
    			const r = Math.random()*255;
    			const g = Math.random()*255;
    			const b = Math.random()*255;
    			data2D.push(r, g, b, 1.0);
  			}
		}
		this.texture2D = new THREE.DataTexture(
  			Uint8Array.from(data2D),
  			size, size
  		);
  		this.texture2D.format = THREE.RGBAFormat,
		this.texture2D.minFilter = THREE.LinearFilter;
		this.texture2D.magFilter = THREE.LinearFilter;
		this.texture2D.mapping = THREE.UVMapping;  		
		this.texture2D.type = THREE.UnsignedByteType;
		this.texture2D.needsUpdate = true;


		//Texture	3D	
		const data3D = [];	
		for ( let z = 0; z < size; z++ ) {
			for ( let y = 0; y < size; y++ ) {
				for ( let x = 0; x < size; x++ ) {
					const r = Math.random()*255;
    				const g = Math.random()*255;
    				const b = Math.random()*255;
    				data3D.push(r, g, b, 1.0);						
				}
			}
		} 		
		this.texture3D = new THREE.Data3DTexture( 
			Uint8Array.from(data3D), 
			size, size, size
		);
		this.texture3D.format = THREE.RGBAFormat;
		this.texture3D.minFilter = THREE.LinearFilter;
		this.texture3D.magFilter = THREE.LinearFilter;
		this.texture3D.mapping = THREE.UVMapping;
		this.texture3D.type = THREE.UnsignedByteType;
		this.texture3D.needsUpdate = true;


		const VS =`

			in vec2 uv;
			out vec2 vUv;

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

		const FS =`
			precision highp sampler3D;
			precision highp sampler2D;
			precision highp float; 
			precision highp int; 	
							
			uniform sampler3D tDiffuse3D;
			uniform sampler2D tDiffuse2D;
			uniform float uZCoord;
			
			in vec2 vUv;
			out vec4 outColor;
			
			void main() {
			
				vec3 color = texture(tDiffuse3D, vec3(vUv, uZCoord)).rgb;
				//vec3 color = texture(tDiffuse2D, vUv).rgb;
				outColor = vec4(color, 1.);

		}`;


		const shaderMaterial = new THREE.RawShaderMaterial({ 
			glslVersion: THREE.GLSL3,
			uniforms: {
				tDiffuse3D: { value: this.texture3D},
				tDiffuse2D: { value: this.texture2D},
				uZCoord: { value: 1 },
			},
			vertexShader: VS, 	
			fragmentShader: FS, 
		});

		this.composer.addPass(new ShaderPass(shaderMaterial));
	
	}//end init	
	
	
	animate(){
		requestAnimationFrame( this.animate.bind(this) );  
		this.render();
	}//end animate
		
	render(){
		this.controls.update();
		this.renderer.render(this.scene, this.camera); 
		this.composer.render();
	}//end render
}//end class
	
main();

1 Like