第三十八章 立方体贴图和GLSL总结

学习一些缓冲函数,以及如何用纹理对象来存储大量的数据。

OpenGL中的缓冲是一个管理特定内存块的对象,没有额外的功能。将它绑定到一个缓冲目标时,才有意义。当前,是使用glBufferData来填充缓冲对象管理的内存,
该函数会分配一块内存,并将数据添加到这块内存中。如果将data参数设置为NULL,那么这个函数只会分配内存,但不进行填充。需要预留特定大小的内存。

现在看下函数glBufferSubData,可以填充缓冲的特定区域。该函数需要一个缓冲目标,一个偏移量,数据的大小和数据本身作为它的参数。
该函数是可以提供一个偏移量,指定从何处开始填充这个缓冲。
当然,缓冲需要有足够的已分配的内存,对一个缓冲调用glBufferSubData之前必须先调用glBufferData
glBufferSubData(GL_ARRAY_BUFFER, 24, sizeof(data), &data); // 范围: [24, 24 + sizeof(data)]

将数据导入缓冲还有一种方法:请求缓冲内存的指针,直接将数据复制到缓冲中。
调用glMapBuffer,会返回当前绑定缓冲的内存指针:
float data[] = {
0.5f, 1.0f, -0.35f

};
glBindBuffer(GL_ARRAY_BUFFER, buffer);
// 获取指针
void *ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
// 复制数据到内存
memcpy(ptr, data, sizeof(data));
// 记得告诉OpenGL我们不再需要这个指针了
glUnmapBuffer(GL_ARRAY_BUFFER);————解除映射后,指针就不再可用了
如果OpenGL能够成功将数据映射到缓冲中,这个函数就会返回GL_TRUE

使用点:
直接映射数据到缓冲,而不事先将其存储到临时内存中,使用glMapBuffer挺好。
可以从文件中读取数据,并直接将它们复制到缓冲内存中。

了解一下:分批顶点属性
通过使用glVertexAttribPointer,可以指定顶点数组缓冲内容的属性布局。
因为,顶点数组中,属性是交错处理的,每一个顶点的位置,法线,纹理坐标都是放到一起的。分批顶点属性是另外一种处理方法:
将每一种属性类型的向量数据打包为一个大的区块,而不是对他们进行交错存储。
当从文件中加载顶点数据的时候,通常获取到的是一个位置数组,一个法线数组和(如果有的话:一个纹理坐标数组)。
可以用分批的方式解决该问题:使用glBufferSubData函数
float positions[] = { … };
float normals[] = { … };
float tex[] = { … };
// 填充缓冲
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(positions), &positions);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions), sizeof(normals), &normals);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(positions) + sizeof(normals), sizeof(tex), &tex);
这样就直接将属性数组作为一个整体传递给缓冲,而不需要事先处理它们。也可以合并成一个大数组,再使用glBufferData来填充。

还需要更新顶点属性指针来反应这些改变:
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), 0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)(sizeof(positions)));
glVertexAttribPointer(
2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)(sizeof(positions) + sizeof(normals)));

stride参数等于顶点属性的大小,因为下一个顶点属性 向量能在x个分量之后找到。

下面看下:复制缓冲
缓冲填充好数据后,可以与其他的缓冲共享其中的数据,或者要将缓冲的内容复制到另一个缓冲当中。glCopyBufferSubData能容易地从一个缓冲中复制数据到另一个
缓冲中。原型如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用OpenGL来创建渐变立方体。以下是一个使用OpenGL和GLSL(OpenGL Shading Language)的示例代码来实现渐变立方体的基本效果: ```c++ #include <GL/glut.h> GLfloat vertices[] = { -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 }; GLfloat colors[] = { 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 1.0f }; GLubyte indices[] = { 0, 3, 2, 1, 2, 3, 7, 6, 0, 4, 7, 3, 1, 2, 6, 5, 4, 5, 6, 7, 0, 1, 5, 4 }; void display() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); gluLookAt(0.0f, 0.0f, 8.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_COLOR_ARRAY); glVertexPointer(3, GL_FLOAT, 0, vertices); glColorPointer(3, GL_FLOAT, 0, colors); glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, indices); glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glutSwapBuffers(); } void reshape(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); glutInitWindowSize(800, 600); glutCreateWindow("Gradient Cube"); glutDisplayFunc(display); glutReshapeFunc(reshape); glEnable(GL_DEPTH_TEST); glutMainLoop(); return 0; } ``` 这段代码使用了OpenGL的固定管线(Fixed Function Pipeline)来绘制一个带有颜色渐变的立方体立方体的顶点坐标存储在`vertices`数组中,每个顶点对应的颜色存储在`colors`数组中,立方体的面索引存储在`indices`数组中。`display`函数用于绘制立方体,`reshape`函数用于处理窗口大小改变时的透视投影变换。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值