您好我已尽力了解代码的这一部分内容,但我没有运气。
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
glBindVertexArrayOES(0);
这属于在xcode 4.2上创建OpenGL游戏的模板。但是我很困惑,如果有人能向我解释,我会很高兴。
首先,如何生成并绑定_vertexArray而不向其添加任何内容?
其次,IF gCubeVertexData是216的数组,具有以下内容:
GLfloat gCubeVertexData[216] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ, normalX, normalY, normalZ,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
我想我正在处理这个数组用于以下命令,其中我启用GLK属性,这就是我使用指针(仍使用prev绑定的)。但是,如果我没有弄错的语法是,(属性设置,顶点的大小,类型,假,结构的大小(我认为不是24),并从数据偏移(12来自哪里?!))
和最后一个问题,为什么我现在将0绑定到顶点数组?
编辑:要诚实我不会尝试在不同的网站上研究opengl但我只能遇到理论而不是实践。这就是我提出这个问题的原因。
答案 0 :(得分:21)
好的,一步一步:
glGenVertexArraysOES(1, &_vertexArray);
glBindVertexArrayOES(_vertexArray);
这会绑定并生成顶点数组对象(VAO)。现在VAO不包含任何数据。它只包含与顶点数组/属性相关的所有状态,例如启用的属性或使用glVertexAttribPointer
进行的设置。
glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);
现在创建并绑定一个顶点缓冲区对象(VBO),它本质上是由OpenGL管理的普通数据缓冲区,并将顶点数据复制到其中。
让我们看看这个数据:
GLfloat gCubeVertexData[216] =
{
// Data layout for each line below is:
// positionX, positionY, positionZ, normalX, normalY, normalZ,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
您的数据被布置为一堆浮点数(每个32位/ 4字节),每六个值代表一个顶点,而顶点又包含一个位置(3个浮点数)和一个正常值(3个浮点数)
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));
这指定了每个顶点包含3个浮点值的第一个属性(位置),每个顶点之间的步长为24个字节。这意味着它是从一个顶点的属性值(在这种情况下为位置)的起点到下一个顶点的属性数据的开头的24个字节。事实上,24个字节是6个浮点数的大小,因此是我们的顶点数据中单个顶点的数据,所以这恰好相符。最后一个参数表示位置数据从当前绑定的VBO(包含我们的顶点数据)的开始处开始,因为它是我们顶点数据中的第一个属性。
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(12));
这指定了第二个属性(法线),每个顶点包含3个浮点值,同样具有24个字节的步长,从同一数据中获取它。所以从一个法线到下一个法线也是24个字节(6个浮点数)。现在最后一个参数表示正常数据在当前绑定的VBO(包含我们的顶点数据)开始后开始12个字节(3个浮点数)。这是必要的,因为法线是我们的顶点数据中的第二个属性,因此我们需要“跳过”前三个值(即位置)以获得正常数据。如果我们再次使用0,我们将采用与位置相同的数据。
glEnableVertexAttribArray(GLKVertexAttribPosition);
glEnableVertexAttribArray(GLKVertexAttribNormal);
这些最终启用了渲染属性。
glBindVertexArrayOES(0);
所以这现在绑定默认(无)VAO,因为我们已完成指定它。我想这整个代码片段是一些初始化例程的一部分。所以现在每当我们想要渲染我们的顶点数据时,可能使用glDrawArrays
,我们只需要在调用draw方法之前使用glBindVertexArray
绑定VAO,并且glEnableVertexAttribArray
生成每个顶点数组状态。或者glVertexAttribPointer
获取VAO最后绑定时设置的值,就像我们的初始化例程一样。如果您不使用VAO,则每次要绘制此顶点数据时都需要调用glBindBuffer
和两个glEnableVetrexAttribArray
和glVertexAttribPointer
调用。
但所有这些解释都假设您或多或少熟悉这些概念。如果所有这些话都没有告诉你任何事情,那么在尝试破译其他人的代码之前,你应该先从一些真实的学习资源中学习。