Basic Principles
1. Multiple rendering, single texture unit
Previously, when we drew the basic graphics in Section 3, we drew a conclusion:
In the example above, in the onDrawFrame, points, lines and triangles are drawn at the same time, that is to say, glDrawArrays are called many times and drawn. We temporarily define glDraw Arrays as a primitive assembly, that is, drawing a layer, then onDraw Frame draws only one frame at a time, and this frame can draw multiple primitives, multiple layers. That is, only one frame is drawn at a time, but one frame can draw multiple layers.
So we can draw multiple textures by calling glDraw Arrays to draw texture vertices many times. In this way, a picture is drawn one by one in order, layer by layer onto the current frame of the picture.
2. Single rendering, multi-texture unit
As mentioned in the previous section, there are 16 texture units in OpenGL that can be operated at the same time, so we can use multiple texture units to draw the same layer to achieve our goal.
code implementation
Single Texture Unit
init { // Loading 2 vertex coordinate data to avoid overlapping of 2 textures mVertexData = BufferUtil.createFloatBuffer(POINT_DATA) mVertexData2 = BufferUtil.createFloatBuffer(POINT_DATA2) mTexVertexBuffer = BufferUtil.createFloatBuffer(TEX_VERTEX) } override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) { // Load 2 texture data mTextureBean = TextureHelper.loadTexture(context, R.drawable.pikachu) mTextureBean2 = TextureHelper.loadTexture(context, R.drawable.tuzki) } override fun onDrawFrame(glUnused: GL10) { GLES20.glClear(GL10.GL_COLOR_BUFFER_BIT) drawPikachu() drawTuzki() } private fun drawPikachu() { mVertexData.position(0) GLES20.glVertexAttribPointer(mAPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, 0, mVertexData) GLES20.glEnableVertexAttribArray(mAPositionLocation) // Set the current active texture unit to texture unit 0 GLES20.glActiveTexture(GLES20.GL_TEXTURE0) // Bind the texture ID to the currently active texture unit GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureBean!!.textureId) GLES20.glUniform1i(uTextureUnitLocation, 0) GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, POINT_DATA.size / POSITION_COMPONENT_COUNT) } private fun drawTuzki() { mVertexData2.position(0) GLES20.glVertexAttribPointer(mAPositionLocation, POSITION_COMPONENT_COUNT, GLES20.GL_FLOAT, false, 0, mVertexData2) GLES20.glEnableVertexAttribArray(mAPositionLocation) // Bind a new texture ID to the activated texture unit GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTextureBean2!!.textureId) GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, POINT_DATA.size / POSITION_COMPONENT_COUNT) }
The code is basically the same as in the previous section. The Shader file remains unchanged. The biggest difference is that when onDrawFrame is used, two textures are bound and two glDrawArrays are invoked to draw different textures.
Multi-texture unit
precision mediump float; varying vec2 v_TexCoord; uniform sampler2D u_TextureUnit1; uniform sampler2D u_TextureUnit2; void main() { vec4 texture1 = texture2D(u_TextureUnit1, v_TexCoord); vec4 texture2 = texture2D(u_TextureUnit2, v_TexCoord); if (texture1.a != 0.0) { gl_FragColor = texture1; } else { gl_FragColor = texture2; } }
By setting Fragment in the above way, the superposition effect of texture 1 and texture 2 can be controlled.
Next, we will explain how to bind the relevant information of multiple texture units.
private fun drawPikachu() { GLES20.glActiveTexture(GLES20.GL_TEXTURE0) GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, pikachuBean!!.textureId) GLES20.glUniform1i(textureLocation1, 0) } private fun drawTuzki() { GLES20.glActiveTexture(GLES20.GL_TEXTURE1) GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tuzkiBean!!.textureId) GLES20.glUniform1i(textureLocation2, 1) }
The advantage of this method is that it can control the relationship between multiple textures and make complex effects. The disadvantage is that the vertex coordinates of multiple texture units must be the same.
Multi-texture rendering.png