在顶点着色器中,您有 gl_Vertex (或者如果您不使用固定管道,则有其他东西),它是模型坐标中顶点的位置。将模型矩阵乘以 gl_Vertex,您将得到世界坐标中的顶点位置。将其分配给可变变量,然后在片段着色器中读取其值,您将获得片段在世界坐标中的位置。
现在的问题是,如果您使用 OpenGL 的默认模型视图矩阵,则不一定有任何模型矩阵,它是模型和视图矩阵的组合。我通常通过使用两个单独的矩阵而不是一个模型视图矩阵来解决这个问题:
- 模型矩阵(将模型坐标映射到世界坐标),以及
- 视图矩阵(将世界坐标映射到相机坐标)。
因此,只需将两个不同的矩阵分别传递给您的顶点着色器。您可以通过定义来做到这一点
uniform mat4 view_matrix;
uniform mat4 model_matrix;
在顶点着色器的开头。然后代替 ftransform(),说:
gl_Position = gl_ProjectionMatrix * view_matrix * model_matrix * gl_Vertex;
在主程序中,您必须将值写入这两个新矩阵。首先,要获取视图矩阵,请使用 glLoadIdentity()、glTranslate()、glRotate() 或 gluLookAt() 或您通常喜欢的任何方法进行相机转换,然后调用 glGetFloatv(GL_MODELVIEW_MATRIX, &array); 为了得到矩阵数据到一个数组。其次,以类似的方式,要获得模型矩阵,也可以调用 glLoadIdentity(); 并使用 glTranslate()、glRotate()、glScale() 等进行对象转换,最后调用 glGetFloatv(GL_MODELVIEW_MATRIX, &array); 从 OpenGL 中获取矩阵数据,以便将其发送到顶点着色器。特别注意,您需要在开始转换对象之前调用 glLoadIdentity()。通常,您会首先转换相机,然后转换对象,这将产生一个同时执行视图和模型功能的矩阵。但是因为您使用的是单独的矩阵,所以您需要在使用 glLoadIdentity() 进行相机转换后重置矩阵。
gl_FragCoord 是像素坐标而不是世界坐标。