OpenGL使用 FrameBufferObject
Posted 松阳
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenGL使用 FrameBufferObject相关的知识,希望对你有一定的参考价值。
在OpenGL中所有的图形,都会绘制到 FrameBufferObject 上。如果想使用界面的做分屏渲染,或需要屏幕图像制成贴图以备后期处理,就需要用到 FrameBufferObject 技术,这种方式也被称为 RTT (Render to Texture)。
原理
通过
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,colorBuffer,0);
可以将ColorBuffer绑定到一张Texture上。当然也可以绑定到多张贴图中。另外使用这个函数也可以取出深度贴图。
当生成了自己的fbo之后,即可将图元绘制到贴图上面,可以理解为是一个预渲染的过程。
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
draw();
glBindFramebuffer(GL_FRAMEBUFFER,0);
然后在实际渲染时使用fbo中的贴图进行绘制。
实现
创建一个产生fbo的函数,并返回ColorBuffer与depthBuffer
GLuint CreateFrameBufferObject(GLuint &colorBuffer,int width,int height)
{
GLuint fbo;
glGenFramebuffers(1,&fbo);
glBindFramebuffer(GL_FRAMEBUFFER,fbo);
//color buffer
glGenTextures(1,&colorBuffer);
glBindTexture(GL_TEXTURE_2D,colorBuffer);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,colorBuffer,0);
glBindTexture(GL_TEXTURE_2D,0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
{
printf("FBO Create Fail\\n");
}
glBindFramebuffer(GL_FRAMEBUFFER,0);
return fbo;
}
接着创建另一个program来做平面承接fbo中的texture。
//create fbo
GLuint colorBuffer;
GLuint fbo = CreateFramebufferObject(colorBuffer, width, height);
//main draw
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
draw();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
RenderFullScreenQuad();
glFlush();
auto draw = [&]()->void
{
//draw work
}
auto RenderFullScreenQuad = [&]()->void
{
glUseProgram(fsqprogram);
glBindTexture(GL_TEXTURE_2D, colorBuffer);
glUniform1i(fsqtextureLocation, 0);
glBindVertexArray(fsqvao);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, fsqibo);
glDrawElements(GL_TRIANGLES, fsqindexCount, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(0);
};
最后在shader中做一个全屏的面片,如果是标准的0.5为模型空间坐标的Quad可以简单的使用:
attribute vec3 pos;
attribute vec2 texcoord;
attribute vec3 normal;
uniform mat4 M;
uniform mat4 V;
uniform mat4 P;
varying vec2 V_Texcoord;
void main()
{
vec4 position=vec4(pos.x*2,pos.y*2,pos.z,1.0);
V_Texcoord=texcoord;
gl_Position=position;
}
来制作一个全屏的面片,最终将贴图贴到面片上即可。这部分的实现可以参考之前的文章:OpenGL(三) 加载贴图。
总结
通过 FrameBufferObject (或称为RTT) 可以将画面抓到一张贴图中,有了这张图,我们就可以做很多后期处理的效果。
以上是关于OpenGL使用 FrameBufferObject的主要内容,如果未能解决你的问题,请参考以下文章