片段操作图
这篇文章将介绍从写入帧缓冲和读取帧缓冲的方式。
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[] = { GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3
};
glDrawBuffers ( , attachments );
通过GL_MAX_COLOR_ATTACHMENTS你可以查询支持最多的颜色数,支持最小的数目是4.
5.声明和使用着色器的输出
layout(location = ) out vec4 fragData0;
layout(location = ) out vec4 fragData1;
layout(location = ) out vec4 fragData2;
layout(location = ) out vec4 fragData3;
完整代码
int InitFBO ( ESContext *esContext )
{
UserData *userData = esContext->userData;
int i;
GLint defaultFramebuffer = ;
const GLenum attachments[] =
{
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
GL_COLOR_ATTACHMENT2,
GL_COLOR_ATTACHMENT3
}; glGetIntegerv ( GL_FRAMEBUFFER_BINDING, &defaultFramebuffer ); // Setup fbo
glGenFramebuffers ( , &userData->fbo );
glBindFramebuffer ( GL_FRAMEBUFFER, userData->fbo ); // Setup four output buffers and attach to fbo
userData->textureHeight = userData->textureWidth = ;
glGenTextures ( , &userData->colorTexId[] );
for (i = ; i < ; ++i)
{
glBindTexture ( GL_TEXTURE_2D, userData->colorTexId[i] ); glTexImage2D ( GL_TEXTURE_2D, , GL_RGBA,
userData->textureWidth, userData->textureHeight,
, 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], );
} glDrawBuffers ( , attachments ); if ( GL_FRAMEBUFFER_COMPLETE != glCheckFramebufferStatus ( GL_FRAMEBUFFER ) )
{
return FALSE;
} // Restore the original framebuffer
glBindFramebuffer ( GL_FRAMEBUFFER, defaultFramebuffer ); return TRUE;
}
fsh代码
#version es
precision mediump float;
layout(location = ) out vec4 fragData0;
layout(location = ) out vec4 fragData1;
layout(location = ) out vec4 fragData2;
layout(location = ) out vec4 fragData3;
void main()
{
// first buffer will contain red color
fragData0 = vec4 ( , , , );
// second buffer will contain green color
fragData1 = vec4 ( , , , );
// third buffer will contain blue color
fragData2 = vec4 ( , , , );
// fourth buffer will contain gray color
fragData3 = vec4 ( 0.5, 0.5, 0.5, );
}