OpenGL中列序储存是什么?以及为什么矩阵乘法顺序要反过来

一、shader中为什么矩阵要反过来乘

首先我们写一个单位矩阵
1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 \begin{matrix} 1 & 0 & 0 &0 \\ 0 & 1 & 0 &0\\ 0 & 0 & 1 &0\\ 0 & 0 & 0 &1 \end{matrix} 1000010000100001
其次我们写一个缩放2倍的缩放矩阵
2 0 0 0 0 2 0 0 0 0 2 0 0 0 0 1 \begin{matrix} 2 & 0 & 0 &0 \\ 0 & 2 & 0 &0\\ 0 & 0 & 2 &0\\ 0 & 0 & 0 &1 \end{matrix} 2000020000200001
再写一个平移(1,2,3)个单位的平移矩阵
1 0 0 1 0 1 0 2 0 0 1 3 0 0 0 1 \begin{matrix} 1 & 0 & 0 &1 \\ 0 & 1 & 0 &2\\ 0 & 0 & 1 &3\\ 0 & 0 & 0 &1 \end{matrix} 1000010000101231
因为我们的向量是,4行1列的,4X1矩阵。
x y z 1 \begin{matrix} x \\ y \\ z\\ 1 \end{matrix} xyz1
根据我们的矩阵相乘的规则,向量只能放在最后面。

即 任意变换矩阵 乘以 向量矩阵。因此变换矩阵的相乘顺序也会有变化。

现在我们进行先缩放后平移的变换,观察两种矩阵相乘的顺序产生的结果

1、缩放矩阵 乘以 平移矩阵
在这里插入图片描述
再乘以我们的向量矩阵
在这里插入图片描述
可以看出,虽然我们的矩阵相乘是缩放矩阵 乘以 平移矩阵,但是结果却是先平移了(1,2,3)单位,然后再进行缩放2倍。与我们的需求不符合

2、平移矩阵 乘以 缩放矩阵
在这里插入图片描述
再乘以我们的向量矩阵
在这里插入图片描述
可以看出,这才是我们想要的结果,先缩放两倍再平移(1,2,3)单位

二、OpenGL矩阵列序储存,是什么意思?有什么影响?

1、是什么意思

首先我们简单了解一下GLSL里的数据类型
在这里插入图片描述
在矩阵变量中有mat2,mat3,mat4三种分析分别代表2x2矩阵,3x3矩阵,4x4矩阵。

在《OpenGL ES 2.0 Programming Guide》这本书中有如下介绍
在这里插入图片描述
矩阵是列优先的,

比如一个4x4矩阵
[ m 00 m 01 m 02 m 03 m 10 m 11 m 12 m 13 m 20 m 21 m 22 m 23 m 30 m 31 m 32 m 33 ] \left[ \begin{matrix} m00 & m01 & m02 &m03 \\ m10 & m11 & m12 &m13\\ m20 & m21 & m22 &m23\\ m30 & m31 & m32 &m33 \end{matrix} \right] m00m10m20m30m01m11m21m31m02m12m22m32m03m13m23m33
​ 在shader储存中就是
[ m 00 m 10 m 20 m 30 m 01 m 11 m 21 m 31 m 02 m 12 m 22 m 32 m 03 m 13 m 23 m 33 ] \left[ \begin{matrix} m00 & m10 & m20 &m30 \\ m01 & m11 & m21 &m31\\ m02 & m12 & m22 &m32\\ m03 & m13 & m23 &m33 \end{matrix} \right] m00m01m02m03m10m11m12m13m20m21m22m23m30m31m32m33
矩阵是转置了的,但是矩阵的乘法却依旧是行*列(和行序一样)

2、有什么影响
2.1传参的影响

我们在传递矩阵数据给shader的时候一定要转置,如下

在OpenGL编程指南这本书中可以查到,正射投影矩阵如下
[ 2 r − l 0 0 − r + l r − l 0 2 t − b 0 − t + b t − b 0 0 − 2 f − n − f + n f − n 0 0 0 1 ] \left[ \begin{matrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l}\\ 0 &\frac{2}{t-b} &0 &-\frac{t+b}{t-b}\\ 0 &0 &-\frac{2}{f-n} &-\frac{f+n}{f-n}\\ 0 & 0 & 0 &1 \end{matrix} \right] rl20000tb20000fn20rlr+ltbt+bfnf+n1
矩阵传入shader之前要转置,传入shader的时候一定要是列序!!!
在我代码中是这样写的

	template <typename valType>
	tmat4x4<valType>  ortho
	(
		valType left,
		valType right,
		valType bottom,
		valType top,
		valType zNear,
		valType zFar
	)
	{
		tmat4x4<valType> res(1);//初始化为单位矩阵

		res[0][0] = valType(2) / (right - left);
		res[1][1] = valType(2) / (top - bottom);
		res[2][2] = -valType(2) / (zFar - zNear);
		res[0][3] = -(right + left) / (right - left);
		res[1][3] = -(top + bottom) / (top - bottom);
		res[2][3] = -(zFar + zNear) / (zFar - zNear);
		return res;
	}
	
CELL::matrix4 screenProj = CELL::ortho<float>(0, float(_width), 0, float(_height), -100.0f, 100);
matMVP = matMVP.transpose();//矩阵转置!!!
glUniformMatrix4fv(_shader._MVP, 1, GL_FALSE, matMVP.data());
void glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat * value)
通过一致变量(uniform修饰的变量)引用将一致变量值传入渲染管线。
location : uniform的位置。
count : 需要加载数据的数组元素的数量或者需要修改的矩阵的数量。
transpose : 指明矩阵是列优先(column major)矩阵(GL_FALSE)还是行优先(row major)矩阵(GL_TRUE)。一定要用GL_FALSE;
value : 指向由count个元素的数组的指针

矩阵传入shader的时候一定要是列序!!!

2.2shader内部定义矩阵的影响

在OpenGL编程指南这本书中可以查到,平移矩阵如下
1 0 0 x 0 1 0 y 0 0 1 z 0 0 0 1 \begin{matrix} 1 & 0 & 0 &x \\ 0 & 1 & 0 &y\\ 0 & 0 & 1 &z\\ 0 & 0 & 0 &1 \end{matrix} 100001000010xyz1
但是在shder中我们去定义,由于列序储存我们就要定义成转置的矩阵
1 0 0 0 0 1 0 0 0 0 1 0 x y z 1 \begin{matrix} 1 & 0 & 0 &0 \\ 0 & 1 & 0 &0\\ 0 & 0 & 1 &0\\ x & y & z &1 \end{matrix} 100x010y001z0001
举例如下

			precision lowp float; 
			uniform   mat4 _MVP;
			attribute vec2 _position;
			attribute vec2 _uv;
			attribute vec4 _color;
			varying   vec4 _outColor;
			varying   vec2 _outUV;

			void main()
			{
				mat4 tran = mat4 (   1.0, 0.0, 0.0, 0.0,
									"0.0, 1.0, 0.0, 0,"
									"0.0, 0.0, 1.0, 0.0,"
									"0.0, -100.0,0.0, 1.0"//y轴下移100像素
								);
			   vec4    pos =   vec4(_position,0,1);
			   _outColor   =   _color;
			   _outUV      =   _uv;
			   gl_Position =  _MVP * tran  *pos  ;
			}

结果对比
在这里插入图片描述在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值