问题描述
我在理解 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 场景)
正确:我想要达到的目标
我花了几个小时研究这个问题,但似乎找不到一个例子来指明正确的方向。
解决方法
您需要使用 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);
}