OpenGL ES rendering textures

 

Drawing a picture needs to use a texture (Texture) In OpenGL ES rendering texture following steps:

Write shader

Rendering the vertex data required texture shader, texture vertex data and texture. Vertex Shader code is as follows:

attribute vec4 a_Position;
attribute vec2 a_TexCoordinate;
varying vec2 v_TexCoord;


void main()
{
    v_TexCoord = a_TexCoordinate;
    gl_Position = a_Position;
}
  • a_Position: vertex data.

  • a_TexCoordinate: texture vertex data.

  • v_TexCoord: varying type, v_TexCoord a_TexCoordinate value is passed to the Fragment Shader used.

Fragment Shader code is as follows:

precision mediump float;
uniform sampler2D u_Texture;
varying vec2 v_TexCoord;


void main()
{
    gl_FragColor = texture2D(u_Texture, v_TexCoord);
}
  • u_Texture: texture, its type is sampler2D.

  • v_TexCoord: Vertex Shader vertex data transmitted over the texture, OpenGL ES texture2D built-in function is called a sampler, acquires the color value of the specified position on the texture.

Create a program and get a handle parameters

Creating program procedure described in detail in "OpenGL ES for Android build environment", the description herein is not directly packaged using tools, as follows:

private fun createProgram() {
            var vertexCode =
                AssetsUtils.readAssetsTxt(
                    context = context,
                    filePath = "glsl/bitmap_vs.glsl"
                )
            var fragmentCode =
                AssetsUtils.readAssetsTxt(
                    context = context,
                    filePath = "glsl/bitmap_fs.glsl"
                )
            mProgramHandle = GLTools.createAndLinkProgram(vertexCode, fragmentCode)
        }

bitmap_vs.glsl and bitmap_fs.glsl are assets / glsl directory file, representing a vertex shader and texture shader.

AssetsUtils.readAssetsTxt tools to read files in the file asset return a String, as follows:

fun readAssetsTxt(context: Context, filePath: String): String {
        try {
            val inputStream = context.assets.open(filePath)
            val size = inputStream.available()
            val buffer = ByteArray(size)
            inputStream.read(buffer)
            inputStream.close()
            return String(buffer, Charset.forName("utf-8"))
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return ""
    }

program to be created (all of the OpenGL ES related operations should be run in GLThread thread) in GLThread threads, created onSurfaceCreated callback Renderer, the code is as follows:

override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
            createProgram()
        }

Acquires vertex data (a_Position) created after the program, the texture vertex data (a_TexCoordinate), texture (u_Texture) of the handle, as follows:

override fun onSurfaceCreated(p0: GL10?, p1: EGLConfig?) {
            createProgram()
            //获取vPosition索引
            vPositionLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_Position")
            texCoordLoc = GLES20.glGetAttribLocation(mProgramHandle, "a_TexCoordinate")
            textureLoc = GLES20.glGetUniformLocation(mProgramHandle, "u_Texture")
        }

a_Poition, a_TexCoordinate, u_Texture name corresponding to the Shader, mProgramHandle program to handle.

Defined vertex data

Create a full vertex data code is as follows:

      var vertexBuffer = GLTools.array2Buffer(
            floatArrayOf(
                -1.0f, 1.0f, 0.0f,  // top left
                -1.0f, -1.0f, 0.0f,  // bottom left
                1.0f, -1.0f, 0.0f,  // bottom right
                1.0f, 1.0f, 0.0f  // top right
            )
        )

There are four points, each point comprising three float data, representative of x, y, z. 4 positions of the vertices follows:

OpenGL ES any shape is drawn by the drawing which consists of a plurality of triangles, we these four points are divided into two triangles, distribution (V1, V2, V3) and (V1, V3, V4), thus defining a triangle indexed array code is as follows:

var index = shortArrayOf(0, 1, 2, 0, 2, 3)

The index into the array buffer, also making this method of packaging tools inside the code is as follows:

 fun array2Buffer(array: ShortArray): ShortBuffer {
        val bb = ByteBuffer.allocateDirect(array.size * 2)
        bb.order(ByteOrder.nativeOrder())
        var buffer = bb.asShortBuffer()
        buffer.put(array)
        buffer.position(0)
        return buffer
    }

Invocation code is as follows:

val indexBuffer = GLTools.array2Buffer(index)

Definition of texture vertices

FIG texture coordinate system as follows:

The upper left corner is the origin of texture coordinates, bottom-right corner is (1,1), the entire drawing image texture vertex data code is as follows:

var texBuffer = GLTools.array2Buffer(
            floatArrayOf(
                0.0f, 0.0f,
                0.0f, 1.0f,
                1.0f, 1.0f,
                1.0f, 0.0f
            )
        )

Order of vertices texture coordinates defined not just to the vertex data defining the correspondence, the texture or disorder may occur, the sequence corresponding to the following diagram:

If the texture vertices are set as follows:

var texBuffer = GLTools.array2Buffer(
            floatArrayOf(
                0.0f, 1.0f,
                1.0f, 1.0f,
                1.0f, 0.0f,
                0.0f, 0.0f
            )
        )

The texture is rotated counterclockwise by 90 degrees, can be rotated by this method, image texture, but we generally do not use this method to rotate the texture image, this operation may be performed by well-known in OpenGL ES MVP matrix.

Load textures

Sources texture is a picture, the picture turned Bitmap, the following code:

var bitmap =
                BitmapFactory.decodeResource(context.resources, R.drawable.bitmap)

Creating 2D texture id, the code is as follows (this method will be encapsulated in tools):

fun createTextureId(): Int {
        val textures = IntArray(1)
        GLES20.glGenTextures(1, textures, 0)
        glCheck("texture generate")
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0])
        glCheck("texture bind")


        GLES20.glTexParameterf(
            GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MIN_FILTER,
            GLES20.GL_LINEAR.toFloat()
        )
        GLES20.glTexParameterf(
            GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_MAG_FILTER,
            GLES20.GL_LINEAR.toFloat()
        )
        GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_S,
            GLES20.GL_CLAMP_TO_EDGE
        )
        GLES20.glTexParameteri(
            GLES20.GL_TEXTURE_2D,
            GLES20.GL_TEXTURE_WRAP_T,
            GLES20.GL_CLAMP_TO_EDGE
        )


        return textures[0]
    }
  • GLES20.glGenTextures (count, array, offset): generating texture parameters as follows:

  • count: the number of generated texture.

  • array: generating texture id storage array.

  • offset: offset texture id storage array.

  • GLES20.glGenTextures (): generating a texture, textures [0] stored texture id.

  • GLES20.glTexParameteri: texture mapping mode.

After a successful return to create texture texture id, the Bitmap passed to the texture code is as follows:

import android.opengl.GLUtils
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0)

GLUtils is the system tools not write our own tools.

Draw texture

override fun onDrawFrame(p0: GL10?) {
            GLES20.glUseProgram(mProgramHandle)
            //设置顶点数据
            vertexBuffer.position(0)
            GLES20.glEnableVertexAttribArray(vPositionLoc)
            GLES20.glVertexAttribPointer(vPositionLoc, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer)
            //设置纹理顶点数据
            texBuffer.position(0)
            GLES20.glEnableVertexAttribArray(texCoordLoc)
            GLES20.glVertexAttribPointer(texCoordLoc, 2, GLES20.GL_FLOAT, false, 0, texBuffer)
            //设置纹理
            GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
            GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
            GLES20.glUniform1i(textureLoc, 0)


            GLES20.glDrawElements(GLES20.GL_TRIANGLES, index.size, GLES20.GL_UNSIGNED_SHORT,indexBuffer)
        }
  • GLES20.glUseProgram (): enable the current program, mProgramHandle the program is to enable the handle.

  • Texture is provided, as follows:

GLES20.glActiveTexture(GLES20.GL_TEXTURE0)
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId)
GLES20.glUniform1i(textureLoc, 0)
  • GLES20.glActiveTexture: activation texture, GLES20.GL_TEXTURE0 0 indicates active texture may be GLES20.GL_TEXTURE1, GLES20.GL_TEXTURE2 like.

  • GLES20.glBindTexture:将纹理绑定到GL_TEXTURE_2D类型。

  • GLES20.glUniform1i(textureLoc, 0):设置纹理,textureLoc是Fragment Shader中纹理句柄,后面的参数0和GLES20.GL_TEXTURE0是对应的,如果启用GLES20.GL_TEXTURE1,那么使用GLES20.glUniform1i(textureLoc, 1)。

  • GLES20.glDrawElements是真正的绘制,函数结构如下:

public static native void glDrawElements(
        int mode,
        int count,
        int type,
        java.nio.Buffer indices
    );

参数说明如下:

  • mode:绘制方式,GLES20.GL_TRIANGLES表示绘制三角形。

  • count:顶点的个数

  • type:索引(indices)数组中的元素类型,注意不是顶点的类型,值必须是GL_UNSIGNED_BYTE或者GL_UNSIGNED_SHORT。

  • indices:索引数组

到此绘制纹理就完成了。

更多相关阅读:

 

发布了123 篇原创文章 · 获赞 68 · 访问量 30万+

Guess you like

Origin blog.csdn.net/mengks1987/article/details/104082184