THREE.js/GLSL: WebGL shader to color fragments based on world space position
Asked Answered
P

1

7

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.

Proboscis answered 27/8, 2017 at 15:1 Comment(5)
You need values between 0 and 1 for colors so you need some way to convert your world coordinates. You use fract(worldCoord.xyz * scale) as one exampleMicrofarad
@Microfarad I am aware of that, I edited the code part to indicate the scaling. But that doesn't answer the question, I am afraid, because I need to get the proper worldPosition in the first place (the position based on object positions in world space, that don't change on camera movement).Proboscis
Have you tried modelMatrix as in worldPosition = modelMatrix * vec4(position, 1);? If three.js doesn't already make it for you you can make your own uniform and pass it inMicrofarad
@Microfarad I have tried that (I suppose three.js's modelViewMatrix == modelMatrix), that is the behavior I want as long as the camera stays fixed. But once the camera moves, the colors change accordingly, which is not the effect I am looking for. A cube at a fixed position should keep its colors even if the camera moves.Proboscis
@Microfarad I stand corrected, you are right, as is @neeh in the answer below. I have mixed up modelMatrix and modelViewMatrix, using your suggestion works of course. Still working on comprehending the relationship between the different matrices.Proboscis
B
8

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.


Note

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.

Position coords to color coords

Brigitte answered 27/8, 2017 at 15:48 Comment(1)
Thank you! Apparently, and a bit embarassingly, I have mixed up modelMatrix and modelViewMatrix. I am still learning the concepts of OpenGL and this slipped through.Proboscis

© 2022 - 2024 — McMap. All rights reserved.