焦点速讯:【教程】矩阵相乘时 我们先写位移再缩放
注意,当矩阵相乘时我们先写位移再写缩放变换的。建议您在组合矩阵时,先进行缩放操作,然后是旋转,最后才是位移,否则它们会(消极地)互相影响。比如,如果你先位移再缩放,位移的向量也会同样被缩放(译注:比如向某方向移动2米,2米也许会被缩放成1米)!
(一)矩阵变换
1、添加头文件
【资料图】
我们需要的GLM的大多数功能都可以从下面这3个头文件中找到:
#include#include#include
2、矩阵初始化
GLM库从0.9.9版本起,默认会将矩阵类型初始化为一个零矩阵(所有元素均为0),而不是单位矩阵(对角元素为1,其它元素为0)。如果你使用的是0.9.9或0.9.9以上的版本,你需要将所有的矩阵初始化改为 glm::mat4 mat = glm::mat4(1.0f)。如果你想与本教程的代码保持一致,请使用低于0.9.9版本的GLM,或者改用上述代码初始化所有的矩阵。
我们来看看是否可以利用我们刚学的变换知识把一个向量(1, 0, 0)位移(1, 1, 0)个单位(注意,我们把它定义为一个glm::vec4类型的值,齐次坐标设定为1.0):
glm::vec4 vec(1.0f, 0.0f, 0.0f, 1.0f);// 译注:下面就是矩阵初始化的一个例子,如果使用的是0.9.9及以上版本// 下面这行代码就需要改为:// glm::mat4 trans = glm::mat4(1.0f)// 之后将不再进行提示glm::mat4 trans;
我们先用GLM内建的向量类定义一个叫做vec的向量。接下来定义一个mat4类型的trans,默认是一个4×4单位矩阵。
3、变换
我们来做些更有意思的事情,让我们来旋转和缩放之前教程中的那个箱子。首先我们把箱子逆时针旋转90度。然后缩放0.5倍,使它变成原来的一半大。随时间变化,使用GLFW的时间函数来获取不同时间的角度
glm::mat4 trans;trans = glm::translate(trans, glm::vec3(0.5f, -0.5f, 0.0f));trans = glm::rotate(trans, (float)glfwGetTime(), glm::vec3(0.0f, 0.0f, 1.0f));
首先,我们把箱子在每个轴都缩放到0.5倍,然后沿z轴旋转90度。GLM希望它的角度是弧度制的(Radian),所以我们使用glm::radians将角度转化为弧度。注意有纹理的那面矩形是在XY平面上的,所以我们需要把它绕着z轴旋转。因为我们把这个矩阵传递给了GLM的每个函数,GLM会自动将矩阵相乘,返回的结果是一个包括了多个变换的变换矩阵。
矩阵传递给着色器
我们在前面简单提到过GLSL里也有一个mat4类型。所以我们将修改顶点着色器让其接收一个mat4的uniform变量,然后再用矩阵uniform乘以位置向量:
#version 330 corelayout (location = 0) in vec3 aPos;layout (location = 1) in vec2 aTexCoord;out vec2 TexCoord;uniform mat4 transform;void main(){ gl_Position = transform * vec4(aPos, 1.0f); TexCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);}
GLSL也有mat2和mat3类型从而允许了像向量一样的混合运算。前面提到的所有数学运算(像是标量-矩阵相乘,矩阵-向量相乘和矩阵-矩阵相乘)在矩阵类型里都可以使用。当出现特殊的矩阵运算的时候我们会特别说明。
变换矩阵传递给着色器:
unsigned int transformLoc = glGetUniformLocation(ourShader.ID, "transform");glUniformMatrix4fv(transformLoc, 1, GL_FALSE, glm::value_ptr(trans));
我们首先查询uniform变量的地址,然后用有Matrix4fv后缀的glUniform函数把矩阵数据发送给着色器。第一个参数你现在应该很熟悉了,它是uniform的位置值。第二个参数告诉OpenGL我们将要发送多少个矩阵,这里是1。第三个参数询问我们我们是否希望对我们的矩阵进行置换(Transpose),也就是说交换我们矩阵的行和列。OpenGL开发者通常使用一种内部矩阵布局,叫做列主序(Column-major Ordering)布局。GLM的默认布局就是列主序,所以并不需要置换矩阵,我们填GL_FALSE。最后一个参数是真正的矩阵数据,但是GLM并不是把它们的矩阵储存为OpenGL所希望接受的那种,因此我们要先用GLM的自带的函数value_ptr来变换这些数据。
(二)画出立方体
顶点坐标
float vertices[] = {-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f};
2、绘制图元
glDrawArrays(GL_TRIANGLES, 0, 36); //画三角形,从第 0 个数据开始画,到最后一个数据(第 3 个)结束//glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
3、增加深度测试
//glEnable(GL_DEPTH_TEST); //深度测试//glDepthFunc(GL_LESS); //深度信息小于当期信息,就把进行测试
4、在清除屏幕的时候,也需要把深度缓存的数据清除掉!
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
附加内容:画出多个立方体
现在我们想在屏幕上显示10个立方体。每个立方体看起来都是一样的,区别在于它们在世界的位置及旋转角度不同。立方体的图形布局已经定义好了,所以当渲染更多物体的时候我们不需要改变我们的缓冲数组和属性数组,我们唯一需要做的只是改变每个对象的模型矩阵来将立方体变换到世界坐标系中。
首先,让我们为每个立方体定义一个位移向量来指定它在世界空间的位置。我们将在一个glm::vec3数组中定义10个立方体位置:
glm::vec3 cubePositions[] = { glm::vec3( 0.0f, 0.0f, 0.0f), glm::vec3( 2.0f, 5.0f, -15.0f), glm::vec3(-1.5f, -2.2f, -2.5f), glm::vec3(-3.8f, -2.0f, -12.3f), glm::vec3( 2.4f, -0.4f, -3.5f), glm::vec3(-1.7f, 3.0f, -7.5f), glm::vec3( 1.3f, -2.0f, -2.5f), glm::vec3( 1.5f, 2.0f, -2.5f), glm::vec3( 1.5f, 0.2f, -1.5f), glm::vec3(-1.3f, 1.0f, -1.5f) };
现在,在游戏循环中,我们调用glDrawArrays 10次,但这次在我们渲染之前每次传入一个不同的模型矩阵到顶点着色器中。我们将会在游戏循环中创建一个小的循环用不同的模型矩阵渲染我们的物体10次。注意我们也对每个箱子加了一点旋转:
glBindVertexArray(VAO);for(unsigned int i = 0; i < 10; i++){ glm::mat4 model; model = glm::translate(model, cubePositions[i]); float angle = 20.0f * i; model = glm::rotate(model, glm::radians(angle), glm::vec3(1.0f, 0.3f, 0.5f)); ourShader.setMat4("model", model); glDrawArrays(GL_TRIANGLES, 0, 36);}
这段代码将会在每次新立方体绘制出来的时候更新模型矩阵,如此总共重复10次。然后我们应该就能看到一个拥有10个正在奇葩地旋转着的立方体的世界。
标签:
相关推荐:
最新新闻:
- 焦点速讯:【教程】矩阵相乘时 我们先写位移再缩放
- realme GT Neo5 手机 240W 快充:充电 30 秒,通话 2 小时-环球快资讯
- 每日短讯:Pinkfong 公司与 Million Volt 合作推出全新 3D 动画情景喜剧“SEALOOK”
- DC高层解释取消《蝙蝠女》:如果发行会伤害品牌
- GI公布《生化4RE》新演示 游戏追加新武器十字弓
- 每日热门:一加手机官宣:与原神正式达成三年期战略合作!
- 可口可乐版手机来了:国产知名品牌打造
- 甲骨文将Red Hat Enterprise Linux引入Oracle Cloud Infrastructure
- 20 万级别?极氪 003 零百加速进入 3 秒俱乐部,秒杀百万超跑
- 新年爆红!小刀电动车再迎产品革新,航天动力系霸气开局势不可挡
- 苹果折叠屏笔记本将亮相:20.5寸超大屏:全球速看料
- 环球微资讯!律师谈12.4万抢购保时捷:商家不能单方面取消订单
- 卡普空更新旗下百万销量游戏名单 怪猎冰原销量突破1千万_环球即时看
- 柯南最新剧场版《黑铁的鱼影》正式海报 4月14日上映
- 网友吐槽手机APP广告乱跳转 晃一下就出现!
- 网易开放暴雪游戏退款申请通道 申请截止日期6月30日|当前消息
- 世界短讯!2023年三分热度品牌获天使轮融资3000万
- 麦克风没声音是什么原因?麦克风没声音具体解决方法
- 下划线在键盘上怎么打?下划线快捷键ctrl加什么?
- UDP端口要如何打开?UDP端口具体打开的方法步骤
- office2010免费密钥怎么找?office2010激活密钥分享及激活码使用步骤
- 本地连接在什么位置?本地连接怎样进行设置?本地连接的相关介绍
- 什么是IPX协议?ipx协议安装教程
- 系统分区是什么意思?win10系统分区怎样进行操作?
- 电脑出现wmiprvse.exe占cpu高怎么操作?wmiprvse.exe占cpu高详细处理步骤
- thumbs.db是什么文件?手机db文件怎么打开?
- 什么是ACPI?ACPI的六种状态介绍
- hiberfil文件是什么意思?hiberfil文件删除的详细步骤
- hiberfil.sys是什么文件?hiberfil.sys删除方法
- 玩穿越火线卡屏怎么办?穿越火线卡屏详细的教程展示解决步骤
- 为什么打开我的电脑很慢?打开我的电脑很慢解决方法
- xp打印机共享怎么设置?教你xp系统打印机共享设置方法
- 本地连接在什么位置?本地连接怎样进行设置?
- 索尼xperiaz1mini手机怎么样?索尼Z1 Mini手机配置参数详解
- 怎么解决蓝屏提示c000021a unknown hard error?解决方法
- 笔记本无线WIFI怎样设置共享?路由器怎么设置共享wifi?
- 怎么查手机短信记录?介绍中国移动查短信记录方法
- 如何建设一个网上商城?网上商城制作步骤
- 天天快看:《赛博朋克2077》DLSS3开启/关闭对比 帧数提升惊人
- 系列新作《尸变纪元:幸存者》公布 Steam页面上线
- 每日视讯:华盛顿大学研发几乎无电池无线通信装置 实现最远7米
- 本届公关,与财富自由无缘:观热点
- 荒野送货人 《Across the wilds》Steam页面上线|微速讯
- 焦点滚动:育碧《飙酷车神3》首曝预告 封闭测试明日开启
- 类魂动作《堕落之主》新截图:地狱魔物降临黑暗世界|环球动态
- 眼红ChatGPT爆火 谷歌竞品曝光 搜索或将大改
- 惠普打印机能打印图片不能打印文档_打印机能打印图片不能打印文档
- 新华三Cloudnet助力中小企业数字转型迈入新一程-热文
- RTX 4090 Ti最新消息:四槽600W 环球看热讯
- 焦点观察:iPhone 16 Ultra成望远镜?支持6倍光学变焦
- 郭明錤爆料称iPhone 16 Ultra或将独占潜望式长焦_全球快讯
- 焦点观察:iPhone 16 Ultra成望远镜?支持6倍光学变焦
- 一个艰难的决定!EA宣布《战地》手游开发终止
- 家人侠归来!《速度与激情10》首张海报公开-环球热点
- Xbox 360线上商店将移除46款游戏 包括《黑暗之魂》:播报
- 《黑豹2》中国角色海报:瓦坎达英雄集结 2月7日上映
- 世界微速讯:《消逝的光芒》全系列热销3000万份 二代将迎来上市一周年
- 《潜渊症》2023年春季发售1.0正式版 Steam定价即将永涨
- 只有高端机型才有?曝潜望相机镜头仅限于iPhone 16 Pro Max
- 当前热点-一加与《原神》达成三年战略合作 开启移动端游戏新体验
- 2399元!三星发布 4TB T7 Shield便携式固态硬盘
- 【热闻】史诗级更新?今年晚些时候你的iPhone将推出5个新的iOS功能
- 焦点讯息:无路可退!苹果关闭iOS 16.2验证通道
- 花刺代理是什么?花刺代理怎么使用?
- DVD解码器如何安装?DVD解码器具体的安装步骤
- 苹果开机一直在开机画面怎么处理?怎么将苹果的界面主色调恢复成正常颜色?
- 自动点击器怎么使用?自动点击器怎么设置参数?
- iphone固件不兼容的原因是什么?苹果固件不兼容怎么办?
- 提示sd卡已受损是什么原因?修复已损坏的手机SD卡方法
- MSN帐号格式是什么?MSN用户名格式的详细介绍
- 尼康D300说明书是什么?尼康D300相机详细参数
- mp4和mp5的区别在哪?mp4和mov格式区别对比
- 如何解决爱奇艺提示播放失败?爱奇艺提示播放失败解决方法
- win7版本区别是什么?不同win7系统版本之间的区别盘点
- sbsettings怎么设置?sbsettings设置步骤
- win7软件程序窗口最小化后找不到了是怎么回事?解决方法步骤
- 无法上网和驱动不能识别?sl410k无线网卡驱动安装说明
- 怎么解决开机后本地连接慢的问题?开机后本地连接慢出现原因及解决方法
- pinterest是什么?pinterest打不开的解决方法
- sd卡根目录是什么?sd卡根目录在哪?
- ipadtv6是什么?苹果IpadTV电视棒的使用方法
- win10系统如何设置桌面下雪屏保?桌面下雪屏保设置步骤
- 电视上的投屏码在哪里?钉钉投屏码怎么找?
- 景区呼吁游客抽打秦桧雕像不能极端 公安部门已介入 观热点
- 【天天新视野】男生和女生初四相亲初八订婚 表示不耽误年后上班