Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three js Shader Material modify depth buffer

In Three js, I'm using a vertex shader to animate a large geometry.

I've also set up a Depth of Field effect on the output. The problem is that the Depth of Field effect doesn't seem to know about the changed positioning created in my vertex shader. It is responding as if the geometry is in the original position.

How can I update the depth information in my shader/material so that the DOF works correctly? THREE.Material has a depthWrite property, but it doesn't seem to be that...

My depth of field pass works like this:

renderer.render( this.originalScene, this.originalCamera, this.rtTextureColor, true );

this.originalScene.overrideMaterial = this.material_depth;
renderer.render( this.originalScene, this.originalCamera, this.rtTextureDepth, true );

rtTextureColor and rtTextureDepth are both WebGLRenderTargets. For some reason rtTextureColor is correct, but rtTextureDepth is not

here is my vertex shader:

int sphereIndex = int(floor(position.x/10.));

            float displacementVal = displacement[sphereIndex].w;
            vec3 rotationDisplacement = displacement[sphereIndex].xyz;

            vNormal = normalize( normalMatrix * normal );
            vec3 vNormel = normalize( normalMatrix * viewVector );
            intensity = abs(pow( c - dot(vNormal, vNormel), p ));


            float xVal = (displacementVal*orbitMultiplier) * sin(timeValue*rotationDisplacement.x);
            float yVal = (displacementVal*orbitMultiplier) * cos(timeValue*rotationDisplacement.y);
            float zVal = 0;

            vec3 rotatePosition = vec3(xVal,yVal,zVal);

            vec3 newPos = (position-vec3((10.*floor(position.x/10.)),0,0))+rotatePosition;
            vec4 mvPosition;
            mvPosition = (modelViewMatrix *  vec4(newPos,1));

            vViewPosition = -mvPosition.xyz;
            vec4 p = projectionMatrix * mvPosition;
            gl_Position = p;
like image 654
Ben Gannaway Avatar asked Nov 09 '22 15:11

Ben Gannaway


1 Answers

Because you set the scene override material (this.originalScene.overrideMaterial = this.material_depth) before rendering into this.rtTextureDepth, the renderer doesn't use your custom vertex shader. The scene override material is a THREE.MeshDepthMaterial, which includes its own vertex shader.

One thing to try is writing a THREE.ShaderMaterial that works like THREE.MeshDepthMaterial but uses your custom vertex shader. Modifying built-in shaders isn't straightforward, but I would start from something like this:

var depthShader = THREE.ShaderLib['depth'];
var uniforms = THREE.UniformsUtils.clone(depthShader.uniforms);

var material = new THREE.ShaderMaterial({
    uniforms: uniforms,
    vertexShader: /* your custom vertex shader */
    fragmentShader: depthShader.fragmentShader
});

You'll have to add the uniforms for your custom vertex shader and also set the uniforms for the built-in depth shaders; search WebGLRenderer.js in the three.js source for MeshDepthMaterial.

like image 111
Max Smolens Avatar answered Nov 15 '22 06:11

Max Smolens