将自定义顶点结构传递给 GLSL 着色器
Passing custom vertex structure to GLSL shaders
我正在尝试将结构传递给简单的GLSL vetrex着色器。以下是结构在C++面的外观:
struct Vertex
{
float position[3];
char boneIndex[4];
float weights[4];
float normals[3];
float textureCords[2];
};
是否可以将此顶点的数组传递给顶点着色器,而无需为每个组件创建单独的数组?
我可以做这样的事情吗:
#version 330 core
uniform mat4 MVP;
layout(location = 0) in struct Vertex
{
vec3 position;
uint boneIndex;
vec4 weights;
vec3 normals;
vec2 textureCords;
} vertex;
out vec2 UV;
void main()
{
gl_Position = MVP * vec4(vertex.position, 1.0f);
UV = vertex.textureCords;
}
(不要介意并非所有组件都在使用中,这只是为了示例。
如果可以的话,如何使用glVertexAttribPointer((函数将数据从C++端传递给它?(根据我的理解,您只能将 1,2,3,4 传递给 size 参数(。
这是正确的做事方式吗?我是OpenGL编程的初学者,所以如果您有答案,请不要犹豫,包括明显的细节。
编辑:
我最终做了这样的事情:
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); //float position[3]
glVertexAttribPointer(1, 1, GL_INT, GL_FALSE, 12, (void*)0); //char boneIndex[4]
glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 16, (void*)0); //float weights[4]
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 32, (void*)0); //float normals[3]
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, 44, (void*)0); //float textureCords[2]
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indiceBuffer);
glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, (void*)0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
在C++大小和 GLSL 顶点着色器上:
#version 330 core
uniform mat4 MVP;
layout(location = 0) in vec3 position;
layout(location = 1) in int boneIndex;
layout(location = 2) in vec4 weight;
layout(location = 3) in vec3 normal;
layout(location = 4) in vec2 UVCords;
out vec2 UV;
void main()
{
gl_Position = MVP * vec4(position, 1.0f);
UV = UVCords;
}
但它仍然不起作用,模型无法正确渲染
用于传输交错数据的方法是正确的(即,使用 glVertexAttribPointer
,但是,最后两个参数不正确(。
倒数第二个是stride
(对于结构中的每个项目都是相同的,并且应该是结构的大小(,最后一个是offset
,每个元素都应该不同(因为它们在结构本身中的偏移量不同(。
此外,最好不要在此处使用常量,而是使用 sizeof()
运算符,以使代码尽可能独立于平台。
下面是它应该看起来像的样子:
glVertexAttribPointer(
0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), nullptr
); //float position[3]
glVertexAttribIPointer(
1, 1, GL_INT, GL_FALSE, sizeof(Vertex),
std::reinterpret_cast<void *>(offsetof(Vertex, boneIndex))
); //char boneIndex[4]
glVertexAttribPointer(
2, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex),
std::reinterpret_cast<void *>(offsetof(Vertex, weights))
); //float weights[4]
glVertexAttribPointer(
3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex),
std::reinterpret_cast<void *>(offsetof(Vertex, normals))
); //float normals[3]
glVertexAttribPointer(
4, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex),
std::reinterpret_cast<void *>(offsetof(Vertex, textureCoords))
); //float textureCoords[2]
此外,您可能应该确保您的Vertex
结构没有打包以适应一个漂亮的单词边界。这是通过使用 #pragma pack(0)
来完成的,前提是编译器支持它。(请记住在结构之后重置它,因为否则编译器将在编译过程的其余部分使用此指令,并且所有聚合数据结构的结构方式都不会屈服于世界对齐的最佳拟合。
#pragma pack(push, 0)
struct Vertex {
float position[3];
char boneIndex[4];
float weights[4],
normals[4],
textureCoords[2];
};
#pragma pack(pop)
相关文章:
- C++映射:具有自定义类的运算符[]不起作用(总是返回0)
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- C++自定义比较函数
- 如何比较自定义类的std::变体
- std::设置自定义比较器
- 如何正确实现和访问运算符的各种自定义枚举器
- flutter:即使shouldRepaint()返回true,自定义画家也不会重新绘制
- 自定义先决条件对移动分配运算符有效吗
- 使用VS Code和CMake Tools运行自定义命令
- 如何创建从Maya(或类似程序)到虚幻引擎的自定义数据导出插件
- std::ranges::elements_view,用于自定义类似元组的数据
- 跟随整数索引列表的自定义类迭代器
- 参数化自定义CMake工具链
- 使用自定义比较函数使用std::sort()对矢量字符串进行排序时出现问题
- 如何在自定义类中启用'auto loops'?
- 使用QJsEngine在Qt中注册自定义类型
- Qt自定义QPush按钮未显示在布局上
- 自定义对象的dlib序列化在gcc中失败
- 将自定义顶点结构传递给 GLSL 着色器
- 使用QGLShaderProgram从Qt传递自定义类型(结构体)统一到GLSL