65c1cac95da4d7e91898653596361e57
Learn OpenGL 5. 变换

预备知识

本节预备知识大都和向量,矩阵变换相关。具体可以直接阅读 变换 中的向量和矩阵部分(建议看明白里面的如何通过矩阵与向量相乘来达到对变换的目的)。

动手画画

这节内容很简单,只需要对顶点着色器中的顶点坐标进行一定的转换即可。这里我们需要传入变换矩阵,使其与顶点坐标向量相乘输出新的顶点坐标位置。

修改顶点着色器

增加一个新的入参:uniform highp mat4 model_matrix; 来接收变换矩阵。

// l5vertex.vsh
attribute vec4 a_position;
attribute vec4 a_color;
attribute vec2 a_texCoord;

varying lowp vec4 frag_color;
varying lowp vec2 frag_texCoord;

uniform highp mat4 model_matrix;

void main(void) {
  frag_color = a_color;
  frag_texCoord = a_texCoord;
  gl_Position = model_matrix * a_position;
}

14 行利用我们的变换矩阵和顶点坐标相乘生成新的顶点坐标(注意:不要写反了,矩阵乘法是不遵循交换律的)。

修改 BaseEffect

这里和上一节也是一样,通过 glGetUniformLocation 获取到顶点着色器中 model_matrix 变量的索引。

var modelMatrix: GLKMatrix4?
private var modelMatrixUniform: Int32 = 0

private func compile(_ vertexShaderName: String, _ fragmentShaderName: String) {
    ...

    // 查询 uniform 信息
    textureUniform = glGetUniformLocation(program, "u_texture")
    modelMatrixUniform = glGetUniformLocation(program, "model_matrix")

    ...
}

同时,我们暴露一个参数 modelMatrix 来让外界赋值这个变换矩阵。

然后修改 prepareToDraw 函数,应用我们获得的 modelMatrix 传输到顶点着色器中。

func prepareToDraw() {
    ...

    if let modelMatrix = modelMatrix {
        let array = (0..<16).map { modelMatrix[$0] } // 矩阵转数组
        glUniformMatrix4fv(
            modelMatrixUniform,
            1,
            GLboolean(GL_FALSE),
            array
        )
    }
}

传输变换矩阵并渲染

这里直接使用 GLKit 提供的矩阵函数来实现,暂时不纠结如何自己生成变换矩阵。

override func glkView(_ view: GLKView, drawIn rect: CGRect) {
    ...
    effect.prepareToDraw()

    // 传入变换矩阵
    effect.modelMatrix = modelMatrix()

    glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(vertices.count))
}

private func modelMatrix() -> GLKMatrix4 {
    var modelMatrix = GLKMatrix4Identity
    modelMatrix = GLKMatrix4Translate(modelMatrix, 0.5, -0.5, 0) // 平移
    modelMatrix = GLKMatrix4Scale(modelMatrix, 0.5, 0.5, 1) // 缩放
    let radians = linearRadians()
    modelMatrix = GLKMatrix4Rotate(modelMatrix, radians, 0, 1, 0) // 旋转, 沿 Y 轴旋转 45°
    return modelMatrix
}

效果

如果我们的代码一切都正常,那我们就会看到下面这样的效果。
上面的代码可以在 https://github.com/xurunkang/learnopengl 中找到。

先平移后缩放
先缩放后平移

第一种效果是对应我们上面的代码,但是如果我们把缩放和平移的函数调用,就会出现下面的状态。可以看到缩放后平移的情况会把平移的距离也同时缩放了(至于为什么可以看文章开头引用的链接)。

下面是旋转的效果。
<p align="center">
<video id="video" controls="" preload="auto" poster="https://images.xiaozhuanlan.com/photo/2019/4b2e443ddd04b9b2b94f40f746543628.png">
<source id="mp4" src="https://images.xiaozhuanlan.com/photo/2019/00be708d5d7d9e2d4d3bfef75a54ab5e.mp4"></video>

小结

了解到如何对坐标进行平移、缩放和旋转等基本变换操作。

© 著作权归作者所有
这个作品真棒,我要支持一下!
🧀 专栏介绍 - 记录日常开发和学习中遇到的知识/问题 🚀 专栏方向 目前专注于 - OpenGL - ...
0条评论
top Created with Sketch.