Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 484
nylki Avatar asked Aug 27 '17 15:08

nylki


1 Answers

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

like image 200
neeh Avatar answered Sep 20 '22 01:09

neeh