OpenGL ES2学习笔记(9)-- 转换矩阵

线性代数计算机图形学的一块基石,本篇文章总结如何在Shader中使用矩阵移动缩放旋转顶点。

代码和效果

下面的代码复制到OpenGL Console里:

import java.nio.ByteBuffer
import java.nio.ByteOrder
import javax.media.opengl.GL
import org.glob.math.Matrix4f

//  shaders

def vertexShaderCode = """
  uniform mat4 u_Matrix;
  attribute vec4 a_Position;
  
  void main() {
    gl_Position = u_Matrix * a_Position;
  }
"""

def fragmentShaderCode = """
  #ifdef GL_ES
  precision mediump float;
  #endif

  void main() {
    gl_FragColor = vec4(0.8, 0.4, 0.2, 1.0);
  }
"""

def shaderProgram = glob.compileAndLink(vertexShaderCode, fragmentShaderCode)
def aPositionLocation = shaderProgram.getAttribLocation("a_Position")
shaderProgram.use()

def matrix = Matrix4f.translationM(-0.5f, -0.5f, 0.0f)
shaderProgram.getUniform("u_Matrix").setMatrix4fv(matrix.floats)

// vertex data

def BYTES_PER_FLOAT = 4
def POSITION_ELEMENT_COUNT = 2
def POINT_COUNT = 4

def vertices = [
  0.0f, 0.0f,
  0.0f, 0.5f,
  0.5f, 0.5f,
  0.5f, 0.0f,
] as float[]

def vertexData = ByteBuffer
        .allocateDirect(vertices.length * BYTES_PER_FLOAT)
        .order(ByteOrder.nativeOrder())
        .asFloatBuffer()
vertexData.put(vertices)
vertexData.position(0)
gl.glVertexAttribPointer(aPositionLocation, POSITION_ELEMENT_COUNT, gl.GL_FLOAT, false, 0, vertexData)
gl.glEnableVertexAttribArray(aPositionLocation)

// draw triangle

gl.glClear(gl.GL_COLOR_BUFFER_BIT)
gl.glDrawArrays(gl.GL_TRIANGLE_FAN, 0, POINT_COUNT)

效果:

Uniform

uniform相当于Shader程序的全局常量,也可以看做是Shader程序的参数,由Shader程序的使用者传入。我们在Vertex Shader程序的第一行定义了一个mat4(4x4矩阵)类型的uniform,并且在main()方法里将顶点位置和它相乘,这样就可以对顶点做mat4所代表的转换:

  uniform mat4 u_Matrix;
  attribute vec4 a_Position;
  
  void main() {
    gl_Position = u_Matrix * a_Position;
  }

Matrix4f类

为了简化矩阵的使用,我封装了一个4x4矩阵类,叫做Matrix4f。下面的代码定义了一个移动矩阵(将x和y坐标分别向负方向移动0.5),然后将它传入Shader程序:

def matrix = Matrix4f.translationM(-0.5f, -0.5f, 0.0f)
shaderProgram.getUniform("u_Matrix").setMatrix4fv(matrix.floats)

ShaderProgram和ShaderUniform相关代码:

public class ShaderProgram extends GLObject {
    ...
    public ShaderUniform getUniform(String name) {
        return new ShaderUniform(objectId, name);
    }
    ...
}
public class ShaderUniform extends GLWrapper {
    
    private final int programId;
    private final String uniformName;
    private int location;

    public ShaderUniform(int programId, String uniformName) {
        this.programId = programId;
        this.uniformName = uniformName;
    }

    public void setMatrix4fv(float[] v) {
        getGL().glUniformMatrix4fv(getLocation(), 1, false, v, 0);
    }

    private int getLocation() {
        if (location == 0) {
            location = getGL().glGetUniformLocation(programId, uniformName);
        }
        return location;
    }
    
}

移动矩阵

上面的代码所达到的移动效果示例图如下:


缩放矩阵

把前面代码里的移动矩阵改成缩放矩阵

def matrix = Matrix4f.scalingM(1.5f, 1.5f, 0.0f)

效果是矩形变成了原来的1.5倍:


旋转矩阵

最后试试旋转矩阵

def matrix = Matrix4f.rotationM(30, 0.0f, 0.0f, 1.0f)

效果是矩形沿着z轴逆时针旋转了30度:



原文地址:https://www.cnblogs.com/suncoolcat/p/3366088.html