(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. 【OpenCV】图像代数运算:平均值去噪,减去背景

    代数运算,就是对两幅图像的点之间进行加.减.乘.除的运算.四种运算相应的公式为: 代数运算中比较常用的是图像相加和相减.图像相加常用来求平均值去除addtive噪声或者实现二次曝光(double-ex ...

  2. webapi中使用token验证(JWT验证)

    本文介绍如何在webapi中使用JWT验证 准备 安装JWT安装包 System.IdentityModel.Tokens.Jwt 你的前端api登录请求的方法,参考 axios.get(" ...

  3. 第十五章 深入分析iBatis框架之系统架构与映射原理(待续)

    iBatis框架主要的类层次结构 iBatis框架的设计策略 iBatis框架的运行原理 iBatis框架对SQL语句的解析 数据库字段映射到Java对象 示例运行的结果 设计模式解析之简单工厂模式 ...

  4. NSFileManager和NSFileHandle使用

    一.NSFileManager: 1.1.获取NSFileManager NSFileManager *manager = [NSFileManager defaultManager];     NS ...

  5. oracle 在xml中批量插入,批量修改及多组条件查询

    最近公司用ibatis开发项目,本来可以用存储过程处理批量插入,批量修改及多组条件查询:但由于使用模块相对较小,暂时就在xml中配置,以前没有在xml做过类似处理,有必要记录一下:好了,代码如下: & ...

  6. 用JS,打印三角形

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  7. python爬虫(1)--Urllib库的基本使用

    这里使用python2.7,pycharm进行代码编写 1.爬一个静态网页示例 import urllib2 response = urllib2.urlopen("http://www.b ...

  8. CSS制作水平垂直居中对齐 多种方式各有千秋

    作为前端攻城师,在制作Web页面时都有碰到CSS制作水平垂直居中,我想大家都有研究过或者写过,特别的其中的垂直居中,更是让人烦恼.这段时间,我收 集了几种不同的方式制作垂直居中方法,但每种方法各有千秋 ...

  9. [bzoj2460] [BeiJing2011]元素(线性基+贪心)

    题目大意: 有一些矿石,每个矿石有一个a和一个b值,要求选出一些矿石,b的和最大且不存在某个矿石子集它们的a的异或和为0. 解题关键:对魔力进行由大到小排序,依次加入线性基,统计即可. #includ ...

  10. 通过iOS中的按钮来触发html文件中按钮所触发的函数

    html文件的代码 <!DOCTYPE html> <html> <head> <title>标题</title> </head> ...