Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to paint textures with Android OpenGL ES 2.0

2025-04-01 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article will explain in detail how to draw texture in Android OpenGL ES 2.0. the content of the article is of high quality, so the editor shares it for you as a reference. I hope you will have some understanding of the relevant knowledge after reading this article.

Texture, in OpenGL, can be understood as a picture loaded into the video memory of the graphics card.

Android devices began to support OpenGL ES2.0 in 2.2, which used to be versions of ES1.0 and ES1.1.

To put it simply, OpenGL ES is a functionally tailored version of OpenGL for embedded devices. ES2.0 is not compatible with version 1.x. See the android official documentation for differences and compatibility.

First, android uses openGL to provide a special view as the basis called GLSurfaceView. Our view needs to inherit GLSurfaceView.

Java code

Public class MyGLSurfaceView extends GLSurfaceView {public MyGLSurfaceView (Context context) {super (context); setFocusableInTouchMode (true); / / Tell the surface view we want to create an OpenGL ES 2.0-compatible / / context, and set an OpenGL ES 2.0-compatible renderer. This.setEGLContextClientVersion (2); this.setRenderer (new MyRenderer ());}}

There is nothing special. The rendering operation of android view needs to implement a render interface, and the rendering interface of GLSurfaceView is android.opengl.GLSurfaceView.Renderer. We need a way to implement the interface.

Java code

Public class MyRenderer implements Renderer {public void onDrawFrame (GL10 gl) {} public void onSurfaceChanged (GL10 gl, int width, int height) {} public void onSurfaceCreated (GL10 gl, EGLConfig config) {}}

The interface implements three methods, corresponding to drawing, drawing region change, and region creation. It is important to note that the parameter GL10 gl is the OpenGL ES1.x version of the object. We won't use it here. Another thing is that the call to the onDrawFrame method has a system call and does not need to be called manually. The system will call back constantly at a certain frequency.

Next, let's go to the use of ES2.0 and start with the code:

Java code

Public void onSurfaceCreated (GL10 gl, EGLConfig config) {GLES20.glEnable (GLES20.GL_TEXTURE_2D); / / Active the texture unit 0 GLES20.glActiveTexture (GLES20.GL_TEXTURE0); loadVertex (); initShader (); loadTexture ();}

1. Enable 2D texture

When the paint area is created, we set the 2D-enabled texture and activate the texture unit unit0. What do you mean? it's a long story, but take your time later. To put it simply, remember that OpenGL is state-based, which is the setting and switching of many states. Enabling GL_TEXTURE_2D here is a state on, indicating that OpenGL can use 2D textures.

What is the active texture unit? This has something to do with the hardware. The OpenGL graphics card will divide more than one storage area for storing textures. Here is the use of the area unit 0, multiple texture painting can be turned on more than one, which will be discussed later. Next, three functions are called to load vertices, initialize shaders, and load textures.

2. Load vertices

OpenGL draws graphics by linking them later based on vertices. Why do you want to do this? in fact, it is very powerful. It is a kind of design. For the time being, a vertex can be simply understood as a coordinate point containing position information.

Java code

Private void loadVertex () {/ / float size = 4 this.vertex = ByteBuffer.allocateDirect (quadVertex.length * 4) .order (ByteOrder.nativeOrder ()) .asFloatBuffer (); this.vertex.put (quadVertex) .position (0); / / short size = 2 this.index = ByteBuffer.allocateDirect (quadIndex.length * 2) .order (ByteOrder.nativeOrder ()) .asShortBuffer (); this.index.put (quadIndex) .position (0);} private FloatBuffer vertex; private ShortBuffer index Private float [] quadVertex = new float [] {- 0.5f, 0.5f, 0.0f, / / Position 0, 1.0f, / / TexCoord 0-0.5f,-0.5f, 0.0f, / / Position 1 0,0, / / TexCoord 1 0.5f,-0.5f, 0.0f, / / Position 2 1.0f, 0, / / TexCoord 2 0.5f, 0.5f, 0.0f, / / Position 3 1.0f, 1.0f / / TexCoord 3} Private short [] quadIndex = new short [] {(short) (0), / / Position 0 (short) (1), / / Position 1 (short) (2), / / Position 2 (short) (2), / / Position 2 (short) (3), / / Position 3 (short) (0), / / Position 0}

FloatBuffer,ShortBuffer is an encapsulated object that encapsulates local data structures. Yes, the data in these two objects is not managed by the java virtual machine, which is equivalent to the storage method of the C language. QuadVertex data is a rectangular coordinate, and texture coordinates. One or two sentences are difficult to explain. Here are several classic coordinate systems of openGL, which we will say next time. In a nutshell, the coordinates of the openGL are unitized, all floating-point from 0. 0 to 1. 0, and the center point of the screen is (0. 0). The lower-left corner of the texture coordinates is (0Power0). Here quadVertex is about to spend a rectangle on the screen posted a picture, position0 is the upper left point, after the lower left, lower right, upper right order, texture coordinates are the same.

QuadIndx is the index arrangement of these vertices just now. Here a rectangle has only 4 vertices, each vertex has 3 position coordinates and 2 texture coordinates. In other words, there are five float data on a vertex. As for why the vertices are arranged in this way, next time, it is two triangles that form a rectangle, which is difficult to explain in a few words.

So, this code is to store the location and texture coordinates of the rectangle into local data for later use.

3. Initialize the shader

This shader is a feature of ES2.0, also known as a programmable shader, and is the essence that distinguishes it from ES1.x. Here is only a brief introduction. A programmable shader is a script with a syntax similar to the C language. Scripts are divided into vertex shaders and fragment shaders, which correspond to different rendering processes of openGL.

Vertex shader:

Java code

Uniform mat4 uplink MVPMatrix; attribute vec4 afigposition; attribute vec2 axitexCoord. varying vec2 vtexCoord. void main () {gl_Position = axiom position; v_texCoord = axitexCoord.}

Clip shader:

Java code

Precision lowp float; varying vec2 vaintexCoord. uniform sampler2D ubiquitous samplerTexture.void main () {gl_FragColor = texture2D (u_samplerTexture, v_texCoord);}

Remember here that vertex shaders are executed on vertices; clip shaders are executed on pixels. The rectangle just now has four vertices, and this script is applied to each vertex. In other words, the vertex is position-related information, and the fragment is color texture-related information.

These 2 scripts are all text and need to be compiled, linked, and so on before they can be used by ES2.0. The process is like the compilation and running process of the C language. OpenGL provides functions to do these things.

Java code

Private void initShader () {String vertexSource = Tools.readFromAssets ("VertexShader.glsl"); String fragmentSource = Tools.readFromAssets ("FragmentShader.glsl"); / / Load the shaders and get a linked program program = GLHelper.loadProgram (vertexSource, fragmentSource); / / Get the attribute locations attribPosition = GLES20.glGetAttribLocation (program, "a_position"); attribTexCoord = GLES20.glGetAttribLocation (program, "a_texCoord"); uniformTexture = GLES20.glGetUniformLocation (program, "u_samplerTexture"); GLES20.glUseProgram (program); GLES20.glEnableVertexAttribArray (attribPosition) GLES20.glEnableVertexAttribArray (attribTexCoord); / / Set the sampler to texture unit 0 GLES20.glUniform1i (uniformTexture, 0);}

As you can see, vertices and fragments work together to form a program, which can be used by openGL and is a compiled script stored in video memory. What is the effect of the words GLES20.glGetAttribLocation and GLES20.glGetUniformLocation? Simply put, the java program communicates with the shader script data. Just like passing parameters, so that the script can change the processing flow of openGL pipeline rendering in real time according to the changes of external parameters.

Auxiliary methods for encapsulated load shaders:

Java code

Public static int loadProgram (String vertexSource, String fragmentSource) {/ / Load the vertex shaders int vertexShader = GLHelper.loadShader (GLES20.GL_VERTEX_SHADER, vertexSource); / / Load the fragment shaders int fragmentShader = GLHelper.loadShader (GLES20.GL_FRAGMENT_SHADER, fragmentSource); / / Create the program object int program = GLES20.glCreateProgram (); if (program = = 0) {throw new RuntimeException ("Error create program.");} GLES20.glAttachShader (program, vertexShader); GLES20.glAttachShader (program, fragmentShader); / / Link the program GLES20.glLinkProgram (program) Int [] linked = new int [1]; / / Check the link status GLES20.glGetProgramiv (program, GLES20.GL_LINK_STATUS, linked, 0); if (linked [0] = = 0) {GLES20.glDeleteProgram (program); throw new RuntimeException ("Error linking program:" + GLES20.glGetProgramInfoLog (program));} / / Free up no longer needed shader resources GLES20.glDeleteShader (vertexShader); GLES20.glDeleteShader (fragmentShader); return program;}

Java code

Public static int loadShader (int shaderType, String source) {/ / Create the shader object int shader = GLES20.glCreateShader (shaderType); if (shader = = 0) {throw new RuntimeException ("Error create shader.");} int [] compiled = new int [1]; / Load the shader source GLES20.glShaderSource (shader, source); / / Compile the shader GLES20.glCompileShader (shader); / / Check the compile status GLES20.glGetShaderiv (shader, GLES20.GL_COMPILE_STATUS, compiled, 0) If (compiled [0] = = 0) {GLES20.glDeleteShader (shader); throw new RuntimeException ("Error compile shader:" + GLES20.glGetShaderInfoLog (shader));} return shader;}

Why are many of the operational targets of openGL of type int? Because openGL will only generate or bind addresses in video memory, return id, and later use the id equivalent of a handle to change its internal state.

4. Load texture

Is to upload the data of the picture to the video memory and use it later. Please note that the length and width of the texture image is 2 to the N power, otherwise you may not be able to draw it.

Java code

Static int [] loadTexture (String path) {int [] textureId = new int [1]; / Generate a texture object GLES20.glGenTextures (1, textureId, 0); int [] result = null; if (textureId [0]! = 0) {InputStream is = Tools.readFromAsserts (path); Bitmap bitmap; try {bitmap = BitmapFactory.decodeStream (is);} finally {try {is.close ();} catch (IOException e) {throw new RuntimeException ("Error loading Bitmap.");} result = new int [3] Result [text _ ID] = textureId [0]; / / TEXTURE_ID result [text _ WIDTH] = bitmap.getWidth (); / / TEXTURE_WIDTH result [text _ HEIGHT] = bitmap.getHeight (); / / TEXTURE_HEIGHT / / Bind to the texture in OpenGL GLES20.glBindTexture (GLES20.GL_TEXTURE_2D, textureId [0]); / / Set filtering GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR) GLES20.glTexParameteri (GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); 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); / / Load the bitmap into the bound texture. GLUtils.texImage2D (GLES20.GL_TEXTURE_2D, 0, bitmap, 0); / / Recycle the bitmap, since its data has been loaded into OpenGL. Bitmap.recycle ();} else {throw new RuntimeException ("Error loading texture.");} return result;}

Here the utility class of android is used to convert bitmap directly into the format needed by the openGL texture. The process is that you make a texture id on the graphics card, then upload the texture data according to the id, and save the id later.

You can manipulate the texture. As for some filtering features of the texture, we will talk about it later.

Now it seems that all that is left is to paint and prepare the vertex information and the texture coordinates corresponding to the vertex. Initialize the shader and upload the texture image. Then they have been drawn together.

Java code

Public void onDrawFrame (GL10 gl) {/ / clear screen to black GLES20.glClearColor (0.0f, 0.0f, 0.0f, 0.0f); GLES20.glClear (GLES20.GL_COLOR_BUFFER_BIT); GLES20.glBindTexture (GLES20.GL_TEXTURE_2D, textureId); vertex.position (0); / / load the position / / 3 (x, y, z) / / (2 + 3) * 4 (float size) = 20 GLES20.glVertexAttribPointer (attribPosition, 3, GLES20.GL_FLOAT, false, 20, vertex) Vertex.position (3); / / load the texture coordinate GLES20.glVertexAttribPointer (attribTexCoord, 2, GLES20.GL_FLOAT, false, 20, vertex); GLES20.glDrawElements (GLES20.GL_TRIANGLES, 6, GLES20.GL_UNSIGNED_SHORT, index);}

To keep the code simple, the state-based representation of OpenGL, the bind function is ubiquitous, where bindTexture tells openGL to use the texture image of that id. The next operation is for bind images. To draw, you need to let openGL know how to draw. So here you need to use vertex, a local data container, which contains vertex and texture coordinate information. GLES20.glVertexAttribPointer is to upload vertex data to the graphics card for storage according to openGL's favorite format. The draw method is called when the texture id is used earlier, so when drawing texture coordinates, the uploaded texture image is used.

Every time you need to upload the data to OpenGL, after all, the video memory and memory are not in the same place, and OpenGL uses CS mode. Of course, using technologies such as VBO, data can be cached in video memory to improve operating performance.

About Android OpenGL ES 2.0 how to draw texture to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report