THREE.js 基于高度的vertexShader颜色混合

THREE.js vertexShader color mix based on height

如何仅在高度为零时为网格设置颜色?

至于现在,我只是混合了颜色:

问题是这种混音不精准。我只想在高度为零时使用蓝色(所以只在我用油漆制作的红色路径内)。

我为网格创建了自定义 material,如下所示:

material = new THREE.ShaderMaterial({
                
                      uniforms: THREE.UniformsUtils.merge([
                      THREE.UniformsLib['lights'],
                      {
                    lightIntensity: {type: 'f', value: 1.0},
                    diffuse: {type: 'c', value: new THREE.Color(0x0000ff)},
                        color0: {
                          value: new THREE.Color("blue")
                        },
                        color1: {
                          value: new THREE.Color("green")
                        },
                        color2: {
                          value: new THREE.Color("brown")
                        },
                        color3: {
                          value: new THREE.Color("black")
                        },
                        bboxMin: {
                          value: geom.boundingBox.min
                        },
                        bboxMax: {
                          value: geom.boundingBox.max
                        }
                
                          }
                        ]),
                      vertexShader: `
                        uniform vec3 bboxMin;
                        uniform vec3 bboxMax;
                        varying vec2 vUv;
                            varying vec3 vPos;
                varying vec3 vNormal;
                        void main() {
                          vPos = (modelMatrix * vec4(position, 1.0 )).xyz;
                          vNormal = normalMatrix * normal;
                          vUv.y = (position.y - bboxMin.y) / (bboxMax.y - bboxMin.y);
                          gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
                        }
                      `,
                      fragmentShader: `
                        uniform vec3 color1;
                        uniform vec3 color2;
                        uniform vec3 color3;
                        uniform vec3 color0;
                        varying vec2 vUv;
                    
                        uniform vec3 diffuse;
                        varying vec3 vPos;
                        varying vec3 vNormal;

                        struct PointLight {
                          vec3 position;
                          vec3 color;
                        };
                        uniform PointLight pointLights[ NUM_POINT_LIGHTS ];
                        
                        void main() {
                    vec4 addedLights = vec4(0.1, 0.1, 0.1, 1.0);
                      for(int l = 0; l < NUM_POINT_LIGHTS; l++) {
                        vec3 adjustedLight = pointLights[l].position + cameraPosition;
                        vec3 lightDirection = normalize(vPos - adjustedLight);
                        addedLights.rgb += clamp(dot(-lightDirection, vNormal), 0.0, 1.0) * pointLights[l].color;
                      }
                
                                  
                                            gl_FragColor = mix(vec4(mix(mix(mix(color0, color1, vUv.y), color1, vUv.y), mix(color1, color2, vUv.y), vUv.y), 1.0),addedLights, addedLights);
                                            }
                                          `,
                                        lights: true
                                        });

尝试使用 step() 函数。 Here's a definition帮你理解。运作方式如下:

float step(float edge, float x)

  • 它接受一个常量来声明 edgex,这是您的变量。
  • 如果 x 低于边缘,则得到 0,如果 x 高于边缘,则得到 1

下面是它的简单用法。当高度低于 0.2 时,您将获得蓝色,当高度高于 0.2 时,您将获得绿色。

vec3 green = vec3(0.0, 1.0, 0.0);
vec3 blue  = vec3(0.0, 0.0, 1.0);

float edge = 0.2;

float colorMix = step(edge, height);
vec3 finalColor = mix(blue, green, colorMix);

我选择了 0.2 来给蓝色带一些厚度,否则它就看不见了。