如何使用着色器和矩阵进行翻译?

时间:2015-02-01 16:19:50

标签: opengl matrix glsl shader lwjgl

我正在使用LWJGL和着色器来尝试翻译我在着色器程序中绘制的所有内容。 我使用4乘4矩阵

1,0,0,x,
0,1,0,y,
0,0,1,z,
0,0,0,1

其中x,y,z是我用来翻译的值。然后我用

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex * transformMatrix

其中transformMatrix是一个统一的mat4,我从上面的矩阵得到。 它可以精确地转换x和y,但不能转换为z轴(向前和向后)。

矩阵或着色器方法是错误的吗? (或两者兼有)

如何解决此问题,使其翻译为glTranslatef?感谢

1 个答案:

答案 0 :(得分:2)

矩阵本身看起来不错。请记住,OpenGL默认使用列主要存储作为矩阵,因此当您指定矩阵时,此矩阵的元素将按此顺序排序:

{1.0f, 0.0f, 0.0f, 0.0f,
 0.0f, 1.0f, 0.0f, 0.0f,
 0.0f, 0.0f, 1.0f, 0.0f,
 x,    y,    z,    1.0f}

如果您想在代码中坚持使用行主要顺序,您还可以将GL_TRUE指定为glUniformMatrix4fv()'的第3个参数(转置)。

看起来你被困在两个不同级别的OpenGL之间。为了说明这一点,让我对OpenGL的一些主要演变阶段进行编号。以下不是官方术语,我刚刚完成了。

  • 第1阶段:修复了功能管道。渲染完全通过指定状态和发出绘制命令来执行。 State包括矩阵堆栈,光照和材料属性等。
  • 第2阶段:具有固定功能属性的可编程管道。着色器用于控制渲染,但仍然使用像矩阵堆栈这样的固定功能状态。使用GLSL代码中的预定义变量访问此状态。
  • 第3阶段:完全可编程。固定功能状态不再使用,并且着色器的所有输入都使用通用属性和制服指定。

与OpenGL版本匹配:

  • OpenGL 1.x严格使用第1阶段。
  • OpenGL 2.x代码通常使用阶段2,即使它完全向后兼容并且仍然支持第1阶段的所有内容。它已经拥有阶段3所需的大部分内容。
  • OpenGL 3.x及更高版本仅支持具有核心配置文件的阶段3(在3.2中引入)。第1阶段和第2阶段的所有固定功能方面仅在兼容性配置文件中可用。

您的代码片段表明您正在使用Stage 2,并且正在尝试迁移到Stage 3.在此过程中,您在两者之间创建了一个可疑的混合。根据您想要的方向,解决方案是不同的。

使用固定功能状态

只要您在着色器(gl_ModelViewProjectionMatrix)中使用固定函数矩阵堆栈中的矩阵,最简单的解决方案就是完全使用它。

因此,要翻译,请调用glTranslatef(),它会为您的模型视图矩阵添加一个转换,然后在GLSL代码中使用gl_ModelViewProjectionMatrix和类似的内置变量进行访问。

固定功能和统一的混合

使用您尝试使用的方法,最合理的解决方案是在内置gl_ModelViewProjectionMatrix之前将额外的转换矩阵与向量相乘:

gl_Position = gl_ModelViewProjectionMatrix * transformMatrix * gl_Vertex;

您需要注意,这会在模型视图转换中的所有其他模型转换之前应用之前的其他转换。假设您还使用固定函数调用指定了旋转:

glRotatef(...);

此轮换是模型视图矩阵的一部分,现在将应用于您添加的翻译。因此,您将旋转翻译的坐标,这可能不是您想要的。

使用这种方法,在其他模型转换后,没有好的方法来应用翻译。你基本上需要的是:

gl_ProjectionMatrix * gl_ViewMatrix * transformMatrix * gl_ModelMatrix * gl_Vertex;

但由于视图和模型矩阵在固定功能状态下组合,因此无法实现。

无固定功能状态

为了获得完全的灵活性以及与当前Core Profile的兼容性,您需要停止使用固定功能状态,以及相应的GLSL内置变量,如gl_ModelViewProjectionMatrix。为此,您需要在着色器代码中将所需的所有矩阵指定为统一变量。这使您可以完全控制使用的矩阵,以及如何在GLSL代码中应用它们。

例如,如果您只需要翻译,则无需使用完整矩阵。您可以使用vec3作为制服,只需将其添加到位置矢量。

完全可编程方法的主要缺点是您不能再使用glRotatef()gluLookAtgluPerspective()等便捷功能。有些开源库可以提供替代品,如果您愿意,也可以自己编写类似的功能。您也不再拥有矩阵堆栈,因此如果您依赖于转换层次结构,则需要在自己的代码中使用更多逻辑。