OpenGL帧缓冲:绑定和管理帧缓冲区对象 Binding and Managing Framebuffer Objects

将帧缓冲对象名称,绑定到指定的目标

void glBindFramebuffer( enum target, uint framebuffer );

target参数可以设置为:

  • GL_DRAW_FRAMEBUFFER:用于指定当前渲染操作的目标帧缓冲区。
  • GL_READ_FRAMEBUFFER:用于读取操作的目标帧缓冲区。
  • GL_FRAMEBUFFER:同时绑定至绘图和读取目标。

当一个新生成的帧缓冲对象被绑定时,它会初始化一组新的状态变量,包括表23.24中列出的所有初始状态值,并且针对帧缓冲区每个附着点都会有一组来自表23.25的状态值,这些状态值同样以初始值开始。

帧缓冲对象支持的最大颜色附着点数量由GL_MAX_COLOR_ATTACHMENTS定义,除此之外,还包括深度和模板各一个附着点。

如果已存在的帧缓冲对象被成功绑定到DRAW_FRAMEBUFFER或READ_FRAMEBUFFER上,原有的绑定关系会被解除,而新绑定的帧缓冲对象状态不会发生变化。

只要帧缓冲对象没有被删除或者另一个帧缓冲对象被绑定到相应的绘制或读取点,那么被绑定至DRAW_FRAMEBUFFER或READ_FRAMEBUFFER的帧缓冲对象就成为相应渲染或读取操作的目标。若使用BindFramebuffer函数并设置target为GL_FRAMEBUFFER,则表示同时将其绑定至绘制和读取两个目标。

创建多个帧缓冲对象(Framebuffer Objects,FBOs)

void glCreateFramebuffers( sizei n, uint *framebuffers );

生成指定数量(n)的新帧缓冲对象名称

void glGenFramebuffers( sizei n, uint *framebuffers );

只有当这些帧缓冲对象首次被绑定(通过BindFramebuffer函数)时,才会获得具体的状态和类型信息,并成为真正可用的帧缓冲对象。在此之前,虽然名字已经被分配并标记为“已使用”,但它们不具备帧缓冲对象的实际功能和属性。

删除帧缓冲对象

void glDeleteFramebuffers( sizei n, const uint *framebuffers );

执行此操作后:

  1. 删除对象:指定的帧缓冲对象将被删除,它们的所有附件(如颜色附件、深度附件和模板附件等)都会自动解除关联,并释放相关资源。

  2. 重置绑定状态:如果被删除的帧缓冲对象当前正绑定到DRAW_FRAMEBUFFER或READ_FRAMEBUFFER目标上,则删除后的效果就像使用glBindFramebuffer函数将相应的目标与0(默认帧缓冲)重新绑定一样。这意味着视口将再次指向默认帧缓冲,并且渲染操作将影响屏幕而非已删除帧缓冲的内容。

  3. 重置名称状态:被删除的帧缓冲对象名称将变为未使用状态,可以再次用于后续的glGenFramebuffers调用。而那些在framebuffers数组中未使用的或者值为0的名字会被API忽略,因为0通常代表默认帧缓冲,它不能被删除也不计入已分配的帧缓冲对象ID中。

检查指定的标识符是否指向一个有效的、当前存在的帧缓冲对象

boolean glIsFramebuffer( uint framebuffer );
  • 该函数接受一个无符号整数参数framebuffer,即你想要检验的潜在帧缓冲对象的名称。
  • 如果framebuffer代表了一个有效且当前存在的帧缓冲对象,则glIsFramebuffer将返回GL_TRUE
  • framebuffer为 0(表示默认或空帧缓冲),或者其为不对应任何已创建帧缓冲对象的非零值时,glIsFramebuffer则会返回GL_FALSE

要查询当前绑定到绘图和读取帧缓冲目标的名称,你可以使用glGetIntegerv函数并搭配相应的符号常量作为参数:

void glGetIntegerv(GLenum pname, GLint *params);

对于当前的绑定状态:

  • 要获取绘图帧缓冲的绑定信息,你需要使用GL_DRAW_FRAMEBUFFER_BINDING
  • 要获取读取帧缓冲的绑定信息,你需要使用GL_READ_FRAMEBUFFER_BINDING
  • 注意,GL_FRAMEBUFFER_BINDING等同于GL_DRAW_FRAMEBUFFER_BINDING。它检索当前绑定到GL_FRAMEBUFFER目标上的帧缓冲对象名称,通常这与绘图目标相关联,除非通过调用glBindFramebuffer并指定不同目标而明确分离。

帧缓冲区对象参数 Framebuffer Object Parameters

void glFramebufferParameteri( enum target, enum pname, int param );
void glNamedFramebufferParameteri( uint framebuffer, enum pname, int param );
  1. void FramebufferParameteri( GLenum target, GLenum pname, GLint param );

    • 此函数用于修改当前绑定到指定目标的帧缓冲对象的参数。target必须是GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER或等价于GL_DRAW_FRAMEBUFFERGL_FRAMEBUFFER
    • pname指定了要设置的帧缓冲对象参数类型:FRAMEBUFFER_DEFAULT_WIDTHFRAMEBUFFER_DEFAULT_HEIGHTFRAMEBUFFER_DEFAULT_LAYERSFRAMEBUFFER_DEFAULT_SAMPLESFRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS
    • param则是对应参数的具体值。
  2. void NamedFramebufferParameteri( GLuint framebuffer, GLenum pname, GLint param );

    • 这个函数直接针对具有指定名称的帧缓冲对象进行参数设置,无需考虑当前绑定的目标。
    • framebuffer参数为帧缓冲对象的名称。
    • 其他参数含义与FramebufferParameteri函数相同。

当一个帧缓冲对象没有附件时,其宽度、高度、层计数、采样计数及采样位置模式通常是由所附加纹理或者渲染缓冲区决定的。如果没有附加任何附件,则这些属性将从帧缓冲参数中获取。

  • 如果pname设定了诸如FRAMEBUFFER_DEFAULT_WIDTHFRAMEBUFFER_DEFAULT_HEIGHT等默认尺寸参数,则param将定义无附件时使用的宽度和高度。
  • pnameFRAMEBUFFER_DEFAULT_LAYERS时,若param不为零,则即使没有附件,该帧缓冲也被视为分层帧缓冲。
  • pnameFRAMEBUFFER_DEFAULT_SAMPLESparam非零,则帧缓冲被视为包含多重采样的,并且具体的采样数量由实现自行决定,类似于RenderbufferStorageMultisample函数的操作方式。
  • 如果帧缓冲包含采样缓冲并且pnameFRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONSparam非零,则该帧缓冲遵循固定的采样位置模式,这与TexImage2DMultisample函数描述的方式类似。

将图像附着到帧缓冲区对象 Attaching Images to Framebuffer Objects

帧缓冲可附加图像(Framebuffer-attachable images)可以被添加到或从帧缓冲对象中移除。相比之下,默认帧缓冲的图像附件是不可通过OpenGL API直接改变的。

一个帧缓冲可附加图像可以同时附加到多个帧缓冲对象上,这样有可能避免数据复制,进而可能降低内存消耗。每个逻辑缓冲区(如颜色缓冲、深度缓冲和模板缓冲等)在帧缓冲对象中都存储了一组状态,这些状态定义了该逻辑缓冲区的附件点。附件点状态包含了足够的信息以识别所附加的单个图像,或者表明没有图像被附加。

帧缓冲可附加图像有多种类型:

  1. 渲染缓冲对象(Renderbuffer Object)的图像,它总是二维的。
  2. 一维纹理的单个层次,被当作高度为1的二维图像处理。
  3. 二维纹理、二维多重采样纹理或矩形纹理的单个层次。
  4. 立方体纹理层次的单个面,也被视为二维图像处理。
  5. 一维数组纹理、二维数组纹理或三维纹理的单个层,同样作为二维图像对待。
  6. 立方体贴图数组纹理的单个层-面,也视作二维图像。

另外,还可以将三维纹理、立方体贴图、立方体贴图数组纹理或一维/二维数组纹理的整个层次附加到附件点上。这样的附件被视为由多层二维图像组成的数组,并且对应的附件点被认为是分层的(参见第9.8节关于“Layered Framebuffers”的描述)。这意味着可以通过帧缓冲同时处理一组具有相同尺寸但不同层次或面的数据,这对于诸如立体渲染或多视点渲染等场景非常有用。

帧缓冲区对象查询 Framebuffer Object Queries

void glGetFramebufferParameteriv( enum target, enum pname, int *params );
void glGetNamedFramebufferParameteriv( uint framebuffer, enum pname, int *params );

对于GetFramebufferParameteriv函数,其查询的目标帧缓冲对象是绑定到target的,target必须是DRAW_FRAMEBUFFERREAD_FRAMEBUFFERFRAMEBUFFER,其中FRAMEBUFFER等同于DRAW_FRAMEBUFFER。而对于GetNamedFramebufferParameteriv函数,framebuffer可以是0,表示默认的绘制帧缓冲,或者是特定帧缓冲对象的名字。

pname参数可以是以下之一:

  • FRAMEBUFFER_DEFAULT_WIDTH
  • FRAMEBUFFER_DEFAULT_HEIGHT
  • FRAMEBUFFER_DEFAULT_LAYERS
  • FRAMEBUFFER_DEFAULT_SAMPLES
  • FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS

这些值用于指示通过FramebufferParameteri函数设置的相关参数(参见第9.2.1节)。这些值只能从帧缓冲对象中查询,不能从默认帧缓冲中查询。

此外,pname还可以是以下参数之一:

  • DOUBLEBUFFER
  • IMPLEMENTATION_COLOR_READ_FORMAT
  • IMPLEMENTATION_COLOR_READ_TYPE
  • SAMPLES
  • SAMPLE_BUFFERS
  • STEREO

这些参数表示的是来自表23.73中的与帧缓冲相关的状态。这些值无论在帧缓冲对象还是默认帧缓冲中,都可通过简单的状态查询获得相同结果。SAMPLESSAMPLE_BUFFERS的值按照第9.2.3.1节描述的方式确定。

最后,调用这些函数后,帧缓冲对象对应于pname参数的值会被存储在指针params指向的整型数组中。

帧缓冲对象的附件或默认帧缓冲区的缓冲区查询

void glGetFramebufferAttachmentParameteriv( enum target, enum attachment, enum pname, int *params );
void glGetNamedFramebufferAttachmentParameteriv( uint framebuffer, enum attachment, enum pname, int *params );

对于GetFramebufferAttachmentParameteriv函数,其查询的目标帧缓冲对象是绑定到target的,target必须是DRAW_FRAMEBUFFERREAD_FRAMEBUFFERFRAMEBUFFER(与DRAW_FRAMEBUFFER等同)。而对于GetNamedFramebufferAttachmentParameteriv函数,framebuffer可以是0或者是一个帧缓冲对象的名字,如果是0,则查询的是默认绘制帧缓冲。

attachment Buffer Queried
FRONT Front Left Color
FRONT_LEFT Front Left Color
FRONT_RIGHT Front Right Color
BACK Back Left Color
BACK_LEFT Back Left Color
BACK_RIGHT Back Right Color
DEPTH Depth buffer
STENCIL Stencil buffer
table 9.1
Name of attachment
COLOR_ATTACHMENTi (see caption)
DEPTH_ATTACHMENT
STENCIL_ATTACHMENT
DEPTH_STENCIL_ATTACHMENT
table 9.2

如果查询的是默认帧缓冲,则attachment参数必须是表9.1中列出的一个值,用于选择单个颜色、深度或模板缓冲。否则,attachment参数必须是表9.2中列出的帧缓冲对象附件点之一。如果attachmentDEPTH_STENCIL_ATTACHMENT,则同一对象必须同时绑定到帧缓冲对象的深度和模板附件点,并返回关于该对象的信息。

在成功调用Get*FramebufferAttachmentParameteriv之后,如果pnameFRAMEBUFFER_ATTACHMENT_OBJECT_TYPE,则params将包含以下之一:NONEFRAMEBUFFER_DEFAULTTEXTURERENDERBUFFER,以标识所附加图像所属的对象类型。其他pname接受的值取决于对象类型,如下所述。

  • 如果FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值为NONE,则表明满足以下条件之一:

    • 没有帧缓冲对象绑定到目标上;
    • 绑定的是默认帧缓冲,且:
      • attachmentDEPTHSTENCIL,而相应的深度或模板位数为0;或者,
      • attachment没有指示分配给默认帧缓冲的颜色缓冲之一。
  • 如果FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值不是NONE,则针对所有其他帧缓冲类型,以下查询适用:

    • 如果pname是关于颜色、深度或模板组件大小的参数(如FRAMEBUFFER_ATTACHMENT_RED_SIZE等),则params会包含相应附件中对应红色、绿色、蓝色、alpha、深度或模板分量的位数。若请求的组件不存在于附件中,或者未为该附件指定数据存储或纹理图像,则params将包含0。
    • 如果pnameFRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE,则params将包含指定附件的组件格式,可能是浮点型、有符号整型、无符号整型、有符号归一化固定点型或无符号归一化固定点型之一。若未为附件指定数据存储或纹理图像,则params将包含NONE。此查询不能应用于组合的深度+模板附件,因为它不具有单一格式。
    • 如果pnameFRAMEBUFFER_ATTACHMENT_COLOR_ENCODING,则params将包含指定附件的组件编码,可以是LINEAR(线性)或SRGB(sRGB编码)。只有颜色缓冲组件可以是sRGB编码;这类组件按照章节17.3.6和17.3.7的规定进行处理。对于默认帧缓冲,颜色编码由实现决定。对于帧缓冲对象,若颜色附件的内部格式是8.24节描述的一种可渲染sRGB格式,则组件会被sRGB编码。若附件不是颜色附件,或未为其指定数据存储或纹理图像,则params将包含LINEAR
  • 如果FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值为RENDERBUFFER,则:

    • pnameFRAMEBUFFER_ATTACHMENT_OBJECT_NAMEparams将包含含有已附加图像的渲染缓冲对象的名字。
  • 如果FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE的值为TEXTURE,则:

    • pnameFRAMEBUFFER_ATTACHMENT_OBJECT_NAME,则params将包含含有已附加图像的纹理对象的名字。
    • pnameFRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL,则params将包含含有已附加图像的纹理对象的.mipmap级别。
    • pnameFRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE,并且FRAMEBUFFER_ATTACHMENT_OBJECT_NAME的值是立方体贴图纹理对象的名字,则params将包含包含已附加图像的立方体贴图面。否则,params将包含0。
    • pnameFRAMEBUFFER_ATTACHMENT_LAYERED,则params将包含TRUE,表示整个三维纹理、立方体贴图纹理或一维或二维数组纹理层级被附加;否则,params将包含FALSE。
    • pnameFRAMEBUFFER_ATTACHMENT_TEXTURE_LAYERFRAMEBUFFER_ATTACHMENT_OBJECT_NAME的值是三维纹理或一维或二维数组纹理对象的名字,并且FRAMEBUFFER_ATTACHMENT_LAYERED的值为FALSE,则params将包含包含已附加图像的纹理层。否则,params将包含0。

你可能感兴趣的:(OpenGL,图形渲染)