【问题标题】:How to change vertex position using glsl如何使用 glsl 更改顶点位置
【发布时间】:2014-04-19 20:17:39
【问题描述】:

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

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 来获取顶点坐标的事实有关?如何将位置转换为世界坐标?

【问题讨论】:

    标签: c++ opengl glsl openscenegraph


    【解决方案1】:

    问题是您将位置转换为剪辑坐标(通过将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;
    }
    

    【讨论】:

    • 位置在物体空间,而相机在世界空间。这个想法是存在的,但它不会奏效
    • 然后你需要分离模型和视图矩阵,将位置乘以模型矩阵,做你的操作,然后乘以视图和投影矩阵。
    • @Colonel 三十二我确实按照你的建议,现在模型在 300 以下的点消失,在 1000 以上的点发生了一些奇怪的事情(我将其更改为 position.z = position.z+200.0所以更容易发现差异)。该模型的大部分被抬高到1000多个单元,有些部分只是单独“悬挂”空气。想法就在那里......我如何分离模型和视图矩阵? gl 没有单独提供它们。
    • 你必须自己做矩阵运算(我推荐GLM)然后通过制服上传它们。 GL 矩阵函数无论如何都是遗留功能,并在 OpenGL 3.1+ 中被删除。
    • @Colonel 三十二 谢谢我会试试的
    【解决方案2】:

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

    您实际上应该在此处将这些坐标添加到您的对象空间位置,然后执行从对象空间到剪辑空间的转换。三十二上校的回答已经很好地说明了如何做到这一点;我只是想解释究竟为什么您不应该将此偏移量应用于剪辑空间坐标。

    【讨论】:

      【解决方案3】:

      想通了:

      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(在对象空间坐标中)转换为世界坐标(也许我没有看到直接转换),然后他才能修改它们并转换回对象空间坐标。

      【讨论】:

        猜你喜欢
        • 2018-11-07
        • 2022-01-04
        • 1970-01-01
        • 2013-07-13
        • 2012-02-21
        • 1970-01-01
        • 1970-01-01
        • 2011-10-18
        • 1970-01-01
        相关资源
        最近更新 更多