Search code examples
c++openglglslopenscenegraph

How to change vertex position using glsl


I am trying to move object depending on camera position. Here is my vertex shader

uniform mat4 osg_ViewMatrixInverse;

void main(){
vec4 position  = gl_ProjectionMatrix * gl_ModelViewMatrix *gl_Vertex;   
vec3 camPos=osg_ViewMatrixInverse[3].xyz;

if( camPos.z >1000.0 )
  position.z = position.z+1.0;
    if( camPos.z >5000.0 )
  position.z = position.z+10.0;
if (camPos.z< 300.0 )
  position.z = position.z+300.0;
gl_Position =  position;
}

But when camera's vertical position is less than 300 or more than 1000 the model simply disappears though in second case it should be moved just by one unit. I read about inside the shader coordinates are different from a world coordinates that's why i am multiplying by Projection and ModelView matrices, to get the world coordinates. Maybe I am wrong at this point? Forgive me if it's a simple question but i couldnt find the answer.

UPDATE: camPos is translated to world coordinates, but position is not. Maybe it has to do with the fact i am using osg_ViewMatrixInverse (passed by OpenSceneGraph) to get camera position and internal gl_ProjectionMatrix and gl_ModelViewMatrix to get the vertex coordinates? How do I translate position into world coordinates?


Solution

  • Figured it out:

    uniform mat4 osg_ViewMatrixInverse;
    uniform mat4 osg_ViewMatrix;
    
    void main(){
        vec3 camPos=osg_ViewMatrixInverse[3].xyz;
    
        vec4 position_in_view_space = gl_ModelViewMatrix * gl_Vertex;
        vec4 position_in_world_space  = osg_ViewMatrixInverse * position_in_view_space;
    
        if( camPos.z >1000.0 )
          position_in_world_space.z = position_in_world_space.z+700.0;
        if( camPos.z >5000.0 )
          position_in_world_space.z = position_in_world_space.z+1000.0;
        if (camPos.z< 300.0 )
          position_in_world_space.z = position_in_world_space.z+200;
        position_in_view_space = osg_ViewMatrix * position_in_world_space;
        vec4 position_in_object_space = gl_ModelViewMatrixInverse * position_in_view_space;
        gl_Position = gl_ModelViewProjectionMatrix * position_in_object_space;
    }
    

    One needs to transform gl_Vertex (which is in object space coords) into a world coordinates through view space coordinates (maybe there is direct conversion i dont see) than he can modify them and transform back into object space coordinates.