gpt4 book ai didi

opengl - 将 VBO 传递给具有不同布局的着色器

转载 作者:行者123 更新时间:2023-12-04 10:24:53 25 4
gpt4 key购买 nike

如果我有一个期望这个的顶点着色器......

layout(location = 0) in vec3 aPos;
layout(location = 1) in vec4 aBoneWeights;
layout(location = 2) in vec4 aBoneIndices;

如何传递已经为每个顶点组织的 VBO 作为
Position(vec3) | Color(vec3) | UV(vec2) | BoneWeight(vec4) | BoneIndex(vec4)
我必须制作一个新的 VBO 吗?如果我的顶点数据是交错的,那么我是否也必须创建一个新的顶点数据缓冲区?

最佳答案

选项 1:为每个着色器创建不同的 VAO

VAO 定义了着色器属性的映射(例如,从 VBO 中的此内存位置读取 vec3,步长为 N 字节,并将其映射到绑定(bind)到位置 X 的属性)。

一些用于存储 VAO 名称的全局变量

GLuint g_vao;

然后创建它 (对于您在着色器中定义的数据布局) :
// create the VAO 
glCreateVertexArrays(1, &g_vao);


// set up: layout(location = 0) in vec3 aPos;
glEnableVertexArrayAttrib(g_vao, 0); //< turn on attribute bound to location 0

// tell OpenGL that attribute 0 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
0, //< the attribute index (location = 0)
0); //< the vertex buffer slot (start from zero usually)

// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
0, //< the attribute index
3, //< there are 3 values xyz
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
0); //< the offset (in bytes) from the start of the buffer where the data starts



// set up: layout(location = 1) in vec4 aBoneWeights
glEnableVertexArrayAttrib(g_vao, 1); //< turn on attribute bound to location 0

// tell OpenGL that attribute 1 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
1, //< the attribute index (location = 1)
0); //< the vertex buffer slot (start from zero usually)

// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
1, //< the attribute index
4, //< there are 4 values
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
sizeof(float) * 8); //< the offset (in bytes) from the start of the buffer where the data starts



// set up: layout(location = 2) in vec4 aBoneIndices;
glEnableVertexArrayAttrib(g_vao, 2); //< turn on attribute bound to location 2

// tell OpenGL that attribute 2 should be read from buffer 0
glVertexArrayAttribBinding(
g_vao, //< the VAO
2, //< the attribute index (location = 2)
0); //< the vertex buffer slot (start from zero usually)

// tell openGL where within the buffer the data exists
glVertexArrayAttribFormat(
g_vao, //< the VAO
2, //< the attribute index
4, //< there are 4 values xyz
GL_FLOAT, //< all of type float
GL_FALSE, //< do not normalise the vectors
sizeof(float) * 12); //< the offset (in bytes) from the start of the buffer where the data starts

但是,我认为属性 2 的着色器定义是错误的(因为您必须将骨骼索引作为浮点数据传递,这对我来说感觉非常错误!)。

我原以为你会想要整数而不是浮点数:
layout(location = 2) in ivec4 aBoneIndices;

但是,当绑定(bind)到整数时,您需要使用 glVertexArrayAttribIFormat 而不是 glVertexArrayAttribFormat:

glVertexArrayAttribIFormat(
g_vao, //< the VAO
2, //< the attribute index
4, //< there are 4 indices
GL_UNSIGNED_INT, //< all of type uint32
sizeof(float) * 12);

毕竟,您需要将顶点缓冲区绑定(bind)到您在上面使用的顶点槽零......
glVertexArrayVertexBuffer(
g_vao, //< the VAO
0, //< the vertex buffer slot
0, //< offset (in bytes) into the buffer
sizeof(float) * 16); //< num bytes between each element

选项 2:只需使用相同的 VAO 和相同的 VBO

只需将索引编码为具有特定含义,然后您就可以始终使用相同的 VAO。
layout(location = 0) in vec3 aPos;
//layout(location = 1) in vec4 aCol; //< not used in this shader
//layout(location = 2) in vec4 aUv; //< not used in this shader
layout(location = 3) in vec4 aBoneWeights;
layout(location = 4) in vec4 aBoneIndices;

/编辑
在回答您的问题时,这在很大程度上取决于您使用的 OpenGL 版本。我在此处发布的答案使用了 OpenGL4.5 中最新的直接状态访问 (DSA) 扩展。如果您可以使用它们,我强烈建议您使用它们。

OpenGL 3.0:glVertexAttribPointer

是的,这会起作用。但是,它是一种与 OpenGL 的绑定(bind)范例紧密相关的机制。每个属性都有效地绑定(bind)到调用 glVertexAttribPointer 时绑定(bind)的缓冲区(即,您将执行以下操作:glBindBuffer(); glEnableVertexAttribArray(); glVertexAttribPointer();)。

这样做的问题是它有点锁定您为每个 VBO(或一组 VBO,如果从多个数据中提取数据)创建 VAO,因为属性绑定(bind)到您指定该属性时绑定(bind)的确切缓冲区。

OpenGL 4.3:glVertexAttribFormat

这个版本很像我上面介绍的那个。与其将 VAO 传递给函数调用,不如先调用 glBindVertexArray(如果您搜索上述方法的文档,没有 VAO 参数的方法只使用当前绑定(bind)的 VAO)。

这种方法相对于旧 API 的优势在于,将 VAO 绑定(bind)到另一个 VBO(即您可以将 VAO 与 GLSL 程序相关联,而不是为每个 VBO/程序对拥有一个 VAO]-只需为每个 VBO 调用 glBindVertexBuffer,它就会很好地工作。

OpenGL 4.5:glVertexArrayAttribFormat

从长远来看,这是迄今为止最容易使用的 API 版本。主要优点是您无需担心当前绑定(bind)了哪个 VAO(因为您将其作为参数传入)。这有很多优点,因为您不再关心绑定(bind)了哪个 VAO,而且它还为从不同线程修改 OpenGL 对象打开了大门(旧 API 版本不允许这样做)。

关于opengl - 将 VBO 传递给具有不同布局的着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60664146/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com