• 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度:



  • 相关阅读:
    给vs2012轻松换肤
    几种软件常用授权方式总结
    Discuz X2多人斗地主[消耗论坛积分]小体积版本,仅25MB!
    关于Socket 设置 IPAddress.Any 情况下,出现服务器积极拒绝的问题
    以前看过一个压缩过的.exe,运行会播放长达半小时的动画,却只有60KB,个人认为其中的原理
    VisualSvn Server安装和使用
    socket短时间内重连需注意的问题
    PostgreSQL在何处处理 sql查询之十一
    PostgreSQL在何处处理 sql查询之十三
    PostgreSQL在何处处理 sql查询之十四
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3366088.html
Copyright © 2020-2023  润新知