The main purpose of this case is to understand how to index drawing in GLSL

The case codes of this paper have OC and Swift versions. For details, see the link at the end of the paper. OC version is the main version for explanation

Before introducing this case, what is an index plot? A graph with many vertices, such as the pyramid in this case, has 5 faces, consisting of 6 triangles, a total of 18 vertices. However, there are only 5 vertices visible to the naked eye, as shown in the following picture

Index drawing technique is a technique that reuses repeated vertices to draw a graph by referring to the connection between the visible vertices in the graph through index

The overall effect of the case is shown below

The overall flow of the case is shown in figure 1

It mainly consists of three parts

  • Preparation: mainly import tripartite mathematical library and global variable definition
  • Custom shaders: Custom vertex and slice shaders
  • LayoutSubview function: Draw graph
  • Button click event: rotate in different directions according to different buttons

The following three main parts

Custom shaders

Use GLSL language custom vertex, slice shader, the steps are as follows

Vertex shader

  • Because in this case the graph will rotate, involving matrix transformation, we need to define uniform decorationProjection matrixandModel view matrix
  • In main, we need to multiply the vertex data by the matrix, which is also in order, because in OpenGL ES, the vertex data is multiplied by the matrixColumn vectorGive priority to,positionIt’s the column vector, 1, 2, 1, 2, 3, 34 * 1 matrix, and the projection matrix, model view matrix is4 * 4 matrixMatrix multiplication is essentiallyMatrix multiplication cross, need to be satisfiedWhen A x B, the number of columns of A is equal to the number of rows of B, so it needs to beposition X mvpThe order of multiplication is reversedpvm X position
// Attribute vec4 position; // Vertex color attribute vec4 positionColor; // uniform mat4 projectionMatrix; // Uniform MAT4 modelViewMatrix; // The vertex color is used to bridge varying LOWP VEC4 varyColor with the slice shader. Void main(){// Assign the vertex color to the bridge vertex color variable varyColor = positionColor; vec4 vPos; VPos = projectionMatrix * modelViewMatrix * position; // Assign the transformed vertex coordinates to the built-in variable gl_Position = vPos; }Copy the code

Chip shader

  • In the fragment shader, it is simpler to assign the vertex color passed from the vertex shader to the built-in variablegl_FragColor
  • If the vertex color is less than the number of vertices, such as only [red, blue], the rest of the vertex color is interpolated, similar to the gradient color, as shown in the illustration above
  • If you do not want to interpolate, you need to specify the face color, not the vertex color
// The vertex color of the bridge varying lowp VEC4 varyColor; Void main(){// Assign the vertex color to the built-in variable gl_FragColor = varyColor; }Copy the code

layoutSubviews

This part is mainly the preparation work and graph drawing before drawing

  • Initialization: Preparation before drawing
  • Draw: Draw graphs using index plotting techniques

Initialize the

This section is no different from OpenGL ES case 04: GLSL loading images

As shown in the figure, there are 5 steps, which are briefly described here

  • Draw layer: Used to create a carrier for displaying the content
  • Draw context: Used to record state
  • Clear cache: avoid the previous cache, which will affect this drawing
  • Set renderBuffer: The cache used to actually store colors, vertices, and so on
  • Set FrameBuffer: Used to manage renderBuffer

Drawing * *

The drawn flow chart is shown in the figure, which is mainly divided into five parts

  • Initialize the

  • GLSL custom shader loading

  • Setting vertex data

  • Build matrix & pass to vertex shader

  • The index mapping

The code for initializing and customizing shaders can refer to OpenGL ES case 04: GLSL loading pictures, or directly view the source code on Github at the end of the article. The following instructions will only briefly describe the general steps

Initialize the

This part mainly includes the following steps:

  • Set the clear screen color
  • Clearing the cache
  • Set the viewport

GLSL custom shader loading

The loading flow of shaders is shown in figure 1

  • Gets the custom shader file address
  • Check whether the program already exists and delete it if it does
  • Load shader

There are four main steps in loading shaders

  • Compiler shader
  • Create the final program: Shader is attached to program
  • Link program & determine whether the link is successful
  • The use of the program

At this point, the custom shader written in GLSL is loaded.

Setting vertex data

Because graph drawing is using index drawing, so in addition to creating vertex array, also need to create index array, the general process is as follows

  • Set vertex array & index array
    • The vertex array contains a vertex containing six data, the first three bits represent the vertex value (x, y, z), and the last three bits represent the color value (RGB).
    • Every three numbers in the index array represent a triangle, where the data is the identifier of the vertices, indicating that the triangle is composed of these three vertices
F GLfloat attrArr [] = {0.5, 0.5 f to 0.0 f to 1.0 f to 0.0 f to 1.0 f, / / upper left 0 f 0.5, 0.5 f, f 0.0, 1.0 f, f 0.0, 1.0 f, 1-0.5 f / / right, 0.5 f, f 0.0, 1.0 f, f 1.0, 1.0, f / / lower left 2 f, 0.5-0.5 f, f 0.0, 1.0 f, f 1.0, 1.0, f / / lower 3 f, 0.0 0.0 f, f 1.0, 0.0 f, f 1.0, 0.0, f // vertex 4}; / / (2). The index array GLuint indices [] = {0, 3, 2, 0, 1, 3, 0, 2, 4, 0, 4, 1, 2, 3, 4, 1, 4, 3,};Copy the code

The last 3 steps of the code in the previous case OpenGL ES case 04: GLSL loading images also involved, not too much explanation

  • Open a cache to copy vertex data from CPU to GPU
  • Processing vertex coordinate data: Open the Attribute channel and pass vertex coordinates into the vertex shader
  • Processing vertex color data: Open the Attribute channel and pass the vertex color into the vertex shader

The part of building matrix is mainly to build MVP matrix. Since the case graph has rotation operation, it also needs to build rotation matrix

There are four main steps

  • Get the entry of uniform modification projection matrix and model view matrix in vertex shader, so that the corresponding matrix can be passed into vertex shader in the future. The entry acquisition is similar to the attribute entry acquisition, where the name must be exactly the same as that in the shader
GLuint projectionMatrixSlot = glGetUniformLocation(self.myPrograme, "projectionMatrix");
GLuint modelViewMatrixSlot = glGetUniformLocation(self.myPrograme, "modelViewMatrix");

Copy the code
  • Gets the aspect ratio of the screen used to set perspective projections
float width = self.frame.size.width; float height = self.frame.size.height; Float aspect = width/height;Copy the code
  • Creating a projection matrix
    • Define a 4 by 4 projection matrix
    • throughksMatrixLoadIdentityInitialize the projection matrix to the element matrix
    • throughksPerspectiveMethod, set perspective projection
    • throughglUniformMatrix4fvMethod, pass the projection matrix to the Vertex shader

The methods involved in matrix are encapsulated in the tripartite library

KSMatrix4 _projectionMatrix; //(1) Get ksMatrixLoadIdentity(&_projectionMatrix); Parameter 1: matrix parameter 2: Angle of view, degree in units parameter 3: aspect ratio parameter 4: near plane distance parameter 5: The far plane distance */ ksperperspective (&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f); Parameter 1-location: specifies the position of the uniform variable to be changed. Parameter 2-count: specifies the number of matrices to be changed. Parameter 3-transpose: specifies whether to transpose the matrix and take it as the uniform variable value. Must be the GL_FALSE argument 4-value: executes a pointer to count elements, GlUniformMatrix4fv (projectionMatrixSlot, 1, GL_FALSE, (GLfloat*) &_projectionmatrix.m [0][0]);Copy the code
  • Create model attempt matrix
    • Define a 4 by 4 model view matrix
    • Model view throughksMatrixLoadIdentityLoad a matrix of elements
    • I’m going to shift it to the screen, z-10, just to make it easier to see
    • Define a 4 by 4 rotation matrix
    • The rotation matrix goes throughksMatrixLoadIdentityLoad a matrix of elements
    • throughksRotateSet the rotation for x, y, and z respectively
    • Multiply the rotation matrix by the model view matrix to store the result in the model view matrix
    • Pass the MV matrix to the Vertex shader
// Create a 4*4 model view matrix ksMatrix4_modelViewmatrix; KsMatrixLoadIdentity (&_modelViewMatrix); // Shift 10 pixels around the z-axis to the screen for easy viewing //(2) shift, z-axis shift -10 ksTranslate(&_modelViewmatrix, 0.0, 0.0, -10.0); (3) Create a 4 * 4 matrix, rotation matrix ksMatrix4_rotationmatrix; //(4) Initialize ksMatrixLoadIdentity(&_rotationMatrix); // It is possible to rotate around any axis x/y/z. KsRotate (&_rotationmatrix, xDegree, 1, 0, 0); ksRotate(&_rotationMatrix, yDegree, 0, 1, 0); ksRotate(&_rotationMatrix, zDegree, 0, 0, 1); //(6) Multiply the transformation matrices. Multiply the _modelViewMatrix by the _rotationMatrix, Modelview = Rotation x ModelView ksMatrixMultiply(&_modelViewmatrix, &_rotationmatrix, &_modelViewMatrix); /* void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); Parameter list: location: Specifies the position of the UNIFORM variable to change count: Specifies the number of matrices to change. Transpose: Specifies whether to transpose the matrix and take it as the value of the UNIFORM variable. Must be GL_FALSE value: executes a pointer to count elements, GlUniformMatrix4fv (modelViewMatrixSlot, 1, GL_FALSE, (GLfloat*) &_modelViewmatrix.m [0][0]);Copy the code

The index mapping

  • Turn on front and back cullingglEnable(GL_CULL_FACE);
  • throughglDrawElementsFunction, using index plot, method in 3 arguments
    • Mode: The drawing mode to be rendered
    • Count: number of plots, not the number of vertices, but the number of indexes
    • Type: type
    • Indices: index array
Mode pattern Type type
GL_POINTS GL_BYTE
GL_LINES GL_UNSIGNED_BYTE
GL_LINE_LOOP GL_SHORT
GL_LINE_STRIP GL_UNSIGNED_SHORT
GL_TRIANGLES GL_INT
GL_TRIANGLE_STRIP GL_UNSIGNED_INT
GL_TRIANGLE_FAN —-
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);

Copy the code
  • Requires the local window to display the rendered target
[self.myContext presentRenderbuffer:GL_RENDERBUFFER];
Copy the code

Button click event

It is mainly the click event of 3 buttons. The click event can be realized in the following two steps

  • Start timer
  • Check rotation
  • Execute timer method
    • Update the Angle
    • To render

See Github – 11_01_GLSL triangle Transform _OC, 11_01_GLSL triangle Transform _Swift for the complete code

Author: Style_ month links: www.jianshu.com/p/fd2f3b815… The copyright of the book belongs to the author. Commercial reprint please contact the author for authorization, non-commercial reprint please indicate the source.