美文网首页
[Note] [2020-03-21] Android Open

[Note] [2020-03-21] Android Open

作者: 赶时间的闹钟 | 来源:发表于2020-03-21 12:27 被阅读0次

第一个的 OpenGL Render [Kotlin]

class MyRender : GLSurfaceView.Renderer {
    private val TAG = "MyRender"

    // Step1: 准备绘制顶点数组
    // 坐标数组
    // 0|3
    // 1|2
    private var vertexs = floatArrayOf(
         -0.5f, 0.5f, 0.0f, // 长方形
        // -0.8f, 0.5f, 0.0f, // 可以增加点,并改变 vertexDrawOrder 的绘制顶点数和顺序
        -0.5f, -0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        0.5f, 0.5f, 0.0f
    )
    // 定义一个顶点的维数,即三维,三个坐标轴:x,y,z,也就是:(-0.5f, 0.5f, 0.0f) 计算为一个顶点
    private val COORDINATES_PER_VERTEX = 3
    // 顶点字节步长:一个顶点的字节数(native 层按字节的位置计算),也就是:(-0.5f, 0.5f, 0.0f) 的字节数
    private val vertexStride = COORDINATES_PER_VERTEX * 4
    // 装载 vertexs 的 buffer
    // size: vertexs 的总字节数
    // byte order:java是big endian,native是small endian
    private var vertexBuffer: FloatBuffer? = null

    // Step2: 准备绘制顶点的顺序
    // 顶点顺序:指定链接坐标点的顺序
    private val vertexDrawOrder = shortArrayOf(0, 1, 2, 0, 2, 3) // 绘制两个三角形,合并后看起来想正方形
    // private val vertexDrawOrder = shortArrayOf(0, 1, 2) // 绘制三角形
    // 装载 vertexDrawOrder 的 buffer
    // size: vertexDrawOrder 的总字节数
    // byte order:java是big endian,native是small endian
    private var vertexDrawOrderBuffer: ShortBuffer? = null

    // Step3: 准备 shader 代码
    // 顶点着色程序代码
    private val vertexShaderCode = """
            attribute vec4 vPosition;
            
            void main(){ 
                gl_Position=vPosition;
            }
        """.trimIndent()
    // 片段着色程序代码
    private val fragmentShaderCode = """
            precision mediump float;
            uniform vec4 vColor;
            
            void main() {
                gl_FragColor = vColor;
            }
        """.trimIndent()
    // 保存 shader 编译后的指针
    private var mProgram = 0
    // 顶点句柄
    private var mPositionHandle: Int? = null
    // 颜色句柄
    private var mColorHandle: Int? = null

    // Step4: 准备color
    // argb
    private val color = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        debug(TAG, "onSurfaceCreated:")
        // Step5: 随意设置一个背景
        // set default background color
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f)

        // Step5: 准备顶点buffer
        // vertexs buffer
        val byteBuffer = ByteBuffer.allocateDirect(vertexs.size * 4)
        // byte order = native order
        byteBuffer.order(ByteOrder.nativeOrder())
        // ByteBuffer to FloatBuffer
        vertexBuffer = byteBuffer.asFloatBuffer()
        // put vertexs into FloatBuffer
        vertexBuffer!!.put(vertexs)
        vertexBuffer!!.flip()

        // Step5: 准备片段着色器buffer
        // vertexDrawOrder: buffer
        val byteBuffer1 = ByteBuffer.allocateDirect(vertexDrawOrder.size * 2)
        // byte order = native order
        byteBuffer1.order(ByteOrder.nativeOrder())
        // ByteBuffer to ShortBuffer
        vertexDrawOrderBuffer = byteBuffer1.asShortBuffer()
        // put vertexDrawOrder into buffer
        vertexDrawOrderBuffer!!.put(vertexDrawOrder)
        vertexDrawOrderBuffer!!.flip()

        // Step6: 加载,链接 shader 到 GLES20 program
        // load vertex shader
        val vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode)
        // load fragment shader
        val fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode)
        // 创建一个OpenGLES程序
        mProgram = GLES20.glCreateProgram()
        GLES20.glAttachShader(mProgram, vertexShader)
        GLES20.glAttachShader(mProgram, fragmentShader)
        // 链接 Shader 到程序
        GLES20.glLinkProgram(mProgram)
        // 声明一个数组,用于存放链接程序结果
        val linkStatus = IntArray(1)
        // 获取链接程序结果,将其存入linkStatus的第0个位置
        GLES20.glGetProgramiv(mProgram, GLES20.GL_LINK_STATUS, linkStatus, 0)
        // 链接结果处理
        if (linkStatus[0] != GLES20.GL_TRUE) {
            error("ES20_ERROR", "Could not link program: ")
            error("ES20_ERROR", GLES20.glGetProgramInfoLog(mProgram))
            GLES20.glDeleteProgram(mProgram)
            mProgram = 0
        }
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        debug(TAG, "onSurfaceChanged:")
        //设置视图大小
        GLES20.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        // debug(TAG, "onDrawFrame:")
        // Step7: 每次绘制前清除之前的绘制
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT or GLES20.GL_DEPTH_BUFFER_BIT)

        if (mPositionHandle == null || mColorHandle == null) {
            // Step8: 运行 GLES20 program 进行绘制
            // 将程序加入到OpenGLES环境
            GLES20.glUseProgram(mProgram)
            // 获取顶点着色器的句柄: shader 中的定义变量
            mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition")
            //启用句柄
            GLES20.glEnableVertexAttribArray(mPositionHandle!!)
            //填入数据
            GLES20.glVertexAttribPointer(
                mPositionHandle!!, COORDINATES_PER_VERTEX, GLES20.GL_FLOAT,
                false, vertexStride, vertexBuffer
            )
            //获取顶点着色器的句柄: shader 中的定义变量
            mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor")
            //填入数据
            GLES20.glUniform4fv(mColorHandle!!, 1, color, 0)
        }

        //开始绘制:用三个顶点(vertexCount)画一个三角形(GL_TRIANGLES)
        // GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vertexCount)
        GLES20.glDrawElements(
            GLES20.GL_TRIANGLE_STRIP, vertexDrawOrder.size,
            GLES20.GL_UNSIGNED_SHORT, vertexDrawOrderBuffer
        )

        // 禁用顶点着色器的句柄【disable 后需要重新 enable 才能继续绘制】
        // GLES20.glDisableVertexAttribArray(mPositionHandle!!)
    }

    fun loadShader(type: Int, shaderCode: String): Int { //根据类型创建着色器
        var shader = GLES20.glCreateShader(type)
        //加入代码
        GLES20.glShaderSource(shader, shaderCode)
        //开始编译
        GLES20.glCompileShader(shader)
        //声明一个数组,用于存放编译结果
        val compiled = IntArray(1)
        //获取编译结果,将其存入到compiled的第0个位置中
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0)
        //根据编译结果做处理
        if (compiled[0] == 0) {
            error("ES20_ERROR", "Could not compile shader $type : $shaderCode")
            error("ES20_ERROR", GLES20.glGetShaderInfoLog(shader))
            GLES20.glDeleteShader(shader)
            shader = 0
        }
        return shader
    }
}

相关文章

网友评论

      本文标题:[Note] [2020-03-21] Android Open

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