2012-02-08 77 views
1

这是我draw()功能用C语言编写,使用顶点数组:如何使用顶点缓冲区对象将使用顶点数组的OpenGL代码转换为代码?

void draw(float x1, float x2, float y1, float y2) 
{ 
    glPushMatrix(); 

    glScalef(1.0/(x2 - x1), 1.0/(y2 - y1), 1.0); 
    glTranslatef(-x1, -y1, 0.0); 
    glColor3f(1.0, 1.0, 1.0); 

    if(pts.size > 0) 
    { 
     glEnableClientState(GL_VERTEX_ARRAY); 
     glVertexPointer(2, GL_FLOAT, 0, (float*)pts.data); 
     glDrawArrays(GL_LINE_STRIP, 0, pts.size/2); 
     glDisableClientState(GL_VERTEX_ARRAY); 
    } 

    glPopMatrix(); 
}; 

调用之前draw()pts获取的更新update()函数内部:

void update(double (* func)(double x), float x1, float x2, int N) 
{ 
    double x, dx = (double)1.0/(double)N; 
    vector_cleanup(&pts); 
    m = 0; 
    for(x = x1; x < x2; x += dx) 
    { 
     vector_resize(&pts, pts.size + 2); 
     *(float*)vector_get(&pts, pts.size-2) = (float)x; 
     *(float*)vector_get(&pts, pts.size-1) = (float)func3(x); 
     m++; 
    } 
} 

我希望通过将这些代码使用VBO,我的图形性能会增加。

编辑:func3()可以是任何东西,例如, sin(x)或只是一些线性映射。我目前正在尝试做的就是了解我能多快地绘制一堆点。

+0

@NicolBolas:我看像http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html和http许多例子://www.opengl .org/wiki/VBO _-_ just_examples,但我甚至不知道如何以及在我的代码中我必须生成传递给'glGenBuffers(1,mybuffers);' – memyself 2012-02-08 16:26:52

+2

@memyself的缓冲区的位置,这可能是因为你用**'glGenBuffers'生成它们**。 – 2012-02-08 16:52:38

回答

1

使用GLEW延期扯皮:

#include <stdio.h> 
#include <stdlib.h> 
#include <math.h> 
#include <GL/glew.h> 
#include <GL/glut.h> 

typedef struct vector /*dynamic vector of void* pointers. This one is used only by the deflate compressor*/ 
{ 
    void* data; 
    size_t size; /*in groups of bytes depending on type*/ 
    size_t allocsize; /*in bytes*/ 
    unsigned typesize; /*sizeof the type you store in data*/ 
} vector; 

static unsigned vector_resize(vector* p, size_t size) /*returns 1 if success, 0 if failure ==> nothing done*/ 
{ 
    if(size * p->typesize > p->allocsize) 
    { 
    size_t newsize = size * p->typesize * 2; 
    void* data = realloc(p->data, newsize); 
    if(data) 
    { 
     p->allocsize = newsize; 
     p->data = data; 
     p->size = size; 
    } 
    else return 0; 
    } 
    else p->size = size; 
    return 1; 
} 

static void vector_cleanup(void* p) 
{ 
    ((vector*)p)->size = ((vector*)p)->allocsize = 0; 
    free(((vector*)p)->data); 
    ((vector*)p)->data = NULL; 
} 

static void vector_init(vector* p, unsigned typesize) 
{ 
    p->data = NULL; 
    p->size = p->allocsize = 0; 
    p->typesize = typesize; 
} 

static void* vector_get(vector* p, size_t index) 
{ 
    return &((char*)p->data)[index * p->typesize]; 
} 


/* function to calculate each data point */ 
float func(float x) 
{ 
    return (float)sin(x); 
} 

GLuint vbo = 0; 
GLsizei vertcount = 0; 
void update(float (* func)(float x), float x1, float x2, int N) 
{ 
    float x, dx = 1.0f/N; 
    vector pts; 

    vector_init(&pts, sizeof(float)); 
    for(x = x1; x < x2; x += dx) 
    { 
     vector_resize(&pts, pts.size + 2); 
     *(float*)vector_get(&pts, pts.size-2) = x; 
     *(float*)vector_get(&pts, pts.size-1) = func(x); 
    } 

    vertcount = (GLsizei)(pts.size/2); 
    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glBufferData(GL_ARRAY_BUFFER, pts.size * pts.typesize, pts.data, GL_DYNAMIC_DRAW); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    vector_cleanup(&pts); 
} 

/* plotting function - very slow */ 
void draw(float x1, float x2, float y1, float y2) 
{ 
    glPushMatrix(); 

    glScalef(1.0f/(x2 - x1), 1.0f/(y2 - y1), 1.0f); 
    glTranslatef(-x1, -y1, 0.0f); 
    glColor3f(1.0f, 1.0f, 1.0f); 

    glBindBuffer(GL_ARRAY_BUFFER, vbo); 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glVertexPointer(2, GL_FLOAT, 0, 0); 
    glDrawArrays(GL_LINE_STRIP, 0, vertcount); 
    glDisableClientState(GL_VERTEX_ARRAY); 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    glPopMatrix(); 
}; 

/* Redrawing func */ 
float xmin = -10, xmax = 10, ymin = -5, ymax = 5; 
void redraw(void) 
{ 
    glClearColor(0, 0, 0, 0); 
    glClear(GL_COLOR_BUFFER_BIT); 
    glMatrixMode(GL_MODELVIEW); 
    glLoadIdentity(); 

    // -x, +x, -y, +y, number points 
    draw(xmin, xmax, ymin, ymax); 

    glutSwapBuffers(); 
}; 

/* Idle proc. Redisplays, if called. */ 
int nPoints = 3000; 
void idle(void) 
{ 
    // shift 'xmin' & 'xmax' by one. 
    xmin++; 
    xmax++; 

    update(func, xmin, xmax, nPoints); 

    glutPostRedisplay(); 
}; 

/* Key press processing */ 
void key(unsigned char c, int x, int y) 
{ 
    if(c == 27) exit(0); 
}; 

/* Window reashape */ 
void reshape(int w, int h) 
{ 
    glViewport(0, 0, w, h); 
    glMatrixMode(GL_PROJECTION); 
    glLoadIdentity(); 
    glOrtho(0, 1, 0, 1, -1, 1); 
    glMatrixMode(GL_MODELVIEW); 
}; 

/* Main function */ 
int main(int argc, char **argv) 
{ 
    GLenum err; 

    glutInit(&argc, argv); 
    glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE); 
    glutCreateWindow("Graph plotter"); 
    glutReshapeWindow(1024, 800); 

    // init GLEW and output some GL info 
    err = glewInit(); 
    printf("GL_VERSION : %s\n", glGetString(GL_VERSION) ); 
    printf("GL_VENDOR : %s\n", glGetString(GL_VENDOR) ); 
    printf("GL_RENDERER : %s\n", glGetString(GL_RENDERER)); 
    if(GLEW_OK != err) 
    { 
     printf("glewInit failed: %s", glewGetErrorString(err)); 
     return EXIT_FAILURE; 
    } 

    if(!glewIsSupported("GL_VERSION_1_5")) 
    { 
     printf("OpenGL version 1.5 or greater required.\n"); 
     return EXIT_FAILURE; 
    } 

    glGenBuffers(1, &vbo); 

    /* Register GLUT callbacks. */ 
    glutDisplayFunc(redraw); 
    glutKeyboardFunc(key); 
    glutReshapeFunc(reshape); 
    glutIdleFunc(idle); 

    /* Init the GL state */ 
    glLineWidth(2.0); 

    /* Main loop */ 
    glutMainLoop(); 
    return 0; 
} 
+0

为什么我需要在'update()'和'draw()'函数中调用'glBindBuffer'?这对性能有什么影响或者是不相关的?另外:我使用中间模式,顶点数组和顶点缓冲区对象获得与代码大致相同的FPS。为什么会这样?我曾希望看到一个显着的加速。 – memyself 2012-02-08 23:07:52

+1

'update()'需要知道哪个VBO加载数据,'draw()'需要知道从哪个VBO渲染。你看到什么样的帧时间(以毫秒为单位)? – genpfault 2012-02-08 23:21:18

+0

如果我设置了'nPoints = 300000',我的整个'idle()'函数花费大约30ms(我知道这有很多要点,但是现在我们不要进入这一点)。然而'redraw()'函数总是0ms。所以我想知道是否需要更改我的代码,以便update()在单独的线程中计算? (我通过调用'glutGet(GLUT_ELAPSED_TIME)'来计算FPS并计算自上次调用以来计数的帧数) – memyself 2012-02-08 23:31:50