GLSL implementation

rendering

Pure color fill

Texture + color blend fill

process

0. Preparation

  • Header file import
#import "GLESMath.h"
#import "GLESUtils.h"
#import <OpenGLES/ES2/gl.h>
Copy the code
  • Extended attributes
@interface HTView() //CAEAGLLayer @property(nonatomic,strong)CAEAGLLayer *htEagLayer; // context @property(nonatomic,strong)EAGLContext *htContext; // Render buffer id @ Property (Nonatomic,assign)GLuint htColorRenderBuffer; // Frame buffer id @ Property (Nonatomic,assign)GLuint htColorFrameBuffer; // Id @property(nonatomic,assign)GLuint htProgram; // Id @property (nonatomic, assign) GLuint htVertices;Copy the code
  • Internal properties
@implementation HTView {float xDegree; Float yDegree; float yDegree; Float zDegree; float zDegree; // Whether to rotate around the x axis BOOL bX; // Whether to rotate around the y axis BOOL bY; // Whether to rotate around the z axis BOOL bZ; // NSTimer* htTimer; }Copy the code

Flow 1-5 Reference:Compile and link custom shader processes

6. Start drawing [self renderLayer]

  • 6.1. Set the screen clearing color and clear the buffer
//1. Set the clear color glClearColor(0.3f, 0.3f, 0.3f, 1.0f); // Clear buffer glClear(GL_COLOR_BUFFER_BIT);Copy the code
  • 6.2. Set the viewport size
GLfloat  scale = [[UIScreen mainScreen] scale];
glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, self.frame.size.width * scale, self.frame.size.height * scale);
Copy the code
  • 6.3. Read vertex shader program and slice shader program
NSString *vertFile = [[NSBundle mainBundle]pathForResource:@"shaderv" ofType:@"vsh"];
NSString *fragFile = [[NSBundle mainBundle]pathForResource:@"shaderf" ofType:@"fsh"];
Copy the code
  • 6.4. Check whether self.htProgram exists and clear its files if it does
If (self.htProgram){glDeleteProgram(self.htProgram); if(self.htProgram){glDeleteProgram(self.htProgram); self.htProgram = 0; }Copy the code
  • 6.5. Load the program into htProgram
self.htProgram = [self loadShader:vertFile withFrag:fragFile];
Copy the code
  • Links to 6.6.
glLinkProgram(self.htProgram);
Copy the code
  • 6.7. Obtain link status
GLint linkStatus; glGetProgramiv(self.htProgram, GL_LINK_STATUS, &linkStatus); if(linkStatus == GL_FALSE){ GLchar message[512]; glGetProgramInfoLog(self.htProgram, sizeof(message), 0, &message[0]); NSString *messageString = [NSString stringWithUTF8String:message]; NSLog(@"Program Link Error:%@",messageString); return; } NSLog(@"Programe Link Success!" );Copy the code
  • 6.8. The use of the program
glUseProgram(self.htProgram);
Copy the code
  • 6.9. Create vertex arrays and index arrays
(x,y,z); (x,y,z) After three (RGB) color values GLfloat attrArr [] = {0.5 f, f 0.5, 0.0 f, f 1.0, 0.0 f, 1.0 f, / / upper left 0 f 0.5, 0.5 f, f 0.0, 1.0 f, 0.0 f, 1.0 f, / / upper 1 f, 0.5-0.5 f, f 0.0, 1.0 f, f 1.0, 1.0, f / / lower right, 2-0.5 f to 0.5 f to 0.0 f to 1.0 f to 1.0 f to 1.0 f, / / lower left 3 f, 0.0 0.0 f, f 1.0, 0.0, f 1.0f, 0.0f, // vertex 4}; / / index array GLuint indices [] = {0, 1, 2, 0, 2, 3, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0,};Copy the code
  • 6.10. Processing vertex data
If (self.htvertices == 0) {glGenBuffers(1, &_htvertices); } glBindBuffer(GL_ARRAY_BUFFER, _htVertices); glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);Copy the code
  • 6.11. Pass the vertex data through htPrograme to position of the vertex shader
//1).glgetAttribLocation, which is used to obtain the entry of vertex attribute. GLuint position = glGetAttribLocation(self.htProgram, "position"); / / 2). Set the appropriate format to read data from a buffer glEnableVertexAttribArray (position); //3). The data is passed from glVertexAttribPointer. glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);Copy the code
  • 6.12. Handle vertex color values
//(1).glgetAttribLocation, which is used to obtain the entry of the vertex attribute. GLuint positionColor = glGetAttribLocation(self.htProgram, "positionColor"); / / (2). Set the appropriate format to read data from a buffer glEnableVertexAttribArray (positionColor); GlVertexAttribPointer (positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);Copy the code
  • 6.13. Find projectionMatrix and in htProgram

modelViewMatrix

GLuint projectionMatrixID = glGetUniformLocation(self.htProgram, "projectionMatrix");
GLuint modelViewMatrixID = glGetUniformLocation(self.htProgram, "modelViewMatrix");
Copy the code
  • 6.14. Setting the projection Matrix
KsMatrixLoadIdentity (&_projectionMatrix); Float width = self.frame.size. Width; float width = self.frame.size. float height = self.frame.size.height; float aspect = width / height; // Get the perspective by the hand (&_projectionmatrix, 30.0, aspect, 5.0f, 20.0f); // Pass the projection matrix to the vertex shader glUniformMatrix4fv(projectionMatrixID, 1, GL_FALSE, (GLfloat*) &_projectionmatrix.m [0][0]);Copy the code
  • 6.15. Set the model view matrix
Ksmatrix4_modelviewmatrix (ksMatrix4_modelViewmatrix); KsMatrixLoadIdentity (&_modelViewMatrix); //(2) ksTranslate(&_modelViewmatrix, 0.0, 0.0, -10.0); //(3) create a 4 * 4 matrix, rotate the matrix, initialize to the element matrix ksMatrix4_rotationMatrix; // Initialize ksMatrixLoadIdentity(&_rotationMatrix); Rotate ksRotate(&_rotationmatrix, xDegree, 1.0, 0.0, 0.0); KsRotate (&_rotationmatrix, yDegree, 0.0, 1.0, 0.0); KsRotate (&_rotationmatrix, zDegree, 0.0, 0.0, 1.0); Ksmultiply (&_modelViewMatrix, &_rotationMatrix, &_modelViewmatrix); GlUniformMatrix4fv (modelViewMatrixID, 1, GL_FALSE, (GLfloat*) &_ModelViewmatrix.m [0][0]);Copy the code
  • 6.16. Enable front and back culling
glEnable(GL_CULL_FACE);
Copy the code
  • 6.17. Use index plotting
glDrawElements(GL_TRIANGLES, sizeof(indices) / sizeof(indices[0]), GL_UNSIGNED_INT, indices);
Copy the code
  • 6.18. Submit rendering to local window system display
[self.htContext presentRenderbuffer:GL_RENDERBUFFER];
Copy the code
  • 6.19 shaderv VSH

attribute vec4 position;
attribute vec4 positionColor;

uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

varying lowp vec4 varyColor;

void main()
{
    varyColor = positionColor;

    vec4 vPos;

        //4*4 * 4*4 * 4*1
    vPos = projectionMatrix * modelViewMatrix * position;

        //ERROR
        //vPos = position * modelViewMatrix  * projectionMatrix ;
    gl_Position = vPos;
}

Copy the code
  • 6.20 shaderf. FSH
varying lowp vec4 varyColor;
void main()
{
    gl_FragColor = varyColor;
}

Copy the code

Click on events and timers to control rotation

#pragma mark - XYClick - (IBAction)XClick:(id)sender {// start timer if (! HtTimer) {htTimer = [NSTimer scheduledTimerWithTimeInterval: 0.05 target: self selector: @ the selector (reDegree) the userInfo: nil repeats:YES]; } // Update X or Y bX; } - (IBAction)YClick (id)sender {// Start timer if (! HtTimer) {htTimer = [NSTimer scheduledTimerWithTimeInterval: 0.05 target: self selector: @ the selector (reDegree) the userInfo: nil repeats:YES]; } // Update X or Y bY =! bY; } - (IBAction)ZClick (id)sender {// Start timer if (! HtTimer) {htTimer = [NSTimer scheduledTimerWithTimeInterval: 0.05 target: self selector: @ the selector (reDegree) the userInfo: nil repeats:YES]; } // Update X or Y bZ; } -(void)reDegree {// If xDegree += bX * 5; // if xDegree += bX * 5; yDegree += bY * 5; zDegree += bZ * 5; // Re-render [self renderLayer]; }Copy the code

Texture + color mix fill logic

To modify shaderf. FSH and shaderv. VSH -> draw function on solid color fill, add set texture coordinate map + load texture

shaderv.vsh


attribute vec4 position;
attribute vec4 positionColor;
attribute vec2 textCoord;



uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;

varying lowp vec4 varyColor;
varying lowp vec2 varyTextCoord;

void main()
{
    varyColor = positionColor;
    varyTextCoord = textCoord;

    vec4 vPos;

        //4*4 * 4*4 * 4*1
    vPos = projectionMatrix * modelViewMatrix * position;

        //ERROR
        //vPos = position * modelViewMatrix  * projectionMatrix ;
    gl_Position = vPos;
}

Copy the code

shaderf.fsh

precision highp float; varying lowp vec4 varyColor; varying lowp vec2 varyTextCoord; uniform sampler2D colorMap; void main () { vec4 weakMask = texture2D(colorMap, varyTextCoord); vec4 mask = varyColor; Float alpha = 0.8; Vec4 tempColor = mask * (1.0-alpha) + weakMask * alpha; gl_FragColor = tempColor; }Copy the code

Drawing process modification

  • 9. Create vertex array and index array (vertex array added texture coordinate map, note the map of the texture map)
F GLfloat attrArr [] = {0.5, 0.5 f to 0.0 f to 1.0 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 f, 1.0 f, / / upper 1 f, 0.5-0.5 f, f 0.0, 1.0 f, f, 1.0 1.0 f, f 1.0, 0.0, f / / lower right, 2-0.5 f to 0.5 f to 0.0 f to 1.0 f to 1.0 f to 1.0 f to 0.0 f to 0.0 f, / / lower left 3 f, 0.0 0.0 f, f, 1.0 0.0 f, f 1.0, 0.0 f, f 0.5, 0.5, f / / vertex 4}; / / index array GLuint indices [] = {0, 1, 2, 0, 2, 3, 0, 4, 1, 1, 4, 2, 2, 4, 3, 3, 4, 0,};Copy the code

11. Pass vertex data to vertex shader position via htPrograme (change the interval between two consecutive reads to 8 when coordinates are read)

//1).glgetAttribLocation, which is used to obtain the entry of vertex attribute. GLuint position = glGetAttribLocation(self.htProgram, "position"); / / 2). Set the appropriate format to read data from a buffer glEnableVertexAttribArray (position); //3). The data is passed from glVertexAttribPointer. glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, NULL);Copy the code
  • 11.2 Processing texture data
//1).glgetattribLocation, which is used to obtain the entry of the vertex attribute. GLuint textCoor = glGetAttribLocation(self.htProgram, "textCoord"); / / 2). Set the appropriate format to read data from a buffer glEnableVertexAttribArray (position); //3). The data is passed from glVertexAttribPointer. glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, NULL);Copy the code
  • 12. Handle vertex color values (change the interval between two consecutive reads to 8 when coordinates are read)
//(1).glgetattribLocation, which is used to obtain the entry of the vertex attribute GLuint positionColor = glGetAttribLocation(self.htProgram, "positionColor"); / / (2). Set the appropriate format to read data from a buffer glEnableVertexAttribArray (textCoor); GlVertexAttribPointer (textCoor, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (float *)NULL + 6);Copy the code
  • 12.2 Loading a Texture and setting the Texture sampler2D
    • Load texture [self setupTexture:@”stone”];
SetupTexture :(NSString *)file {//1. CGImageRef spriteImage = [UIImage imageNamed:file].CGImage; If (! spriteImage){ NSLog(@"Failed to load image: %@",file); exit(1); Size_t width = CGImageGetWidth(spriteImage); size_t height = CGImageGetHeight(spriteImage); GLubyte *spriteData = (GLubyte *)calloc(width*height*4,sizeof(GLubyte)); //4. Create context /* Parameter 1: data, pointing to the memory address of the drawn image to be rendered 2: width,bitmap width, in pixels 3: height,bitmap height, in pixels 4: BitPerComponent, the number of bits per component of pixels in memory, such as 32-bit RGBA, is set to 8. KCGImageAlphaPremultipliedLast colorSpace, bitmap using the color space: RGBA */ CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast); CGRect rect = CGRectMake(0, 0, width, height); CGContextDrawImage(spriteContext, rect, spriteImage); CGContextRelease(spriteContext); //7. Bind the texture to the default texture ID glBindTexture(GL_TEXTURE_2D, 0); GlTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); Parameter 1: texture mode, GL_TEXTURE_1D, GL_TEXTURE_2D, GL_TEXTURE_3D parameter 2: loading level, generally set to 0 parameter 3: texture color value GL_RGBA parameter 4: wide parameter 5: high parameter 6: 7: format 8: type 9: texture data */ float fw = width, fh = height; glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData); //10. Free spriteData free(spriteData); return 0; }Copy the code
* Set the texture sampler2DCopy the code
glUniform1f(glGetAttribLocation(self.htProgram, "colorMap"), 0);
Copy the code
  • Open the hybrid
glEnable(GL_BLEND);
Copy the code

Complete code implementation:

Pure color fill

Texture + color blend fill