THREE.js vertexShader color mix based on height

Viewed 268

How do I set the color to the mesh only when the height is zero?

As for now, i just mixed the colors:

enter image description here

The problem is that this kind on mixing is not precise. I just want the color blue only when the height is zero (so only inside that red path I made with paint).

I created a custom material for the mesh, like so:

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
                                        });
1 Answers

Try using the step() function. Here's a definition to help you understand it. Here's how it works:

float step(float edge, float x)

  • It takes in a constant to declare the edge, and x, which is your variable.
  • If x is below the edge, you get 0, and if x is above the edge, you get 1.

Here's a simplified use of it. When height is below 0.2, you'll get blue, and when height is above 0.2, you'll get green.

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

I picked 0.2 to give the blue band some thickness, otherwise it wouldn't be visible.

Related