這是一篇OpenGlES 系統(tǒng)學(xué)習(xí)教程柱搜,記錄自己的學(xué)習(xí)過(guò)程。
環(huán)境: Xcode10.2.1 + OpenGL ES 3.0
目標(biāo): 幀緩存
代碼已上傳github
舔亭,Tutorial-08-幀緩存,你的star和fork是對(duì)我最好的支持和動(dòng)力。
概述
目前為止我們所有的渲染都是在默認(rèn)的幀緩存善绎,也就是當(dāng)前屏幕緩存。雖然這類(lèi)緩存已經(jīng)能夠滿足我們各種各樣的技術(shù)了诫尽,但是仍然有很多操作需要在不同的緩存之間大量地遷移數(shù)據(jù)禀酱。這就是幀緩存存在的意義。場(chǎng)景:如賽車(chē)的后視鏡牧嫉、王者和吃雞的小地圖等等剂跟。
默認(rèn)幀緩存是唯一可以被圖形服務(wù)器顯示系統(tǒng)所識(shí)別的幀緩存,也就是說(shuō)酣藻,我們?cè)谄聊簧峡吹降闹荒苁沁@個(gè)緩存曹洽。相比較應(yīng)用程序中創(chuàng)建的幀緩存無(wú)法被顯示器所顯示,也就出現(xiàn)了離屏渲染臊恋。
幀緩存
幀緩沖存儲(chǔ)器(Frame Buffer):簡(jiǎn)稱(chēng)幀緩存或顯存衣洁,它是屏幕所顯示畫(huà)面的一個(gè)直接映象,又稱(chēng)為位映射圖(Bit Map)或光柵抖仅。幀緩存的每一存儲(chǔ)單元對(duì)應(yīng)屏幕上的一個(gè)像素坊夫,整個(gè)幀緩存對(duì)應(yīng)一幀圖像。
- 創(chuàng)建一個(gè)幀緩存
void glGenFramebuffers (GLsizei n, GLuint* framebuffers)
- 綁定幀緩存
void glBindFramebuffer (GLenum target, GLuint framebuffer)
- 刪除幀緩存
void glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers)
- 獲取創(chuàng)建緩存狀態(tài)
let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))
if status == GL_FRAMEBUFFER_COMPLETE {
print("fbo complete succeed width \(frameBuffer1Size.width) height \(frameBuffer1Size.height)")
} else if status == GL_FRAMEBUFFER_UNSUPPORTED {
print("fbo unsupported")
} else {
print("Framebuffer Error")
}
幀緩存附件
當(dāng)我們開(kāi)始渲染時(shí)撤卢,可以將渲染結(jié)果保存到以下幾個(gè)地方:
- 創(chuàng)建圖像到顏色緩存环凿,甚至是多個(gè)顏色緩存,前提是你使用了多重渲染目標(biāo)(multiple render targets)
- 將遮擋信息保存到深度緩存
- 將逐像素的渲染掩碼保存到模板緩存
這些緩存類(lèi)型每個(gè)都表示一種幀緩存的附件放吩,換句話說(shuō)智听,就是將對(duì)應(yīng)的圖像緩存(無(wú)論是剛渲染完成的,還是準(zhǔn)備讀取的),直接附加到幀緩存上到推。如下:
附件名稱(chēng) | 描述 |
---|---|
GL_COLOR_ATTACHMENTi | 第i個(gè)顏色緩存考赛。i 的范圍從0(默認(rèn)顏色緩存)到GL_MAX_COLOR_ATTACHMENTS - 1 |
GL_DEPTH_ATTACHMENT | 深度緩存 |
GL_STENCIL_ATTACHMENT | 模板緩存 |
GL_DEPTH_STENCIL_ATTACHMENT | 這是一種特殊的附件類(lèi)型,用于保存壓縮后的深度——模板緩存(此時(shí)需要渲染緩存的像素格式被設(shè)置為GL_DEPTH_STENCIL) |
綁定幀附件
void glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
渲染到紋理貼圖(紋理附件)
當(dāng)我們?yōu)閹彺娼壎ㄒ粋€(gè)渲染紋理是莉测,所有的渲染命令都會(huì)寫(xiě)入到紋理上颜骤,然后我們就可以把它當(dāng)成普通紋理渲染到其他場(chǎng)景。
glGenTextures(1, &fboTextId)
glBindTexture(GLenum(GL_TEXTURE_2D), fboTextId)
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_S), GL_CLAMP_TO_EDGE)
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_WRAP_T), GL_CLAMP_TO_EDGE)
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MAG_FILTER), GL_LINEAR)
glTexParameteri(GLenum(GL_TEXTURE_2D), GLenum(GL_TEXTURE_MIN_FILTER), GL_LINEAR)
// 生成紋理捣卤,數(shù)據(jù)給nil
glTexImage2D(GLenum(GL_TEXTURE_2D), 0, GL_RGBA, GLsizei(frameBuffer1Size.width), GLsizei(frameBuffer1Size.height), 0, GLenum(GL_RGBA), GLenum(GL_UNSIGNED_BYTE), nil)
glBindTexture(GLenum(GL_TEXTURE_2D), 0)
// 生成幀緩存
glGenFramebuffers(1, &frameBuffer1)
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer1)
// 紋理關(guān)聯(lián)到幀緩存顏色附件(渲染成紋理貼圖)
glFramebufferTexture2D(GLenum(GL_FRAMEBUFFER), GLenum(GL_COLOR_ATTACHMENT0), GLenum(GL_TEXTURE_2D), fboTextId, 0)
let status = glCheckFramebufferStatus(GLenum(GL_FRAMEBUFFER))
if status == GL_FRAMEBUFFER_COMPLETE {
print("fbo complete succeed width \(frameBuffer1Size.width) height \(frameBuffer1Size.height)")
} else if status == GL_FRAMEBUFFER_UNSUPPORTED {
print("fbo unsupported")
} else {
print("Framebuffer Error")
}
// 解除綁定
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), 0)
渲染過(guò)程
// 渲染到紋理貼圖
glUseProgram(program1)
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer1)
glClearColor(1.0, 1.0, 1.0, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glViewport(0, 0, GLsizei(frameBuffer1Size.width), GLsizei(frameBuffer1Size.height))
glBindVertexArray(vbo1)
glActiveTexture(GLenum(GL_TEXTURE0))
glBindTexture(GLenum(GL_TEXTURE_2D), textId)
glUniform1i(glGetUniformLocation(program1,"u_Texture"), 0)
glDrawArrays(GLenum(GL_TRIANGLES), 0, 6)
// 渲染到默認(rèn)幀緩存
glUseProgram(program)
glBindFramebuffer(GLenum(GL_FRAMEBUFFER), frameBuffer)
glClearColor(0.0, 1.0, 1.0, 1.0)
glClear(GLbitfield(GL_COLOR_BUFFER_BIT))
glViewport(0, 0, GLsizei(frame.size.width), GLsizei(frame.size.height))
glBindVertexArray(vbo)
glActiveTexture(GLenum(GL_TEXTURE1))
glBindTexture(GLenum(GL_TEXTURE_2D), fboTextId)
glUniform1i(glGetUniformLocation(program1,"u_Texture"), 1)
glDrawArrays(GLenum(GL_TRIANGLES), 0, 6)
presentContex?.presentRenderbuffer(Int(GL_RENDERBUFFER))
注:可以前往demo查看細(xì)節(jié)