OpenGL超级宝典(第7版)笔记19 用缓冲为VS提供数据 清单5.1-5.8

OpenGL超级宝典(第7版)笔记19 用缓冲为VS提供数据 清单5.1-5.8


前言

上一篇我们把向量、矩阵、摄像机的类做了介绍,并且实现了3D下的移动。但是我们遇到了一个比较麻烦的事情,就是我们在输入顶点数据的时候,仍然采用将数据内置到shader中并用gl_VertexID来调用,非常的麻烦。如果我们有建模软件得到的模型(可能包含成千上万的三角面),我们不能都把它弄到shader中去,太麻烦了。

这回我们将通过建立缓存,并把缓冲中的数据自动的填充到shader中去,实现大量顶点的输入。

1 具体的思路

首先我们要学习怎样建立缓冲区,怎样设置缓冲区大小并初始化,怎样修改缓冲区中的数据(直接修改、通过指针修改),怎样实现缓冲区之间的数据拷贝,怎样把缓冲区中的数据填充到顶点着色器的顶点属性中。
涉及到的清单为5.1-5.8

先放一个函数的流程图:
在这里插入图片描述
我们将慢慢带大家把这个流程走一遍,大家也在看完之后可以在回到这个流程图,看看这些内容是否都理解了。(先提示一下这节比较难的是两个,一是glVertexArrayAttribFormat解释缓冲区的数据结构,二是glVertexArrayAttribBinding主要是VAO中的各种绑定,这里很容易乱)

2 创建缓冲区并进行初始化 清单5.1

我们首先要创建一个缓冲区,使用glCreateBuffers来创建,可以同时创建多个缓冲区。glCreateBuffers通过指针传回的是缓冲区的一串数字,用于代表该缓冲区的名字(其本事并不是缓冲区的指针,OpenGL把这个名字的值和缓冲区本身做了分离,不像我们自己的数组,数组名字就代表了指向数据的指针),你可以把这个数字看成是缓冲区的编号。

创建完缓冲区后我们要对缓冲区进行初始化(指定大小,并初始化数据)。可以有两种方法:
一是通过缓冲区的编号来对缓冲区做初始化,即glNamedBufferStorage,
二是对指定的绑定点上绑定的缓冲区做初始化,即glBufferStorage。注意需要先用glBindBuffer把需要初始化的缓冲区绑定在特定的绑定点上。
(打个比方:第一种就是把数据送给叫张三的人,只可能给到张三不会给到其他人。而第二种是把数据送给绑在第X根柱子上的人,绑在第X根柱子上的人可能是张三也可能是其他人,就看谁在那之前被绑在了第X根柱子上)

比如我下面就通过两种方式分别把两个缓冲区进行了初始化:

	GLuint vertex_buffer[2];
	glCreateBuffers(2,&vertex_buffer[0]);
	//这时候就生成了两个缓冲区对象,分别是vertex_buffer[0]和vertex_buffer[1]
	
	glNamedBufferStorage(vertex_buffer[1], 128 * 128, NULL, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);
	//这里直接通过缓冲区对象进行初始化
	//注意这里是|而不是||

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]);
	glBufferStorage(GL_ARRAY_BUFFER, 128 * 128, NULL, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);
	//这里通过先把vertex_buffer[0]绑定在绑定点GL_ARRAY_BUFFER上
	//再通过指明 向GL_ARRAY_BUFFER上绑定的缓冲区(即vertex_buffer[0])进行初始化,来完成vertex_buffer[0]的初始化
	//注意这里是|而不是||

目前看来glNamedBufferStorage还是方便一些。

3 更新缓冲中的内容 清单5.2-5.3

初始化完成后,我们要知道怎样对之前缓冲区中的初始数据进行修改,这里有两类方法一是直接拷贝覆盖,二是通过指针拷贝覆盖。而两种方法又各自分为直接对缓冲区对象操作、通过绑定点进行间接操作(就和glBufferStorage与glNamedBufferStorage的关系一样)

我将他们依次展示一遍:
直接拷贝(对绑定点间接操作)

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]);
	glBufferSubData(GL_ARRAY_BUFFER,0,sizeof(Data0),Data0);

直接拷贝(对缓冲区对象直接操作)

	glNamedBufferSubData(vertex_buffer[1],0,sizeof(Data1),Data1);

指针拷贝(对绑定点间接操作)

	glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer[0]);
	void* vptr0 = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);//找到位置
	memcpy(vptr0, Data0, sizeof(Data0));
	glUnmapBuffer(GL_ARRAY_BUFFER);//解除对缓存的映射

指针拷贝(对缓冲区对象直接操作)

	void* vptr1 = glMapNamedBuffer(vertex_buffer[1], GL_WRITE_ONLY);//找到位置
	memcpy(vptr1, Data1, sizeof(Data1));
	glUnmapNamedBuffer(vertex_buffer[1]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值