当试图通过统一缓冲区将数据传递到着色器时,面对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对齐方式的工作原理?