实现一个正常的无分屏滤镜以及多分屏
//顶点着色器
attribute vec4 Position;
attribute vec2 TextureCoords;
varying vec2 TextureCoordsVarying;
void main() {
gl_Position = Position;
TextureCoordsVarying = TextureCoords;
}
片元着色器
precision highp float;
uniform sampler2D Texture;
varying vec2 TextureCoordsVarying;
void main() {
vec4 mask = texture2D(Texture, TextureCoordsVarying);
gl_FragColor = vec4(mask.rgb, 1.0);
}
初始化上下文
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:self.context];
设置顶点数据&顶点缓存区
//开辟顶点数组内存空间
self.vertices = malloc(sizeof(SenceVertex) * 4);
//初始化顶点(0,1,2,3)的顶点坐标以及纹理坐标
self.vertices[0] = (SenceVertex){{-1, 1, 0}, {0, 1}};
self.vertices[1] = (SenceVertex){{-1, -1, 0}, {0, 0}};
self.vertices[2] = (SenceVertex){{1, 1, 0}, {1, 1}};
self.vertices[3] = (SenceVertex){{1, -1, 0}, {1, 0}};
//设置顶点缓冲区
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
GLsizeiptr bufferSizeBytes = sizeof(SenceVertex) * 4;
glBufferData(GL_ARRAY_BUFFER, bufferSizeBytes, self.vertices, GL_STATIC_DRAW);
创建 layer &绑定渲染、帧缓存区
//创建图层(CAEAGLLayer)
CAEAGLLayer *layer = [[CAEAGLLayer alloc] init];
//设置图层frame
layer.frame = CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width);
//设置图层的scale
layer.contentsScale = [[UIScreen mainScreen] scale];
//给view添加layer
[self.view.layer addSublayer:layer];
//渲染缓存区,帧缓存区对象
GLuint renderBuffer;
GLuint frameBuffer;
//获取帧渲染缓存区名称,绑定渲染缓存区以及将渲染缓存区与layer建立连接
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
[self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
//获取帧缓存区名称,绑定帧缓存区以及将渲染缓存区附着到帧缓存区上
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);
图片解压缩&加载纹理
//获取处理的图片路径
NSString *imgPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"xiaochen.png"];
//读取图片
UIImage *img = [UIImage imageWithContentsOfFile:imgPath];
//将 UIImage 转化为 CGImageRef
CGImageRef cgImageRef = [img CGImage];
//获取图片的大小、宽高
GLuint width = (GLuint)CGImageGetWidth(cgImageRef);
GLuint height = (GLuint)CGImageGetHeight(cgImageRef);
//获取图片的rect
CGRect rect = CGRectMake(0, 0, width, height);
//获取图片的颜色空间
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
//获取图片字节数 宽*高*4(RGBA)
void *spriteData = malloc(width*height*4);
//创建上下文
CGContextRef context = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
//将图片翻转过来(图片默认是倒置的)
CGContextTranslateCTM(context, 0, height);
CGContextScaleCTM(context, 1.0f, -1.0f);
CGColorSpaceRelease(colorSpace);
CGContextClearRect(context, rect);
//对图片进行重新绘制,得到一张新的解压缩后的位图
CGContextDrawImage(context, rect, cgImageRef);
//设置纹理属性
//获取纹理ID
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
//载入纹理2D数据
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
//设置纹理属性
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//绑定纹理
glBindTexture(GL_TEXTURE_2D, 0);
//释放context,spritedata
CGContextRelease(context);
free(spriteData);
设置视口
glViewport(0, 0, self.drawableWidth, self.drawableHeight);
编译着色器
//获取 shader 路径
NSString *shaderPath = [[NSBundle mainBundle] pathForResource:name ofType:shaderType == GL_VERTEX_SHADER ? @"vsh" : @"fsh"];
NSString *shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:nil];
//创建 shader->根据 shaderType
GLuint shader = glCreateShader(shaderType);
//获取 shader source
const char *shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = (int)[shaderString length];
glShaderSource(shader, 1, &shaderStringUTF8, &shaderStringLength);
//编译 shader
glCompileShader(shader);
获取着色器程序
//编译顶点/片元着色器
GLuint vertexShader = [self compileShaderWithName:shaderName type:GL_VERTEX_SHADER];
GLuint fragmentShader = [self compileShaderWithName:shaderName type:GL_FRAGMENT_SHADER];
//将顶点/片元附着到 program
GLuint program = glCreateProgram();
glAttachShader(program, vertexShader);
glAttachShader(program, fragmentShader);
//链接 program
glLinkProgram(program);
数据传递、绑定纹理
//获取着色器的 program
GLuint program = [self programWithShaderName:name];
//use program
glUseProgram(program);
//获取 Position、Texture、TextureCoords 的索引位置
GLuint positionSlot = glGetAttribLocation(program, "position");
GLuint textureSlot = glGetUniformLocation(program, "texture");
GLuint textureCoordsSlot = glGetAttribLocation(program, "textureCoords");
//激活纹理、绑定纹理
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, self.textureID);
//纹理 sample
glUniform1i(textureSlot, 0);
//打开positionSlot 属性并且传递数据到positionSlot中(顶点坐标)
glEnableVertexAttribArray(positionSlot);
glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, sizeof(SenceVertex), NULL + offsetof(SenceVertex, positionCoord));
//打开 textureCoordsSlot 属性并传递数据到 textureCoordsSlot(纹理坐标)
glEnableVertexAttribArray(textureCoordsSlot);
glVertexAttribPointer(textureCoordsSlot, 2, GL_FLOAT, GL_FALSE, sizeof(SenceVertex), NULL + offsetof(SenceVertex, textureCoord));
渲染
// 清除画布
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(1, 1, 1, 1);
//使用program
glUseProgram(self.program);
//绑定buffer
glBindBuffer(GL_ARRAY_BUFFER, self.vertexBuffer);
// 重绘
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//渲染到屏幕上
[self.context presentRenderbuffer:GL_RENDERBUFFER];