免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2234 | 回复: 7
打印 上一主题 下一主题

分享成果: 双缓冲能提高渲染速度且数据整体传输比零散传输快 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-03-12 09:50 |只看该作者 |倒序浏览
本帖最后由 三月廿七 于 2011-03-12 16:25 编辑

绘制1000 张 240x320 的图片, 双缓冲 比 普通绘图快 5 倍左右,
同样是绘制1000 张 240x320 的图片,  整体绘制比零散绘制快 10倍左右,

  1. #include <GL/glut.h>
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <time.h>

  5. GLubyte*  readImage(const char*, GLsizei*, GLsizei* );
  6. GLubyte  *pixels;
  7. GLsizei   width, height;

  8. void init(void)
  9. {
  10.         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  11.         glClearColor(0.0, 0.0, 0.0, 0.0);
  12.        
  13. }

  14. void display(void)
  15. {
  16.         GLubyte*  buffer;
  17.         int i;

  18.     static clock_t start = 0, end = 0, t1 = 0, t2 = 0;

  19.         buffer = (GLubyte*)malloc(width * height * 3);

  20.         glClear(GL_COLOR_BUFFER_BIT);
  21.         glRasterPos2i(0, 0);
  22.        
  23.         start = clock();
  24.         for (i = 0; i < 1000; i++)
  25.         {
  26.                 glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels );
  27.         }
  28.         end = clock();

  29.         t1 = end - start;

  30.         glRasterPos2i(240, 100);

  31.         start = clock();
  32.         for (i = 0; i < 1000; i++)
  33.         {
  34.                 memcpy(buffer, pixels, width * height * 3);
  35.                 //glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels );
  36.         }
  37.         glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);
  38.         end = clock();
  39.        
  40.         t2 = end - start;

  41.         glFlush();
  42. }
  43. void reshape(int w, int h)
  44. {
  45.         glViewport(0, 0, (GLsizei) w, (GLsizei) h);
  46.         glMatrixMode(GL_PROJECTION);
  47.         glLoadIdentity();
  48.         glOrtho (0, w, 0, h, -1.0, 1.0);
  49.         glMatrixMode(GL_MODELVIEW);
  50. }
  51. void keyboard(unsigned char key, int x, int y)
  52. {
  53.         switch (key)
  54.         {
  55.         case 27:
  56.                 exit(0);
  57.                 break;
  58.         default:
  59.                 break;
  60.         }
  61. }
  62. /*  Main Loop
  63. *  Open window with initial window size, title bar,
  64. *  RGBA display mode, and handle input events.
  65. */
  66. int main(int argc, char** argv)
  67. {
  68.         pixels = readImage("blueguy\\blueguy.bmp", &width, &height);   
  69.        
  70.         glutInit(&argc, argv);
  71.         glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  72.         glutInitWindowSize(500, 500);
  73.         glutInitWindowPosition(100, 100);
  74.         glutCreateWindow(argv[0]);
  75.         init();
  76.         glutReshapeFunc(reshape);
  77.         glutKeyboardFunc(keyboard);
  78.         glutDisplayFunc(display);
  79.         glutMainLoop();
  80.         return 0;
  81. }
  82. GLubyte* readImage( const char* filename, GLsizei* width, GLsizei *height )
  83. {
  84.     FILE* file;
  85.         GLubyte*  pixels;
  86.     unsigned long size;                 /* size of the image in bytes.*/
  87.     unsigned long i;                    /* standard counter.*/
  88.     unsigned short int planes;          /* number of planes in image (must be 1) */
  89.     unsigned short int bpp;             /* number of bits per pixel (must be 24)*/
  90.     char temp;                          /* temporary color storage for bgr-rgb conversion.*/
  91.        
  92.     /* make sure the file is there.*/
  93.     if ((file = fopen(filename, "rb"))==NULL)
  94.         {
  95.                 printf("File Not Found : %s\n",filename);
  96.                 return 0;
  97.     }
  98.    
  99.     /* seek through the bmp header, up to the width/height:*/
  100.     fseek(file, 18, SEEK_CUR);
  101.        
  102.     /* No 100% errorchecking anymore!!!*/
  103.        
  104.     /* read the width*/
  105.     *width = getInt(file);
  106.     printf("Width of %s: %lu\n", filename, *width);
  107.    
  108.     /* read the height */
  109.     *height = getInt(file);
  110.     printf("Height of %s: %lu\n", filename, *height);
  111.    
  112.     /* calculate the size (assuming 24 bits or 3 bytes per pixel).*/
  113.     size = (*width) * (*height) * 3;
  114.        
  115.     /* read the planes*/
  116.     planes = getShort(file);
  117.        
  118.     if (planes != 1)
  119.         {
  120.                 printf("Planes from %s is not 1: %u\n", filename, planes);
  121.                 return 0;
  122.     }
  123.        
  124.     /* read the bpp*/
  125.     bpp = getShort(file);
  126.        
  127.     if (bpp != 24)
  128.         {
  129.                 printf("Bpp from %s is not 24: %u\n", filename, bpp);
  130.                 return 0;
  131.     }
  132.        
  133.     /* seek past the rest of the bitmap header.*/
  134.     fseek(file, 24, SEEK_CUR);
  135.        
  136.     /* read the data. */
  137.     pixels = (GLubyte*)malloc(size);
  138.        
  139.     if (pixels == NULL)
  140.         {
  141.                 printf("Error allocating memory for color-corrected image data");
  142.                 return 0;
  143.     }
  144.        
  145.     if ((i = fread(pixels, size, 1, file)) != 1)
  146.         {
  147.                 printf("Error reading image data from %s.\n", filename);
  148.                 return 0;
  149.     }
  150.        
  151.        
  152.     for (i = 0; i < size; i += 3)
  153.         { /* reverse all of the colors. (bgr -> rgb)*/
  154.                 temp = pixels[i];
  155.                 pixels[i] = pixels[i+2];
  156.                 pixels[i+2] = temp;
  157.     }
  158.        
  159.        
  160.     /* we're done.*/
  161.     return pixels;
  162. }
  163. static unsigned int getInt(FILE* fp)
  164. {
  165.         int c, c1, c2, c3;
  166.        
  167.         /* get 4 bytes*/
  168.         c = getc(fp);  
  169.         c1 = getc(fp);  
  170.         c2 = getc(fp);  
  171.         c3 = getc(fp);
  172.        
  173.         return ((unsigned int) c) +   
  174.                 (((unsigned int) c1) << 8) +
  175.                 (((unsigned int) c2) << 16) +
  176.                 (((unsigned int) c3) << 24);
  177. }
  178. static unsigned int getShort(FILE* fp)
  179. {
  180.         int c, c1;
  181.        
  182.         /*get 2 bytes*/
  183.         c = getc(fp);  
  184.         c1 = getc(fp);
  185.         return ((unsigned int) c) + (((unsigned int) c1) << 8);
  186. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-03-12 16:21 |只看该作者
#include <GL/glut.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

GLubyte*  readImage(const char*, GLsizei*, GLsizei* );
GLubyte  *pixels;
GLsizei   width, height;

void init(void)
{
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glClearColor(0.0, 0.0, 0.0, 0.0);
       
}

void display(void)
{
        unsigned int i, j, k, m;
        GLbyte r, g, b;
        GLubyte*  buffer;
       
    static clock_t start = 0, end = 0, t1 = 0, t2 = 0;
       
        buffer = (GLubyte*)malloc(width * height * 3);
       
        glClear(GL_COLOR_BUFFER_BIT);
        glRasterPos2i(240, 100);
       
        start = clock();
        for (i = 0; i < 1000; i++)
        {
                glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
        }
        end = clock();
        t1 = end - start;
       
        start = clock();
        for (m = 0; m < 1000; m++)
        {
                k = 0;
                glBegin(GL_POINTS);
                for (i = 0; i < height; i++)
                {
                        for (j = 0; j < width; j++)
                        {
                                r = pixels[k];
                                g = pixels[k+1];
                                b = pixels[k+2];
                               
                                glColor3ub(r, g, b);
                                glVertex2i(j, i);
                               
                                k += 3;
                        }
                }
                glEnd();
        }
        end = clock();
        t2 = end - start;
       
        glFlush();
}
void reshape(int w, int h)
{
        glViewport(0, 0, (GLsizei) w, (GLsizei) h);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho (0, w, 0, h, -1.0, 1.0);
        glMatrixMode(GL_MODELVIEW);
}
void keyboard(unsigned char key, int x, int y)
{
        switch (key)
        {
        case 27:
                exit(0);
                break;
        default:
                break;
        }
}
/*  Main Loop
*  Open window with initial window size, title bar,
*  RGBA display mode, and handle input events.
*/
int main(int argc, char** argv)
{
        pixels = readImage("blueguy\\blueguy.bmp", &width, &height);   
       
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
        glutInitWindowSize(500, 500);
        glutInitWindowPosition(100, 100);
        glutCreateWindow(argv[0]);
        init();
        glutReshapeFunc(reshape);
        glutKeyboardFunc(keyboard);
        glutDisplayFunc(display);
        glutMainLoop();
        return 0;
}
GLubyte* readImage( const char* filename, GLsizei* width, GLsizei *height )
{
    FILE* file;
        GLubyte*  pixels;
    unsigned long size;                 /* size of the image in bytes.*/
    unsigned long i;                    /* standard counter.*/
    unsigned short int planes;          /* number of planes in image (must be 1) */
    unsigned short int bpp;             /* number of bits per pixel (must be 24)*/
    char temp;                          /* temporary color storage for bgr-rgb conversion.*/
       
    /* make sure the file is there.*/
    if ((file = fopen(filename, "rb")==NULL)
        {
                printf("File Not Found : %s\n",filename);
                return 0;
    }
   
    /* seek through the bmp header, up to the width/height:*/
    fseek(file, 18, SEEK_CUR);
       
    /* No 100% errorchecking anymore!!!*/
       
    /* read the width*/
    *width = getInt(file);
    printf("Width of %s: %lu\n", filename, *width);
   
    /* read the height */
    *height = getInt(file);
    printf("Height of %s: %lu\n", filename, *height);
   
    /* calculate the size (assuming 24 bits or 3 bytes per pixel).*/
    size = (*width) * (*height) * 3;
       
    /* read the planes*/
    planes = getShort(file);
       
    if (planes != 1)
        {
                printf("lanes from %s is not 1: %u\n", filename, planes);
                return 0;
    }
       
    /* read the bpp*/
    bpp = getShort(file);
       
    if (bpp != 24)
        {
                printf("Bpp from %s is not 24: %u\n", filename, bpp);
                return 0;
    }
       
    /* seek past the rest of the bitmap header.*/
    fseek(file, 24, SEEK_CUR);
       
    /* read the data. */
    pixels = (GLubyte*)malloc(size);
       
    if (pixels == NULL)
        {
                printf("Error allocating memory for color-corrected image data";
                return 0;
    }
       
    if ((i = fread(pixels, size, 1, file)) != 1)
        {
                printf("Error reading image data from %s.\n", filename);
                return 0;
    }
       
       
    for (i = 0; i < size; i += 3)
        { /* reverse all of the colors. (bgr -> rgb)*/
                temp = pixels[i];
                pixels[i] = pixels[i+2];
                pixels[i+2] = temp;
    }
       
       
    /* we're done.*/
    return pixels;
}
static unsigned int getInt(FILE* fp)
{
        int c, c1, c2, c3;
       
        /* get 4 bytes*/
        c = getc(fp);  
        c1 = getc(fp);  
        c2 = getc(fp);  
        c3 = getc(fp);
       
        return ((unsigned int) c) +   
                (((unsigned int) c1) << +
                (((unsigned int) c2) << 16) +
                (((unsigned int) c3) << 24);
}
static unsigned int getShort(FILE* fp)
{
        int c, c1;
       
        /*get 2 bytes*/
        c = getc(fp);  
        c1 = getc(fp);
        return ((unsigned int) c) + (((unsigned int) c1) << ;
}

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
3 [报告]
发表于 2011-03-12 16:40 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
4 [报告]
发表于 2011-03-12 16:41 |只看该作者
本帖最后由 三月廿七 于 2011-03-12 16:48 编辑
很专业。看不太懂
static unsigned int getInt(FILE* fp)中的
int c, c1, c2, c3;能否定义为unsigned int ...
pmerofc 发表于 2011-03-12 16:40


当然可以,

说实话, 我很佩服你啊, 细节搞的那么透彻,
唉, 我只是(半调子/5) 的水平~~~

本人支持你打击一切不自然的写法~~

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
5 [报告]
发表于 2011-03-12 16:48 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
6 [报告]
发表于 2011-03-12 16:50 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
7 [报告]
发表于 2011-03-12 17:04 |只看该作者
本帖最后由 三月廿七 于 2011-03-12 17:14 编辑
过奖过奖。说实话我很想了解一下“双缓冲”,看了半天没看懂。能否给详细说说
pmerofc 发表于 2011-03-12 16:50


双缓冲原理很简单,

绘制图片 就是将内存中的 像素数据 传输到 帧缓冲区(屏幕缓冲),
原先不使用双缓冲(也就是不使用自己开辟的内存), 每绘制一次图片, 把内存中的 像素数据 传输到 帧缓冲区一次,
绘制1000次, 就得从内存传送数据1000次 到 帧缓冲区。
for (i = 0; i < 1000; i++)

        {

                glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels );

        }



现在自己开辟一块内存, 每绘制一次图片都是在自己开辟的内存中操作像素数据, 我记得 J2ME 有离屏缓冲, 可以很简单的使用 双缓冲, 如果是用c 语言
实现双缓冲, 就需要自己实现 图片的 旋转, 镜像等一系列操作。绘制1000次, 就在自己开辟的内存中绘图1000次, 最后再把 内存中的像素数据传输到 帧缓冲区,
这样就节省了大量的像素传输时间。
for (i = 0; i < 1000; i++)

        {

                memcpy(buffer, pixels, width * height * 3);

                //glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels );

        }

        glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer);


所以, 双缓冲的优点是能够 提高渲染速度, 相对的缺点是 需要耗掉与帧缓冲区一样大小的内存

论坛徽章:
2
程序设计版块每日发帖之星
日期:2015-06-17 22:20:00每日论坛发贴之星
日期:2015-06-17 22:20:00
8 [报告]
发表于 2011-03-12 17:10 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP