上一篇文章我們實(shí)現(xiàn)了用GLIKit加載一張圖片,本篇文章,我們稍微深入點(diǎn),實(shí)現(xiàn)一個(gè)立方體貼圖+旋轉(zhuǎn)。

效果
設(shè)置立方體的頂點(diǎn)坐標(biāo)
static GLfloat vertexData[] = {
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f
};
屬性設(shè)置

image.png
配置基本信息
- (void)setupConfig{
// 使用OpenGLES3
// EAGLContext是蘋果iOS平臺(tái)下實(shí)現(xiàn)OpenGLES渲染層
self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
// 判斷是否創(chuàng)建成功
if (!self.context) {
NSLog(@"Create ES context failed");
return;
}
// 設(shè)置當(dāng)前上下文
[EAGLContext setCurrentContext:self.context];
// 獲取GLKView
GLKView *glkView = (GLKView *)self.view; // 因?yàn)楫?dāng)前VC是繼承自`GLKViewController`,所有可以這樣直接獲取
glkView.delegate = self;
// 設(shè)置`GLKView`的`context`
glkView.context = self.context;
// 配置視圖渲染緩沖區(qū)
glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
// 設(shè)置背景顏色
glClearColor(0.5, 0.5, 0.5, 1);
}
配置頂點(diǎn)數(shù)據(jù)
- (void)setupVertexData{
// 每一行的前面3個(gè)是頂點(diǎn)坐標(biāo),后面2個(gè)是紋理坐標(biāo)
// 紋理坐標(biāo)系取值范圍[0,1];原點(diǎn)是左下角(0,0);
// 故而(0,0)是紋理圖像的左下角, 點(diǎn)(1,1)是右上角.
/*
頂點(diǎn)數(shù)組: 開發(fā)者可以選擇設(shè)定函數(shù)指針,在調(diào)用繪制方法的時(shí)候,直接由內(nèi)存?zhèn)魅腠旤c(diǎn)數(shù)據(jù),也就是說這部分?jǐn)?shù)據(jù)之前是存儲(chǔ)在內(nèi)存當(dāng)中的,被稱為頂點(diǎn)數(shù)組
頂點(diǎn)緩存區(qū): 性能更高的做法是,提前分配一塊顯存,將頂點(diǎn)數(shù)據(jù)預(yù)先傳入到顯存當(dāng)中。這部分的顯存,就被稱為頂點(diǎn)緩沖區(qū)
*/
// 開辟頂點(diǎn)緩沖區(qū)
// (1) 創(chuàng)建頂點(diǎn)緩沖區(qū)標(biāo)識(shí)符ID
GLuint bufferID;
glGenBuffers(1, &bufferID); // 開辟1個(gè)頂點(diǎn)緩沖區(qū),所以傳入1
NSLog(@"bufferID:%d", bufferID);
// (2) 綁定頂點(diǎn)緩沖區(qū)
glBindBuffer(GL_ARRAY_BUFFER, bufferID);
// (3) 將頂點(diǎn)數(shù)組的數(shù)據(jù)copy到頂點(diǎn)緩沖區(qū)中(GPU顯存中)
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
// 打開讀取通道
glEnableVertexAttribArray(GLKVertexAttribPosition); // 頂點(diǎn)坐標(biāo)數(shù)據(jù)
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 0);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0); // 紋理坐標(biāo)數(shù)據(jù)
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, (GLfloat *)NULL + 3); // 第一個(gè)紋理坐標(biāo)前面有3個(gè)值,是頂點(diǎn)坐標(biāo)
}
配置紋理
- (void)setupTexture{
// 獲取紋理圖片
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"];
// 初始化紋理
NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft: @(1)}; // 紋理坐標(biāo)原點(diǎn)是左下角,但是圖片顯示原點(diǎn)應(yīng)該是左上角
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
NSLog(@"textureInfo.name: %d", textureInfo.name);
// 使用蘋果`GLKit`提供的`GLKBaseEffect`完成著色器工作(頂點(diǎn)/片元)
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.texture2d0.enabled = GL_TRUE;
self.baseEffect.texture2d0.name = textureInfo.name;
// 設(shè)置透視投影矩陣
CGFloat aspect = fabs(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0);
self.baseEffect.transform.projectionMatrix = projectionMatrix;
}
更新場(chǎng)景
會(huì)多次調(diào)用該方法
- (void)updateScene{
_angle = (_angle + 2);
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -4.0);
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(_angle), 0.3, 0.5, 0.7);
self.baseEffect.transform.modelviewMatrix = modelViewMatrix;
}
實(shí)現(xiàn)GLKViewDelegate代理
正方體有6個(gè)面,需要12個(gè)三角形,每個(gè)三角形由三個(gè)頂點(diǎn)組成,所以這兒是12x3=36個(gè)點(diǎn)
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
// 清除顏色緩沖區(qū)、深度緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// 開啟深度測(cè)試
glEnable(GL_DEPTH_TEST);
[self updateScene];
// 準(zhǔn)備繪制
[self.baseEffect prepareToDraw];
// 開始繪制
// 從第一個(gè)開始,所以是0
glDrawArrays(GL_TRIANGLES, 0, 48); // 正方體有6個(gè)面,需要12個(gè)三角形,每個(gè)三角形由三個(gè)頂點(diǎn)組成,所以這兒是12x3=36個(gè)點(diǎn)
}