了解glVertexAttribPointer? [英] understanding glVertexAttribPointer?

查看:121
本文介绍了了解glVertexAttribPointer?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

private int vbo;
private int ibo;

vbo = glGenBuffers();
ibo = glGenBuffers();

glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertices), GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);




glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
//glEnableVertexAttribArray(2);

//glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, Vertex.SIZE * 4, 12);
//glVertexAttribPointer(2, 3, GL_FLOAT, false, Vertex.SIZE * 4, 20);

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
//glDisableVertexAttribArray(2);

顶点着色器代码如下

#version 330

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;

out vec2 texCoord0;

uniform mat4 transform;

void main()
{
    gl_Position = transform * vec4(position, 1.0);
    texCoord0 = texCoord;
}

所以,这是我的理解. glVertexAttribPointer的目的是定义顶点缓冲区对象中的数据格式.因此,在vbo中,它按如下方式存储数据

So, here is my understanding. The purpose of glVertexAttribPointer is to define the format of data in the vertex buffer object. So, in vbo it stores data as follows

buffer.put(vertices[i].getPos().getX());
buffer.put(vertices[i].getPos().getY());
buffer.put(vertices[i].getPos().getZ());
buffer.put(vertices[i].getTexCoord().getX());
buffer.put(vertices[i].getTexCoord().getY());
buffer.put(vertices[i].getNormal().getX());
buffer.put(vertices[i].getNormal().getY());
buffer.put(vertices[i].getNormal().getZ());

因此,我们有两条glVertexAttribPointer行,因为我们在顶点着色器中定义了两个变量.因此,基本上,我们正在定义这两个变量所指向的对象.因此,第一个glVertexAttribPointer定义第一个变量位置"是一个顶点,其中三个坐标均为浮点型.第二个glVertexAttribPointer定义第二个变量"texCoord"为一对纹理坐标,每个坐标均为浮点型.因此,如果到目前为止我的理解是正确的,那么我假设我们首先需要首先绑定顶点缓冲区对象,即使在注释掉这行之后

So, we have two glVertexAttribPointer lines because we have two variables defined in the vertex shader. So basically we are defining what these two variables point to. So, the first glVertexAttribPointer defines that the first variable "position" is a vertex with three coordinates each being float. The second glVertexAttribPointer defines the second variable "texCoord" being a pair of texture coordinates each being float. So, if my understanding is correct so far then i was assuming we first need to bind the vertex buffer object first but even after commenting out this line

glBindBuffer(GL_ARRAY_BUFFER, vbo);

它仍然有效.我很迷惑.既然有两个vbo,它怎么知道我们在谈论哪个缓冲区对象?

it still works. I am confused. How does it know which buffer object we are talking about since there are two vbos?

推荐答案

@datenwolf已经在上面的评论中介绍了关键方面.详细说明:

@datenwolf already covered the key aspect in a comment above. To elaborate some more:

您不必不必glDrawElements()调用之前再次绑定GL_ARRAY_BUFFER.重要的是,当您对该属性进行glVertexAttribPointer()调用时,绑定了您要从中获取给定属性的缓冲区.

You do not have to bind GL_ARRAY_BUFFER again before the glDrawElements() call. What matters is that the buffer you want to source a given attribute from is bound when you make the glVertexAttribPointer() call for that attribute.

对此进行描绘的最好方法是,当您拨打电话时:

The best way to picture this is that when you make this call:

glVertexAttribPointer(0, 3, GL_FLOAT, false, Vertex.SIZE * 4, 0);

您正在指定告诉OpenGL从何处获取属性0(第一个参数)的数据以及如何读取数据的所有状态.该状态的大部分直接由参数给出:

you're specifying all the state needed to tell OpenGL where to get the data for attribute 0 (first argument) from, and how to read it. Most of that state is given directly by the arguments:

  • 它有3个组成部分
  • 组件是浮点值
  • 以20个字节的步幅读取顶点...
  • ...并从缓冲区的字节0开始

但是当您拨打电话时,还有一个隐含的状态状态也存储在属性0中:

But there's an additional implied piece of state that is also stored away for attribute 0 when you make the call:

  • 从当前绑定到GL_ARRAY_BUFFER
  • 的缓冲区中读取数据
  • the data is read from the buffer currently bound to GL_ARRAY_BUFFER

换句话说,与每个属性关联的状态包括属性数据来源的缓冲区的ID.对于多个/所有属性,这可以是相同的缓冲区,对于每个属性,可以是不同的缓冲区.

In other words, the state associated with each attribute includes the id of the buffer the attribute data is sourced from. This can be the same buffer for multiple/all attributes, or it can be a different buffer for each attribute.

请注意,GL_ELEMENT_ARRAY_BUFFER并非如此.需要在glDrawElements()调用时绑定该对象.尽管看起来有些不一致,但这是必要的,因为索引数组没有等效于glVertexAttribPointer()的内容.可以将API定义为具有这种调用,但是...没有.原因很可能是根本没有必要的,因为只能将一个索引数组用于绘制调用,而可以使用多个顶点缓冲区.

Note that the same is not true for GL_ELEMENT_ARRAY_BUFFER. That one needs to be bound at the time of the glDrawElements() call. While it seems somewhat inconsistent, this is necessary because there's no equivalent to glVertexAttribPointer() for the index array. The API could have been defined to have this kind of call, but... it was not. The reason is most likely that it was simply not necessary, since only one index array can be used for a draw call, while multiple vertex buffers can be used.

这篇关于了解glVertexAttribPointer?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆