- 著色器的渲染過(guò)程
在渲染過(guò)程中,必須存儲(chǔ)2中著色器,分別是頂點(diǎn)著色器、片元著色器。頂點(diǎn)著色器是第一個(gè)著色器、片元著色器是最后一個(gè)。頂點(diǎn)著色器處理頂點(diǎn)、片元著色器處理像素點(diǎn)顏色。
//
// ViewController.m
// OpenGL ES GLKitView
//
// Created by apple on 2019/11/27.
// Copyright ? 2019年 apple. All rights reserved.
//
#import "ViewController.h"
#import <GLKit/GLKit.h>
typedef struct {
GLKVector3 positionCoord; //頂點(diǎn)坐標(biāo)
GLKVector2 textureCoord; //紋理坐標(biāo)
GLKVector3 normal; //法線
}SFVertex;
//頂點(diǎn)數(shù)
static NSInteger const kCoordCount = 36;
@interface ViewController ()<GLKViewDelegate>
@property (nonatomic, strong) GLKView *glkView;
@property (nonatomic, strong) GLKBaseEffect *baseEffect;
@property (nonatomic, assign) SFVertex *vertices;
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) NSInteger angle;
@property (nonatomic, assign) GLuint vertexBuffer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//1設(shè)置背景色
self.view.backgroundColor = UIColor.lightGrayColor;
//2.OpenGL ES 相關(guān)初始化
[self commonInit];
//3.頂點(diǎn)、紋理坐標(biāo)數(shù)據(jù)
[self vertexDataSetup];
//4. 添加CADisplayLink
[self addCADisplayLink];
}
-(void)commonInit{
//1.創(chuàng)建context
EAGLContext *context = [[EAGLContext alloc]initWithAPI:kEAGLRenderingAPIOpenGLES2];
//設(shè)置當(dāng)前context
[EAGLContext setCurrentContext:context];
//2.創(chuàng)建GLKView 并設(shè)置代理
CGRect frame = CGRectMake(0, 100, self.view.frame.size.width, self.view.frame.size.width);
self.glkView = [[GLKView alloc] initWithFrame:frame context:context];
self.glkView.backgroundColor = UIColor.clearColor;
self.glkView.delegate = self;
//3。使用深度緩沖區(qū)
self.glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
//默認(rèn)是(0,1)這里用于翻轉(zhuǎn) z軸 使正方形屏幕朝外
//4.將GLKView 添加self.view 上
[self.view addSubview:self.glkView];
//5.獲取紋理圖片
NSString *imagePath = [[[NSBundle mainBundle]resourcePath] stringByAppendingPathComponent:@"girl.png"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
//6.設(shè)置參數(shù)
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft : @(YES)};
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithCGImage:[image CGImage] options:options error:nil];
//7.使用baseEffect
self.baseEffect = [[GLKBaseEffect alloc]init];
self.baseEffect.texture2d0.name = textureInfo.name;
self.baseEffect.texture2d0.target = textureInfo.target;
}
- (void)vertexDataSetup{
/*
使用每 3 個(gè)點(diǎn)畫一個(gè)三角形的方式,需要12個(gè)三角形,則需要36個(gè)頂點(diǎn)
以下的數(shù)據(jù)用來(lái)繪制(0,0,0)為中心,邊長(zhǎng)為1 的立方體
*/
//8,開辟頂點(diǎn)數(shù)據(jù)空間(數(shù)據(jù)結(jié)構(gòu)SenceVertex大小 * 頂點(diǎn)個(gè)數(shù) kCoordCount)
self.vertices =malloc(sizeof(SFVertex) * kCoordCount);
//前面
self.vertices[0] = (SFVertex){{-0.5,0.5,0.5},{0,1}}; //左上角
self.vertices[1] = (SFVertex){{-0.5,-0.5,0.5},{0,0}};//左下角
self.vertices[2] = (SFVertex){{0.5,0.5,0.5},{1,1}};//右上角
self.vertices[3] = (SFVertex){{-0.5, -0.5, 0.5}, {0, 0}};
self.vertices[4] = (SFVertex){{0.5, 0.5, 0.5}, {1, 1}};
self.vertices[5] = (SFVertex){{0.5, -0.5, 0.5}, {1, 0}};
// 上面
self.vertices[6] = (SFVertex){{0.5, 0.5, 0.5}, {1, 1}};
self.vertices[7] = (SFVertex){{-0.5, 0.5, 0.5}, {0, 1}};
self.vertices[8] = (SFVertex){{0.5, 0.5, -0.5}, {1, 0}};
self.vertices[9] = (SFVertex){{-0.5, 0.5, 0.5}, {0, 1}};
self.vertices[10] = (SFVertex){{0.5, 0.5, -0.5}, {1, 0}};
self.vertices[11] = (SFVertex){{-0.5, 0.5, -0.5}, {0, 0}};
// 下面
self.vertices[12] = (SFVertex){{0.5, -0.5, 0.5}, {1, 1}};
self.vertices[13] = (SFVertex){{-0.5, -0.5, 0.5}, {0, 1}};
self.vertices[14] = (SFVertex){{0.5, -0.5, -0.5}, {1, 0}};
self.vertices[15] = (SFVertex){{-0.5, -0.5, 0.5}, {0, 1}};
self.vertices[16] = (SFVertex){{0.5, -0.5, -0.5}, {1, 0}};
self.vertices[17] = (SFVertex){{-0.5, -0.5, -0.5}, {0, 0}};
// 左面
self.vertices[18] = (SFVertex){{-0.5, 0.5, 0.5}, {1, 1}};
self.vertices[19] = (SFVertex){{-0.5, -0.5, 0.5}, {0, 1}};
self.vertices[20] = (SFVertex){{-0.5, 0.5, -0.5}, {1, 0}};
self.vertices[21] = (SFVertex){{-0.5, -0.5, 0.5}, {0, 1}};
self.vertices[22] = (SFVertex){{-0.5, 0.5, -0.5}, {1, 0}};
self.vertices[23] = (SFVertex){{-0.5, -0.5, -0.5}, {0, 0}};
// 右面
self.vertices[24] = (SFVertex){{0.5, 0.5, 0.5}, {1, 1}};
self.vertices[25] = (SFVertex){{0.5, -0.5, 0.5}, {0, 1}};
self.vertices[26] = (SFVertex){{0.5, 0.5, -0.5}, {1, 0}};
self.vertices[27] = (SFVertex){{0.5, -0.5, 0.5}, {0, 1}};
self.vertices[28] = (SFVertex){{0.5, 0.5, -0.5}, {1, 0}};
self.vertices[29] = (SFVertex){{0.5, -0.5, -0.5}, {0, 0}};
// 后面
self.vertices[30] = (SFVertex){{-0.5, 0.5, -0.5}, {0, 1}};
self.vertices[31] = (SFVertex){{-0.5, -0.5, -0.5}, {0, 0}};
self.vertices[32] = (SFVertex){{0.5, 0.5, -0.5}, {1, 1}};
self.vertices[33] = (SFVertex){{-0.5, -0.5, -0.5}, {0, 0}};
self.vertices[34] = (SFVertex){{0.5, 0.5, -0.5}, {1, 1}};
self.vertices[35] = (SFVertex){{0.5, -0.5, -0.5}, {1, 0}};
//開辟緩存區(qū)
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(SFVertex) * kCoordCount, self.vertices, GL_STATIC_DRAW);
//頂點(diǎn)數(shù)據(jù)
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(SFVertex), offsetof(SFVertex, positionCoord) + NULL);
//紋理數(shù)據(jù)
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(SFVertex), offsetof(SFVertex, textureCoord) + NULL);
}
-(void) addCADisplayLink{
self.angle = 0;
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
[self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}
#pragma mark -- update --
- (void)update{
//1.計(jì)算旋轉(zhuǎn)的度數(shù)
self.angle = (self.angle + 5) % 360;
NSLog(@"self.angle:%ld",(long)self.angle);
//2.修改baseEffect.transfom.modeviewMatrix GLKMathDegreesToRadians 角度轉(zhuǎn)弧度
self.baseEffect.transform.modelviewMatrix = GLKMatrix4MakeRotation(GLKMathDegreesToRadians(self.angle) , 0.3, 1, -0.7);
//3.重新渲染
[self.glkView display];
}
#pragma mark - GLKViewDelegate
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
//1.開啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
//2.清楚顏色緩存區(qū) & 深度緩存區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//3.準(zhǔn)備繪制
[self.baseEffect prepareToDraw];
//4.繪圖
glDrawArrays(GL_TRIANGLES, 0, kCoordCount);
}
-(void)dealloc{
if ([EAGLContext currentContext] == self.glkView.context) {
[EAGLContext setCurrentContext: nil];
}
if (self.vertices) {
free(self.vertices);
self.vertices = nil;
}
if (self.vertexBuffer) {
glDeleteBuffers(1, &_vertexBuffer);
_vertexBuffer = 0;
}
//displayLink 失效
[self.displayLink invalidate];
self.displayLink = nil;
}
@end

紋理加載的具體效果圖
自定義著色器的實(shí)現(xiàn)
- 不使用GLKBaseEffect 使用編譯鏈接自定義的著色器(shader)
- 用簡(jiǎn)單的glsl(Graphics library shader language)圖形庫(kù)著色器語(yǔ)言來(lái)實(shí)現(xiàn)頂點(diǎn)、片元著色器
實(shí)現(xiàn)步驟:
- 創(chuàng)建圖層
- 創(chuàng)建上下文
- 清空緩存區(qū)
- 設(shè)置RenderBuffer
- 設(shè)置FrameBuffer
- 開始繪制
圖片顯示原理
- CPU: 計(jì)算視圖frame,圖片解碼,需要繪制紋理圖片通過(guò)數(shù)據(jù)總線交給GPU
- GPU:紋理混合,頂點(diǎn)變換與計(jì)算,像素點(diǎn)的填充計(jì)算,渲染到幀緩沖區(qū)
- 時(shí)鐘信號(hào):垂直同步信號(hào)V-Sync / 水平同步信號(hào)H-Sync
- iOS設(shè)備雙緩沖機(jī)制:顯示系統(tǒng)通常會(huì)引用兩個(gè)幀緩沖區(qū),雙緩沖
圖片顯示到屏幕上市CPU和GPU的協(xié)作完成
圖片濾鏡實(shí)現(xiàn)思路:
- 前提:使用GLSL顯示普通圖片
思路:
1、 初始化上下文,頂點(diǎn)數(shù)組,頂點(diǎn)數(shù)據(jù),頂點(diǎn)緩存區(qū),CAEAGLLayer,綁定渲染緩存區(qū)、幀緩存區(qū),獲取圖片路徑并將圖片-> 紋理,設(shè)置視口,link默認(rèn)著色器
2、創(chuàng)建CADisplayLink 刷新圖片