OpenGL(3) —— OpenGL 的矩阵变换

2020-01-27  本文已影响0人  你可记得叫安可

基本计算

向量之间的计算有 点积叉积
矩阵之间的计算有加减数乘矩阵间乘法

矩阵的缩放

矩阵缩放
OpenGL 中,我们用 4 维向量来表示 3 维空间的数据,其中多出来的 w 维适用于透视投影的,因此在缩放中 w 依然为 1,因为在 3 维空间中变换 w 值没有意义。

位移

位移矩阵
这里就表现出了 w 分量的意义,如果没有 w 分量,上面的向量 (x, y, z) 就不能位移,这个坐标就只能表示方向向量。

旋转

一个向量在三维空间中旋转,主要受两个条件影响:1. 旋转角度;2. 旋转轴。


沿 x 轴旋转 沿 y 轴旋转 沿 z 轴旋转

上面我们只能沿着某个单位轴进行旋转,但是更方便的情况是,我们希望能够沿着任意方向轴旋转,这个有点复杂了,待研究。

组合变换

矩阵可以进行组合,达到用一个矩阵就进行多种变换的效果。假设有顶点 (x, y, z),我们将其放大两倍,然后位移 (1, 2, 3),那么我们需要一个位移矩阵和一个缩放矩阵来完成这个事。

组合变换
矩阵相乘不满足交换律,因此参加计算的矩阵位置顺序很重要。当矩阵相乘时,最右边的矩阵是第一个与向量计算的矩阵,因此上图中的矩阵乘法我们应该从右往左读。即先放大两倍,然后平移的。如果我们交换顺序,就会变为先平移,再放大,那么平移的量就也会被放大。
组合变换最终计算式

OpenGL 中相关 API

代码中的写法

  1. 定义模型矩阵:
private float[] modelMatrix = new float[16];

这里使用长度为 16 的 float 数组,这是因为我们上面已经解释了,这里使用的矩阵都是 4x4 的矩阵。

  1. onSurfaceChanged() 中初始化模型矩阵:
@Override
public void onSurfaceChanged(GL10 gl10, int width, int height) {
    glViewport(0, 0, width, height);
    setIdentityM(modelMatrix, 0);
    Matrix.translateM(modelMatrix, 0, 0.5f, 0, 0); // 沿 x 轴平移 0.5 个单位
    // Matrix.rotateM(modelMatrix, 0, 90, 0f, 0, 1); // 沿 z 轴旋转 90º
    // Matrix.scaleM(modelMatrix, 0, 0.5f, 1.0f, 0); // x 轴缩放 0.5 倍,y轴不变。注意这里 y 轴如果写 0.0f,就会把 y 轴直接缩放没了(0 倍)
}
  1. Shader 中使用矩阵进行变换:
attribute vec4 a_Position;
uniform mat4 u_Matrix;

void main(){

    gl_Position = u_Matrix * a_Position;
}

申明一个 uniform mat4 的 4x4 矩阵 u_Matrix,按照上面的教程,我们左乘这个矩阵。

  1. onSurfaceCreated() 中获得 u_MatrixGPU
    中的地址,然后在 onDrawFrame() 中使用这个模型矩阵:
uMatrixLocation = glGetUniformLocation(program, U_MATRIX);
...
glUniformMatrix4fv(uMatrixLocation, 1, false, modelMatrix, 0);

上面 glUniformMatrix4fv() 中第一个参数表示数据所要传输到 GPU 中的地址,第二个参数表示需要加载的数据数量(会按照 u_Matrix 类型进行加载),第三个表示内存中数据是列优先(false)还是行优先(true),第四个参数表示要传输到 GPU 中的内存数据,第五个参数表示 modelMatrix 的偏移量。


https://github.com/fightyz/OpenGLPlayground checkout 1fecc7a6cb2ec61fe45ee7e781e6a3cc74dad0a8

上一篇 下一篇

猜你喜欢

热点阅读