我今天刚开始从本教程开始学习OpenGL:http://openglbook.com/the-book/
我到了第2章,在那里画了一个三角形,我理解除了VAO之外的一切(这个首字母缩略词好吗?).本教程有以下代码:
glGenVertexArrays(1, &VaoId);
glBindVertexArray(VaoId);
Run Code Online (Sandbox Code Playgroud)
虽然我知道代码是必要的,但我不知道它的作用.虽然我从不使用VaoId(除了销毁它),但如果没有它,代码就无法运行.我假设这是因为它需要被绑定,但我不知道为什么.这个确切的代码是否只需要成为每个OpenGL程序的一部分?该教程将VAO解释为:
顶点数组对象(或VAO)是描述顶点属性如何存储在顶点缓冲区对象(或VBO)中的对象.这意味着VAO不是存储顶点数据的实际对象,而是顶点数据的描述符.顶点属性可以通过glVertexAttribPointer函数及其两个姐妹函数glVertexAttribIPointer和glVertexAttribLPointer来描述,我们将在下面探讨其中的第一个.
我不明白VAO如何描述顶点属性.我没有以任何方式描述它们.它是否从glVertexAttribPointer获取信息?我想这一定是它.VAO只是glVertexAttribPointer信息的目的地吗?
另外,我遵循的教程是否可以接受?有什么我应该注意的或更好的教程可以遵循?
经过多年关于顶点缓冲对象(VBO)的讨论,我终于决定尝试它们(我的东西通常不是性能关键,显然......)
我将在下面描述我的实验,但总而言之,我看到"简单"直接模式(glBegin()/ glEnd()),顶点数组(CPU端)和VBO(GPU端)之间无法区分性能渲染模式.我试图理解为什么会这样,并且在什么条件下我可以期待看到VBO明显优于他们原始(双关语)的祖先.
对于实验,我生成了一个具有大量点的(静态)3D高斯云.每个点都有与之关联的顶点和颜色信息.然后我在连续的帧中围绕云旋转相机,这是一种"轨道"行为.同样,这些点是静态的,只有眼睛移动(通过gluLookAt()).数据在任何渲染之前生成一次并存储在两个数组中以用于渲染循环.
对于直接渲染,整个数据集在单个glBegin()/ glEnd()块中呈现,其中包含一个循环,每个循环包含glColor3fv()和glVertex3fv().
对于顶点数组和VBO渲染,整个数据集使用单个glDrawArrays()调用进行渲染.
然后,我只需在紧凑的循环中运行一分钟左右,并使用高性能计时器测量平均FPS.
如上所述,我的台式机(XP x64,8GB RAM,512 MB Quadro 1700)和笔记本电脑(XP32,4GB RAM,256 MB Quadro NVS 110)的性能难以区分.然而,它确实按照预期的点数进行了扩展.显然,我也禁用了vsync.
笔记本电脑运行的具体结果(使用GL_POINTS渲染):
在glBegin()/ glEnd():
顶点阵列(CPU端):
顶点缓冲对象(GPU端):
我用C++和OpenGL编写了一个模型加载器.我用std::vectors来存储我的顶点数据,但现在我想把它传递给它glBufferData(),但是数据类型却截然不同.我想知道如果有之间进行转换的方式std::vector所记录const GLvoid *的glBufferData().
typedef struct
{
float x, y, z;
float nx, ny, nz;
float u, v;
}
Vertex;
vector<Vertex> vertices;
Run Code Online (Sandbox Code Playgroud)
glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
Run Code Online (Sandbox Code Playgroud)
我得到以下(预期)错误:
error: cannot convert ‘std::vector<Vertex>’ to ‘const GLvoid*’ in argument passing
Run Code Online (Sandbox Code Playgroud)
如何将矢量转换为兼容的类型glBufferData()?
NB.我不关心目前正确的内存分配; vertices.size() * 3 * sizeof(float)很可能是段错误,但我想先解决类型错误.
我试图理解这两个,如何使用它们以及它们是如何相关的.假设我想创建一个简单的地形和一个纹理立方体.对于这两个对象,我有三角形顶点的数组,对于立方体,我有一个包含纹理数据的数组.我的问题是:如何使用VAO和VBO来创建和渲染这两个?
有许多教程和书籍,但我仍然不知道如何理解和使用这些概念.
我正在使用OpenGL ES 2.0,但我认为它也与非ES有关:如何知道在创建VBO时选择什么"用法"?
这个特殊的VBO将在完全更新之前使用1到4次,我不确定是否必须选择GL_STREAM_DRAW或GL_DYNAMIC_DRAW.
从效率的角度来看(或者如果它很重要的另一种观点),什么是可取的?
情况
一种OpenGL应用程序,每帧(60 fps)在不同位置绘制许多行.可以说有10行.或100 000行.答案会有所不同吗?
每一帧每行都会有一个glDrawArrays调用,而在两者之间会有矩阵变换来定位我们的一行
每个帧都有一个绘制调用
我有许多粒子,每个帧都会改变顶点.当前正在使用"客户端"内存中的顶点数组绘制顶点.如果我使用顶点缓冲区对象,我可以期待什么性能特征?
因为我必须使用一些glBuffersubData来更新粒子顶点,所以我无论如何都要将每个帧的顶点转移到视频内存(就像我使用常规顶点数组一样)?在这种情况下,VBO有什么好处吗?
这适用于iOS设备.实际的绘制调用:glDrawElements(GL_POINTS,num_particles,GL_UNSIGNED_SHORT,pindices);
我应该使用GL_STREAM_DRAW或GL_DYNAMIC_DRAW?
在给定的绘图调用中解除使用glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)和/或glBindBuffer(GL_ARRAY_BUFFER, 0)结束时,对我来说似乎更清晰.我喜欢确定什么都不应该是不应该的; 但是,这有很大的性能影响吗?
有人会认为这样做是"干净"的方式吗?或者我应该沿着快速而漫长的路线走下去?
(是的,我知道绑定的缓冲区对象将被下一个要绑定在该目标上的缓冲区对象替换 - 无论是在这个还是下一个渲染更新中.是的,我可以进行性能测试.但是快速的人类反应会很好.)
我必须绘制一个包含几千个顶点的缓冲区.我正在使用vbo来存储数据.
我知道我将不得不多次更新VBO - 但一次只能处理一小部分.
所以我想知道这样做的最佳方法是:
glBufferSubData()电话?glMapBuffer()和一个大的VBO?我想要做的是使用相同的vbo多次渲染网格但具有不同的偏移.例:
//Load VBO
glGenBuffers(2, &bufferObjects[0]);
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)*size(vertices)*3, &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(int)*size(indices), &indices[0], GL_STATIC_DRAW);
//Render VBO
glBindBuffer(GL_ARRAY_BUFFER, bufferObjects[VERTEX_DATA]);
glVertexPointer(3, GL_FLOAT, 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bufferObjects[INDEX_DATA]);
glDrawElements(renderFlag, nrIndices, GL_UNSIGNED_INT, 0);
Run Code Online (Sandbox Code Playgroud)
如果我同时绘制孔网格没有问题,但是可以使用不同的起始索引绘制相同的网格,如下所示:
glDrawElements(renderFlag, 20, GL_UNSIGNED_INT, "WHAT TO WRITE HERE"?);
Run Code Online (Sandbox Code Playgroud)