关于c ++:如何使用glsl更改顶点位置

How to change vertex position using glsl

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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时,模型就消失了,不过在第二种情况下,模型应该只移动一个单元。我读到了关于材质球内部坐标不同于世界坐标,这就是为什么我要乘以投影和模型视图矩阵,得到世界坐标。也许我在这一点上是错的?如果这是个简单的问题,请原谅我,但我找不到答案。

更新:Campos被转换为世界坐标,但位置不是。也许这与我使用osg_viewMatrixinverse(由openscegraph传递)获取相机位置和内部gl_ProjectionMatrix和gl_ModelViewMatrix获取顶点坐标有关?如何将位置转换为世界坐标?


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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在剪辑空间中,为任何坐标输出的值必须大于等于gl_Position.W或小于等于gl_Position.W或将被剪辑。如果基本体的所有坐标都在该范围之外,则不会绘制任何内容。这样做的原因是,在顶点着色完成后,OpenGL将剪辑空间坐标除以W,以生成范围为[-1,1](ndc)的坐标。此卷之外的任何内容都不会显示在屏幕上。

您在这里实际应该做的是将这些坐标添加到对象空间位置,然后执行从对象空间到剪辑空间的转换。32上校的回答已经很好地展示了如何做到这一点;我只是想确切地解释为什么你不应该把这个偏移应用到剪辑空间坐标。


找出答案:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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_顶点(在对象空间坐标中)转换为世界坐标,这样他就可以修改它们并转换回对象空间坐标。