React-three-fiber Ouline rendering behind other geometries

I have a few cubes I’d like to outline. But I also have geometries (including a base plane) that I’d like to not be outlined. What I am facing, however, is that the outline is being rendered behind all elements that are not also being outlined even if their actual position is behind the outlined object. Could someone please help me fix this issue? My code and image are included


x


> export default function ThreeScene() {
>     return (
>         <div style={{ width: "100vw", height: "100vh" }}>
>             <Canvas shadows>
>                 <ambientLight/>
>                 <directionalLight position={[5,5,5]} intensity={3} castShadow/>
>                 <directionalLight position={[-1,7,3]} intensity={2}/>
>                 <Selection>
>                     <EffectComposer autoClear={false}>
>                         <Outline blur visibleEdgeColor="black" hiddenEdgeColor="black" edgeStrength={100} width={800} />
>                     </EffectComposer>
>                     <Select enabled={true}>
>                         <Box position={[ 0, 0.5, 0 ]}/>
>                         <Box position={[ 0, 0.5, 2 ]}/>
>                     </Select>
>                     <mesh receiveShadow rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.01, 0]}>
>                         <planeGeometry args={[1000, 1000]} />
>                         <meshStandardMaterial color="gray" />
>                     </mesh>
>                 </Selection>
>                 <OrbitControls makeDefault maxPolarAngle={Math.PI / 2}/>
>             </Canvas>
>         </div>
>     )
> }

I wasn’t able to reproduce your problem.
It may be the versions you are using.
Here is an example that shows using visibleEdgeColor and hiddenEdgeColor with different colours.

and to add to what @seanwasere said, there is also a possibility to do this without postpro

2 Likes

Thank you for your response! Do you have any idea what could be causing this issue? I am using @react-three/fiber 8.15.14 and @react-three/postprocessing 2.15.12.

I don’t know if this is related but when I have geometry with a lower opacity, the base plane and grid also seem to interfere with it (illustrated in picture).

Yo are using recent versions so that isn’t the issue.

It looks like post processing ignores/overrides fog on the material you are using. I don’t have a solution for your case since I don’t know what your code looks like.

I also don’t know what method you are using to create the blue lines.

But this example below uses fog, meshPhysicalMaterial transmission, and drei outlines direclty (not via post processing). It seems to respect the fog distance.

Thank you for your help. I am not so much worried about the fog, as I am about the plane. With both the post-processing outlines and the low-opacity geometry (which is simply a standardMeshMaterial with reduced opacity, not done with post-processing) other geometries seem to be rendered above, when in reality its actual position is behind the geometry. I don’t know if the opacity issue and the outline issue are related. Do you know of anything I could explore to find out where the problem is?

I don’t know what your code looks like. Its now different from your original post. I don’t know how to reproduce your exact problem.
My most recent suggestion was to explore using meshphysicalmaterial with transmission. Thats how i fixed something similar to your problem because thats all i was able to reproduce.

Hello, I apologize. My code got more complex but the general problem remains the same. I have now included the code for a simplified version of the opacity issue. The code is simpler for convenience but it causes the same error, I have attatched an image of it. I have also noticed that removing the geometries from the Selection component fixes it. So it must be something in the postprocessing like you said, I just don’t have any idea how to fix it, or if it is possible.

Also thank you for your suggestion on meshPhysicalMaterial and drei Outlines. It seems to be a good workaround for now.

export default function ThreeScene(props) {
    return (
        <div style={{ width: "100vw", height: "100vh" }}>
            <Canvas shadows camera={{position: [50, 50, 50]}}>
                <ambientLight/>
                <directionalLight position={[10,90,10]}  intensity={1} castShadow/>
                <OrbitControls makeDefault maxPolarAngle={Math.PI / 2}/>
                <Selection>
                    <EffectComposer>
                        <Outline/>
                    </EffectComposer>
                    <Select enabled={false}>
                        <mesh position={[0, 10, 0]} scale={[20, 20, 20]}>
                            <boxGeometry/>
                            <meshStandardMaterial color='red' opacity={0.5} transparent/>
                        </mesh>
                    </Select>
                </Selection>
                <mesh position={[0,0,0]} scale={[50,50,50]} rotation={[-Math.PI / 2, 0, 0]} >
                    <planeGeometry/>
                    <meshBasicMaterial color="white"  transparent opacity={0.1}/>
                </mesh>
            </Canvas>
        </div>
    )
}

image

I don’t really understand what your problem is in this last code you shared. It’s doing exactly what you are asking it to do.

I am still unable to reproduce your problem, or understand it.

Because the plane is white and has opacity 0.1 I would not expect to see it behind the cube, since I dont see it when the cube it not on top of it. The cube is merely less opaque, so if I don’t see something when the cube is not there, I would not expect tot see it when the cube is there. For example this is what I’d expect to see – and what i do in fact get when I put my box outside of the Selection component.

image

Transparency means you can see things behind.

Maybe you want alphatest.

https://threejs.org/docs/#api/en/materials/Material.alphaTest

Put it into a slider to see if it fixes your issue

https://sbcode.net/threejs/materials/

Thanks for your response and the links provided, the alphaTest seems useful, and it might be a good workaround.

But I don’t think thats quite what my issue is. I do want to see what’s behind, but only if those things are visible in the first place. The box should only let me see through it, and not make invisible things visible. I’ll show you two examples with the codes:

Expected behavior (which I get when my box is outside Selection)
image

        <div style={{ width: "100vw", height: "100vh" }}>
            <Canvas shadows camera={{position: [50, 50, 50]}}>
                <ambientLight/>
                <DirectionalLightWrapper position={[100, 100, 100]} intensity={3} castShadow />
                <DirectionalLightWrapper position={[-10,70,30]} intensity={1}/>
                <OrbitControls makeDefault maxPolarAngle={Math.PI / 2}/>
                <mesh position={[0, 1, 0]}>
                        <boxGeometry/>
                        <meshStandardMaterial color="red" opacity={0.5} transparent/>
                </mesh>
                <mesh position={[0, 1, 3]}>
                        <boxGeometry/>
                        <meshStandardMaterial color="yellow"/>
                </mesh>
                <mesh 
                    rotation={[-Math.PI / 2, 0, 0]}
                    position={[0, 0, 0]} 
                    scale={[50, 50, 50]}>
                    <planeGeometry/>
                    <meshStandardMaterial color="white" opacity={0.1} transparent/>
                </mesh>
            </Canvas>
        </div>

Problem behavior:
image

        <div style={{ width: "100vw", height: "100vh" }}>
            <Canvas shadows orthographic={orthographicCamera} camera={{position: [50, 50, 50]}}>
                <ambientLight/>
                <DirectionalLightWrapper position={[100, 100, 100]} intensity={3} castShadow />
                <DirectionalLightWrapper position={[-10,70,30]} intensity={1}/>
                <OrbitControls makeDefault maxPolarAngle={Math.PI / 2}/>
                <Selection>
                    <EffectComposer>
                        <Outline/>
                    </EffectComposer>
                    <Select enabled={false}>
                        <mesh position={[0, 1, 0]}>
                            <boxGeometry/>
                            <meshStandardMaterial color="red" opacity={0.5} transparent/>
                        </mesh>
                        <mesh position={[0, 1, 3]}>
                            <boxGeometry/>
                            <meshStandardMaterial color="yellow"/>
                        </mesh>
                        
                    </Select>
                </Selection>
                <mesh 
                    rotation={[-Math.PI / 2, 0, 0]}
                    position={[0, 0, 0]} 
                    scale={[50, 50, 50]}>
                    <planeGeometry/>
                    <meshStandardMaterial color="white" opacity={0.1} transparent/>
                </mesh>
            </Canvas>
        </div>

As you can see the plane is not visible when there is no box there. Why should it be when there is one? I don’t understand why “Selection” and effectComposer are affecting this. Especially since the only effect in there is Outline, and it has enabled={false}. Is there a mistake in the way I am using Selection and EffectComposer?

The issue gets a bit jarring if I use a lower opacity box, let’s say 0.2 and a full opacity plane which is what I actually intend to use:
image

Check the CSS of your HTML document. What is the background colour?

Having a Threejs material matching the same colour of the HTML background doesn’t make it hidden in the threejs scene.

It is still there, and you can see it because you have a transparent object in front of it.

Maybe you want this property
https://threejs.org/docs/#api/en/core/Object3D.visible

Or maybe just don’t add the white floor at all, if its intention is not to be scene

Thank you for your suggestions and for your time in helping me so far.

My biggest concern is that the Selection and EffectComposer functions from postprocessing are not behaving the same as when they are not present – even if they are disabled. The material opacity issue is just something i noticed that could be related to my original Outline issue, where the outline was hidden by a plane that was behind it. When I reduced the opacity of my materials I noticed that the same effect (where the geometries outside selection behave unexpectedly with the ones inside it) was happening. So I wondered if the two could be related.

Sorry for bringing this back to life after so long, but I decided to take a shot at this once more and I get the same error with Drei Outlines as I did with postprocessing outlines.

This happens with every single geometry I add to the scene, the outline is always rendered at the very back. When I switch to orthographic view, it gets a little better, some geometries show up behind the outline, but others still do appear in front of it. Do you have any idea what this could be? Here is the code for reference:

<mesh
    ref={ref}
    position={[0, y, 0]}
    scale={[1, 1, -1]}
    rotation={[Math.PI/2, 0, 0]} 
>
    <boxGeometry/>
    <meshStandardMaterial/>
    {drawOutlines && 
        <Outlines 
            screenspace
            color="red"
            angle={Math.PI}
            thickness={8}
        />
    }
</mesh>

Update: I had logarithmicDepthBuffer turned on and completely forgot about it. Turning it off fixed the issue with Drei outlines, which now work as expected. It did not improve the issue for post-processing outlines though.