Android openGL渲染图片纹理

使用openGL渲染图片纹理,需要特别注意纹理坐标问题:openGL纹理坐标原点在左下角,Android中坐标系原点在左上角,即openGL纹理坐标与Android坐标系在Y轴恰好相反。因此在纹理采样时,按照openGL纹理坐标采样,则Android窗体中显示时会出现上下翻转的问题,未解决此问题,可以在采样阶段将openGL纹理坐标上下翻转,最终采样结束在窗体可以正常显示。(个人理解)

顶点着色器

attribute vec4 a_Position;
attribute vec2 a_TextureCoordinate;
varying vec2 vTextureCoord;
void main() {
    vTextureCoord = a_TextureCoordinate;
    gl_Position =  a_Position;
}

片元着色器

precision mediump float;
uniform sampler2D u_TextureSampler;
varying vec2 vTextureCoord;
void main() {
    gl_FragColor = texture2D(u_TextureSampler, vTextureCoord);
}
private val VERTEX = floatArrayOf(
    -1f, 1f, 0f,
    -1f, -1f, 0f,
    1f, 1f, 0f,
    1f, -1f, 0f,
)

private val TEXTURE = floatArrayOf(
    0f, 0f,
    0f, 1f,
    1f, 0f,
    1f, 1f,
)

private val INDICES = intArrayOf(
    0, 1, 2, 1, 2, 3
)

class OpenGLImageActivity : Activity(), GLSurfaceView.Renderer {

    private var mProgram: Int = GLES30.GL_NONE
    private var mVao: Int = GLES30.GL_NONE
    private var mTextureId: Int = GLES30.GL_NONE

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_opengl_video)

        findViewById(R.id.surfaceView).apply {
            setEGLContextClientVersion(3)
            setRenderer(this@OpenGLImageActivity)
        }
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT or GLES30.GL_DEPTH_BUFFER_BIT)
        mProgram = newProgram(R.raw.vertex_image, R.raw.fragment_image)
        bufferData()
        mTextureId = createTexture()
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClearColor(0f, 0f, 0f, 1f)

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId)
        GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, decodeResource(resources, R.drawable.scs), 0)

        GLES30.glUseProgram(mProgram)
        GLES30.glBindVertexArray(mVao)
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureId)

        GLES30.glDrawElements(GLES30.GL_TRIANGLES, INDICES.size, GLES30.GL_UNSIGNED_INT, 0)
    }

    private fun newProgram(vertex: Int, fragment: Int): Int {
        val vShader = GLES30.glCreateShader(GLES30.GL_VERTEX_SHADER)
        GLES30.glShaderSource(vShader, ResReadUtils.readResource(this, vertex))
        GLES30.glCompileShader(vShader)

        val fShader = GLES30.glCreateShader(GLES30.GL_FRAGMENT_SHADER)
        GLES30.glShaderSource(fShader, ResReadUtils.readResource(this, fragment))
        GLES30.glCompileShader(fShader)

        val program = GLES30.glCreateProgram()
        GLES30.glAttachShader(program, vShader)
        GLES30.glAttachShader(program, fShader)
        GLES30.glLinkProgram(program)
        return program
    }

    private fun bufferData() {
        val aPosition = GLES30.glGetAttribLocation(mProgram, "a_Position")
        val uTexturePosition = GLES30.glGetAttribLocation(mProgram, "a_TextureCoordinate")

        val vao = IntArray(1)
        val vbo = IntArray(2)
        GLES30.glGenVertexArrays(vao.size, vao, 0)
        GLES30.glGenBuffers(vbo.size, vbo, 0)
        GLES30.glBindVertexArray(vao[0])
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, VERTEX.size * 4 + TEXTURE.size * 4, null, GLES30.GL_STATIC_DRAW)
        GLES30.glBufferSubData(GLES30.GL_ARRAY_BUFFER, 0, VERTEX.size * 4, RenderUtils.floatBuffer(VERTEX))
        GLES30.glBufferSubData(GLES30.GL_ARRAY_BUFFER, VERTEX.size * 4, TEXTURE.size * 4, RenderUtils.floatBuffer(TEXTURE))

        GLES30.glEnableVertexAttribArray(aPosition)
        GLES30.glVertexAttribPointer(aPosition, 3, GLES30.GL_FLOAT, false, 3 * 4, 0)
        GLES30.glEnableVertexAttribArray(uTexturePosition)
        GLES30.glVertexAttribPointer(uTexturePosition, 2, GLES30.GL_FLOAT, false, 2 * 4, VERTEX.size * 4)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, vbo[1])
        GLES30.glBufferData(GLES30.GL_ELEMENT_ARRAY_BUFFER, INDICES.size * 4, RenderUtils.intBuffer(INDICES), GLES30.GL_STATIC_DRAW)
        mVao = vao[0]
    }

    private fun createTexture(): Int {
        val textureArray = IntArray(1)
        GLES30.glGenTextures(1, textureArray, 0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureArray[0])
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_S, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_WRAP_T, GLES30.GL_CLAMP_TO_EDGE)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR)
        GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR)
        return textureArray[0]
    }
}

你可能感兴趣的:(工作,学习,android)