单缓冲与双缓冲的区别

 摘自:http://zhidao.baidu.com/question/145477958.html

OpenGL单缓冲与双缓冲的区别(追加10分)

最佳答案
单缓冲,实际上就是将所有的绘图指令在窗口上执行,就是直接在窗口上绘图,这样的绘图效率是比较慢的,如果使用单缓冲,而电脑比较慢,你回到屏幕的闪烁。
双缓冲,实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。
一般用OpenGL绘图都是用双缓冲,单缓冲一般只用于显示单独的一副非动态的图像
 
 
http://thatax.blog.163.com/blog/static/20892680200871242445116/
 

OpenGL的消隐与双缓冲  

2008-08-12 16:24:45|  分类: OpenGL |  标签: |字号 订阅

首先是大家可能已经发现,在我们之前提到的所有例子中,在图形的旋转过程中整个图形都有一定程度的闪烁现象,显得图形的过渡极不平滑,这当然不是我们所要的效果,幸好opengl 支 持一个称为双缓存的技术,可以有效的帮助我们解决这个问题。我们知道在我们电脑中,屏幕中显示的东西都会被放在一个称为显示缓存的地方,在通常情况下我们 只有一个这样的缓冲区,也就是单缓冲,在单缓冲中任何绘图的过程都会被显示在屏幕中,这也就是我们为什么会看到闪烁,而所谓双缓冲就是再这个显示的缓冲区 之外 再建立一个不显示的缓冲区,我们所有的绘图都将在这个不显示的缓冲区中进行,只有当一帧都绘制完了之后才会被拷贝到真正的现实缓冲区显示出来,这样中间过程对于最终用户就是不可见的了,那即使是速度比较慢也只会出现停顿而不会有闪烁的现象出现。

OpenGL 中我们可以通过glut 库中的函数

void glutSwapBuffers(void) 来实现从非显示缓冲区到显示缓冲区的复制

当然在使用双缓冲之前我们也要在 glutInitDisplayMode 设定参数的时候选择GLUT_DOUBLE 而不是之前我们用的 GLUT_SINGLE 相信这两个参数的意思也应该很明白了

在解决了闪烁的问题之后 我们来解决另一个问题 首先我们在窗口中画两个交叉的分别位于ZOX ZOY 平面的长方形 并用不同的颜色填充它们,然后让它们旋转很快我们发现有个比较严重的问题发生了,因为我们发现opengl显然没有空间的位置观念因为它根本不能分辨物体的前后关系,当然也不能做出适当的显示,在opengl中我们使用深度缓冲区来解决这个问题,在这个缓冲区中存放着每个象素深度信息,当有一个新的象素需要显示的时候,我们可以通过一个被称为深度测试的函数来确定它们的先后关系,要使用深度缓冲区有以下几个步骤:

1. 在函数 glutInitDisplayMode(mode) 中将GLUT_DEPTH置位 表明要使用深度缓冲区

2. 使用函数glEnable(GL_DEPTH_TEST) 打开深度测试函数

void glEnable(GLenum cap);

void glDisable(GLenum cap);

这两个函数属于基本状态管理函数 用来打开和关闭一些常用的功能,常用的参数有以下几个

GL_BLEND GL_DEPTH_TEST GL_FOG GL_LINE_STIPPLE GL_LIGHTING

3. 是用函数glDepthFunc()来设置深度测试函数

void glDepthFunc(GLenum func)

这里我们比较常用的深度测试函数有 GL_LESS GL_LEQUAL 两者的区别在于当深度相同时是显示新的象素 还是老的象素

4. 使用下面的函数来设置深度缓冲区的值

void glClearDepth(GLclampd depth)

           这里的参数是背景的深度 一般来说 我们都将背景深度设成最大值1

5.   最后在我们使用glClear(bits) 刷新背景的同时 我们要将GL_DEPTH_BUFFER_BIT置位 表示我们在刷新背景颜色的同时 用刷新背景深度

#include "stdafx.h"

 

#include <math.h>

#include <gl/glut.h>

#include <gl/gl.h>

 

bool mouseisdown=false;

bool loopr=false;

int mx,my;

int ry=30;

int rx=30;

void timer(int p)

{

     ry-=5;

        glutPostRedisplay();

     if (loopr)

          glutTimerFunc(200,timer,0);

}

void mouse(int button, int state, int x, int y)

{

    if(button == GLUT_LEFT_BUTTON)

     {

        if(state == GLUT_DOWN)

         {    mouseisdown=true; loopr=false;}

         else

              mouseisdown=false;

     }

     if (button== GLUT_RIGHT_BUTTON)

         if(state == GLUT_DOWN)

         {loopr=true; glutTimerFunc(200,timer,0);}

   

}

void motion(int x, int y)

{

    if(mouseisdown==true)

    {

        ry+=x-mx;

         rx+=y-my;

         mx=x;

         my=y;

         glutPostRedisplay();

    }

}

void special(int key, int x, int y)

{

    switch(key)

    {

    case GLUT_KEY_LEFT:

        ry-=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_RIGHT:

       ry+=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_UP:

        rx+=5;

        glutPostRedisplay();

        break;

    case GLUT_KEY_DOWN:

        rx-=5;

      

        glutPostRedisplay();

        break;

    }

}

void init()

    //设置OpenGL的一些状态变量的初始值

{

    glEnable(GL_DEPTH_TEST);     //深度测试

    glDepthFunc(GL_LESS);                      //设置深度测试函数

    glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);        //设置多边形显示模式为正反面都是填充显示

    glClearColor(1,1,1,1);          //设置刷新背景色

    glClearDepth(1);          //设置清除深度缓冲区所用的值

}

void display()

{

       

         float red[3]={1,0,0};

         float blue[3]={0,1,0};

         float green[3]={0,0,1};

         float yellow[3]={1,1,0};   

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        

        

         glLoadIdentity();

         glRotatef(ry,0,1,0);      

         glRotatef(rx,1,0,0);

        

             

         glBegin(GL_QUADS);

              glColor3fv(green);

              glVertex3f(0.5,0.5,0);

              glVertex3f(-0.5,0.5,0);

              glVertex3f(-0.5,-0.5,0);

              glVertex3f(0.5,-0.5,0);

             

        

         glEnd();

        

         glBegin(GL_QUADS);

              glColor3fv(red);

              glVertex3f(0.5,0.5,0.3);

              glVertex3f(-0.5,0.5,-0.3);

              glVertex3f(-0.5,-0.5,-0.3);

              glVertex3f(0.5,-0.5,0.3);

             

        

         glEnd();

        

         glBegin(GL_QUADS);

             

              glColor3fv(yellow);

              glVertex3f(0.5,0.5,-0.3);

              glVertex3f(-0.5,0.5,0.3);

              glVertex3f(-0.5,-0.5,0.3);

              glVertex3f(0.5,-0.5,-0.3);

             

        

         glEnd();

        glFlush();

         glutSwapBuffers();

 

}

   

 

int main(int argc, char** argv)

{

  

    glutInit(&argc, argv);

    glutInitDisplayMode (GLUT_DOUBLE| GLUT_RGBA|GLUT_DEPTH);         //设置显示模式:单缓冲区, RGBA颜色模式

    glutInitWindowSize (400, 400);        //设置窗口宽度、高度

    glutInitWindowPosition(100,100);         //设置窗口位置

    glutCreateWindow ("double");        //弹出窗口

     init();

    glutDisplayFunc (display);        //设置窗口刷新的回调函数

     glutMouseFunc(mouse);         //设置鼠标器按键回调函数

    glutMotionFunc(motion);

     glutSpecialFunc(special);

    glutMainLoop();        //开始主循环

    return 0;

}

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
双缓冲技术在Python中可用于实现平滑动画和减少屏幕闪烁。它基于两个缓冲区,一个用于显示,另一个用于绘制。 在Python中,您可以使用`curses`模块来实现双缓冲。首先,您需要导入`curses`模块并初始化屏幕,然后创建两个窗口作为缓冲区。您可以在一个窗口中绘制动画,然后将其复制到另一个窗口,并使用`refresh()`方法刷新屏幕以显示更新后的缓冲区。 这是一个简的示例代码,演示了如何使用双缓冲实现平滑动画: ```python import curses def main(stdscr): # 初始化屏幕 curses.curs_set(0) stdscr.nodelay(1) stdscr.timeout(100) # 创建两个窗口作为缓冲区 height, width = stdscr.getmaxyx() buffer1 = curses.newwin(height, width, 0, 0) buffer2 = curses.newwin(height, width, 0, 0) # 初始动画状态 x = 0 dx = 1 while True: # 清空缓冲buffer1.erase() # 在缓冲区中绘制动画 buffer1.addstr(0, x, "Hello, World!") # 复制缓冲区到另一个缓冲buffer2.refresh() # 刷新屏幕,显示更新后的缓冲区 stdscr.refresh() # 更新动画状态 x += dx if x >= width or x <= 0: dx *= -1 # 暂停一段时间以控制动画速度 curses.napms(100) # 获取用户输入 c = stdscr.getch() if c == ord('q'): break curses.wrapper(main) ``` 在上面的代码中,我们使用了两个窗口`buffer1`和`buffer2`作为缓冲区。我们首先在`buffer1`中绘制动画,然后通过调用`buffer2.refresh()`将其复制到`buffer2`中。最后,我们调用`stdscr.refresh()`来刷新屏幕以显示更新后的缓冲区。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值