I have seen solution to color fragments based on their position in screen space or in their local object space like Three.js/GLSL - Convert Pixel Coordinate to World Coordinate.
Those are working with screen coordinates and do change when the camera moves or rotates; or only apply to local object space.
What I like to accomplish instead is to color fragments based on their position
in world space (as in world space of the three.js scene graph).
Even when the camera moves the color should stay constant.
Example of wished behaviour: A 1x1x1 cube positioned in world space at (x:0,y:0,z:2) would have its third component (blue == z) always between 1.5 - 2.5. This should be true even if the camera moves.
What I have got so far:
vertex shader
varying vec4 worldPosition;
void main() {
// The following changes on camera movement:
worldPosition = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
// This is closer to what I want (colors dont change when camera moves)
// but it is in local not world space:
worldPosition = vec4(position, 1.0);
// This works fine as long as the camera doesnt move:
worldPosition = modelViewMatrix * vec4(position, 1.0);
// Instead I'd like the above behaviour but without color changes on camera movement
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
fragment shader
uniform vec2 u_resolution;
varying vec4 worldPosition;
void main(void)
{
// I'd like to use worldPosition something like this:
gl_FragColor = vec4(worldPosition.xyz * someScaling, 1.0);
// Here this would mean that fragments xyz > 1.0 in world position would be white and black for <= 0.0; that would be fine because I can still divide it to compensate
}
Here is what I have got: https://glitch.com/edit/#!/worldpositiontest?path=index.html:163:15
If you move with wasd you can see that the colors don't stay in place. I'd like them to, however.
Your worldPosition
is wrong. You shouldn't implicate the camera in the calculation. That means, no projectionMatrix
nor viewMatrix
.
// The world poisition of your vertex: NO CAMERA
vec4 worldPosition = modelMatrix * vec4(position, 1.0);
// Position in normalized screen coords: ADD CAMERA
gl_Position = projectionMatrix * viewMatrix * worldPosition;
// Here you can compute the color based on worldPosition, for example:
vColor = normalize(abs(worldPosition.xyz));
Check this fiddle.
Notice that the abs()
used here for the color can potentially give the same color for different position, which might not be what you're looking for.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With