I need a sampler3D for my 3D data texture in my postprocessing shader. I made this example to keep it as simple as possible and to minimize the influence of errors caused by other code parts. A postprocessing with just a red screen. So I know that the postprocessing process works. So I’m not transferring a 3D texture here either, and that’s not necessary in this step. First of all, the functionality must allow it at all and that’s where it depends. As soon as I integrate the “sampler3D” I don’t see a red screen anymore, the postprocessing doesn’t work longer. My expectation is that with a solution i see the red screen and then i can continue. Babysteps…
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';
function main() {
new Main();
}
class Main {
constructor(){
this.init();
this.animate();
}
init(){
this.renderer = new THREE.WebGLRenderer( { 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 geometry = new THREE.BoxGeometry( 10, 10, 10 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
this.scene.add( cube );
const VS =`
//#version 300 es
void main() {
gl_Position = vec4( (uv - 0.5)*2.0, 0.0, 1.0 );
}`;
const FS =`
//#version 300 es
//uniform sampler3D tDiffuse; //I need this
void main() {
gl_FragColor = vec4(1., 0., 0., 1.);
}`;
const shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
},
//glslVersion: THREE.GLSL3,
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
export {main};
Any errors in the console? Whenever shaders fail, they’ll usually explain in the devtools precisely what’s wrong
I see no error message in the console. The program is running and I can see the green cube. The cube should not be visible but the red postprocessing screen. Do I have to include “webgl” because of webgl2? I read something about it when I was looking for a solution
I modified the code. I included WebGL. I looked at the class. Doesn’t look that special now. It didn’t do anything either. I still see the green cube and not the red postprocessing screen
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';
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', {alpha: false});
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 geometry = new THREE.BoxGeometry( 10, 10, 10 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
this.scene.add( cube );
const VS =`
attribute vec2 uv;
void main() {
gl_Position = vec4( (uv - 0.5)*2.0, 0.0, 1.0 );
}`;
const FS =`
//uniform sampler3D tDiffuse; //I need this
void main() {
gl_FragColor = vec4(1., 0., 0., 1.);
}`;
const shaderMaterial = new THREE.ShaderMaterial({
uniforms: {
},
glslVersion: THREE.GLSL3, //here is the problem!!! without this line i see the red screen but with not. what is wrong in this line?
vertexShader: VS,
fragmentShader: FS,
});
this.composer.addPass(new RawShaderPass(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();
and the html file:
<!DOCTYPE html>
<head>
<title>Loader</title>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
#container {
margin: auto ;
width: screen.width;
height: 800px;
}
</style>
}
</head>
<body style="background-color:#000000;" >
<div id="container"></div>
<script src="./src/main.js" type="module"</script>
</body>
</html>
I have now recreated this beautiful example and it works without problems.
https://threejs.org/examples/?q=webgl2#webgl2_volume_perlin
I don’t understand why in my simplest possible example the postprocessing screen no longer works as soon as I include “glslVersion: THREE.GLSL3,”.
why does it work for me with the perlinnoise example but not in my very simple postprocessing shader.
puh …, solved
The shader language is different in webgl2. gl_fragColor, varying, attributes, all of that is deprecated. That’s why it only works with a raw shader, because the normal shader includes webgl1 standards
here the working correction:
const VS =`
in vec2 uv;
void main() {
gl_Position = vec4( (uv - 0.5)*2.0, 0.0, 1.0 );
}`;
const FS =`
precision highp float;
precision highp int;
precision mediump sampler3D;
uniform sampler3D dtex;
out vec4 outColor;
void main() {
outColor = vec4(1.0, 0.0, 0.0, 1.0);
}`;
const shaderMaterial = new THREE.RawShaderMaterial({
glslVersion: THREE.GLSL3,
uniforms: {
},
vertexShader: VS,
fragmentShader: FS,
});