preface

Last time we looked at drawing The Hello World of OpenGL ES which is a triangle. Now let’s take a look at another foundation of OpenGL ES, texture, and write the simplest demo to draw an image.

texture

For beginners, we can understand texture as an image, we can draw the whole image to the circle, rectangle and other target graphics, can draw part of the image, also can reuse the image drawing, that is, texture ha.

A rectangular diagram

Our goal is to draw a rectangular graph, and any complex graph in OpenGL ES is made up of points, lines, and triangles. Very simple. A rectangle is just two triangles. Ho ho. So easy.

Ok, so we have the six vertices of the rectangle

const GLfloatAre [] = {1, 1, 0.0 f/D / 1, 1, 0.0, f/A/B - 1, 1, 0.0 f, / / A, 1, 1, 0.0 f/D / 1, 1, 0.0 f, / / A - 1, 1, 0.0 f, / / C};Copy the code

Obviously our vertices need to correspond to texture coordinates one by one, as shown below.

Note that the bottom left corner of the texture coordinate system is the vertex of the coordinate system, while the center of the vertex coordinate screen is the vertex

Ok, so we have our data source.

// typedef struct {GLKVector3 positionCoords; GLKVector2 textureCoords; / /} SceneVertex grain; / / rectangular six vertices static const SceneVertex are [] = {{{1, 1, 0.0 f,}, {1.0 f to 0.0 f}}, / / lower {{1, 1, 0.0 f}, {1.0 f to 1.0 f}}, / / right {{1, 1, 0.0 f}, {0.0 f to 1.0 f}}, / / upper left {{1, 1, 0.0 f}, {1.0 f to 0.0 f}}, / / lower {{1, 1, 0.0 f}, {0.0 f to 1.0 f}}, / / upper left {{1, 1, 0.0f},{0.0f,0.0f}, // bottom left};Copy the code

Texturecods are texture locations.

Set the OpenGLES context

GLKView *view = (GLKView *)self.view; view.context = [[EAGLContext alloc]initWithAPI: kEAGLRenderingAPIOpenGLES2]; // Sets the current context [EAGLContext]setCurrentContext:view.context]; self.baseEffect = [[GLKBaseEffect alloc]init]; self.baseEffect.useConstantColor = GL_TRUE; Self. BaseEffect. ConstantColor = GLKVector4Make (1.0 f to 1.0 f to 1.0 f to 1.0 f);Copy the code

That’s the first step.

Set the vertex buffer

- (void)fillVertexArray{ glGenBuffers(1, &vertextBufferID); glBindBuffer(GL_ARRAY_BUFFER, vertextBufferID); GlBufferData (GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(GLKVertexAttribPosition); GlVertexAttribPointer (GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), NULL + offsetof(SceneVertex, positionCoords)); glEnableVertexAttribArray(GLKVertexAttribTexCoord0); / / texture glVertexAttribPointer (GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof (SceneVertex), NULL + offsetof(SceneVertex, textureCoords)); }Copy the code

Here we generate the bound vertex and texture buffer and set the corresponding pointer offset.

To generate the texture

Here we use GLKTextureInfo in GLkit to easily generate image textures.

ImageRef = [[UIImage imageNamed:@"Demo.jpg"] CGImage]; //GLKTextureInfo encapsulates the texture cache, Including whether contains MIP map GLKTextureInfo * textureInfo = [GLKTextureLoader textureWithCGImage: imageRef options: nil error: NULL]; self.baseEffect.texture2d0.name = textureInfo.name; self.baseEffect.texture2d0.target = textureInfo.target;Copy the code

GLKBaseEffect lets us avoid writing shader Language.

Draw & Release

The last step is to draw, which is very simple

- (void)glkView:(glkView *)view drawInRect:(CGRect)rect{// clear background glClearColor(0.0f,0.0f,0.0f,1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); [self.baseEffect prepareToDraw]; glDrawArrays(GL_TRIANGLES, 0, 6); } - (void)dealloc{ GLKView *view = (GLKView *)self.view; [EAGLContextsetCurrentContext:view.context];
    if(0! = vertextBufferID) { glDeleteBuffers(1, &vertextBufferID); vertextBufferID = 0; } [EAGLContextsetCurrentContext:nil];
}

Copy the code

A quick thought: since we’re drawing a static graph this time, we generate the bound vertex cache directly in viewDidLoad, not in the drawInRect method. If you want to make some dynamic changes, you need to refresh the cache data dynamically in the drawInRect method

Let’s look at the final run result

The image appears correctly, but upside down, because of the CoreGraphics coordinate system. When we generate the texture option plus a coordinate transformation is OK.

 NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:imageRef options:options error:NULL];
Copy the code

Quick thought: here we have achieved the simplest texture image drawing, but since the size of the icon itself is stretched in full screen, how can we ensure that the image is drawn to scale on the screen?

Code address: LearnOpenGLESDemo

References: 1. OpenGL ES Application Development Practice Guide: iOS Volume