Three.js:用一种颜色填充mesh shaderMaterial到某个位置

问题描述

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

  • 我需要让绿色在网格高度的 50% 处“停止”
  • 对于网格的其余部分(超过 50%),要么填充另一种颜色,要么根本不填充(这两种情况都适用)

着色器代码

    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.setFr@R_404_6425@otationMatrix(element.matrixWorld,'XYZ');

            scene.add(wall);

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

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

正确:我想要达到的目标

Three.js scene and the desired result

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

解决方法

您需要使用 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);
}