문제

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?

도움이 되었습니까?

해결책 3

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.

다른 팁

The problem is that you are transforming the position into clip coordinates (by multiplying gl_Vertex by the projection and modelview matrices), then performing a world-coordinate operation on those clip coordinates, which does not give the results you want.

Simply perform your transformations before you multiply by the modelview and projection matrices.

uniform mat4 osg_ViewMatrixInverse;

void main() {
    vec4 position = 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 = gl_ProjectionMatrix * gl_ModelViewMatrix * position;
}

gl_Position is in clip-space, the values you output for any coordinate must be >= -gl_Position.W or <= gl_Position.W or they will be clipped. If all of your coordinates for a primitive are outside this range, then nothing will be drawn. The reasoning for this is that after the vertex shader completes, OpenGL divides the clip-space coordinates by W to produce coordinates in the range [-1,1] (NDC). Anything outside this volume will not be on screen.

What you should actually do here is add these coordinates to your object-space position and then perform the transformation from object-space to clip-space. Colonel Thirty Two's answer already does a very good job of showing how to do this; I just wanted to explain exactly why you should not apply this offset to the clip-space coordinates.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top