片段操作圖

這篇文章將介紹從寫入幀緩沖和讀取幀緩沖的方式。
Buffers(緩沖)
OpenGL ES支持三種緩沖:
OpenGL ES
•• Color buffer顏色緩沖
•• Depth buffer深度緩沖
•• Stencil buffer模板緩沖
創建緩沖區
OpenGL ES 是一個交互式的渲染系統,假設每幀的開始,你希望初始化所有緩沖區中數據的默認值。調用glClear 函數來清除緩沖區內容,參數mask 指定清除的緩沖區。

你可能不要求清除每一個緩沖區,不在同時清除它們。但如果你想同時清除所有的緩沖區,只調用一次glClear 可以獲得更好的性能。



如果你的幀緩沖區中有多個繪制緩沖,你也可以清除指定的緩沖區,如下:

為減少調用函數的次數,你可以同時清除深度和模板緩沖區內容,如下:

使用掩碼來控制寫入緩沖區
一般你可以控制對緩沖區的操作,哪部分可以寫,哪部分不可寫。在顏色緩沖區中,glColorMask 指定顏色緩沖區的組成里那部分可被更新。如果mask 被設為GL_FALSE,這個組成部分不能更新,默認值是GL_TRUE。對於深度同樣



讀取和寫入像素到幀緩沖區


多渲染目標MRTs
MRTs允許應用程序同時渲染多個顏色緩沖區。下面是流程
1.創建幀緩沖對象framebuffer objects,使用
glGenFramebuffers ( 1, &fbo );創建幀緩沖對象
glBindFramebuffer ( GL_FRAMEBUFFER, fbo );綁定為當前使用的幀緩沖對象。
2.創建紋理對象
glGenTextures(4,textureId);創建
glBindTexture ( GL_TEXTURE_2D, textureId );綁定
glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA,
textureWidth, textureHeight,
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
// Set the filtering mode
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST );
glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
GL_NEAREST );
3.幀緩沖對象綁定相關的紋理。
glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
textureId, 0 );
4.指定渲染的附加顏色
glDrawBuffers(GLsizei n, const GLenum* bufs)

例如你可以使用4種顏色輸出建立一個FBO對象
const GLenum attachments[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; glDrawBuffers ( 4, attachments );
通過GL_MAX_COLOR_ATTACHMENTS你可以查詢支持最多的顏色數,支持最小的數目是4.
5.聲明和使用着色器的輸出
layout(location = 0) out vec4 fragData0; layout(location = 1) out vec4 fragData1; layout(location = 2) out vec4 fragData2; layout(location = 3) out vec4 fragData3;
完整代碼
int InitFBO ( ESContext *esContext ) { UserData *userData = esContext->userData; int i; GLint defaultFramebuffer = 0; const GLenum attachments[4] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3 }; glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer ); // Setup fbo glGenFramebuffers ( 1, &userData->fbo ); glBindFramebuffer ( GL_FRAMEBUFFER, userData->fbo ); // Setup four output buffers and attach to fbo userData->textureHeight = userData->textureWidth = 400; glGenTextures ( 4, &userData->colorTexId[0] ); for (i = 0; i < 4; ++i) { glBindTexture ( GL_TEXTURE_2D, userData->colorTexId[i] ); glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGBA, userData->textureWidth, userData->textureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL ); // Set the filtering mode glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); glFramebufferTexture2D ( GL_DRAW_FRAMEBUFFER, attachments[i], GL_TEXTURE_2D, userData->colorTexId[i], 0 ); } glDrawBuffers ( 4, attachments ); if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ) { return FALSE; } // Restore the original framebuffer glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer ); return TRUE; }
fsh代碼
#version 300 es precision mediump float; layout(location = 0) out vec4 fragData0; layout(location = 1) out vec4 fragData1; layout(location = 2) out vec4 fragData2; layout(location = 3) out vec4 fragData3; void main() { // first buffer will contain red color fragData0 = vec4 ( 1, 0, 0, 1 ); // second buffer will contain green color fragData1 = vec4 ( 0, 1, 0, 1 ); // third buffer will contain blue color fragData2 = vec4 ( 0, 0, 1, 1 ); // fourth buffer will contain gray color fragData3 = vec4 ( 0.5, 0.5, 0.5, 1 ); }
