繁体   English   中英

将自定义顶点结构传递给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)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM