EGE专栏:EGE专栏
上一篇:EGE基本介绍(8):清屏和重绘
下一篇:
文章目录
- 一、双缓冲机制
-
- 1. 单缓冲绘图
-
- 1.1 单缓冲绘图的缺点
- 1.2 系统读取帧缓冲
- 2. 双缓冲绘图
-
- 2.1 双缓冲绘图流程
- 2.2 缓冲区之间的数据交换操作 : SwapBuffers()
- 二、EGE双缓冲机制和手动渲染模式
-
- 1. EGE双缓冲
- 2. 如何触发SwapBuffers操作?
- 3. EGE手动渲染模式
-
- 3.1 EGE渲染模式
-
- 3.1.1 自动渲染模式
- 3.1.2 手动渲染模式
- 3.2 设置渲染模式
-
- 3.2.1 设置窗口初始化时
- 3.2.2 setrendermode函数
一、双缓冲机制
??是一种基本的动画技术,主要用于解决单缓冲及所带来的问题。
??它指的是一种绘图技术,用于图片显示的帧缓冲区,只使用一个帧缓冲区。 
1. 单缓冲绘图
??这意味着程序只使用一个帧缓冲来绘图显示。此时,帧缓冲不仅要被系统读取并显示在屏幕上,还要作为程序绘图的目标。
1.1 单缓冲绘图的缺点
??。 ??这样,就有一个大问题。如果系统在程序绘制下一帧图像之前读取帧缓存,则会出现以下情况:
??哟,大哥!你是怎么来的? ??这不是时候了吗?我来收集这幅画!快拿你的画,我抄一份,拿出来给上级看! ??哦,我的时钟不准确,又快又慢。不,我看到外面的风景变了,想重点画一幅画。没想到这么巧合,刚画了一半,你就来了! ??外面的人等不及了,就这样,这次画的就算了,拿上次画的那个吧,看起来都差不多,那个也行。 ??哦!你不知道,我家只有这样一块宝贝画板。要重新画画,只能把之前画的擦掉,不然看起来很乱。 ??只有你的男孩有很多事情要做。你为什么这么吝啬?你不愿意再买一块画板了!唉,算了吧。直接给我你这个。如果你没有完成绘画,你就没有完成绘画。总比没有交差好。否则,如果你责怪它,你就必须辞职!这次我先帮你,下次给我一个好的表现! ??大哥放心,下次一定,下次一定! ??话毕,大哥临摹了一幅半成品,匆匆跑到下一家。 ??… ??看着墙上的时钟,大哥捏了捏出去,跑了几次,看着手里拿着几件好作品,非常满意。不久之后,哥哥又来到了门口。这几幅画都很好,上级肯定会赞美我更多!上次这个男孩的画有问题,虽然上级什么也没说,但心一定有点不高兴。这次不要给我任何飞蛾! ??大哥怀着期待的心情推开了门。他一进屋,似曾相识的感觉扑面而来。。。然后他们留下两个人看着空白的画板,瞪着小眼睛。 ??…
??
??系统通常以每秒60次的频率读取窗框缓冲器,然后显示在屏幕上。通常,程序绘图和系统读取窗框缓冲器的时间很难保持同步。 ??如果这些未绘制的相邻帧之间有很大的对比,人眼会感觉到窗户在闪烁。
1.2 系统读取帧缓冲
??由于系统读取帧缓冲和程序绘图时间不同步,系统很可能在绘图的任何阶段读取程序帧缓冲。 ??如下图所示,在一个中分为和。在该程序尚未完成绘图,此时不应由系统读取,否则未完成的图形将显示在屏幕上。此时,显示在屏幕上将是绘图过程中的任何图形。如果绘图过程中的图形变化很大,很容易引起闪烁。 ??在该系统允许在缓冲区读取一帧。
??在读取时,图形变化过程中的任何图形都可能显示在屏幕上,顺序不确定。在屏幕上图形的不断变化中,人眼可以明显感觉到闪烁。
2. 双缓冲绘图
??双缓冲绘图采用两帧缓冲,一帧缓冲用于显示,另一帧缓冲用于绘图。
用于帧缓冲称为,也叫。 用于帧缓冲称为,也叫。
2.1 双缓冲绘图过程
??系统将继续从前台缓冲区(屏幕缓冲区)读取图像数据,程序绘图需要确保前台缓冲区的数据是完整的帧,。 ??,才会两个缓冲区的数据使图像数据与原后台缓冲区一致。这样,屏幕上就完成了一帧绘图操作,并平稳地显示出来。
??这个操作,通常是或者,这取决于每个平台的实现。windows通常通过平台来实现。 ??参见 Front, Back, and Other Buffers 和 Buffer Functions
??因为系统只从前台缓冲区读取图像数据,我们是,绘制完成后。因此,绘图过程中的不完整帧不会被系统读取或显示在屏幕上,因此。
2.2 缓冲区之间的数据交换操作 : SwapBuffers()
??上面提到的,当在绘制一帧后,需要将此帧的图像数据交换到中。 ??这种操作通常被称为。这里的交换并非真的是两个缓冲区的交换,而是有两种不同的实现方式:
??一种是通过直接实现上,这也是windows上述常用实现。 Front, Back, and Other Buffers 和 Buffer Functions),当然,这样无疑会有很多开销。
??另一种是通过
交换缓冲区的指针或引用来实现,而这一种实现也被称作 。交换仅仅只需要改变一个指针的操作,非常高效。
这两种不同的实现方式各有利弊,至于使用哪种实现,各平台有自己的考量。这里仅列出《游戏编程模式》中的解释:
参考链接:《游戏编程模式》双缓冲模式
二、EGE中的双缓冲机制与手动渲染模式
1. EGE双缓冲
除了窗口本身的帧缓冲外,EGE还额外创建了一块帧缓冲,构成。 EGE以作为,绘图都是在这块缓冲区中进行,绘图完成后,调用特定的函数即可将后台缓冲区中的数据复制到前台缓冲区中,完成图像显示。
2. 如何触发SwapBuffers操作?
EGE中的 操作是通过实现,而不是交换缓冲区指针。
EGE触发有两种方式,一种是靠内部50ms定时器触发,另一种是调用EGE延时及阻塞类函数时触发。
EGE延时及阻塞类函数包括 等,这些函数的调用会触发操作,前提是调用了EGE的绘图函数,让其检测有绘图操作。
由内部50ms定时器触发的操作,这个是十分不建议的。因为双缓冲本身就是为了防止因未完成的图形内容显示到屏幕上造成的闪烁,如果绘图未完成时定时器触发了操作,那么就会使得未完成的图形内容在屏幕上显示,无法达到避免闪烁的效果。这样也仅仅是将闪烁频率从60Hz降到了20Hz而已,只能用于不断叠加绘制的绘图中,一旦清屏重绘,闪烁将十分明显。 内部50ms定时器是默认开启的,那么通过什么设置可以关闭定时器触发SwapBuffers操作呢?这就是接下来的。
3. EGE手动渲染模式
EGE通过设置,直接由内部定时器触发的 操作。这样后台缓冲区和前台缓冲区的交换操作,,不会有在绘图过程中莫名触发交换缓冲区的情况发生。 用户就可以在手动调用来进行,完成双缓冲的功能。
当程序有清屏重绘的操作时,就需要设置,来避免图形闪烁。 设置为手动渲染模式后,通过调用常用的。
#include <graphics.h>
int main()
{
//创建窗口,设置手动渲染模式
initgraph(640,480, INIT_RENDERMANUAL);
//帧循环,通过delay_fps()触发缓冲区交换
for ( ; is_run(); delay_fps(60)) {
//清屏
cleardevice();
//绘图,中途可使用getch()暂停,或者调用delay_ms(0)触发缓冲区交换
}
closegraph();
return 0;
}
在初始化参数中传入
3.1 EGE中的渲染模式
渲染模式 分为自动渲染 和手动渲染 。默认为自动渲染 。
3.1.1 自动渲染模式
(50ms定时),把绘画的内容显示到窗口上。
优点 :绘画后显示缺点 :少量绘制后便会刷新一次窗口,当绘制复杂时,多次刷新比较费时,造成绘制慢。因为不确定刷新时间点,可能在没有绘制完一帧时就显示内容,容易出现窗口闪烁 现象。
3.1.2 手动渲染模式
优点 :减少刷新次数,加快绘制。并且只在调用某些延时类函数时刷新,避免显示不完整的一帧,减少闪烁。缺点 :不调用延时函数时不会刷新窗口,如果整个循环没有调用带刷新功能延时类函数,将看不到绘制内容。
绘制时推荐
如果你的程序有清屏之类窗口颜色变化极大的,那就必须设置为手动渲染模式,否则画面容易出现问题。
3.2 渲染模式的设置
3.2.1 在窗口初始化时设置
调用initgraph() 初始化图形环境时,在
initgraph(640, 480, INIT_RENDERMANUAL);
初始化模式参数也可在
setinitmode(0, 0, INIT_RENDERMANUAL);
initgraph(640, 480);
3.2.2 setrendermode函数
void setrendermode(rendermode_e mode);
参数 自动模式用于简单静态绘图,手动模式用于制作动画或者游戏
-
RENDER_AUTO (自动渲染,默认模式) -
RENDER_MANUAL (手动渲染)
EGE专栏:EGE专栏
上一篇:EGE基础入门篇(八):清屏与重绘
下一篇: