(Python OpenGL)

原文:http://ogldev.atspace.co.uk/www/tutorial06/tutorial06.html  (英文)

下面是我翻译过来的:

背景

在本教程中,我们开始着眼于各种转换,它们以3D形式呈现对象,并使其能够在屏幕上显示,同时保持场景中的深度错觉。这样做的常用方法是使用矩阵表示每个转换,将它们逐个相乘,然后将顶点位置乘以最终产品。每个教程都将致力于检查一个转换。

在这里,我们看看翻译变换,它负责沿着任意长度和方向的矢量移动对象。假设您想要将左侧图片中的三角形移动到右侧的位置:

一种方法是将偏移矢量(在本例中为-1,1)作为统一变量提供给着色器,并将其简单地添加到每个处理过的顶点的位置。但是,这打破了将一组矩阵乘以一个以获得单一全面转换的方法。此外,稍后您会看到,翻译通常不是第一个翻译,所以您需要将位置乘以代表翻译前转换的矩阵,然后将矩阵中的位置和最终的多位加上表示翻译后转换的矩阵。这太尴尬了。更好的方法是找到一个表示翻译并参与所有矩阵乘法的矩阵。但是,你能找到一个矩阵,当乘以点(0,0)时,左边三角形的左下角顶点,给出结果(1,1)?事实是,你不能用2D矩阵来做它(你不能用(0,0,0)的3D矩阵来做)。一般来说,我们可以说我们需要的是给定点P(x,y,z)和向量V(v1,v2,v3)的矩阵M给出M * P = P1(x + v1,y + v2 ,z + v3)。简而言之,这意味着矩阵M将P转换成位置P + V。在P1中,我们可以看到每个分量是来自P的分量和V的对应分量的和。每个求和方程的左侧由单位矩阵提供:z)和向量V(v1,v2,v3)提供M * P = P1(x + v1,y + v2,z + v3)。简而言之,这意味着矩阵M将P转换成位置P + V。在P1中,我们可以看到每个分量是来自P的分量和V的对应分量的和。每个求和方程的左侧由单位矩阵提供:z)和向量V(v1,v2,v3)提供M * P = P1(x + v1,y + v2,z + v3)。简而言之,这意味着矩阵M将P转换成位置P + V。在P1中,我们可以看到每个分量是来自P的分量和V的对应分量的和。每个求和方程的左侧由单位矩阵提供:
I * P = P(x,y,z)。因此,看起来我们应该从单位矩阵开始,找出将在每个分量(... + V1,... + V2,... + V3)中完成总和方程右侧的变化。我们来看看身份矩阵是怎样的:

我们想修改单位矩阵,结果是:

如果我们坚持使用3x3矩阵,真的不是一个简单的方法,但如果我们改变为4x4矩阵,我们可以做到以下几点:

使用像这样的4矢量来表示3矢量被称为同质坐标,并且对3D图形非常流行和有用。第四个组件被称为'w'。实际上,我们在前面教程中看到的内部着色器符号gl_Position是一个4向量,而w分量对于从3D到2D进行投影具有非常重要的作用。常用符号是对于向量使用w = 1,对于向量使用w = 0。原因是点可以翻译,但矢量不能。您可以更改矢量的长度或其方向,但所有具有相同长度/方向的矢量都被视为相等,无论其“起始位置”如何。所以你可以简单地使用所有矢量的原点。设置w = 0并将平移矩阵乘以该向量将导致相同的向量。

源walkthru

struct Matrix4f {
    float m[4][4];
};

我们在math_3d.h中添加了一个4x4矩阵定义。这将用于我们从现在开始的大多数转换矩阵。

GLuint gWorldLocation;

我们使用这个句柄来访问着色器中的世界矩阵统一变量。我们将它命名为'世界',因为我们正在对物体做的事情是将其位置移动(翻译)到我们想要的虚拟“世界”坐标系中的位置。

Matrix4f World;
World.m[0][0] = 1.0f; World.m[0][1] = 0.0f; World.m[0][2] = 0.0f; World.m[0][3] = sinf(Scale);
World.m[1][0] = 0.0f; World.m[1][1] = 1.0f; World.m[1][2] = 0.0f; World.m[1][3] = 0.0f;
World.m[2][0] = 0.0f; World.m[2][1] = 0.0f; World.m[2][2] = 1.0f; World.m[2][3] = 0.0f;
World.m[3][0] = 0.0f; World.m[3][1] = 0.0f; World.m[3][2] = 0.0f; World.m[3][3] = 1.0f;

在渲染函数中,我们根据上面的解释准备一个4x4矩阵并将其排列。我们将v 2和v 3 设置为零,因此我们预计对象的Y和Z坐标不会发生变化,并且我们将v 1设置为正弦函数的结果。这会将X坐标转换为在-1和1之间很好地摆动的值。现在我们需要将该矩阵加载到着色器中。

glUniformMatrix4fv(gWorldLocation, 1, GL_TRUE, &World.m[0][0]);

这是将数据加载到统一着色器变量的glUniform *函数的另一个示例。该特定功能加载4x4矩阵,并且还有2x2,3x3,3x2,2x4,4x2,3x4和4x3版本。第一个参数是统一变量的位置(在使用glGetUniformLocation()着色器编译后检索)。第二个参数表示我们正在更新的矩阵的数量。我们对一个矩阵使用1,但我们也可以使用此函数在一次调用中更新乘法矩阵。第三个参数经常让新人感到困惑。它指示矩阵是按行 - 主还是列 - 主要顺序提供的。行 - 主要意味着从顶部开始一行一行地提供矩阵。列专业是相同的,但在列。关键是C / C ++默认是行主语言。这意味着当你使用值填充一个二维数组时,它们被放置在内存行中,并且在较低地址处使用“顶部”行。例如,请参阅以下数组:

int a[2][3];
a[0][0] = 1;
a[0][1] = 2;
a[0][2] = 3;
a[1][0] = 4;
a[1][1] = 5;
a[1][2] = 6;

在视觉上,阵列看起来像下面的矩阵:

1 2 3 
4 5 6

内存布局如下:1 2 3 4 5 6(在较低地址处有1)。

所以我们对glUniformMatrix4fv()的第三个参数是GL_TRUE,因为我们按行优先顺序提供矩阵。我们也可以创建第三个参数GL_FALSE,但我们需要转置矩阵值(C / C ++内存布局将保持不变,但OpenGL会“认为”我们提供的前4个值实际上是矩阵列,等等并会相应地表现出来)。第四个参数只是内存中矩阵的起始地址。

其余的来源是着色器代码。

uniform mat4 gWorld;

这是一个4x4矩阵的统一变量。mat2和mat3也可用。

gl_Position = gWorld * vec4(Position, 1.0);

三角形顶点在顶点缓冲区中的位置是3个分量的向量,但我们同意我们需要第四个分量的值为1.有两种选择:将4个分量的顶点放置在顶点缓冲区中或添加第四个分量在顶点着色器中。第一个选项没有优势。每个顶点位置将为已知为始终为1的组件额外消耗4个字节。使用3分量向量并将w分量连接到着色器会更高效。在GLSL中,这是使用'vec4(位置,1.0)'完成的。我们将该矩阵乘以该向量,结果进入gl_Position。总而言之,在每一帧中,我们都会生成一个转换矩阵,它将X坐标转换为-1和1之间的第四个值。着色器将每个顶点的位置乘以该矩阵,从而导致组合对象向左和向右移动。在大多数情况下,其中一个三角形边将在顶点着色器和裁剪器将裁剪出该边后从标准化框中移出。我们只能看到标准化框内的区域。

代码:

(Python OpenGL)【5】平移 PyOpenGL的更多相关文章

  1. 初试PyOpenGL四 (Python+OpenGL)GPU粒子系统与基本碰撞

    这篇相当于是对前三篇的总结,基本效果如下: 在初试PyOpenGL一 (Python+OpenGL)讲解Pyopengl环境搭建,网格,球体,第一与第三人称摄像机的实现.在初试PyOpenGL二 (P ...

  2. (Python OpenGL)【4】Uniform变量 PyOpenGL

    (Python OpenGL) 原文:http://ogldev.atspace.co.uk/www/tutorial05/tutorial05.html(英文) __author__ = " ...

  3. (Python OpenGL)【3】着色器 PyOpenGL

    (Python OpenGL)现在开始我们使用着色器来进行渲染.着色器是目前做3D图形最流行的方式. OpenGL的渲染管线流程: 数据传输到OpenGL—>顶点处理器—>细分着色—> ...

  4. 【Python OpenGL】【2】第一个三角形(Pyopengl)

    根据顶点缓存来生成图元(Python OpenGL) 原文(英文链接)http://ogldev.atspace.co.uk/www/tutorial03/tutorial03.html __auth ...

  5. (Python OpenGL)【1】你好顶点 PyOpenGL

    原文链接(C语言环境)(Python OpenGL) 我用python实现的代码: __author__ = "WSX" from OpenGL.GLUT.freeglut imp ...

  6. OpenGL ES平移矩阵和旋转矩阵的左乘与右乘效果

    OpenGL ES平移矩阵和旋转矩阵的左乘与右乘 在OpenGL .OpenGL ES中矩阵起着举足轻重的作用,而矩阵之间的左乘与右乘在效果上是不同的. 一.先平移后旋转 场景效果:人绕树旋转. 原理 ...

  7. (Python OpenGL)【 0】关于VAO和VBO以及OpenGL新特性

    (Python OpenGL)关于新版OpenGL需要了解的: 随着OpenGL状态和固定管线模式的移除,我们不在用任何glEnable函数调用,而且也不会有glVertex.glColor等函数调用 ...

  8. 初试PyOpenGL一 (Python+OpenGL)

    很早就一直想学Python,看到一些书都有介绍,不管是做为游戏的脚本语言,还是做为开发项目的主要语言都有提及(最主要的CUDA都开始支持Python,CUDA后面一定要学),做为先熟悉一下Python ...

  9. 初试PyOpenGL二 (Python+OpenGL)基本地形生成与高度检测

    在上文中,讲述了PyOpenGL的基本配置,以及网格,球形的生成,以及基本的漫游.现在利用上一篇的内容,来利用高程图实现一个基本的地形,并且,利用上文中的第三人称漫游,以小球为视角,来在地形上前后左右 ...

随机推荐

  1. 使用spring-boot-starter-amqp开发生产者应用

    上一篇我们介绍了如何使用spring AMQP和RabbitMQ结合,开发消费者应用程序,使用的是Xml配置的Spring框架. 本篇我们仍然使用Spring AMQP开发生产者应用,不过我们使用零 ...

  2. CAD库中列举所有航路点

    select distinct f1.airway_point_name,f1.latitude,f1.longitude,upper(f1.airway_point_type_name)type,f ...

  3. rsync 同步mac机器目录数据到windows2008R2

    openssh rsync -azvP --progress -e "ssh -p 6099" /ahwater/rsync/ ahwater@ip:/ahwater

  4. java中的自动转型的学习理解

    java当中的继承是和c++中的继承类似,只是java中的继承时的父类只能有一位. 我们今天在这里讲的是关于java中的自动转型的理解:顾名思义,自动转型值得就是使用时自动的将自身的类型进行转化. 自 ...

  5. adb pull 和 adb push

    1. 操作单个文件 通过adb push,则可将文件添加到SD卡中.如果想在push的时候修改文件名称的话,只需要修改push的第二个参数改成完整路径(目录+文件名),如/sdcard/test-0. ...

  6. import time

    时间相关的操作,时间有三种表示方式: 时间戳               1970年1月1日之后的秒,即:time.time() 格式化的字符串    2014-11-11 11:11,    即:t ...

  7. java中的面向对象的三大基本特征

    转载,原文来自http://blog.sina.com.cn/s/blog_5f79a56a0100c6ig.html 众所周知,java中的面向对象的三大基本特征是:[封装].[继承].[多态] 一 ...

  8. 算法Sedgewick第四版-第1章基础-2.1Elementary Sortss-001选择排序法(Selection sort)

    一.介绍 1.算法的时间和空间间复杂度 2.特点 Running time is insensitive to input. The process of finding the smallest i ...

  9. 算法Sedgewick第四版-第1章基础-005一封装输入(可以文件,jar包里的文件或网址)

    1. package algorithms.util; /*********************************************************************** ...

  10. rvm 安装后的补充工作:source $HOME/.profile

    rvm安装后会在 $HOME/.bash_profile 文件追加一行代码: [[ -s "$HOME/.rvm/scripts/rvm" ]] && source ...