OpenGL ES(四) GLKit+立方體貼圖+旋轉(zhuǎn)

上一篇文章我們實(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)
}

Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容