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)
- 它接受一个常量来声明
edge
和 x
,这是您的变量。
- 如果 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 来给蓝色带一些厚度,否则它就看不见了。
如何仅在高度为零时为网格设置颜色?
至于现在,我只是混合了颜色:
问题是这种混音不精准。我只想在高度为零时使用蓝色(所以只在我用油漆制作的红色路径内)。
我为网格创建了自定义 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)
- 它接受一个常量来声明
edge
和x
,这是您的变量。 - 如果 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 来给蓝色带一些厚度,否则它就看不见了。