使用glVertexArrayAttribFormat / glVertexArrayVertexBuffer访问属性时遇到问题

时间:2020-10-08 22:24:48

标签: c++ opengl

我有此代码:

Upp::Vector<float> verticesTriangle{
     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.5f, -0.5f, 0.0f,
     0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.5f, -0.5f, 0.0f,
     0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.0f,  0.5f, 0.0f,
};

glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

//Setting up the VAO Attribute format
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); //Will be colors (R G B in float)
glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3); //Will be texture coordinates
glVertexArrayAttribFormat(VAO, 2, 3, GL_FLOAT, GL_FALSE, 5); //Normals
glVertexArrayAttribFormat(VAO, 3, 3, GL_FLOAT, GL_FALSE, 8); //Will be my position 

glEnableVertexArrayAttrib(VAO, 0);
glEnableVertexArrayAttrib(VAO, 1);
glEnableVertexArrayAttrib(VAO, 2);
glEnableVertexArrayAttrib(VAO, 3);

//Generating a VBO
glGenBuffers(1, &VBOCarre);
glBindBuffer(GL_ARRAY_BUFFER, VBOCarre);
glBufferStorage(GL_ARRAY_BUFFER, sizeof(float) * verticesTriangle.GetCount(), verticesTriangle, GL_MAP_READ_BIT  | GL_MAP_WRITE_BIT);

//Binding the VBO to be read by VAO
glVertexArrayVertexBuffer(VAO, 0, VBOCarre, 0 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 1, VBOCarre, 3 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 2, VBOCarre, 5 * sizeof(float), 11 * sizeof(float));
glVertexArrayVertexBuffer(VAO, 3, VBOCarre, 8 * sizeof(float), 11 * sizeof(float));
//Bind VAO
glBindVertexArray(VAO);

我在着色器中检索第一个属性没有问题,但是,当我尝试检索其他属性时,它不起作用。为了测试它,我设置了一个float数组和一个简单的着色器程序,然后尝试检索位置以绘制一个三角形。 这是我的数据排序的方式:

how my datas are ordered

这是我的顶点着色器:

#version 400 
layout (location = 0) in vec3 colors;
layout (location = 1) in vec2 textCoords;
layout (location = 2) in vec3 normals;
layout (location = 3) in vec3 positions;

out vec3 fs_colors;

void main()
{
    gl_Position = vec4(positions.x, positions.y, positions.z, 1.0);
//  gl_Position = vec4(colors.x, colors.y, colors.z, 1.0); //This line work, proofing my
//  first attribute is sended well to my shader
    fs_colors = colors;
}

问题是,除了第一个属性外,所有其他属性似乎都没有发送到着色器。我想念什么?!

1 个答案:

答案 0 :(得分:2)

您将东西放错了位置。

glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3); //Will be texture coordinates

此处的“ 3”将作为字节偏移量从数组中顶点的开始传递到属性中该顶点的特定数据。显然,纹理坐标距离顶点的起点不是3个字节;而是一个3个字节。从顶点开始起3 * sizeof(float)个字节。

类似地:

glVertexArrayVertexBuffer(VAO, 1, VBOCarre, 3 * sizeof(float), 11 * sizeof(float));

这也没有道理。您只使用一个缓冲区,所有四个属性都从同一绑定读取。因此,您应该只绑定一个缓冲区。

偏移量应为0,因为这是缓冲区中顶点的起点。大步应该是你写的。

您也永远不会直接使用glVertexArrayAttribBinding设置属性和绑定索引之间的关联。您可能可以依靠默认设置来工作,但是这里不应该使用默认设置。

正确的代码是:

//Generating a VBO
glCreateBuffers(1, &VBOCarre);
//No need to call glBindBuffer(GL_ARRAY_BUFFER, VBOCarre);, since we're doing DSA.

glNamedBufferStorage(VBOCarre, sizeof(float) * verticesTriangle.GetCount(), verticesTriangle, GL_MAP_READ_BIT  | GL_MAP_WRITE_BIT);


glCreateVertexArrays(1, &VAO);
//No need to glBindVertexArray(VAO);, since we're using DSA.

//Setting up the VAO Attribute format
glEnableVertexArrayAttrib(VAO, 0);
glVertexArrayAttribFormat(VAO, 0, 3, GL_FLOAT, GL_FALSE, 0); //Will be colors (R G B in float)
glEnableVertexArrayAttrib(VAO, 1);
glVertexArrayAttribFormat(VAO, 1, 2, GL_FLOAT, GL_FALSE, 3 * sizeof(float)); //Will be texture coordinates
glEnableVertexArrayAttrib(VAO, 2);
glVertexArrayAttribFormat(VAO, 2, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float)); //Normals
glEnableVertexArrayAttrib(VAO, 3);
glVertexArrayAttribFormat(VAO, 3, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float)); //Will be my position 

//One buffer, one binding.
glVertexArrayVertexBuffer(VAO, 0, VBOCarre, 0, 11 * sizeof(float));

//Make all attributes read from the same buffer.
glVertexArrayAttribBinding(VAO, 0, 0);
glVertexArrayAttribBinding(VAO, 1, 0);
glVertexArrayAttribBinding(VAO, 2, 0);
glVertexArrayAttribBinding(VAO, 3, 0);

//We can glBindVertexArray(VAO); when we're about to use it, not just because we finished setting it up.