OpenGL 编程指南 (3.2)

1、帧缓冲对象

  帧缓冲对象对于离屏渲染、纹理贴图更新、缓存乒乓技术(buffer ping-pongqing,GPGPU的一种数据传输方式)的实现意义非凡,它减少了大量的数据拷贝工作。

  建立帧缓冲需要负责建立帧缓冲使用的其它缓冲内容,也就是说,新建的帧缓冲只是一个空壳,具体的渲染缓冲对象被称之为帧缓冲附件。下面是一个简单的可用帧缓冲建立示例:

OpenGL 编程指南 (3.2)

  帧缓冲是比较消耗内存的,所以OpenGL提供了可以将帧缓冲一部分或者全部无效化从而立即释放内存的操作

  void glInvalidFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attackments)//numAttachments是附件的数目,attachments是附件的id

  void glInvalidSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attackments, GLint x, GLint y, GLsizei width, GLsizei height)

2、帧缓冲附件

  GL_COLOR_ATTACHMENTi:第i个颜色缓冲,取值范围从0到GL_MAX_COLOR_ATTACHMENT-1

  GL_DEPTH_ATTACHMENT:深度缓冲

  GL_STENCIL_ATTACHMENT:模板缓冲

  GL_DEPTHx_STENCILy_ATTACHMENT:深度缓冲与模板缓冲的压缩格式(x、y是占用的空间以 位 为单位)

 需要注意的一点是,GL_DRAW_FRAMEBUFFER GL_FRAMEBUFFER是等价的,只是在字面意义上使用起来会比较鲜明。由上面的帧缓冲示例可以看出,最后一步是检查它的完整性,结果又以下几种:

OpenGL 编程指南 (3.2)

 

3、渲染缓冲(render buffer)

  渲染缓冲内容的存储格式是是格式化后的图像数据,GPU能够直接使用,因此它是一个高效的内存缓冲。同时它也是依附于帧缓冲,只有被关联到帧缓冲对象之后它才有意义。首先分配存储空间

  void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)//target必须是GL_RENDERBUFFER,internalformat是内容的存储格式作为颜色缓冲时应该为下面众多中的一种:

OpenGL 编程指南 (3.2)

作为深度缓冲、模板缓冲等应该是GL_DEPTH_COMPONENT、GL_DEPTH_COMPONENT16、GL_STENCIL_INDEX、GL_STENCIL_INDEX16、GL_DEPTH_STENCIL等中的一种

  void glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)//samples是多采样的数目

 

4、多重缓冲

  帧缓冲对象的多渲染缓冲特性是在一个fragment shader中同时写入多个缓冲的能力,也叫MRT(Multiple-Render Target)渲染,能够避免对统一组数据进行多次光栅化等行为。常被用于GPGPU领域,也能能够用于生成几何体或其它信息(如纹理、法线贴图)。fragment shader中使用layout区分多缓冲,如下:

  layout (location = 0) out vec4 normal;

  layout (location = 1) out vec4 color;

  建议在shader中使用layout限定符来确保输出与帧缓冲的附件互相关联,否则OpenGL会在shader的链接阶段完成这项工作。也可以在代码来进行设置

  void glBindFragDataLocation(GLuint program, Gluint colorNumber, const GLchar* name)//colorNumber对应于shader的变量name

  void glBindFragDataLoactionIndexed(GLuint program, Gluint colorNumber, GLuint index, const GLchar* name)//index的取值只能是0或1(没理解这是干啥的???)下面是api英文说明

  设置正确,shader程序链接完成后可以通过下面方法获取索引、位置

  GLint glGetFragDataLocation(GLuint program, const GLchar* name)

  GLint glGetFragDataIndex(GLuint program, const GLchar* name)

 1)选择颜色缓冲进行读写

  绘制或读取通常与下面几种颜色缓冲内容关联:(1)默认帧缓冲的前、后、左前、左后、右前、右后

                                    (2)自定义帧缓冲的前缓冲,或是任意渲染缓冲附件

  void glDrawBuffer(GLenum mode)//model是上面的关联内容,有GL_FRONT、GL_LEFT、GL_BACK_LEFT等,如果当前绑定的帧缓冲不是默认的,只能使用GL_NONE或者GL_COLOR_ATTACHMENTi

  void glDrawBuffers(Glsizei n, const GLenum* buffers)//buffers只接受GL_NONE、GL_FRONT_LEFT、GL_FRONT_RIGHT、GL_BACK_LEFT、GL_BACK_RIGHT这几种

 2)双源融混

  同一个片元的两个输出作用于同一个帧缓冲中的同一个颜色缓冲,通过fragment shader的第二个输出量实现。

  layout (location = 0, index = 0) out vec4 first_output;

  layout (location = 0, index = 1) out vec4 second_output;

  混合(blend)时glBlendFunc等设置状态使用GL_SRC_COLOR、GL_SRC_ALPHA、GL_ONE_MINUS_SRC_COLOR等时,这些参数作用于第一个输出first_output;GL_SRC1_COLOR、GL_SRC1_ALPHA等则会作用于第二个输出second_output。

  双源融混的实现使用了fragment shader第二个输出,同时这个变量可能关联到多个帧缓冲附件上,因此fragment shader的总输出变量数目会减少,需要对GL_MAX_DUAL_SOURCE_DRAW_BUFFERS进行查询,如果为1,说明这两种功能只能取其一使用。

 

上一篇:WebGL编程笔记3:纹理图片texture


下一篇:Flutter Widgets 之 ShaderMask