如何使用glsl更改顶点位置

时间:2014-03-14 13:43:01

标签: c++ opengl glsl openscenegraph

我正在尝试根据相机位置移动物体。这是我的顶点着色器

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;
}

但是当相机的垂直位置小于300或大于1000时,模型会消失,但在第二种情况下它应该只移动一个单位。我读到有关着色器坐标内部不同于世界坐标,这就是为什么我乘以Projection和ModelView矩阵,以获得世界坐标。也许我现在错了?请原谅我这是一个简单的问题,但我找不到答案。

更新:camPos被转换为世界坐标,但位置不是。也许它与我使用osg_ViewMatrixInverse(由OpenSceneGraph传递)获取相机位置以及内部gl_ProjectionMatrix和gl_ModelViewMatrix来获取顶点坐标的事实有关?如何将位置转换为世界坐标?

3 个答案:

答案 0 :(得分:5)

问题是你正在将位置转换为剪辑坐标(通过将gl_Vertex乘以投影和模型视图矩阵),然后对那些剪辑坐标执行世界坐标操作,这不会给你带来结果想。

在乘以模型视图和投影矩阵之前,只需执行转换。

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;
}

答案 1 :(得分:3)

gl_Position位于剪辑空间中,您为任何坐标输出的值必须为&gt; = - gl_Position.W或&lt; = gl_Position.W,否则它们将被剪裁。如果基元的所有坐标都在此范围之外,则不会绘制任何内容。这样做的原因是在顶点着色器完成后,OpenGL将剪辑空间坐标除以W以生成范围[-1,1](NDC)中的坐标。此卷外的任何内容都不会出现在屏幕上。

这里你应该做的是将这些坐标添加到对象空间位置,然后执行从对象空间到剪辑空间的转换。三十二上校的答案已经很好地展示了如何做到这一点;我只想解释究竟为什么你不应该将这个偏移应用于剪辑空间坐标。

答案 2 :(得分:2)

想出来:

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;
}

需要将gl_Vertex(在对象空间坐标中)转换为通过视图空间坐标的世界坐标(可能有直接转换我看不到),而不是修改它们并转换回对象空间坐标。