Search code examples
three.jsfragment-shadervertex-shader

Three.js: Objects intersected and shader material


I have a scene with objects intersected using Lambert material, like in this jsFiddle.

Now I need/want to switch the material of that plane to a Shader material and the plane turns into a background thing, like here.

The question is, can I use different materials in objects and still preserve the intersection effect? Is this a Three.js limitation or this is how shaders works? Or am I missing a parameter in the renderer/material?

At the moment is not an option no switch all my work to shader materials in order to take advantage of shaders.

This is how I set up the material:

var material1 = new THREE.ShaderMaterial( { 
    uniforms: {
        color: { type: "c", value: new THREE.Color( 0x22A8E7 ) }
    },
    vertexShader: document.getElementById( 'vertexShader' ).textContent, 
    fragmentShader: document.getElementById( 'fragmentShader' ).textContent, 
    opacity: 0.5, 
    transparent: true, 
} );

Thanks!


Solution

  • With ShaderMaterial you control the shader glsl; so in order for logarithmicDepthBuffer to work you need to add four sets of code to your shaders.

    The code is in:

    Vertex shader declares

    https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_vertex.glsl

    #ifdef USE_LOGDEPTHBUF
    
        #ifdef USE_LOGDEPTHBUF_EXT
    
            varying float vFragDepth;
    
        #endif
    
        uniform float logDepthBufFC;
    
    #endif
    

    Vertex shader body

    https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/logdepthbuf_vertex.glsl

    #ifdef USE_LOGDEPTHBUF
    
        gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
    
        #ifdef USE_LOGDEPTHBUF_EXT
    
            vFragDepth = 1.0 + gl_Position.w;
    
        #else
    
            gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
    
        #endif
    
    #endif
    

    Fragment shader declares

    https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/logdepthbuf_pars_fragment.glsl

    #ifdef USE_LOGDEPTHBUF
    
        uniform float logDepthBufFC;
    
        #ifdef USE_LOGDEPTHBUF_EXT
    
            #extension GL_EXT_frag_depth : enable
            varying float vFragDepth;
    
        #endif
    
    #endif
    

    Fragment shader body

    https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderChunk/logdepthbuf_fragment.glsl

    #if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
    
        gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
    
    #endif
    

    If you are building the shaders in js, rather than pulling directly from the HTML then you can include these with ShaderChunks e.g. THREE.ShaderChunk[ "logdepthbuf_pars_vertex" ]

    See https://github.com/mrdoob/three.js/blob/master/src/renderers/shaders/ShaderLib.js for examples of this.