0
votes

In my scene I have two overlapping / crossing plane meshes. The first one uses a MeshBasicMaterial and the second one a custom ShaderMaterial (simple cut-out fragment shader). It seems as if the mesh with the ShaderMaterial doesn't have any depth information as the other plane is always rendered on top of it.

How can I add the plane mesh with the ShaderMaterial to the scene so the collisions and overlapping with other meshes is shown correctly? Do I have to do this in the fragment shader or is it something I have to set up in the material?

Edit: I've made two different variants: A and B. A: works as it should, both Plane Meshes have depth information and use the MeshBasicMaterial:

var movieMaterial = new THREE.MeshBasicMaterial( { map: videoTexture, overdraw: true, side:THREE.DoubleSide } );

Screenshot of Variant A, two crossing Plane Meshes using MeshBasicMaterial
Screenshot of Variant A, two crossing Plane Meshes using MeshBasicMaterial

Variant B uses a custom ShaderMaterial on one Plane Mesh:

    var movieMaterial = new THREE.ShaderMaterial({
    uniforms: {
      texture: { type: "t", value: videoTexture }
    },
    vertexShader: [
        "varying vec2 vUv;",
        "void main() {",
            "vUv = uv;",
            "gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);",
        "}",
    ].join("\n"),
    fragmentShader: [
        "varying vec2 vUv;",
        "uniform sampler2D texture;",
        "void main() {",
            "gl_FragColor = texture2D(texture, vUv);",
            "if (gl_FragColor.r + gl_FragColor.b + gl_FragColor.g > 1.5) discard;",
        "}",
    ].join("\n"),
    side:THREE.DoubleSide
});  

Screenshot of Variant B, now one Plane Mesh is using a custom ShaderMaterial Screenshot of Variant B, now one Plane Mesh is using a custom ShaderMaterial

And now the depth information is lost. The code I posted is the only difference here.

Thanks in advance

1
That cutout around the tv looks really weird, i must admit i'm not sure what is going on. A working example would help. Nothing in your code indicates an issue. You sample some color from the texture and based on some threshold and logic you discard it. Not sure what overdraw does for you. - pailhead
@pailhead Any idea why applying the ShaderMaterial kills the depth information so that the TV is always rendered on top? - david.stack
No, ShaderMaterial should't do anything differently than other materials. If you set depthWrite depthTest depthFunc, you will change how the depth logic works. Otherwise its default. Changing transparency may change the rendering order, but it doesnt look like you activated that. Either way, using discard as you are, this should just work, order shouldnt matter. - pailhead
can you make a fiddle? - pailhead

1 Answers

1
votes

This is an old question but I've recently come across this problem. The issue was with the usage of the logarithmic depth buffer. The shaders passed to the ShaderMaterial do not work with it out of the box. Option one is to disable the logarithmic depth buffer. Option two is to append a few pieces of glsl code to your shaders provided by three, something like this:

import { ShaderChunk } from 'three';

const VertexShader = ShaderChunk.common + '\n' + ShaderChunk.logdepthbuf_pars_vertex + `
  ...
  void main() {
    ...
    ` + ShaderChunk.logdepthbuf_vertex + `
  }
`;

const FragmentShader = ShaderChunk.logdepthbuf_pars_fragment + `
  ...
  void main() {
    ...
    ` + ShaderChunk.logdepthbuf_fragment + `
  }
`;