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) 可以将画面抓到一张贴图中,有了这张图,我们就可以做很多后期处理的效果。

关注我的微信公众号,获取更多优质内容

时间: 2024-10-24 06:47:20

OpenGL(九)使用 FrameBufferObject的相关文章

Android HWUI硬件加速模块浅析

关键词:RenderNode,ThreadedRenderer,DisplayList,UvMapper,FontRenderer 原文:https://github.com/TsinStudio/AndroidDev 什么是硬件加速(What) 传统软件的UI绘制是依靠CPU来完成的,硬件加速就是将绘制任务交由GPU来执行.GPU相比CPU更加适合完成光栅化.动画变换等耗时任务,在移动设备上比起使用CPU来完成这些任务,GPU会更加省电些,带来的用户体验也会更佳. 为什么要硬件加速(Why)

NeHe OpenGL教程 第二十九课:Blt函数

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第二十九课:Blt函数 Blitter 函数: 类似于DirectDraw的blit函数,过时的技术,我们有实现了它.它非常的简单,就是把一块纹理贴到另一块纹理上. 这篇文章是有Andreas Lffler所写的,它写了一份原始的教

NeHe OpenGL教程 第三十九课:物理模拟

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十九课:物理模拟 物理模拟简介: 还记得高中的物理吧,直线运动,自由落体运动,弹簧.在这一课里,我们将创造这一切. 物理模拟介绍 如果你很熟悉物理规律,并且想实现它,这篇文章很适合你. 在这篇教程里,你会创建一个非常简单的物理引

OpenGL基础图形编程(九)OpenGL颜色

九.OpenGL颜色 几乎所有OpenGL应用目的都是在屏幕窗口内绘制彩色图形,所以颜色在OpenGL编程中占有很重要的地位.这里的颜色与绘画中的颜色概念不一样,它属于RGB颜色空间,只在监视器屏幕上显示.另外,屏幕窗口坐标是以象素为单位,因此组成图形的每个象素都有自己的颜色,而这种颜色值是通过对一系列OpenGL函数命令的处理最终计算出来的.本章将讲述计算机颜色的概念以及OpenGL的颜色模式.颜色定义和两种模式应用场合等内容,若掌握好颜色的应用,你就能走进缤纷绚丽的色彩世界,从中享受无穷的乐

Android OpenGL ES(九)----构建几何物体

1.三角形扇 一个三角形扇以一个中心顶点作为起始,使用相邻的两个顶点创建第一个三角形,接下来的每个顶点都会创建一个三角形,围绕起始的中心点按扇形展开.为了使这个扇形闭合,我们只需要在最后重复第二个点.(以长方形为例) 构建三角形扇的步骤,如下图所示: 要使用OpenGL绘制这个三角形扇,需要在渲染类的onDrawFrame()中,使用如下方法: GLES20.glDrawArray(GLES20.GL_TRIANGLE_FAN,0,6); 第一个参数是告诉OpenGL要绘制一个三角形扇,第二参数

OpenGL ES 3.0之VertexAttributes,Vertex Arrays,and Buffer Objects(九)

顶点数据,也称为顶点属性,指每一个顶点数据.指能被用来描述每个顶点的数据,或能被所有顶点使用的常量值.例如你想绘制一个具有颜色的立方体三角形.你指定一个恒定的值用于三角形的所有三个顶点颜色.但三角形的三个顶点位置是不同的,你需要指定一个顶点矩阵存储三个位置值. 指定顶点属性数据 顶点属性数据可以使用顶点数组或常量值指定每个顶点数据,OpenGL ES 3.0 必须至少支持16 个顶点属性.应用应该能够查询编译器支持的确切属性数.下面的程序指出如何查询. GLint maxVertexAttrib

【OpenGL】Shader实例分析(九)- AngryBots中的主角受伤特效

转发请保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一个非常棒的样例.非常有研究价值. 曾经研究的时候.因为其内容丰富,一时间不知道从哪入手写文章分析. 这一段时间研究shader技术比較多一些,就从shader的这一方面開始吧.首先分析当中的一个屏幕特效:当主角受到攻击时会出现的全屏效果(postScreenEffect).效果例如以下: 事实上这是一种的Bloom效果,相关文件有:M

OpenGL进阶(十九) - 多光源

从光说起 先看一段wiki中对光的定义 光是一种人类眼睛可以见的电磁波(可见光谱),视知觉就是对于光的知觉[1].光只是电磁波谱上的某一段频谱,一般是定义为波长介于400至700纳米(nm)之间的电磁波,也就是波长比紫外线长,比红外线短的电磁波.有些资料来源定义的可见光的波长范围也有不同,较窄的有介于420至680纳米,较宽的有介于380至800纳米. 光既是一种高频的电磁波,又是一种由称为光子的基本粒子组成的粒子流.因此光同时具有粒子性与波动性,或者说光具有"波粒二象性". 按波动理

OpenGL之路(九)颜色混合实现透明效果

用alpha混合实现透明的效果,可以穿透3d物体 源码如下: #include <gl/glut.h> #include <gl/glaux.h> #include <stdio.h> #pragma comment(lib, "opengl32.lib") #pragma comment(lib, "glut32.lib") #pragma comment(lib, "glu32.lib") #pragma