OPENGL学习笔记整理(三):缓冲区对象

缓冲区对象对于OPENGL来说,很重要,虽然我并不经常用它,在红宝书上它属于高级话题。

“在许多OPENGL操作中,我们都向OPENGL发送一大块数据,例如向它传递需要处理得顶点数组数据。传输这种数据可能非常简单,例如把数据从系统的内存中复制到图形卡。但是,由于OPENGL是按照客户机-服务器模式设计的,在OPENGL需要数据的任何时候,都必须把数据从客户机内存传到服务器。如果数据并没有修改,或者客户机和服务器位于不同的计算机(分布式渲染),数据的传输可能会比较缓慢,或者是冗余的。
OPENGL 1.5版本增加了缓冲区对象(buffer object),允许应用程序显式地指定把哪些数据存储在图形服务器中。”

由此可知,缓冲区对象在个人PC上,它存在于图形卡的显存中。最近经常需要用到缓冲区,因为开始接触到CUDA。CUDA是NVIDIA推出的GPU上的通用计算产品。因为是在显卡上做计算,想要和OPENGL进行互操作,用缓冲区比较方便。当然,在这里,我没打算把这两者结合起来说。这里只是简单的理一下缓冲怎么用而已。

在OPENGL中,我们经常看到glGen*、glBind*这样的函数,缓冲区的操作也不例外。

1.创建缓冲区对象 void glGenBuffers(GLsizei n, GLuint *buffers);(这个函数。。。顾名思义,就不用解释了)

2.激活缓冲区对象 void glBindBuffer(GLenum target, GLuint buffer);

3.用数据分配和初始化缓冲区对象 void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);

  (data为NULL,则缓冲区仅仅分配了空间,没有有意义的初始值;如果不是NULL,那就是data所指向的大小为size的内存的数据)

上面的很机械,也很好理解。本人刚开始接触OPENGL的时候,创建和初始化都没问题,但老是搞不清楚该怎么用,尤其是如何把它和纹理联系在一起。后来发现关键在下面这个函数GLvoid *glMapBuffer(GLenum target, GLenum access),这个函数的返回值是一个指针,就是指向这个缓冲区的指针,只要注意设置,确实能返回指向缓冲区的指针。

缓冲一经具体使用之后,只需要改变缓冲区的内容,即在glMapBuffer和glUnmapBuffer之间改变数据即可。

下面是个简单程序,其实就是红宝书上的,我简单的修改了一下而已,-_-! 

在键盘处理事件中可以看到如何更新缓冲区,让它放大,但如果改成缩小,貌似就会有问题,很奇怪的一个现象。

#include " stdafx.h "
#include
" stdlib.h "
#include
" gl/glew.h "
#include
" gl/glut.h "

#define BUFFER_OFFSET(bytes) ((GLubyte*) NULL + (bytes))
#define VERTICES 0
#define INDICES 1
#define NUM_BUFFERS 2
GLuint buffers[NUM_BUFFERS];

GLfloat vertices[][
3 ] = {
{
- 1.0f , - 1.0f , - 1.0f },
{
1.0f , - 1.0f , - 1.0f },
{
1.0f , 1.0f , - 1.0f },
{
- 1.0f , 1.0f , - 1.0f },
{
- 1.0f , - 1.0f , 1.0f },
{
1.0f , - 1.0f , 1.0f },
{
1.0f , 1.0f , 1.0f },
{
- 1.0f , 1.0f , 1.0f }
};
GLubyte indices[][
4 ] = {
{
0 , 1 , 2 , 3 },
{
4 , 7 , 6 , 5 },
{
0 , 4 , 5 , 1 },
{
3 , 2 , 6 , 7 },
{
0 , 3 , 7 , 4 },
{
1 , 5 , 6 , 2 }
};

GLfloat
* bdata;

void changeSize( int w, int h)
{
glViewport(
0 , 0 ,(GLsizei)w,(GLsizei)h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(
45.0 ,( double )w / ( double )h, 0.01 , 30 );
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void keyDown(unsigned char key, int x, int y)
{
switch (key)
{
case ' b ' :
bdata
= (GLfloat * )glMapBuffer(GL_ARRAY_BUFFER,GL_READ_WRITE);
for ( int i = 0 ; i < 24 ; i ++ )
{
* (bdata + i) *= 1.1f ;
}
glUnmapBuffer(GL_ARRAY_BUFFER);
glutPostRedisplay();
break ;
}
}

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

}
void display( void )
{
glLoadIdentity();
glTranslatef(
0.0f , 0.0f , - 5.0f );
glRotatef(
30.0f , 1.0f , 1.0f , 0.0f );


glDrawElements(GL_QUADS,
24 ,GL_UNSIGNED_BYTE,BUFFER_OFFSET( 0 ));

glutSwapBuffers();
}

void init( void )
{
glClearColor(
0.0f , 0.0f , 0.0f , 0.0f );
glShadeModel(GL_FLAT);
glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT);
glewInit();
glGenBuffers(NUM_BUFFERS,buffers);
glBindBuffer(GL_ARRAY_BUFFER,buffers[VERTICES]);
glBufferData(GL_ARRAY_BUFFER,
sizeof (vertices),vertices,GL_DYNAMIC_DRAW);
glVertexPointer( 3 ,GL_FLOAT, 0 ,BUFFER_OFFSET( 0 ));

glEnableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,buffers[INDICES]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof (indices),indices,GL_STATIC_DRAW);
}

int main( int argc, char * argv[])
{
glutInit(
& argc, argv);
glutInitDisplayMode(GL_DOUBLE
| GLUT_RGBA | GLUT_DEPTH);
glutInitWindowSize(
512 , 512 );
glutCreateWindow(
" Buffer Demo " );
glutReshapeFunc(changeSize);
glutMouseFunc(mouse);
glutKeyboardFunc(keyDown);
glutDisplayFunc(display);
init();
glutMainLoop();
return 0 ;
}

转载于:https://www.cnblogs.com/unsigned/archive/2011/02/24/1963875.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值