5.1何为“帧”缓冲区(Frame buffer)?
图形流水线
帧缓冲区(Frame buffer)与片元处理
1、缓冲区的每个单元对应的就是屏幕上一个个像素
2、对片元的处理就是在利用并修改缓冲区的数据
显示器的分类
光栅扫描显示器---Raster-Scan Display |
随机扫描显示器(向量显示器)---Random-Scan Display(Vector Displays) |
随机扫描显示器(向量显示器)
像一个电子枪在画图
光栅扫描显示器(Raster-Scan Display)
1、像素的颜色都存储在一块缓冲区中
2、需要不断重复绘制,即不断刷新屏幕
帧缓冲区(Frame buffer)
1、存储视口中每个像素的信息
2、与视口像素一一对应
Refersh Rate(刷新率)
1、存储视口中每个像素的信息
2、常用单位:FPS,Frame per second
5.2颜色缓冲区
多种类型的帧缓冲区
颜色缓冲(Color buffer)
深度缓冲(Depth buffer)
模板缓冲(Stencil buffer)
累积缓冲(Accumulation buffer)----已废除
用户自定义的缓冲
颜色缓冲
存储视口中每个像素的颜色
颜色缓冲所占的存储空间
1、Resolution(分辨率):1024*768
2、像素颜色:采用RGB三个分量来表示颜色,每个分量采用8bits来表示
问题:该颜色缓冲需要多大的存储空间?
1024 * 768 * 8 bit / 1024 = 6144Kb
清除缓冲的操作
glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClearDepth(1.0);
glClear(GL_DEPTH_BUFFER_BIT);
1、同时清除帧缓冲和深度缓冲
2、glClearColor(0.0,0.0,0.0,0.0);
glClear(GL_COLOR_BUFFER_BIT);
glClearDepth(1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
3、尽量同时清除多块缓冲,这样效率更高
问题:GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT是什么意思?
GL_COLOR_BUFFER_BIT :指定当前被激活为写操作的颜色缓存。
GL_DEPTH_BUFFER_BIT: 指定深度缓存。
单缓冲与双缓冲
双缓冲可避免屏幕闪烁
单缓冲只在Front Buffer缓冲,边画边缓冲,可能会出现闪屏的现象。
双缓冲先在Back Buffer缓冲,然后一次性复制到Front Buffer。
5.3深度缓冲去与Z-buffer消隐算法
Color Buffer and Depth Buffer
深度缓冲(Depth buffer)
1、Projection:3D->2D
(x,y,z)->(wx,wy)其实投影后也有一个z值,当为(wx,wy,wz)
2、在投影时,每个投影点的深度也会被记录下来,写入深度缓冲。
3、其实是:在光栅化时,每个片元的深度会计算出来,写入深度缓冲
视域空间中的深度范围
透视投影后的深度坐标范围是[0,1],其深度分布不均匀
深度缓冲(Depth buffer)
Depth buffer 也叫Z-buffer,为什么呢?
因为Z值,物体的Z值表示它的深度,
深度缓冲用处很多,但其中最主要的一个应用是“消隐(Visible surface detection)”
消隐(Visible surface detection)
若不作消隐处理,后绘之物总会挡住先绘之物
消隐的方法
Depth Sorting Method(深度排序算法)
Area-Subdivision Method(区域子算法)
Ray Casting Method(光线投射法)
Z-buffer算法
Z-buffer消隐算法
1、在把显示对象的每个面上每一点的颜色值填入帧缓冲器相应单元前,要把这点的深度值和Z-buffer中相应单元的值进行比较。
2、只有前者小于后者时才改变缓冲器的那一单元的值,同时Z-buffer中相应单元的值也要改成这点的深度值;否则帧缓冲器相应单元的值不变。
Z-buffer Method
1、Z-buffer算法在像素级上以近物取代远物。面片在屏幕上的出现顺序是无关紧要的。
2、这种取代方法实现起来远比总体排序灵活简单,有利于硬件实现。
3、缺点:占用空间大,没有利用图形的相关性与连续性。
深度精度不够的导致的闪烁现象
透视投影后的深度坐标范围是[0,1],其深度分布不均匀。
5.4OpenGL中关于深度缓冲的函数
深度缓冲使用相关的三个函数
glEnable(GL_DEPTH_TEST);
会进行深度比较 注意:是两个作用
会根据当前绘制内容更新 depth buffer
Void glDepthFunc(GLenum func);
深度比较的方式:Func
Func可取:
GL_NEVER,GL_LESS,GL_LEQUAL,GL_EQUAL,
GL_GREATER,GL_NOTEQUAL,GL_GEQUAL,GL_ALWAYS
Void glDepth Mask(GLboolean flag);
设置是否更新深度缓冲
如果不想更新深度,那么将flag设为false
glDisable(GL_DEPTH_TEST);
---深度比较和更新深度缓冲这两个动作都不会发生
如果不想更新深度缓冲,只想比较,那可以:
glEnable(GL_DEPTH_TEST);
glDepthMask(false);
默认是:
glDisablee(GL_DEPTH_TEST);
glDepthMask(false);
glDepthFunc(GL_LESS);
深度缓冲的使用技巧举例
预绘制:
打开深度绘制;
绘制这片树林,记录其深信度值到深度缓冲;
保存绘制的树木图像。
实时绘制:
把预存的树木图像画到屏幕上;
glEnable(GL_DEPTH_TEST);
glDepthMask(false);
画树林中的物体。---也就是说进行深度比较,但并不更新深度缓存。
问题:如果不想比较深度值,只想更新深度缓冲,那怎么办?
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glDepthMask(true);