opengl - 如何在 OpenGL 3.x 中翻译单个对象?

标签 opengl

我有一些编写 OpenGL 2 应用程序的经验,想学习使用 OpenGL 3。为此,我购买了 Addison Wesley“红皮书”和“橙皮书”(GLSL),它们描述了固定功能的弃用和新的可编程管道(着色器)。但我无法掌握的是如何在不使用已弃用的 translate*、rotate* 和 scale* 函数的情况下构建具有多个对象的场景。

我过去在 OGL2 中所做的是使用平移和旋转功能在 3D 空间中“移动”,并使用 glBegin ... glEnd 在我想要的本地坐标中创建对象。在 OGL3 中,这些函数都被弃用了,据我所知,被着色器取代。但是我不能为我制作的每个对象调用一个着色器程序,对吗?这不会影响所有其他对象吗?

我不确定我是否已经令人满意地解释了我的问题,但它的核心是如何使用 OpenGL 3.1 中本地坐标中定义的多个对象对场景进行编程。我发现的所有初学者教程都只使用一个对象并且没有/解决这个问题。

编辑:想象一下你想要两个旋转的立方体。手动修改每个顶点坐标会很痛苦,而且您不能简单地修改模型 View 矩阵,因为那样会使相机围绕两个静态立方体旋转......

最佳答案

让我们从基础开始。

通常,您希望通过以下步骤转换局部三角形顶点:
local-space coords-> world-space coords -> view-space coords -> clip-space coords
在标准 GL 中,前 2 个转换是通过 GL_MODELVIEW_MATRIX 完成的。 ,第三个是通过 GL_PROJECTION_MATRIX 完成的

这些模型 View 转换,对于我们通常想要应用的许多有趣的转换(例如,平移、缩放和旋转),当我们在 homogeneous coordinates 中表示顶点时,恰好可以表示为向量矩阵乘法。 .通常,顶点 V = (x, y, z)在本系统中表示为 (x, y, z, 1) .

好的。假设我们要通过平移、旋转和平移来变换顶点 V_local。每个变换都可以表示为一个矩阵*,我们称它们为 T1、R1、T2。
我们想对每个顶点应用变换:V_view = V_local * T1 * R1 * T2 .矩阵乘法是关联的,我们可以一劳永逸地计算M = T1 * R1 * T2 .

这样,我们只需要将 M 向下传递给顶点程序,并计算 V_view = V_local * M .最后,典型的顶点着色器将顶点位置乘以单个矩阵。计算该矩阵的所有工作就是如何将对象从本地空间移动到剪辑空间。

好的...我浏览了一些重要的细节。

首先,我到目前为止所描述的只是真正涵盖了我们通常想要对 View 空间进行的转换,而不是剪辑空间。然而,硬件期望顶点着色器的输出位置在那个特殊的剪辑空间中表示。没有重要的数学很难解释剪辑空间坐标,所以我会忽略它,但重要的是将顶点带到剪辑空间的变换通常可以表示为相同类型的矩阵乘法。这是旧的 gluPerspective、glFrustum 和 glOrtho 计算的。

其次,这就是您应用于顶点位置的内容。转换法线的数学有点不同。那是因为您希望法线在转换后保持垂直于表面(作为引用,在一般情况下,它需要乘以模型 View 的逆转置,但在许多情况下可以简化)

第三,您永远不会将 4-D 坐标发送到顶点着色器。一般来说,你会通过 3-D 的。 OpenGL 会将这些 3-D 坐标(或 2-D,顺便说一句)转换为 4-D 坐标,这样顶点着色器就不必添加额外的坐标。它扩展每个顶点以添加 1 作为 w协调。

所以...将所有这些重新组合在一起,对于每个对象,您需要根据要应用于该对象的所有变换来计算那些神奇的 M 矩阵。在着色器内部,您必须将每个顶点位置乘以该矩阵并将其传递给顶点着色器位置输出。典型的代码或多或少(这是使用旧命名法):

mat4 MVP;
gl_Position=MVP * gl_Vertex;

* 实际矩阵可以在网络上找到,特别是在每个函数的手册页上:rotate , translate , scale , perspective , ortho

关于opengl - 如何在 OpenGL 3.x 中翻译单个对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1638292/

相关文章:

c++ - 弃用的函数和 fseek()

java - 我写的最简单的jogl代码没有显示真实的 View ?

c++ - 为 VBO 创建动态对象数组

c++ - OpenGL 转换无法按预期在 z 轴上工作

c++ - OpenGL 两个屏幕

java - 获取 float[] 作为 FloatBuffer 类

c# - 构建 OpenGL C# 应用程序来替换 GDI 是否明智

c++ - 查看动画网格的截锥体剔除

linux - Go 导致 OpenGL 与 time.Tick 但不是 time.After 发生段错误

c++ - 如何更快地绘制许多带纹理的四边形,并保留 glScissor(或类似的东西)?