GLSL和C ++结构中的字段顺序不匹配(std140布局)

时间:2019-01-03 16:05:42

标签: c++ opengl glsl memory-alignment glm-math

当试图通过统一缓冲区将数据传递到着色器时,面对std140布局的奇怪行为。好像我声明的C结构中的字段顺序与GLSL代码中声明的结构中的顺序不匹配。

我的GLSL代码中的结构如下:

struct SpotLight
{
    vec3 position;
    vec3 color;
    vec3 direction;

    float linear;
    float quadratic;
    float cutOffCos;
    float cutOffOuterCos;

    mat4 modelMatrix;
};

但是我需要一个数组theese结构,并且我这样声明了统一块:

layout(std140) uniform spotLightsUniform
{
    SpotLight[MAX_SPOT_LIGHTS] spotLights;
};

然后,根据std140布局规则,我在我的c ++代码中声明了结构

struct Std140SpotLightSettings
{
    glm::vec4 position;     // vec3 (12 bytes) + 4 bytes alignment
    glm::vec4 color;        // vec3 (12 bytes) + 4 bytes alignment
    glm::vec4 direction;    // vec3 (12 bytes) + 4 bytes alignment

    GLfloat linear;         // 4 bytes
    GLfloat quadratic;      // 4 bytes
    GLfloat cutOffCos;      // 4 bytes
    GLfloat cutOffOuterCos; // 4 bytes

    glm::mat4 modelMatrix;  // 64 bytes

    Std140SpotLightSettings(
        const glm::vec3& positionIn,
        const glm::vec3& colorIn,
        const glm::vec3& directionIn,
        const GLfloat& linearIn,
        const GLfloat& quadraticIn,
        const GLfloat& cutOffCosIn,
        const GLfloat& cutOffOuterCosIn,
        const glm::mat4& modelMatrixIn) :
        position({ positionIn.x,positionIn.y,positionIn.z,0.0f }),
        color({ colorIn.r,colorIn.g,colorIn.b,0.0f }),
        direction({ directionIn.x,directionIn.y,directionIn.z,0.0f }),
        linear(linearIn),
        quadratic(quadraticIn),
        cutOffCos(cutOffCosIn),
        cutOffOuterCos(cutOffOuterCosIn),
        modelMatrix(modelMatrixIn)
    {};
};

结构的总大小为128字节,是16的倍数,因此我们无需在此结构上添加额外的填充。

在渲染器初始化中,我执行以下操作:

GLuint spotLightsUboBindingID = glGetUniformBlockIndex(this->shaders_.shaderLighting_->getId(), "spotLightsUniform");
glUniformBlockBinding(this->shaders_.shaderLighting_->getId(), spotLightsUboBindingID, 7);

glGenBuffers(1, &uboSpotLights_);
glBindBuffer(GL_UNIFORM_BUFFER, uboSpotLights_);
glBufferData(GL_UNIFORM_BUFFER, sizeof(Std140SpotLightSettings) * MAX_SPOT_LIGHTS, nullptr, GL_STATIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0);

glBindBufferRange(GL_UNIFORM_BUFFER, 7, this->uboSpotLights_, 0, sizeof(Std140SpotLightSettings) * MAX_SPOT_LIGHTS);

在我的“并条机”功能中,我执行以下操作:

if(light->getType() == LightType::SPOT_LIGHT)
{
    Std140SpotLightSettings settings(
        light->position, 
        light->color, 
        light->getDirection(), 
        light->attenuation.linear, 
        light->attenuation.quadratic, 
        glm::cos(glm::radians(light->cutOffAngle)), 
        glm::cos(glm::radians(light->cutOffOuterAngle)), 
        light->getModelMatrix());


    glBindBuffer(GL_UNIFORM_BUFFER, uboSpotLights_);
    glBufferSubData(GL_UNIFORM_BUFFER, sizeof(Std140SpotLightSettings)*spotLights, sizeof(Std140SpotLightSettings), &settings);
    glBindBuffer(GL_UNIFORM_BUFFER, 0);

    spotLights++;
}

结果,数据被传输,但是由于某些原因,结构中字段的顺序不匹配。仅当按以下顺序指定字段顺序时,所有内容才能开始正常工作:

glm::vec4 position;
glm::vec4 color;
glm::vec4 direction;

GLfloat linear;
GLfloat cutOffCos;
GLfloat cutOffOuterCos;
GLfloat quadratic;

glm::mat4 modelMatrix;

但是为什么?

也许我错过了什么?也许我不完全了解std140对齐方式的工作原理?

0 个答案:

没有答案