iOS視覺-- (04) OpenGL ES+GLSL實(shí)現(xiàn)金字塔解析

前面一篇我們了解了OpenGL渲染一張圖片的過程。接下來我們要了解的是使用GLSL如何渲染金字塔以及一些簡(jiǎn)單的變換。先看效果圖


效果圖

步驟還是和之前是一樣的。

    1. 日常開發(fā)中OpenGL開發(fā)流程
  • 1.設(shè)置圖層
  • 2.設(shè)置圖形上下文
  • 3.設(shè)置渲染緩沖區(qū)(renderBuffer)
  • 4.設(shè)置幀緩沖區(qū)(frameBuffer)
  • 5.編譯、鏈接著色器(shader)
  • 6.設(shè)置VBO (Vertex Buffer Objects)
  • 7.設(shè)置紋理
  • 8.渲染

前5步除了著色器外和第7步是一致的代碼,就不貼了。

  • 頂點(diǎn)著色器代碼:
attribute vec4 position;
attribute vec4 positionColor; //頂點(diǎn)顏色
attribute vec2 textCoordinate; //紋理坐標(biāo)
uniform mat4 projectionMatrix; //投影矩陣
uniform mat4 modelViewMatrix;  //模型視圖矩陣

varying lowp vec4 varyColor; //頂點(diǎn)顏色
varying lowp vec2 varyTextCoord; //傳遞給片元著色器紋理坐標(biāo)

void main()
{
    varyColor = positionColor;
    varyTextCoord = textCoordinate;
    
    vec4 vPos;
    vPos = projectionMatrix * modelViewMatrix * position;
    gl_Position = vPos;
}
  • 片元著色器代碼:
varying lowp vec4 varyColor; //頂點(diǎn)顏色
varying lowp vec2 varyTextCoord; //頂點(diǎn)著色器傳遞過來的紋理坐標(biāo)

uniform sampler2D colorMap; //紋理

void main()
{
    gl_FragColor = texture2D(colorMap, varyTextCoord) * varyColor;
}
    1. 設(shè)置VBO (Vertex Buffer Objects)

金字塔一共有5個(gè)面:4面+底面(正方形) = 6個(gè)三角形


框架圖
    //6.設(shè)置VBO (Vertex Buffer Objects)
    func setupVBO() {
        //6.設(shè)置頂點(diǎn)、紋理坐標(biāo)
        //頂點(diǎn)數(shù)組
        //前3個(gè)元素,是頂點(diǎn)數(shù)據(jù);中間3個(gè)元素,是頂點(diǎn)顏色值,最后2個(gè)是紋理坐標(biāo)
        let attrArr: [GLfloat] = [
            -0.5, 0.5, 0.0,      0.0, 0.0, 0.5,       0.0, 1.0,//左上
            0.5, 0.5, 0.0,       0.0, 0.5, 0.0,       1.0, 1.0,//右上
            -0.5, -0.5, 0.0,     0.5, 0.0, 1.0,       0.0, 0.0,//左下
            0.5, -0.5, 0.0,      0.0, 0.0, 0.5,       1.0, 0.0,//右下
            0.0, 0.0, 1.0,       1.0, 1.0, 1.0,       0.5, 0.5,//頂點(diǎn)
        ]
        
        //創(chuàng)建繪制索引數(shù)組
        let indices: [GLuint] = [
            0, 3, 2,
            0, 1, 3,
            0, 2, 4,
            0, 4, 1,
            2, 3, 4,
            1, 4, 3,
        ]
        self.indices = indices
        
        //-----處理頂點(diǎn)數(shù)據(jù)--------
        //頂點(diǎn)緩存區(qū)
        var attrBuffer: GLuint = 0
        //申請(qǐng)一個(gè)緩存區(qū)標(biāo)識(shí)符
        glGenBuffers(1, &attrBuffer)
        //將attrBuffer綁定到GL_ARRAY_BUFFER標(biāo)識(shí)符上
        glBindBuffer(GLenum(GL_ARRAY_BUFFER), attrBuffer)
        //把頂點(diǎn)數(shù)據(jù)從CPU拷貝到GPU上
        glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size * attrArr.count, attrArr, GLenum(GL_DYNAMIC_DRAW))
    }
  • 8.渲染繪制

我這么這里是通過索引來繪制的,這里我們繪制的是一個(gè)立體的圖形,所以我們引入了,OpenGL的另一個(gè)知識(shí)點(diǎn),就是投影和變換,都是通過矩陣來實(shí)現(xiàn)的。這里有兩個(gè)重點(diǎn)的知識(shí)點(diǎn)。

    1. 投影有兩種方式:正交投影(2D)、透視投影(3D)
    1. MVP矩陣模型矩陣、觀察矩陣、投影矩陣
      視圖矩陣:將虛擬空間中的所有的物體都做縮放,旋轉(zhuǎn),移動(dòng)的操作。視圖矩陣和 model 矩陣的不同點(diǎn)在于 model 矩陣作用于一個(gè)物體上,視圖矩陣作用于空間中所有的物體上。
      setLookAtM(viewMatrix, 0,
      0f, 0f, 1f, // 眼睛的位置
      0f, 0f, -1f, // 眼睛看的方向
      0f, 1f, 0f // 視線的法線
      ); // 獲得一個(gè)視圖矩陣
      MVP矩陣的推導(dǎo)
    //8.開始繪制
    func renderLayer() {
        //設(shè)置清屏顏色
        glClearColor(0.0, 0.0, 1.0, 1.0)
        //清除屏幕
        glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
        
        //1.設(shè)置視口大小
        let scale = UIScreen.main.scale
        glViewport(GLint(self.frame.origin.x * scale), GLint(self.frame.origin.y * scale), GLsizei(self.frame.size.width * scale), GLsizei(self.frame.size.height * scale))

        //使用著色器
        glUseProgram(myProgram)

#warning("注意??:想要獲取shader里面的變量,這里要記住要在glLinkProgram后面、后面、后面")
        /*
         一個(gè)一致變量在一個(gè)圖元的繪制過程中是不會(huì)改變的,所以其值不能在glBegin/glEnd中設(shè)置。一致變量適合描述在一個(gè)圖元中、一幀中甚至一個(gè)場(chǎng)景中都不變的值。一致變量在頂點(diǎn)shader和片段shader中都是只讀的。首先你需要獲得變量在內(nèi)存中的位置,這個(gè)信息只有在連接程序之后才可獲得。
         */
        
        //--------處理頂點(diǎn)數(shù)據(jù)-------
        //1.將頂點(diǎn)數(shù)據(jù)通過myProgram中的傳遞到頂點(diǎn)著色程序的position
        let position = glGetAttribLocation(myProgram, "position")
        //2.
        glEnableVertexAttribArray(GLuint(position))
        
        //3.設(shè)置讀取方式
        //參數(shù)1:index,頂點(diǎn)數(shù)據(jù)的索引
        //參數(shù)2:size,每個(gè)頂點(diǎn)屬性的組件數(shù)量,1,2,3,或者4.默認(rèn)初始值是4.
        //參數(shù)3:type,數(shù)據(jù)中的每個(gè)組件的類型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默認(rèn)初始值為GL_FLOAT
        //參數(shù)4:normalized,固定點(diǎn)數(shù)據(jù)值是否應(yīng)該歸一化,或者直接轉(zhuǎn)換為固定值。(GL_FALSE)
        //參數(shù)5:stride,連續(xù)頂點(diǎn)屬性之間的偏移量,默認(rèn)為0;
        //參數(shù)6:指定一個(gè)指針,指向數(shù)組中的第一個(gè)頂點(diǎn)屬性的第一個(gè)組件。默認(rèn)為0
        glVertexAttribPointer(GLuint(position), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 8), nil)
        
        //--------處理頂點(diǎn)顏色值-------
        //1.將頂點(diǎn)數(shù)據(jù)通過myProgram中的傳遞到頂點(diǎn)著色程序的positionColor
        let positionColor = glGetAttribLocation(myProgram, "positionColor")
        glEnableVertexAttribArray(GLuint(positionColor))
        glVertexAttribPointer(GLuint(positionColor), 3, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 8), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 3))
        
        
        //----處理紋理數(shù)據(jù)-------
        //1.glGetAttribLocation,用來獲取vertex attribute的入口的.
        //注意:第二參數(shù)字符串必須和shaderv.vsh中的輸入變量:textCoordinate保持一致
        let textCoord = glGetAttribLocation(myProgram, "textCoordinate")
        
        //設(shè)置合適的格式從buffer里面讀取數(shù)據(jù)
        glEnableVertexAttribArray(GLuint(textCoord))
        
        //3.設(shè)置讀取方式
        //參數(shù)1:index,頂點(diǎn)數(shù)據(jù)的索引
        //參數(shù)2:size,每個(gè)頂點(diǎn)屬性的組件數(shù)量,1,2,3,或者4.默認(rèn)初始值是4.
        //參數(shù)3:type,數(shù)據(jù)中的每個(gè)組件的類型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默認(rèn)初始值為GL_FLOAT
        //參數(shù)4:normalized,固定點(diǎn)數(shù)據(jù)值是否應(yīng)該歸一化,或者直接轉(zhuǎn)換為固定值。(GL_FALSE)
        //參數(shù)5:stride,連續(xù)頂點(diǎn)屬性之間的偏移量,默認(rèn)為0;
        //參數(shù)6:指定一個(gè)指針,指向數(shù)組中的第一個(gè)頂點(diǎn)屬性的第一個(gè)組件。默認(rèn)為0
        glVertexAttribPointer(GLuint(textCoord), 2, GLenum(GL_FLOAT), GLboolean(GL_FALSE), GLsizei(MemoryLayout<GLfloat>.size * 8), UnsafeRawPointer(bitPattern: MemoryLayout<GLfloat>.size * 6))
        
        
        //----處理矩陣數(shù)據(jù)-------
        //找到myProgram中的projectionMatrix、modelViewMatrix 2個(gè)矩陣的地址。如果找到則返回地址,否則返回-1,表示沒有找到2個(gè)對(duì)象。
        let projectionMatrixSlot = glGetUniformLocation(myProgram, "projectionMatrix")
        let modelViewMatrixSlot = glGetUniformLocation(myProgram, "modelViewMatrix")
        
        let width = self.frame.size.width
        let height = self.frame.size.height
        
        //創(chuàng)建4 * 4矩陣 獲取單元矩陣
        var _projectionMatrix: GLKMatrix4 = GLKMatrix4Identity
        
        //計(jì)算縱橫比例 = 長(zhǎng)/寬
        let aspect = width / height; //長(zhǎng)寬比
        
        //獲取透視矩陣
        /*
         參數(shù)1:矩陣
         參數(shù)2:視角,度數(shù)為單位
         參數(shù)3:縱橫比
         參數(shù)4:近平面距離
         參數(shù)5:遠(yuǎn)平面距離
         參考PPT
         */
        //源碼實(shí)現(xiàn):在這里面
        //        ksPerspective(<#T##result: UnsafeMutablePointer<KSMatrix4>!##UnsafeMutablePointer<KSMatrix4>!#>, <#T##fovy: Float##Float#>, <#T##aspect: Float##Float#>, <#T##nearZ: Float##Float#>, <#T##farZ: Float##Float#>)
        let perspectiveMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(30), Float(aspect), 5, 20)
        _projectionMatrix = GLKMatrix4Multiply(_projectionMatrix, perspectiveMatrix)
        
        //設(shè)置glsl里面的投影矩陣
        /*
         void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value);
         參數(shù)列表:
         location:指要更改的uniform變量的位置
         count:更改矩陣的個(gè)數(shù)
         transpose:是否要轉(zhuǎn)置矩陣,并將它作為uniform變量的值。必須為GL_FALSE
         value:執(zhí)行count個(gè)元素的指針,用來更新指定uniform變量
         */
//        let count = MemoryLayout.size(ofValue: _projectionMatrix.m) / MemoryLayout.size(ofValue: _projectionMatrix.m.0)
//        withUnsafePointer(to: &_projectionMatrix.m) { (pointer) in
//            pointer.withMemoryRebound(to: GLfloat.self, capacity: count, { (pon) in
//                glUniformMatrix4fv(projectionMatrixSlot, 1, GLboolean(GL_FALSE), pon)
//            })
//        }
        glUniformMatrix4fv(projectionMatrixSlot, 1, GLboolean(GL_FALSE), &_projectionMatrix.m.0)
        
        //開啟剔除操作效果 (三角形逆時(shí)針方向?yàn)檎妫?        glEnable(GLenum(GL_CULL_FACE))
        
        //創(chuàng)建一個(gè)4 * 4 矩陣,模型視圖
        var _modelViewMatrix: GLKMatrix4 = GLKMatrix4Identity
        //平移,z軸平移-10
        _modelViewMatrix = GLKMatrix4Translate(_modelViewMatrix, 0.0, 0.0, -10.0)
        
        //創(chuàng)建一個(gè)4 * 4 矩陣,旋轉(zhuǎn)矩陣
        var _rotationMatrix: GLKMatrix4 = GLKMatrix4Identity
        //旋轉(zhuǎn)
        _rotationMatrix = GLKMatrix4Rotate(_rotationMatrix, GLKMathDegreesToRadians(xDegree), 1.0, 0.0, 0.0)
        _rotationMatrix = GLKMatrix4Rotate(_rotationMatrix, GLKMathDegreesToRadians(yDegree), 0.0, 1.0, 0.0)
        _rotationMatrix = GLKMatrix4Rotate(_rotationMatrix, GLKMathDegreesToRadians(zDegree), 0.0, 0.0, 1.0)
        
        //注意??????:把變換矩陣相乘,注意先后順序 ,將平移矩陣與旋轉(zhuǎn)矩陣相乘,結(jié)合到模型視圖
        _modelViewMatrix = GLKMatrix4Multiply(_modelViewMatrix, _rotationMatrix)
        
        // 加載模型視圖矩陣 modelViewMatrixSlot
        //設(shè)置glsl里面的投影矩陣
        /*
         void glUniformMatrix4fv(GLint location,  GLsizei count,  GLboolean transpose,  const GLfloat *value);
         參數(shù)列表:
         location:指要更改的uniform變量的位置
         count:更改矩陣的個(gè)數(shù)
         transpose:是否要轉(zhuǎn)置矩陣,并將它作為uniform變量的值。必須為GL_FALSE
         value:執(zhí)行count個(gè)元素的指針,用來更新指定uniform變量
         */
//        let count1 = MemoryLayout.size(ofValue: _modelViewMatrix.m) / MemoryLayout.size(ofValue: _modelViewMatrix.m.0)
//        withUnsafePointer(to: &_modelViewMatrix.m) { (pointer) in
//            pointer.withMemoryRebound(to: GLfloat.self, capacity: count1, { (pon) in
//                glUniformMatrix4fv(modelViewMatrixSlot, 1, GLboolean(GL_FALSE), pon)
//            })
//        }
        glUniformMatrix4fv(modelViewMatrixSlot, 1, GLboolean(GL_FALSE), &_modelViewMatrix.m.0)
        
        //使用索引繪圖
        /*
         void glDrawElements(GLenum mode,GLsizei count,GLenum type,const GLvoid * indices);
         參數(shù)列表:
         mode:要呈現(xiàn)的畫圖的模型
                    GL_POINTS
                    GL_LINES
                    GL_LINE_LOOP
                    GL_LINE_STRIP
                    GL_TRIANGLES
                    GL_TRIANGLE_STRIP
                    GL_TRIANGLE_FAN
         count:繪圖個(gè)數(shù)
         type:類型
                 GL_BYTE
                 GL_UNSIGNED_BYTE
                 GL_SHORT
                 GL_UNSIGNED_SHORT
                 GL_INT
                 GL_UNSIGNED_INT
         indices:繪制索引數(shù)組

         注意:??????
         glArrayElements()、glDrawElements()和glDrawRangeElements()能夠?qū)?shù)據(jù)數(shù)組進(jìn)行隨機(jī)存取,
         但是glDrawArrays()只能按順序訪問它們。因?yàn)榍罢咧С猪旤c(diǎn)索引的機(jī)制
         */
        let dotCount = MemoryLayout<GLfloat>.size * indices.count / MemoryLayout<GLfloat>.size
        glDrawElements(GLenum(GL_TRIANGLES), GLsizei(dotCount), GLenum(GL_UNSIGNED_INT), indices)
        
        myContext.presentRenderbuffer(Int(GL_RENDERBUFFER))
        
    }

到此,金字塔就完成了。那么正方體又該如何渲染呢?聰明的同學(xué)已經(jīng)知道了。那就是,修改我們的頂點(diǎn)數(shù)據(jù)。接下來一起走進(jìn)正方體的渲染。
金字塔Demo


    //6.設(shè)置VBO (Vertex Buffer Objects)
    func setupVBO() {
        //------------- 正方體 -------------
        let attrArr: [GLfloat] = [
            // 頂點(diǎn):(x, y, z)      顏色:(r, g, b)      紋理: (s, t)
            // 前面
            -0.5, 0.5, 0.5,        1.0, 1.0, 1.0,       0.0, 0.0, // 前左上 0
            -0.5, -0.5, 0.5,       1.0, 1.0, 1.0,       0.0, 1.0, // 前左下 1
            0.5, -0.5, 0.5,        1.0, 1.0, 1.0,       1.0, 1.0, // 前右下 2
            0.5, 0.5, 0.5,         1.0, 1.0, 1.0,       1.0, 0.0, // 前右上 3
            // 后面
            -0.5, 0.5, -0.5,        1.0, 1.0, 1.0,       0.0, 1.0, // 后左上 4
            -0.5, -0.5, -0.5,       1.0, 1.0, 1.0,       0.0, 0.0, // 后左下 5
            0.5, -0.5, -0.5,        1.0, 1.0, 1.0,       1.0, 0.0, // 后右下 6
            0.5, 0.5, -0.5,         1.0, 1.0, 1.0,       1.0, 1.0, // 后右上 7
            // 左面
            -0.5, 0.5, -0.5,        1.0, 1.0, 1.0,       0.0, 0.0, // 后左上 8
            -0.5, -0.5, -0.5,       1.0, 1.0, 1.0,       0.0, 1.0, // 后左下 9
            -0.5, 0.5, 0.5,        1.0, 1.0, 1.0,       1.0, 0.0, // 前左上 10
            -0.5, -0.5, 0.5,       1.0, 1.0, 1.0,       1.0, 1.0, // 前左下 11
            // 右面
            0.5, 0.5, 0.5,         1.0, 1.0, 1.0,       0.0, 0.0, // 前右上 12
            0.5, -0.5, 0.5,        1.0, 1.0, 1.0,       0.0, 1.0, // 前右下 13
            0.5, -0.5, -0.5,        1.0, 1.0, 1.0,       1.0, 1.0, // 后右下 14
            0.5, 0.5, -0.5,         1.0, 1.0, 1.0,       1.0, 0.0, // 后右上 15
            // 上面
            -0.5, 0.5, -0.5,        1.0, 1.0, 1.0,       0.0, 0.0, // 后左上 16
            -0.5, 0.5, 0.5,        1.0, 1.0, 1.0,       0.0, 1.0, // 前左上 17
            0.5, 0.5, 0.5,         1.0, 1.0, 1.0,       1.0, 1.0, // 前右上 18
            0.5, 0.5, -0.5,         1.0, 1.0, 1.0,       1.0, 0.0, // 后右上 19
            // 下面
            -0.5, -0.5, 0.5,       1.0, 1.0, 1.0,       0.0, 0.0, // 前左下 20
            0.5, -0.5, 0.5,        1.0, 1.0, 1.0,       1.0, 0.0, // 前右下 21
            -0.5, -0.5, -0.5,       1.0, 1.0, 1.0,       0.0, 1.0, // 后左下 22
            0.5, -0.5, -0.5,        1.0, 1.0, 1.0,       1.0, 1.0, // 后右下 23
        ]
        
        //創(chuàng)建繪制索引數(shù)組
        let indices: [GLuint] = [
            // 前面
            0, 1, 2,
            0, 2, 3,
            // 后面
            4, 6, 5,
            4, 7, 6,
            // 左面
            8, 9, 11,
            8, 11, 10,
            // 右面
            12, 13, 14,
            12, 14, 15,
            // 上面
            16, 17, 18,
            16, 18, 19,
            // 下面
            20, 22, 23,
            20, 23, 21,
        ]
        
        
        self.indices = indices
        
        //-----處理頂點(diǎn)數(shù)據(jù)--------
        //頂點(diǎn)緩存區(qū)
        var attrBuffer: GLuint = 0
        //申請(qǐng)一個(gè)緩存區(qū)標(biāo)識(shí)符
        glGenBuffers(1, &attrBuffer)
        //將attrBuffer綁定到GL_ARRAY_BUFFER標(biāo)識(shí)符上
        glBindBuffer(GLenum(GL_ARRAY_BUFFER), attrBuffer)
        //把頂點(diǎn)數(shù)據(jù)從CPU拷貝到GPU上
        glBufferData(GLenum(GL_ARRAY_BUFFER), MemoryLayout<GLfloat>.size * attrArr.count, attrArr, GLenum(GL_DYNAMIC_DRAW))
    }

但是會(huì)出現(xiàn)一種比較奇怪的現(xiàn)象:


奇怪現(xiàn)象1

原因:是開啟了背面剔除

關(guān)閉之后還是有其他的奇怪現(xiàn)象,就是感覺被遮擋,如下圖:


奇怪現(xiàn)象2

被遮擋了,怎么辦?--> 開啟深度測(cè)試。因?yàn)殚_啟深度測(cè)試后, OpenGL 就不會(huì)再去繪制模型被遮擋的部分。

深度測(cè)試
    //4.設(shè)置FrameBuffer
    func setupFrameBuffer() {
        //1.定義一個(gè)緩存區(qū)
        var buffer: GLuint = 0
        //2.申請(qǐng)一個(gè)緩存區(qū)標(biāo)志
        glGenFramebuffers(1, &buffer)
        //3.將標(biāo)識(shí)符綁定到GL_FRAMEBUFFER
        glBindFramebuffer(GLenum(GL_FRAMEBUFFER), buffer)
        //4.
        frameBuffer = buffer
        
        //生成空間之后,則需要將renderbuffer跟framebuffer進(jìn)行綁定,調(diào)用glFramebufferRenderbuffer函數(shù)進(jìn)行綁定,后面的繪制才能起作用
        //5.將_renderBuffer 通過glFramebufferRenderbuffer函數(shù)綁定到GL_COLOR_ATTACHMENT0上。
        glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_RENDERBUFFER), renderBuffer)
        
        #warning("設(shè)置深度測(cè)試")
        // 設(shè)置深度調(diào)試
        var width: GLint = 0
        var height: GLint = 0
        glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_WIDTH), &width)
        glGetRenderbufferParameteriv(GLenum(GL_RENDERBUFFER), GLenum(GL_RENDERBUFFER_HEIGHT), &height)

        var depthRenderBuffer: GLuint = 0
        // 申請(qǐng)深度渲染緩存
        glGenRenderbuffers(1, &depthRenderBuffer)
        glBindRenderbuffer(GLenum(GL_RENDERBUFFER), depthRenderBuffer)
        // 設(shè)置深度測(cè)試的存儲(chǔ)信息
        glRenderbufferStorage(GLenum(GL_RENDERBUFFER), GLenum(GL_DEPTH_COMPONENT16), width, height)

        // 將渲染緩存掛載到GL_DEPTH_ATTACHMENT這個(gè)掛載點(diǎn)上
        glFramebufferRenderbuffer(GLenum(GL_FRAMEBUFFER), GLenum(GL_DEPTH_ATTACHMENT), GLenum(GL_RENDERBUFFER), depthRenderBuffer)
        // GL_RENDERBUFFER綁定的是深度測(cè)試渲染緩存,所以要綁定回色彩渲染緩存
        glBindRenderbuffer(GLenum(GL_RENDERBUFFER), renderBuffer)
        
        //接下來,可以調(diào)用OpenGL ES進(jìn)行繪制處理,最后則需要在EGALContext的OC方法進(jìn)行最終的渲染繪制。這里渲染的color buffer,這個(gè)方法會(huì)將buffer渲染到CALayer上。- (BOOL)presentRenderbuffer:(NSUInteger)target;
    }

申請(qǐng)了深度緩沖區(qū)之后還要開啟,默認(rèn)是關(guān)閉的。所以在渲染的時(shí)候進(jìn)行開啟:

//清除屏幕
glClear(GLbitfield(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT))
// 開啟深度測(cè)試
glEnable(GLenum(GL_DEPTH_TEST))
效果圖

  • 問題是解決了。但是為什么開啟背后剔除還是不行?
    奇怪現(xiàn)象

想到了是背后剔除,那就是可能頂點(diǎn)數(shù)據(jù)有問題。背面的三角形與正面的三角形的頂點(diǎn)順序相反

頂點(diǎn)順序相反

修改背面頂點(diǎn)索引順序:

 // 后面
 4, 6, 5,
 4, 7, 6,

也是可以達(dá)到效果的,而且還開了背面剔除。那么應(yīng)該不需要開啟深度測(cè)試了為什么呢?

我猜想是因?yàn)闆]修改頂點(diǎn)順序之前,如上圖?? 正面:[1, 2, 3],背面:[1,3, 2],OpenGL也以為是正面,但是實(shí)際是相反的。

效果圖

到此正方體渲染就結(jié)束了??赡苡行┩瑢W(xué)會(huì)想到正方體每個(gè)面怎么貼不一樣的圖片呢?那我們下回分解。

?著作權(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ù)。

相關(guān)閱讀更多精彩內(nèi)容

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