OpenGL3.3缓冲数据

阅读: 评论:0

OpenGL3.3缓冲数据

OpenGL3.3缓冲数据

什么是VAO

Vertex Array Object 顶点数组对象
存储了所有需要提供给 ”Vertex data“的”状态“信息

VAO有什么用

OpenGL在绘制的时候,需要知道顶点信息——”位置“、”颜色“、”法线“等可以在哪里取得,怎么取得,在VAO出现以前,我们在绘制之前需要调用glVertexAttribPointer(…)函数设置这些信息,如果不使用VAO 那么每一次绘制都需要重新设置顶点状态信息,而有了VAO之后,我们便可以将这些顶点状态信息存储起来,需要绘制时,我们只需要在绘制之前调用之前绑定相应的VAO就行
简单来说VAO有点像一个中介,把所有繁琐的绑定和顶点设置工作都集中起来处理,我们需要绘制时,直接找这个中介就好了
通过测试:
从glBindVertexArray(VAO);开始 到 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);之间 中间的 对顶点的设置都会被记录到VAO 记住 只是这些设置会被记录 而不是这些顶点数据会被记录 VAO并不存储顶点数据,只是记录了顶点相关的状态(譬如顶点位置的格式(几个数字算一个顶点)以及顶点位置的数据(?)、纹理坐标的格式以及纹理坐标的数据)。而且他记录了是哪一个VBO VBO这个变量就像一个指针 他指示了他管理的那一片缓冲的地址 所以如果在VAO记录VBO之后 使用glBindBuffer变换当前绑定在GL_ARRAY_BUFFER的vbo 使用VAO绘制出来的图像也不会变
所以就能解释如果在glVertexAttribPointer之前 glBindbufferData没有存入数据 而是NULL开辟空间 此时VAO记录了当前VBO 之后给VAO绑定的VBO里面存储顶点 那么还是可以绘制出来的

什么是VBO

Vertex Buffer Objects顶点缓冲对象
VBO主要是管理存储顶点数据的GPU中的内存
使用这VBO的好处是我们可以一次性的发送一大批数据到显卡上,而不是每个顶点发送一次

什么是EBO

glGenBuffers函数(就是用来创建缓冲对象的 比如VBO这种)

unsigned int VBO; glBenBuffers(1,&VBO);使用glBenBuffers函数和一个缓存id生产一个VBO对象(这个函数会给VBO一个缓冲id,从此VBO就是一个缓冲对象了)

glBindBuffer函数 (绑定缓冲)

glBindBuffer(GL_ARRAY_BUFFER,VBO);
使用glBindBuffer函数把新创建的缓冲绑定到GL_ARRAY_BUFFER上,GL_ARRAY_BUFFER是顶点缓冲对象的缓冲类型(OpenGL允许同时绑定多个缓冲,只要他们是不同的缓冲类型)(也就是把VBO定义为了一个顶点缓冲对象)
在绑定缓冲后 我们使用的任何(在GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)
除了GL_ARRAY_BUFFER 还有其他的 例如GL_COPY_READ_BUFFER等

glBufferData函数 (给缓冲存数据)

glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_TAIC_DRAW);调用glBufferData函数把之前定义的顶点数据复制到缓冲的内存中(vertices是之前定义的一个float类型的顶点数组)(就是把顶点数组里面的信息复制给顶点缓冲目标GL_ARRAY_BUFFER,因为VBO绑定在这个上面,所以就是配置了VBO)
glBufferData函数第一个参数是目标缓冲的类型(就是要把数据传给谁)
第二个参数是传输数据的大小
第三个参数是实际发送的数据
第四个参数是我们希望显卡如何管理给定的数据
GL_STATIC_DRAW:数据不会或几乎不会改变
GL_DYNAMTC_DRAW:数据会被改变很多
GL_STREAM_DRAW:数据每次绘制时都会改变
也就是当你的这个数据在运行的时候如果经常可能变化 就用后面两种,这样能确保显卡把数据放在能够高速写入的内存部分

在顶点着色器中 GL_POSITION后面的就是最终的输出位置 是vec4类型

glNamedBufferStorage(GLuint buffer,GLsizeiptr size,const void *data,GLbirfield flags)(和上面函数类似 也是给buff存数据)

其他参数和上面差不多 就是flags参数
GL_DYNAMIC_STORAGE_BIT: 设置之后缓存的内容可以通过glNamedBufferSubData()直接进行修改
**GL_MAP_READ_BIT:**映射缓存数据到CPU端进行读取 如果没有设置的话 当前缓存调用glMapNamedBufferRange()来获取权限的做法都会失败
**GL_MAP_WRITE_BIT:**设置之后 映射缓存数据到CPU端进行写入 后面的同上
**GL_MAP_PERSISTENT_BIT:**缓存数据的映射是永久性的 在渲染中始终有效 这个标识必须在映射的时候同时进行设置才能创建一致的映射表
**GL_MAP_COHERENT_BIT:**数据在CPU端和GPU端映射保持一致 后面同上一个
GL_MAP_STORAGE_BIT: 对于不一致的内存系统架构来说 有些内存可能从宿主主机访问更为高效 而有些内存可能从GPU访问效率更高 在确保其他表示量都设置正确之后 我们可以通过这个标识来应道OPENGL优先从CPU(宿主)端进行访问来提高效率

void glBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const GLvoid * data);

用这个函数先要用glBufferData开辟一下空间

(缓存的部分初始化)glNamedBufferSubData(GLuint buffer,GLintptr offset,GLsizeiptr size,const void *data)

缓存从offset字节处开始需要使用地址为data 大小为size的数据块进行更新 如果offset和data综合超出缓存对象绑定的数据范围则会返回一个错误
这里实际上就是把应用程序内存中的数据拷贝到OpenGL管理的内存中

(拷贝缓存数据)glCopyNamedBufferSubData(GLuint readBuffer,GLuint writeBuffer,GLintptr readoffset,GLintptr wrieoffset,GLsizeiptr size)

将名为readBuffer的缓存对象的一部分数据拷贝到名为writer Buffer的缓存对象的数据区域上 readBuffer的数据从readoffset位置开始复制size个字节 拷贝到 writerBuffer数据的writeroffset的位置
这里实际上就是把OpenGL管理的内存中的一部分数据拷贝到另一个OpenGL管理的内存中

(读取缓存数据)glGetNamedBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,void *data)

但是glGetBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,void *data)用的更多
glGetBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(cubeModel), feedback);
将target类型的部分数据读取到data中
这里实际上就是把OpenGL管理内存中的一部分数据拷贝到应用程序内存中

glMapBuffer(GLenum target,GLenum access)

void *data = glMapbuffer(GL_COPY_WEITE_BUFFER,GL_WRITE_ONLY);
这样data这个指针就是指向绑定在GL_COPY_WEITE_BUFFER的缓存对象 如果我们给data添加数据 缓存对象也会相应增加数据
创建了一个指针 可以直接在应用程序中队OpenGL管理的指定内存进行访问
将当前绑定到target的缓存对象的整个数据区域映射到客户端的地址空间下 也就是返回的那个指针就是被映射到客户端的地址空间
将一个缓冲区对象中的数据映射为客户端中的地址空间

例子

主要完成的功能是 我们需要不断地更新VBO里面的顶点信息 虽然使用
glBufferData();再将数据放进VBO也能实现同样功能 但是会执行不必要的操作(开辟空间等) 而下面代码就是将temp是更新后的顶点数组(也就是比如将顶点(1.0,0.0)删除等)给指针data 这样就实现了VBO的数据更新

 void* data = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);memcpy(data, temp, QuadVertices.size()  * sizeof(float));

GLboolean glUnmapBuffer( GLenum target)

释放缓冲区对象与客户端地址空间的关系

glMapNamedBufferRange(GLuint buffer,GLintptr offset,GLsizeiptr length,GLbitfield access)(和上面的类似)

将缓存对象buffer中的数据的一部分映射到应用程序的地址空间中
access位必须包含GL_MAP_READ_BIT和GL_MAP_WRITE_BIT中的一个或者两个 以确认应用程序是否队映射数据进行读操作或者写操作 或者两者都有
access可以包含一个或者多个其他标识符 其他的还有:
GL_MAP_INVALIDATE_RANGE_BIT 给定的缓冲区域内任何数据都可以被抛弃以及无效化 如果给定区域范围内任何数据没有被随后重新写入 那么他将变成未定义的数据 该标识符无法与GL_MAP_READ_BIT同用
GL_MAP_INVALIDATE_BUFFER_BIT缓存的整个内容都可以被抛弃和无效化 不再受区域范围的设置影响 和上面的区别就是变成整个范围(不要队每个区域都设置GL_MAP_INVALIDATE_BUFFER_BIT 否则只有最后一个映射区域的数据才是有效的)
GL_MAP_GLUSH_EXPLICIT_BIT应用程序将负责通知OpenGL映射范围内的哪个部分包含了可用数据 方法是 调用flUnmapNamedBuffer()之前调用glFlushMappedNamedBufferRange()
GL_MAP_UNSYNCHRONIZED_BIT如果这个位标识符没有设置的化 那么OpenGL会等待所有正在处理的缓存访问操作结束 然后再返回映射范围的内存 如果设置了这个标识符 OpenGL将不会尝试进行这样的缓存同步操作

*glVertexAttribPointer(GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const GLvoid pointer)函数 (设置相应规则在VAO中)

glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3sizeof(float),(void)0);glVertexAttribPointer告诉OpenGL如何解析顶点数据 这些规则都记录在当前绑定的VAO中
第一个参数是指定我们要配置的顶点属性,因为前面写的layout(location=0);(应该也就是从0这个位置传入数据)
第二个参数是指定顶点属性的大小(因为顶点属性是vec3)每个顶点中需要更新的元素个数 这里一般是1,2,3,4 也可也是GL_BGRA(这个专用于压缩顶点数据的格式设置)
第三个参数是数据的类型(因为vec3里面都是float类型)
第四个参数是是否希望传入的数据标准化(也就是所有数据都映射在0-1之间)
第五个参数是说明顶点数据之间的间隔(也就是每个顶点之间隔了多远的数据间隔)
第六个参数是void*目前不知道是干嘛的 目前感觉应该是跨越多少个字符

关于normalize:

一般整形的数据传进去 OpenGL都会将这些数据转换为浮点数 才可以将他们读取到浮点数的顶点属性中 如果normalize是false 那就是强制转换为float
整数4传进来 type设置的是4.0 则着色器中传入的值就是4.0
如果是ture则有 如果数据类型是有符号的 计算公式是:
f= c(2b-1) 如果是有符号的则 f= (2c+1)/(2b-1) f是浮点数值 c标识输入的整数分量 b标识数据类型的位数(GL_SHORT是16 GL_UNSIGNED_BYTE是8)

关于type


type也可也是特殊值 GL_INT_2_10_10_10_REV或者GL_UNSIGNED_INT_2_10_10_10_REV 表示了一种有4个分量的数据类型 前三个分量每个都占据10个字节 第四个分量占据2个字节 具体看书89面

glEnabelVertexAttribArray函数

glEnabelVertexAttribArray(0);函数是以顶点属性位置值作为参数,启用顶点属性。顶点属性默认是禁用的

缓存的掩码

缓存掩码一般在混合时使用 因为如果立方体是透明的时候 我们希望的是透过立方体的前面能看到立方体的后面 但是混合是针对物体间,立方体6个面之间不能存在混合,所以我们看到的效果是立方体前面遮盖住了立方体后面
(由于启用深度测试,后面Z值在后,因此不会绘画)如果此时我们关闭GL_DEPTH_TEST,就会让立方体的每个面都进行绘画,哪怕他们的Z序是被遮挡的 glDepthMask();就是解决这个问题 感觉就是在立方体内部绘制的时候可以关闭深度测试
所有GLboolean的掩码的默认值都是GL_TRUE GLuint掩码默认值为1

glColorMask(GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)

glColorMask(GLuint buffer,GLboolean red,GLboolean green,GLboolean blue,GLboolean alpha)

glDeprhMask(GLboolean flag)

参数flag为GL_TRUE 那么深度缓存可以写入 否则无法写入

glStencilMask(GLboolean mask)

mask参数用于与模板值进行按位“与”操作 如果对应位操作的结果为1 像素的模板值可以写入 如果为0无法写入

glSrencilMaskSeparate(GLenum face,Gluint mask)

本文发布于:2024-01-30 03:43:23,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170655740918986.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23