Three.js: 用一种颜色填充网格 shaderMaterial 到特定位置

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

我在理解 Three.js 着色器时遇到一些问题。我正在尝试用一种颜色为网格着色,但仅限于某个位置。到目前为止,这是我最接近实现的目标。

着色器代码:

    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代码:

            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);

这张图片有助于说明我想要实现的目标:

LEFT: 我发布的代码看起来如何(Three.js 场景)

右:我想达到的目标

我花了几个小时研究这个问题,但我似乎找不到能为我指明正确方向的例子。

您需要使用 GLSL step() 函数。你可以 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);
}