Rendering order problem

Hello, I would like to inquire again.
In the first photo, the rising line is rendered as if it were inside a circle.

However, in the case of the second photo, when you turn the camera viewpoint, the line rises and is like a circle.

What part can I fix?
Please help me.
Below is my code for rendering a line and a circle.
thank you.


let lineAnimateTime;
let isShot = false;
let trajectoryIteration = 2;
let previousLine;
let previousShadowLine;

function setupLine() {
    // Animation Sensor Time
    const PERSPECTIVE_LAYER = 2;

    const PATH_SEGMENTS = 32;
    const LINE_THICKNESS = 0.4;
    const SHADER_THICKNESS = 0.4;
    const Roundness = 12;
    const IS_Closed = false;

    const LINE_Y_POSITION = -20;


    const linePoints = [new THREE.Vector3(0, 0, 0).multiplyScalar(1)];
    const shaderPoints = [new THREE.Vector3(0, 0, 0).multiplyScalar(1)];


    const lineMaterial = new THREE.ShaderMaterial({
        uniforms: {
            color: { value: new THREE.Color("red") },
            maxZ: { value: 0.0 },  
            minZ: { value: 0.0 }   
        },
        vertexShader: `
        uniform float maxZ;
        uniform float minZ;
            varying float alpha;
            void main() {
            float range = maxZ - minZ;
            alpha = smoothstep(0.7, 1.0, (abs(position.z - minZ) / range));
            alpha = min(alpha, 0.7);  // 최대 0.7까지 제한
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec3 color;
            varying float alpha;
            void main() {
            gl_FragColor = vec4(color, 1.0 - alpha);  // 처음이 밝고 뒷부분이 어둡게
            }
        `,
        transparent: true,
        depthTest: true,  // 선이 다른 객체를 가리지 않도록 depthTest를 비활성화
    });

    const shaderLineMaterial = new THREE.ShaderMaterial({
        uniforms: {
            color: { value: new THREE.Color("black") },
            maxZ: { value: 0.0 },  
            minZ: { value: 0.0 }   
        },
        vertexShader: `
        uniform float maxZ;
        uniform float minZ;
            varying float alpha;
            void main() {
            float range = maxZ - minZ;
            alpha = smoothstep(0.7, 1.0, (abs(position.z - minZ) / range));
            alpha = min(alpha, 0.7);  // 최대 0.7까지 제한
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec3 color;
            varying float alpha;
            void main() {
            gl_FragColor = vec4(color, 1.0 - alpha);  // 처음이 밝고 뒷부분이 어둡게
            }
        `,
        transparent: true,
        depthTest: true,  
    });

    if (trajectoryIteration < trajectory.length) {
        if(lineAnimateTime + 0.02 < clock.getElapsedTime()) {
            lineAnimateTime = clock.getElapsedTime();

            for (let i = 1; i < trajectoryIteration; i++) {
                linePoints.push( new THREE.Vector3(trajectory[i].x, trajectory[i].z, -trajectory[i].y).multiplyScalar(1));
                shaderPoints.push( new THREE.Vector3(trajectory[i].x, 0, -trajectory[i].y).multiplyScalar(1));
            }

            let isXWithinXBounds = trajectory[trajectoryIteration].x >= targetCircle.position.x - targetRadius && trajectory[trajectoryIteration].x <= targetCircle.position.x + targetRadius;
            let isZWithinZBounds = trajectory[trajectoryIteration].y >= Math.abs(targetCircle.position.z) - targetRadius && trajectory[trajectoryIteration].y <= Math.abs(targetCircle.position.z) + targetRadius;
            
            if(isXWithinXBounds && isZWithinZBounds) {
                // shadowCircle.material.color.set('blue');
            } else {
                // shadowCircle.material.color.set('red');
            }
            
            const maxZ = Math.max(...linePoints.map(point => point.z));
            const minZ = Math.min(...linePoints.map(point => point.z));
            lineMaterial.uniforms.maxZ = { value: maxZ };
            lineMaterial.uniforms.minZ = { value: minZ };
        
            const tubeGeometry = new THREE.TubeGeometry(
                new THREE.CatmullRomCurve3(linePoints),
                PATH_SEGMENTS,
                LINE_THICKNESS,
                Roundness,
                IS_Closed
            );
    
            const shaderTubeGeometry = new THREE.TubeGeometry(
                new THREE.CatmullRomCurve3(shaderPoints),
                PATH_SEGMENTS,
                SHADER_THICKNESS,
                Roundness,
                IS_Closed 
            );
    
            scene2.remove(previousLine);
            scene2.remove(previousShadowLine);
    
            const line = new THREE.Mesh(shaderTubeGeometry, shaderLineMaterial);
            const shadowLine = new THREE.Mesh(tubeGeometry, lineMaterial);

            previousLine = line;
            previousShadowLine = shadowLine;        
    
            line.layers.set(PERSPECTIVE_LAYER);
            shadowLine.layers.set(PERSPECTIVE_LAYER);

            line.position.y = LINE_Y_POSITION;        
            shadowLine.position.y = LINE_Y_POSITION;

            renderer.setTransparentSort((a , b) => {
                return 1;
            })

            scene2.add(line)
            line.renderOrder = 1;
            scene2.add(shadowLine);

            trajectoryIteration++;
        }
    } else {
        setTimeout(() => {
            // shadowCircle.material.color.set('white');
        }, 1000)

        isShot = false;
        trajectoryIteration = 2;
        trajectory = [];
    }

}

function setupTarget(radius, thickness, numRectangles, distance) {
    const circle = new THREE.Group();
    const circle2 = new THREE.Group();
    const borderMaterial = new THREE.MeshBasicMaterial({
        color: 0xffdd00, // Set color as needed
        side: THREE.DoubleSide, // Render on the back side
        transparent: true,
        opacity: 0.9,
      });

    const borderMaterial2 = new THREE.MeshBasicMaterial({
        color: 0xffffff, // Set color as needed
        side: THREE.DoubleSide, // Render on the back side
        transparent: true,
        opacity: 0.9,
      });

    for (let i = 0; i < numRectangles; i+=radius / 4) {
      const angle = (i / numRectangles) * Math.PI * 2;

      const rectangle = new THREE.Mesh(
        new THREE.BoxGeometry(1, 3, 0.5),
        borderMaterial
      );

      const rectangle2 = new THREE.Mesh(
        new THREE.BoxGeometry(1, 3, 0.5),
        borderMaterial2
      );

      // Set position in a circle
      rectangle.position.x = radius * Math.cos(angle);
      rectangle.position.y = radius * Math.sin(angle);

      rectangle.rotation.z = angle;
      rectangle.layers.set(2);

      rectangle2.position.x = radius * Math.cos(angle);
      rectangle2.position.y = radius * Math.sin(angle);

      rectangle2.rotation.z = angle;
      rectangle2.layers.set(2);

      circle.add(rectangle);
      circle2.add(rectangle2);
    }

    circle.position.z = DEFAULT_Z_AXIS_VALUE - distance;
    circle2.position.z = DEFAULT_Z_AXIS_VALUE - distance;
    circle.rotateX(-Math.PI / 2);
    circle.position.y = -20;
    circle2.position.y = -16;
    circle2.rotateX(-Math.PI / 2);
    circle2.renderOrder = 4;
    circle.renderOrder = 4;

    const f1 = gui.addFolder('Target Controls');
    f1.add(circle.position, 'z', -1000, 1000);
    f1.add(circle.position, 'y', -1000, 1000);

    scene2.add(circle);
    scene2.add(circle2);
    return {targetCircle : circle, shadowCircle : circle2};
};

Can you provide a working example in a glitch/codepen/jsfiddle?

There isn’t really enough information in your post to understand what you need?

Can I give you an answer in this form?

Are you talking about the shape of the red line, not being a parabola shape?

image

There is a problem where the parabolic rising curve appears to be inside a circle when the camera position is still.

I have both depthTest and depthWrite enabled and this is happening.

There is a problem where the parabolic rising curve appears to be inside a circle when the camera position is still.

I have both depthTest and depthWrite enabled and this is happening.

When .transparent = true

Objects are sorted by object.position.distanceTo( camera.position ) and rendered in that order.

If the object positions are all 0,0,0 then they will probably render in the order they were added to the scene.

You can manually control the rendering order with mesh.renderOrder = 2 or whatever… which forces them to render in a specific order…

https://threejs.org/docs/#api/en/core/Object3D.renderOrder

Does this help?



No, renderorder doesn’t work…
What I want to do is to use the same



No, renderorder doesn’t work…
What I want to do is to use the same

Transparency doesn’t really work that way. If you want them to sort independently, you will have to break the geometry into separate pieces, each with its own position, so that the sorting can have a chance to work… or you can use blending:THREE.AdditiveBlending which is additive, so ordering isn’t relevant.