I. Introduction to GLSL

GLSL stands for OpenGL Shading Language, which is the Language used for Shading programming in OpenGL, short custom programs written by developers

GLSL is executed on the GPU (Graphic Processor Unit) of the graphics card, replacing part of the fixed rendering pipeline, so that different levels in the rendering pipeline have programmability. For example: view conversion, projection conversion and so on. GLSL (GL Shading Language) Shader code is divided into two parts: Vertex Shader, Fragment Shader, and sometimes Geometry Shader. The vertex shader is responsible for running the vertex shader. It can get the current state in OpenGL, which is passed by GLSL built-in variables. GLSL uses C as its basic high-level coloring language, avoiding the complexity of using assembly language or hardware specification language.

Second, GLSL common data types

In the use of GLSL, some vectors, matrices and variables are often used, and the system defines these data types:

  • Vector data type

  • Matrix data type

  • Variables store qualifiers

Third, the use of GLSL

In Xcode, the compiler itself does not support GLSL compilation and linking. So we need to manually create the GLSL file, and manually compile and link the GLSL file to the program.

Creating GLSL files is as simple as creating two empty files in Xcode and changing the suffix. The vertex and slice shader files are created. The usual suffix is VSH/FSH, which can be defined by the developer.

VSH/FSH is just an NSString in OpenGL ES. It is also possible to fill in GLSL code directly in OpenGL ES code, but this is not recommended. And GLSL does not support Chinese and comments, so try not to use comments and Chinese in GLSL files to avoid unnecessary errors.

3.1 GLSL data modification type

There are three types of data modifiers in GLSL:

  • uniform
  • attribute
  • Varying (stated in a later chapter)

Uniform: Mainly used for passing vertex and slice shader variables from app code (using methods such as GlUniform). In the shader file, only variables that use this modifier are not changed.

Attribute: can only be passed to the vertex shader in app code, not directly to the chip shader. They are used to modify vertex data, the left side of a texture, etc.

Varying: The variable is used to transfer data between the vertex and the chip shader. Generally, the Vertex Shader modifies the value of the variable varying, and the Fragment shader uses the value of that variable. Therefore, the declarations of varying variables must be consistent between vertex and Fragment shader.

Use GLSL to load an image

The previous article used GLKit to load an image. Here we use GLSL to load an image.

4.1. VSH and FSH

The VSH vertex shader needs vertex data, texture data, and texture data to be passed to the chip shader:

attribute vec4 position; // Attribute Vec2 textCoordinate; // Texture coordinates varying lowp VEC2 varyTextCoord; Void main() {varyTextCoord = textCoordinate; Gl_Position = position; // Submit the vertex data}Copy the code

Next is the FSH slice shader file:

precision highp float; // Define float precision VARYING LOWp VEC2 varyTextCoord; Uniform sampler2D colorMap; //texture int main() {//texture2D(texture, texture coordinates), return color gl_FragColor = texture2D(colorMap, varyTextCoord); // Submit color values}Copy the code

4.2 GLSL compilation and linking

Compiling and linking are divided into six steps:

  1. Create a vertex shader object and a slice shader object
  2. The source code links to each shader object
  3. Compile the shader object
  4. Create a program object
  5. The compiled shader object links to the program object
  6. Linker object

4.2.1 GLSL-related functions

The following functions are used in the program:


GLuint glCreateShader(GLenum type)

Creates a shader object handle

  • Type: shader type (vertex or slice)
  • Return: Returns the shader object handle

void glDeleteShader(GLuint shader)

Removes a shader object handle

  • Shader: Handle to the shader object that needs to be deleted

void glShaderSource(GLuint shader, GLSize count, const GLChar * string, const GLint * length)

Link the source code to the shader object

  • Shader: Shader object handle
  • Count: Number of shader source strings
  • String: An array pointer to the shader source string that holds the number count
  • Length: pointer to an array of integers holding the size of each shader string and the number of elements count

void glCompileShader(GLuint shader)

Compile the shader object

  • Shader: Shader object to compile

GLuint glCreateProgram()

Creating program objects

  • Return: Returns the handle to the executor object

void glDeleteProgram(GLuint program)

Creating program objects

  • Program: Handle to the deleted program object

Void glAttachShader(GLuint Program, GLuint Shader)

Shaders and program links

  • Program: Handle to a program object
  • Shader: Shader object

void glDetachShader(GLuint program)

disconnect

  • Program: Handle to a program object
  • Shader: Handle to the shader object from which the program is disconnected

void glLinkProgram(GLuint program)

Link to the program

  • Program: Handle to a program object

*void glGetProgramiv (GLuint program,GLenum pname, GLint params)

Check whether the link is successful

  • Program: Handle to a program object
  • Pname: parameter used to obtain information
  • Params: pointer to the location where the query result integer is stored

4.2.2. Compile and link shaders

The custom method reads the VSH/FSH file, attaches the source to the shader, and compiles:

- (void)compileShader:(GLuint *)shader type:(GLenum)type file:(NSString *)file {// read NSString *content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil]; const GLchar * source = (GLchar *)[content UTF8String]; *shader = glCreateShader(type); GlShaderSource (*shader, 1, &source, NULL); / / compile glCompileShader (* shader); }Copy the code

A custom method is used to call the compiler method to compile two shaders, and attach the shader to the program, return program:

// link shaders to applications - (GLuint)loaderShaders:(NSString *)vert withFrag:(NSString *)frag { fragShader; //program GLuint program = glCreateProgram(); [self compileShader: &vershader type:GL_VERTEX_SHADER file:vert]; // Self compileShader: &vershader type:GL_VERTEX_SHADER file:vert]; [self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:frag]; // Attach the compiled shader to the program glAttachShader(program, verShader); glAttachShader(program, fragShader); // Delete shader glDeleteShader(verShader); glDeleteShader(fragShader); return program; }Copy the code

4.2.3 Link program objects

Through the custom method to obtain the program programe after processing, link the program object, and judge whether the link is successful for use.

After processing the texture data, pass the texture data to FSH:

- (void)renderLayer {// omit... NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@" VSH "]; NSBundle mainBundle = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@" VSH "]; NSString *fragFile = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"fsh"]; self.myPrograme = [self loaderShaders:vertFile withFrag:fragFile]; // glLinkProgram(self.myprograme); GLint linkStatus; glGetProgramiv(self.myPrograme, GL_LINK_STATUS, &linkStatus); if (linkStatus == GL_FALSE) { GLchar message[512]; glGetProgramInfoLog(self.myPrograme, sizeof(message), 0, &message[0]); NSString *messageString = [NSString stringWithUTF8String:message]; NSLog(@"Program Link Error: %@", messageString); return; } NSLog(@"Program Link Success!" ); // Reference the program object glUseProgram(self.myprograme); / / to omit... GlUniform1i (glGetUniformLocation(self.myame, "colorMap"), 0); // Draw glDrawArrays(say, GL_TRIANGLES, 0, 6); // Render to screen [self.myContext presentRenderbuffer:GL_RENDERBUFFER]; }Copy the code