美文网首页
OpenGL es Android 第二课 绘制三角形

OpenGL es Android 第二课 绘制三角形

作者: mrwangyong | 来源:发表于2018-11-12 20:22 被阅读18次

    有了第一篇的基础,现在开始着手绘制一个三角形,
    先总结一下 OpenGL es 绘制的基本流程

    1. 编写 vertex Shader 和 Fragment shader 的代码
    2. 编译 vertex Shader和Fragment shader
    3. 创建 programs 对象,连接两个 shader
    4. onDrawFrame 中,绘制 shader
    

    我们按照上面的步骤一步步的来

    第一步 编写shader

    顶点着色器(vertex shader)
     attribute vec4 vPosition;
     void main() {
         gl_Position = vPosition;
     }
    

    发现比上一篇的的多了一个东西,其实就是多定义了一个成员变量vPosition,其中 attribute表示成员变量,vec4表示类型为齐次坐标,也就是说gl_Position这个变量的内容取自vPosition这个变量,而这个变量在后面会被我们 Java 层赋值

    片元着色器
     uniform vec4 vColor;
     void main() {
         gl_FragColor = vColor;
     }
    

    原理和上面一致,定义变量让外界赋值

    第二步 处理 shader

    这一步在步骤十分固定 样板代码

    1. 设置背景
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f)
    
    1. 编译 链接 处理 shader 源码
    val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                    VERTEX_SHADER)
    val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,FRAGMENT_SHADER)
    //创建一个空的OpenGLES程序
    mProgram = GLES20.glCreateProgram()
    //将顶点着色器加入到程序
    GLES20.glAttachShader(mProgram, vertexShader)
    //将片元着色器加入到程序中
    GLES20.glAttachShader(mProgram, fragmentShader)
    //连接到着色器程序
    GLES20.glLinkProgram(mProgram)
    
    fun loadShader(type: Int, shaderString: String): Int {
            val shader = GLES20.glCreateShader(type)
            GLES20.glShaderSource(shader, shaderString)
            GLES20.glCompileShader(shader)
            return shader
    }
    
    1. 把图形坐标点数据转化成 openGL 可以识别的格式
    //申请底层空间
    val bb = ByteBuffer.allocateDirect(triangleCoords.size * 4)
    //数据硬件对齐
    bb.order(ByteOrder.nativeOrder())
    //将坐标数据转换为FloatBuffer,用以传入给OpenGL ES程序
    vertexBuffer = bb.asFloatBuffer()
    vertexBuffer.put(triangleCoords)
    vertexBuffer.position(0)
    
    1. 最后 绘制三角形

    设置 shader

    GLES20.glUseProgram(mProgram)
    

    更改 Vertex Shader的 里面 vPosition 的值,把三角形的顶点数值赋值上去

    //获取顶点着色器的vPosition成员句柄
    val mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition")
    //启用三角形顶点的句柄
    GLES20.glEnableVertexAttribArray(mPositionHandle)
    //准备三角形的坐标数据
    GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
            GLES20.GL_FLOAT, false,
            vertexStride, vertexBuffer)
    

    同理,设置 Fragment shader 里面 vColor 的值

    //获取片元着色器的vColor成员的句柄
    val mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor")
    //设置绘制三角形的颜色
    GLES20.glUniform4fv(mColorHandle, 1, color, 0)
    

    绘制三角形

    //绘制三角形
    GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount)
    

    回收资源 回收顶点数组引用

    //禁止顶点数组的句柄
    GLES20.glDisableVertexAttribArray(mPositionHandle)
    

    第一个参数表示绘制方式,定义如下

    int GL_POINTS       //将传入的顶点坐标作为单独的点绘制
    int GL_LINES        //将传入的坐标作为单独线条绘制,ABCDEFG六个顶点,绘制AB、CD、EF三条线
    int GL_LINE_STRIP   //将传入的顶点作为折线绘制,ABCD四个顶点,绘制AB、BC、CD三条线
    int GL_LINE_LOOP    //将传入的顶点作为闭合折线绘制,ABCD四个顶点,绘制AB、BC、CD、DA四条线。
    int GL_TRIANGLES    //将传入的顶点作为单独的三角形绘制,ABCDEF绘制ABC,DEF两个三角形
    int GL_TRIANGLE_FAN    //将传入的顶点作为扇面绘制,ABCDEF绘制ABC、ACD、ADE、AEF四个三角形
    int GL_TRIANGLE_STRIP   //将传入的顶点作为三角条带绘制,ABCDEF绘制ABC,BCD,CDE,DEF四个三角形
    

    5.贴上完整代码

    open class Triangle : Shape() {
        private val VERTEX_SHADER =
                "attribute vec4 vPosition;\n" +
                        " void main() {\n" +
                        "     gl_Position = vPosition;\n" +
                        " }"
    
    
        //gl_FragColor是fragment shader的内置变量,用于指定当前顶点的颜色,
        // 四个分量(r, g, b, a)。这里是想指定为红色,不透明。
        private val FRAGMENT_SHADER =
                "precision mediump float;\n" +
                        " uniform vec4 vColor;\n" +
                        " void main() {\n" +
                        "     gl_FragColor = vColor;\n" +
                        " }"
        private var triangleCoords = floatArrayOf(0.5f, 0.5f, 0.0f, // top
                -0.5f, -0.5f, 0.0f, // bottom left
                0.5f, -0.5f, 0.0f  // bottom right
        )
    
        private var color = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f) //白色
    
        //顶点之间的偏移量
        private val vertexStride = COORDS_PER_VERTEX * 4 // 每个顶点四个字节
        //顶点个数
        private val vertexCount = triangleCoords.size / COORDS_PER_VERTEX
    
        private var mProgram: Int = 0
        private lateinit var  vertexBuffer:FloatBuffer
    
        override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
            //将背景设置为灰色
            GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f)
            //申请底层空间
            val bb = ByteBuffer.allocateDirect(
                    triangleCoords.size * 4)
            //数据硬件对齐
            bb.order(ByteOrder.nativeOrder())
            //将坐标数据转换为FloatBuffer,用以传入给OpenGL ES程序
            vertexBuffer = bb.asFloatBuffer()
            vertexBuffer.put(triangleCoords)
            vertexBuffer.position(0)
    
            val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                    VERTEX_SHADER)
            val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                    FRAGMENT_SHADER)
    
            //创建一个空的OpenGLES程序
            mProgram = GLES20.glCreateProgram()
            //将顶点着色器加入到程序
            GLES20.glAttachShader(mProgram, vertexShader)
            //将片元着色器加入到程序中
            GLES20.glAttachShader(mProgram, fragmentShader)
            //连接到着色器程序
            GLES20.glLinkProgram(mProgram)
        }
    
    
        override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
            GLES20.glViewport(0, 0, width, height)
        }
    
        override fun onDrawFrame(gl: GL10?) {
    
            GLES20.glUseProgram(mProgram)
    
            //获取顶点着色器的vPosition成员句柄
            val mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition")
            //启用三角形顶点的句柄
            GLES20.glEnableVertexAttribArray(mPositionHandle)
            //准备三角形的坐标数据
            GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX,
                    GLES20.GL_FLOAT, false,
                    vertexStride, vertexBuffer)
    
    
            // 这里其实就是取出源码里面的 变量 进行赋值
    
            //获取片元着色器的vColor成员的句柄
            val mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor")
            //设置绘制三角形的颜色
            GLES20.glUniform4fv(mColorHandle, 1, color, 0)
            //绘制三角形
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount)
            //禁止顶点数组的句柄
            GLES20.glDisableVertexAttribArray(mPositionHandle)
        }
    
    }
    

    相关文章

      网友评论

          本文标题:OpenGL es Android 第二课 绘制三角形

          本文链接:https://www.haomeiwen.com/subject/fjqhfqtx.html