平時我們都是渲染到的預設的螢幕緩沖,通過swapbuffer來渲染到螢幕上,相對的我們可以同樣建立一個離屏的幀緩沖來渲染到紋理。
建立一個fbo
glGenFramebuffers(,&frame);
glBindFramebuffer(GL_FRAMEBUFFER,frame);
fbo需要我們為他準備一個至少一個緩沖(顔色、深度或模闆緩沖),我們通常使用的是紋理附件
glGenTextures(,&textureFrame);
glBindTexture(GL_TEXTURE_2D,textureFrame);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, , GL_RGBA, width, width, , GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,textureFrame,);
這裡我們選擇的是顔色緩沖,通過生成一個隻配置設定了控件的紋理對象,并沒有填充資料。
我們同樣可以為fbo添加渲染緩沖附件,這個緩沖是隻寫的,如果需要從緩沖中讀取資料,還是需要使用紋理。我們這裡使用渲染緩沖來作為fbo深度緩沖的附加。
glGenRenderbuffers(,&render);
glBindRenderbuffer(GL_RENDERBUFFER,render);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, width);
glBindFramebuffer(GL_FRAMEBUFFER,frame);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,render);
以上的代碼需要注意,需要和紋理附加的緩沖寬高一緻。
使用fbo繪制到紋理
建立好了fbo之後的繪制流程就比較正常了
- 綁定fbo
- 正常繪制
- 解綁fbo
- 繪制fob綁定的紋理
//綁定生成的fbo
picPreviewTexture->bindFrameBuffer();
glViewport(_backingLeft, _backingTop, _backingWidth, _backingHeight);
//設定一個顔色狀态
glClearColor(, , , );
//使能顔色狀态的值來清屏
glClear(GL_COLOR_BUFFER_BIT);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glUseProgram(program);
static const GLfloat _vertices[] = {-, ,//左上
-, -,//左下
, ,//右上
, -//右下
};
//stride設定為0自動決定步長
//設定定點緩存指針
glVertexAttribPointer(ATTRIBUTE_VERTEX, , GL_FLOAT, GL_FALSE, , _vertices);
glEnableVertexAttribArray(ATTRIBUTE_VERTEX);
//注意位置颠倒
static const GLfloat texCoords[] = {, , , , , , , };
//設定紋理緩存指針,varying變量會被插值傳入片元着色器
glVertexAttribPointer(ATTRIBUTE_TEXCOORD, , GL_FLOAT, , , texCoords);
glEnableVertexAttribArray(ATTRIBUTE_TEXCOORD);
//綁定紋理
picPreviewTexture->bindTexture(uniformSampler);
glDrawArrays(GL_TRIANGLE_STRIP, , );
//切換回螢幕緩沖并繪制fbo之前綁定的空紋理
glBindFramebuffer(GL_FRAMEBUFFER,);
glClearColor(, , , ); // set clear color to white (not really necessery actually, since we won't be able to see behind the quad anyways)
glClear(GL_COLOR_BUFFER_BIT);
picPreviewTexture->bindTextureFrame(uniformSampler);
glDrawArrays(GL_TRIANGLE_STRIP, , );
幀緩沖就說到這裡了,主要的作用可以從紋理中擷取對應的資料來進行後期處理,總的來說使用還是非常簡單。
源碼位址