Reputation: 193
I am having some trouble understanding Three.js shaders. I am attempting to color a mesh with a color, but only up to a certain position. So far, this is the closest I have come to achieving that.
Shader code:
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 code:
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.setFromRotationMatrix(element.matrixWorld, 'XYZ');
scene.add(wall);
This image helps illustrate what I want to achieve:
LEFT: How it looks with the code I posted (Three.js scene)
RIGHT: What I want to achieve
I have spent several hours researching this issue and I can't seem to find an example that points me in the right direction.
Upvotes: 1
Views: 846
Reputation: 28472
You need to use the GLSL step()
function. You can 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);
}
Upvotes: 2