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.

nylki
  • 498
  • 5
  • 15
  • 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 example – gman Aug 27 '17 at 15:07
  • @gman 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). – nylki Aug 27 '17 at 15:13
  • 1
    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 in – gman Aug 27 '17 at 15:17
  • @gman 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. – nylki Aug 27 '17 at 15:22
  • @gman 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. – nylki Aug 27 '17 at 16:06

1 Answers1

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

neeh
  • 2,777
  • 3
  • 24
  • 32
  • 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. – nylki Aug 27 '17 at 16:09