0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

简述OpenGL帧缓冲区多线(FBO)基本概念

电子工程师 来源:CSDN技术社区 作者:图形码农 2021-03-24 15:56 次阅读

帧缓存:它是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。

帧缓冲区是指服务器(显存)中存储像素相关信息(颜色、深度)的存储空间。系统提供了帧缓冲区对象包括多个缓冲区,有颜色缓冲区、深度缓冲区、模板缓冲区等。

一、缓存的分类

1. 颜色缓存

程序员绘图所用的缓存,分为:

左、右缓存——用于立体感视图(必须要有左缓存);
前、后缓存——用于双缓存(必须要有前缓存);
4个辅助缓存——可选择的、不可显示(程序员可以自己定义和使用它们)。

2. 深度缓存

用来存储每个象素的深度值,也称为Z缓存。

3. 模板缓存

可以将作图限制在屏幕的某些部分中进行。

4. 累积缓存

包含RGBA颜色数据,通常用于将一系列图象累加成一幅最终的合成图象。

象素不能直接绘制到累积缓存中,累加操作常常先在矩形块中进行,然后再与颜色缓存交换数据。

二、缓存的操作

1. 清空缓存

(1). 指定要写入缓存的清除值:

glClearColor()——为颜色缓存设置清除值(red,green,blue,alpha);
glClearIndex()——为颜色索引缓存设置清除值(index);
glClearDepth()——为深度缓存设置清除值(默认为1.0);
glClearStencil()——为模板缓存设置清除值(默认为0.0);
glClearAccum()——为累积缓存设置清除值(red,green,blue,alpha);

(2). 清除指定的缓存:

glClear(GLbitfield mask);
mask的值是GL_COLOR_BUFFER_BIT、GL_DEPTH_BUFFER_BIT、GL_STENCIL_BUFFER_BIT和GL_ACCUM_BUFFER_BIT等常数的按位逻辑或(OR)。可以一次清除多个缓存,如硬件支持同时清除这些缓存,则操作同时进行;否则,按顺序清除各个缓存。

2. 为读写操作选择颜色缓存

绘图操作的结果可以放入任何一个颜色缓存中:前、后、左前、左后、右前、右后或任意辅存,程序员可选择单个缓存作为绘图目标或读取目标。对绘制图形而言,也可将目标同时绘制到几个缓存中,用glDrawBuffer()函数来选择将要写入的缓存;用glReadBuffer()函数来选择缓存,作为glReadPixels()、glCopyPixels()、glCopyTexImage*()和glCopyTexSubImage*()的应用目标。

3. 缓存的屏蔽(掩码)

OpenGL在向激活的颜色、深度和模板缓存中写入数据之前,需按下面函数指定的掩码对这些数据进行屏蔽操作。每个掩码要与对应的待写数据进行按位逻辑与(AND)操作。
void glIndexMask(GLuint mask);
mask默认为1。若掩码中出现1,则颜色索引模式中相应的位被写入;而在0出现的位,
void glColorMask(GLboolean red,green,blue,alpha);
默认为GL_TRUE,表示相应的分量已写入;若为GL_FALSE,则没写入。
void glDepthMask(GLboolean flag);
默认为GL_TRUE,表示深度缓存被激活用于写操作;若为GL_FALSE,则取消。
void glStencilMask(GLuint mask);
默认为1,和颜色索引类似。

三、片元的测试和操作

在OpenGL确定了应该生成的片元及绘制颜色后,仍然需要几个处理过程来控制如何将该片元作为一个象素绘制到帧缓存中,以及确定是否需要这样做。本节描述了在放入帧缓存之前,片元所必须通过的完整测试集合,并且描述了在片元写入时可能进行的最后操作。测试和操作按下列次序进行,若在前面的测试中片元被删除,则不再进行后面的测试或操作。

1 .剪取测试

剪取测试只是使用屏幕矩形区域进行的模板测试的翻版,但是由于很容易用硬件快速实现,所以比以软件方式执行的模板要快。

利用glScissor()函数,可以定义窗口中的一个矩形区域,并将作图限制在其中。若片元落在该矩形区,则剪取测试通过,否则片元被删除。

void glScissor(GLint x,GLint y,GLsizei width,GLsizei height);
glEnable(GL_SCISSOR_TEST):激活剪取测试;
glDisable(GL_SCISSOR_TEST):取消剪取测试。

默认情况下,矩形与窗口的大小相同,剪取处于取消状态。

2. alpha测试

在RGBA模式下,根据alpha测试中的alpha值,来确定是接收还是拒绝一个片元。

glEnable/glDisable(GL_DEPTH_TEST):激活/取消alpha测试
glAlphaFunc设置alpha测试的参考值和比较函数:
void glAlphaFunc(GLenum func,GLclampf ref);
参考值ref取值在0和1之间截取。参数func的可能值及其含义如下:
GL_NEVER:总不接受该片元;GL_ALWAYS:总是接受该片元;
GL_LESS:若片元alpha < 参考alpha ,接受该片元;GL_LEQUAL:片元alpha≤参考alpha,接受;
GL_EQUAL:片元alpha=参考alpha,接受;GL_GEQUAL:片元alpha≥参考alpha,接受;
GL_GREATER:片元alpha > 参考alpha,接受;GL_NOTEQUAL:片元alpha≠参考alpha,接受;

3. 模板测试

只在有模板缓存的情况下才会发生。如果没有模板缓存,则模板测试总能通过。模板化适用于这样的测试,这种测试对存储于模板缓存中的象素值与参考值进行比较,根据比较的结果,对模板缓存中的值进行修改。void glStencilFunc(GLenum func,GLint ref,GLuint mask);此函数为模板测试设置比较函数(func)、参考值(ref)以及掩码(mask)。利用比较函数可以对参考值和模板缓存中的值进行比较,而比较仅适用于掩码的相应位为1的位。比较函数的可能值与glAlphaFunc()中的比较函数的可能值相同,但含义相反。void gltencilOp(GLenum fail,GLenum zfail,GLenum zpass);

此函数说明当片元通过或未通过模板测试时,如何对模板缓存中的数据进行修正。三个参数fail、zfail、zpass可以为:
GL_KEEP:保持当前值
GL_ZERO:以0替换
GL_REPLACE:以参考值替换
GL_INCR:增加该值(在0~最大无符号整数值之间)
GL_DECR:减小该值(在0~最大无符号整数值之间)
GL_INVERT:对该值按位取反

若片元未通过模板测试,则应用fail函数;
若片元通过模板测试,但深度测试失败,则应用zfail函数;
若片元通过模板测试,且通过深度测试,或没有深度测试,则应用zpass函数。
默认情况下,三个模板操作都是GL_KEEP。
模板测试最典型的应用就是屏蔽掉屏幕的不规则区域,以避免在该区域作图。

4. 深度测试

对于屏幕上的每个象素,深度缓存时刻追踪视点与占据该象素的物体之间的距离。若通过了深度测试,输入的深度值就将取代深度缓存中的相应值。

深度缓存通常用于消除隐藏表面的操作。最初,深度缓存通常是以距离视点尽可能远的值来填充的,因此任何物体的深度都比初始状态更近。

glEnalbe(GL_DEPTH_TEST);//激活深度测试
glClearDepth(1.0);//清除深度缓存
可以用glDepthunc()函数为深度测试选择不同的比较函数。
void glDepthFunc(GLenum func);
此函数为深度测试设置比较函数。func的值必须为GL_NEVER、GL_ALWAYS、GL_LESS、GL_LEQUAL、GL_EQUAL、
GL_GEQUAL、GL_GREATER或GL_NOTEQUAL。如果z值与深度缓存中的值满足确定的关系,则输入片元通过深度测试。

5. 混合、抖动和逻辑操作

一旦输入的片元通过了所有的测试,它就可以与颜色缓存中的当前内容按某种方式合并起来。最简单的方法,也是默认操作,就是将当前值覆盖掉。

在RGBA模式中,如果希望片元是半透明的或是消除了锯齿现象的,程序员可以将该片元值与缓存中的值作一平均,即混合。

对于可用颜色较少的系统,可以以牺牲分辨率为代价,通过颜色值的抖动来增加可用颜色数量。抖动操作是和硬件相关的,OpenGL允许程序员所做的操作就只有打开或关闭抖动操作。实际上,若机器的分辨率已经相当高,激活抖动操作根本就没有任何意义。要激活或取消抖动,可以用glEnable(GL_DITHER)和glDisable(GL_DITHER)函数。默认情况下,抖动是激活的。在颜色索引模式中,可以利用任意的按位逻辑操作,将输入片元与已写入的象素进行合成。

编辑:jq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • RGB
    RGB
    +关注

    关注

    4

    文章

    798

    浏览量

    58385
  • OpenGL
    +关注

    关注

    1

    文章

    85

    浏览量

    29217
  • 函数
    +关注

    关注

    3

    文章

    4304

    浏览量

    62427
  • 帧存
    +关注

    关注

    0

    文章

    3

    浏览量

    12386
收藏 人收藏

    评论

    相关推荐

    分享一个嵌入式通用FIFO环形缓冲区实现库

    开源项目ringbuff ,是一款通用FIFO环形缓冲区实现的开源库,作者MaJerle,遵循 MIT 开源许可协议。
    的头像 发表于 10-23 16:20 255次阅读
    分享一个嵌入式通用FIFO环形<b class='flag-5'>缓冲区</b>实现库

    内存缓冲区和内存的关系

    内存缓冲区和内存之间的关系是计算机体系结构中一个至关重要的方面,它们共同协作以提高数据处理的效率和系统的整体性能。
    的头像 发表于 09-10 14:38 422次阅读

    单片机中的几种环形缓冲区的分析和实现

    单片机中的几种环形缓冲区的分析和实现一、简介环形缓冲区(RingBuffer)是一种高效的使用内存的方法,它将一段固定长度的内存看成一个环形结构,用于存储数据,能够避免使用动态申请内存导致的内存碎片
    的头像 发表于 08-14 08:39 705次阅读
    单片机中的几种环形<b class='flag-5'>缓冲区</b>的分析和实现

    ESP8266有双缓冲区吗?

    我想实时传输一些信号的测量数据。信号的采样周期为 1 ms。我想每 500 毫秒发送 2048 字节(一个数据包)。ESP8266有双缓冲区(2x 2048字节)吗?其想法是计数填充一个缓冲区(周期
    发表于 07-16 07:29

    创建DMA通道时,能否将DMA缓冲区的大小指定为8字节,并将DMA缓冲区的编号指定为1?

    创建 DMA 通道时,能否将 DMA 缓冲区的大小指定为 8 字节,并将 DMA 缓冲区的编号指定为 1?
    发表于 05-31 07:46

    stm32野火开发板上做USB通信,PC端USB的缓冲区和串口缓冲区的大小是多少?

    stm32野火开发板上做USB通信,用的CDC虚拟串口。 stm32端将ADC采集的数据通过USB传给电脑,传输速率理论上是12Mbps,上位机是从PC端的串口缓冲区拿数据,用C#编写的上位机将
    发表于 05-17 14:02

    具有八进制反相缓冲区的扫描测试设备数据表

    电子发烧友网站提供《具有八进制反相缓冲区的扫描测试设备数据表.pdf》资料免费下载
    发表于 05-17 09:58 0次下载
    具有八进制反相<b class='flag-5'>缓冲区</b>的扫描测试设备数据表

    实现稳健的微控制器到FPGA SPI接口: 双缓冲区

    在介绍双缓冲器之前,我们将简要探讨Verilog 脉宽调制器 (PWM) 的工作原理。这一点很重要,因为双缓冲区最好被看作是硬件模块 (如 PWM) 的可寻址接口。
    的头像 发表于 05-16 09:36 638次阅读
    实现稳健的微控制器到FPGA SPI接口: 双<b class='flag-5'>缓冲区</b>!

    Stm32采用环形缓冲区接收rk3588的数据代码

    Stm32采用环形缓冲区接收rk3588的数据代码
    的头像 发表于 05-15 10:10 509次阅读

    交换机与路由器缓冲区:寻找完美大小

    *本文系SDNLAB编译自瞻博网络技术专家兼高级工程总监Sharada Yeluri领英 在路由器和交换机中,缓冲区至关重要,可以防止网络拥塞期间的数据丢失。缓冲区到底要多大?这个问题在
    的头像 发表于 04-11 16:56 1073次阅读
    交换机与路由器<b class='flag-5'>缓冲区</b>:寻找完美大小

    交换芯片缓冲区大小是什么

    交换芯片缓冲区大小并不一定是固定的。缓冲区的设计和实现会根据芯片的具体型号、规格以及应用场景的不同而有所差异。一些交换芯片可能具有固定大小的缓冲区,以满足特定的性能需求或成本限制。然而,随着技术
    的头像 发表于 03-18 14:42 536次阅读

    使用UART FIFO缓冲区时,缓冲区中的数据有时会损坏的原因?

    我在使用 UART FIFO 缓冲区时遇到了以下问题。 问题描述: 当通过两个 UART 通道使用完整的 UART FIFO 缓冲区并通过两个通道进行通信时,缓冲区中的数据有时会损坏,例如,UART
    发表于 03-06 06:59

    没有办法通过FX3固件检查缓冲区是卡住了还是已满?

    使用通道 DMA 来获得输出 1080p60 所需的 FX3 数据带宽。 在随附的照片中,你可以看到多次写入,然后突然间 WATERMARK 和 READY 同时断言。 有没有办法通过FX3固件检查缓冲区是卡住了还是已满? 发生这种情况时,我能否附上一张 UART 调试
    发表于 02-23 08:01

    西门子博诊断缓冲区的使用方法

    可从在线和诊断视图中“诊断”文件夹的“诊断缓冲区”组中读出 CPU 的诊断缓冲区
    的头像 发表于 12-11 10:24 3944次阅读
    西门子博诊断<b class='flag-5'>缓冲区</b>的使用方法

    使用malloc建立缓冲区时出现错误怎么解决?

    ,我不知道现在这个已知系统的中断频率,所以我做了一个偷懒的想法,先把输入数据3秒的数据放在自建的缓冲区,再将这个数据处理后再输出,延时大概3s数据的时间,现在但是使用malloc建立缓冲区时出现错误,请问,怎么拯救?
    发表于 11-30 07:39