First through a simple case to get familiar with OpenGL ES and GLKit framework.

The effect is shown below:

As you can see, this is a simple image presentation that can be done using UIImageView, but today we are going to use GLKit to render the image (why the image is stretched is explained in this article).

Preparations:

  • Create an iOS project that changes the parent class of ViewController from UIViewController to GLKViewController,
  • Import the GLKit framework header file in viewController.h#import <GLKit/GLKit.h>
  • Import Opengl ES header file from viewController. m:#import <OpenGLES/ES3/gl.h>、#import <OpenGLES/ES3/glext.h>
  • Import a local image

Implementation flowchart:

Specific implementation process

Import header file

#import <OpenGLES/ES3/gl.h>
#import <OpenGLES/ES3/glext.h>
Copy the code

Declare global variables

{
    EAGLContext *context;
    GLKBaseEffect *cEffect;
}
Copy the code

setUpConfig

  1. Initialization context
  2. Setting the current Context
  3. Get the GLKView and set the context
  4. Configure the render cache created by the view
  5. Set Beijing color

Configure the color cache and depth cache through GLKView

DrawableColorFormat: indicates the color cache format

OpenGL ES has a cache that stores the colors that will be displayed on the screen. You can use its properties to set the color format of each pixel in the buffer.

  • GLKViewDrawableColorFormatRGBA8888 = 0, the default. The minimum component of each pixel of the cache (RGBA) uses 8 bits, (so 4 bytes per pixel, 4*8 bits).

  • GLKViewDrawableColorFormatRGB565, if your APP allows a smaller range of color, can set this. Makes your APP consume less resources (memory and processing time)

  • GLKViewDrawableColorFormatSRGBA8888

DrawableDepthFormat: Deep cache format

  • GLKViewDrawableDepthFormatNone = 0 means no depth buffer
  • GLKViewDrawableDepthFormat16,
  • GLKViewDrawableDepthFormat24,

If you want to use this property (usually used in 3 d games), you should choose GLKViewDrawableDepthFormat16 or GLKViewDrawableDepthFormat24. The difference here is using GLKViewDrawableDepthFormat16 will consume fewer resources

Initialization - (void) setUpConfig {/ / context / * EAGLContext OpenGLES render layer is apple's iOS platform. KEAGLRenderingAPIOpenGLES1 = 1, Fixed line kEAGLRenderingAPIOpenGLES2 = 2, kEAGLRenderingAPIOpenGLES3 = 3, */ context =[[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES3]; // Check whether the context is created successfully. context) { NSLog(@"Create ES context fialed"); } / / set the current context You can create multiple context, but only one current context [EAGLContext setCurrentContext: context]; GLKView *view =(GLKView *)self.view; view.context = context; / / configuration view create render buffer the drawableColorFormat = GLKViewDrawableColorFormatRGBA8888; view.drawableDepthFormat = GLKViewDrawableDepthFormat24; // Set the background color glClearColor(1, 0, 0, 1); }Copy the code

setUpVertexData

  1. Set the vertex array (vertex coordinates, vertex textures)
  2. Open up the vertex cache
  3. Open the channel

Create vertex data

Vertex data contains vertex coordinates (x, y, z) and vertex textures (s, T)

// set the vertex array (vertex coordinates, texture coordinates) /* texture coordinates range [0,1]; The origin is the lower left corner (0,0); So (0, 0) is the lower left corner of the texture image, point (1, 1) is the top right corner. * / GLfloat vertexData [] = {0.5, 0.5, 0.0 f, f 1.0, 0.0, f / / lower 0.5, 0.5, 0.0 f, 1.0 f, 1.0 f, / / right - 0.5, 0.5, 0.0 f, f 0.0, 1.0, f / / upper left 0.5, 0.5, 0.0 f, f 1.0, 0.0, f / / right - 0.5, 0.5, 0.0 f, f 0.0, 1.0, f / / upper left - 0.5, 0.5, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left};Copy the code

Creating a vertex buffer

  • Vertex arrays: The developer has the option to set the function pointer to pass the vertex data directly from memory when calling the draw method, that is, the data was previously stored in memory, called vertex arrays

  • Vertex cache: Better performance is to pre-allocate a block of video memory to which vertex data is pre-passed. This part of video memory is called the vertex buffer

Copy the vertex array data to the vertex buffer

// Create vertex buffer identifier ID GLuint bufferID; glGenBuffers(1, &bufferID); //2\. Bind vertex buffer glBindBuffer(GL_ARRAY_BUFFER, bufferID); GL_ARRAY_BUFFER (GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);Copy the code

Open the channel

In iOS, all vertex shader Attribute variables are turned off by default for performance reasons. Meaning that vertex data is not available on the shader side (server side). Even if you already use the glBufferData method, copy the vertex data from memory to the vertex cache (GPU memory).

  • Must by open channel glEnableVertexAttribArray method. Specify access properties to allow vertex shaders to access data copied from CPU to GPU.
  • Note: data on the GPU is visible, that is, to the shader can read data, is determined by whether to enable the corresponding attribute, that’s the function of glEnableVertexAttribArray, allowed to read the vertex shader GPU (server) data.

Upload vertex data to video memory: glVertexAttribPointer

glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
Copy the code

Function: Upload vertex data to video memory (set the appropriate way to read data from buffer)

/ / vertex coordinate data glEnableVertexAttribArray (GLKVertexAttribPosition); /* index specifies the index value of the vertex attribute to be modified, such as size, the number of reads per time. (For example, position is composed of three (x,y,z), color is four (R, G, B,a), and texture is two.) Type, specifying the data type of each component in the array. Available symbolic constants are GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT,GL_UNSIGNED_SHORT, GL_FIXED, and GL_FLOAT, starting with GL_FLOAT. Normalized, specifies whether the fixed point data value should be normalized (GL_TRUE) or converted to a fixed point value (GL_FALSE) stride when accessed, specifies the offset between consecutive vertex attributes. If 0, the vertex attributes are understood to mean that they are tightly packed together. PTR specifies a pointer to the first component of the first vertex property in the array. GlVertexAttribPointer (GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0); / / texture coordinates data glEnableVertexAttribArray (GLKVertexAttribTexCoord0); glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3);Copy the code

setUpTexture

  • Set the texture image path

  • Setting texture Parameters

  • Initialize the cEffect setting property

    NSString *filePath = [[NSBundle mainBundle]pathForResource:@”kunkun” ofType:@” JPG “];

    // The origin of the texture coordinates is the lower left corner, but the image shows that the origin should be the upper left corner. NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil]; GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil]; CEffect = [[GLKBaseEffect alloc]init]; GLKBaseEffect alloc = [GLKBaseEffect alloc]init]; cEffect.texture2d0.enabled = GL_TRUE; cEffect.texture2d0.name = textureInfo.name;Copy the code

    }

GLKViewDelegate

Draw view contents

  • Clear the color cache

  • The course of preparing

  • Began to draw

    The GLKView object makes its OpenGL ES context the current context and binds its framebuffer to the target of the OpenGL ES render command. The delegate method should then draw the contents of the view. * /

    • (void)glkView:(GLKView *)view drawInRect:(CGRect)rect

    { //1. glClear(GL_COLOR_BUFFER_BIT);

    //2. Prepare [cEffect prepareToDraw]; //3. Say, Say, Say, glDrawArrays(Say, GL_TRIANGLES, 0, 6);Copy the code

    }

Picture stretching problem

Call the above method once in viewDidLoad and the executable will see our image above, but we set the coordinates to be square and the image is stretched. Why is this?

The reason is that the aspect ratio of the viewport causes stretching, which can be solved by setting the perspective projection matrix. In addition, due to the problem of the visual range of perspective projection, we need to shift the vertex back by 4.0 units to display an appropriate size on the mobile phone screen

CGFloat aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height); GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective (GLKMathDegreesToRadians (60.0), the aspect, 0.1, 100.0); cEffect.transform.projectionMatrix = projectionMatrix; GLKMatrix4 modelviewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -5.0); cEffect.transform.modelviewMatrix = modelviewMatrix;Copy the code

Let’s see what happens

Demo address attached:

Github complete Demo 02-OpenGL-ES- Load images