André Gollubits
André Gollubits

Reputation: 193

Three.js: Fill mesh shaderMaterial with one color up to certain position

I am having some trouble understanding Three.js shaders. I am attempting to color a mesh with a color, but only up to a certain position. So far, this is the closest I have come to achieving that.

Shader code:

    const _VS = `

        uniform vec3 bboxMin;
        uniform vec3 bboxMax;

        varying vec2 vUv;

        void main() {
            vUv.x = (position.x - bboxMin.x) / (bboxMax.x - bboxMin.x);
            gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
    `;

    const _FS = `

        uniform vec3 incompleteColor;
        uniform vec3 completenessColor;

        varying vec2 vUv;

        void main() {

            gl_FragColor = vec4(mix(incompleteColor, completenessColor, vUv.x), 1.0);
        }
    `;

Javascript code:

            let geometries = element.geometry.clone(); // Inherits geometries from parent element

            let wall = new THREE.Mesh(
                geometries,
                new THREE.ShaderMaterial({
                    uniforms: {
                        incompleteColor: {
                            value: new THREE.Color('red')
                        },
                        completenessColor: {
                            value: new THREE.Color('green')
                        },
                        bboxMin: {
                            value: element.geometry.boundingBox.min
                        },
                        bboxMax: {
                            value: element.geometry.boundingBox.max
                        }
                    },
                    vertexShader: _VS,
                    fragmentShader: _FS,
                })
            );

            wall.castShadow = true;
            wall.position.setFromMatrixPosition(element.matrixWorld);
            wall.rotation.setFromRotationMatrix(element.matrixWorld, 'XYZ');

            scene.add(wall);

This image helps illustrate what I want to achieve:

LEFT: How it looks with the code I posted (Three.js scene)

RIGHT: What I want to achieve

Three.js scene and the desired result

I have spent several hours researching this issue and I can't seem to find an example that points me in the right direction.

Upvotes: 1

Views: 846

Answers (1)

M -
M -

Reputation: 28472

You need to use the GLSL step() function. You can read about it here.

void main() {
    // First, create a hard step when UV crosses the 0.5 threshold
    float switch = step(0.5, vUv.x);

    // Then use that hard step on your mix function
    gl_FragColor = vec4(mix(incompleteColor, completenessColor, switch), 1.0);
}

Upvotes: 2

Related Questions