[英]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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.