我正在尝试着色器存储缓冲区对象(又称缓冲区块),还有一些我还没有完全掌握的东西。我要做的是将不确定数量的灯光({1}}的(简化)数据存储在其中,因此我的着色器可以遍历它们并执行计算。
首先我要说的是,我得到了正确的结果,并且没有来自OpenGL的错误。但是,我不知道为什么 正在工作。
所以,在我的着色器中,我得到了以下内容:
n
并在我的申请中:
struct PointLight {
vec3 pos;
float intensity;
};
layout (std430, binding = 0) buffer PointLights {
PointLight pointLights[];
};
void main() {
PointLight light;
for (int i = 0; i < pointLights.length(); i++) {
light = pointLights[i];
// etc
}
}
在最后一个循环中,我存储的struct PointLightData {
glm::vec3 pos;
float intensity;
};
class PointLight {
// ...
PointLightData data;
// ...
};
std::vector<PointLight*> pointLights;
glGenBuffers(1, &BBO);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, BBO);
glNamedBufferStorage(BBO, n * sizeof(PointLightData), NULL, GL_DYNAMIC_STORAGE_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, BBO);
...
for (unsigned int i = 0; i < pointLights.size(); i++) {
glNamedBufferSubData(BBO, i * sizeof(PointLightData), sizeof(PointLightData), &(pointLights[i]->data));
}
结构的偏移量等于其大小乘以我已存储的数量(因此第一个偏移PointLightData
。)< / p>
所以,正如我所说,一切似乎都是正确的。绑定点被正确设置为零,我有足够的内存分配给我的对象,等等。图形结果没问题。
现在回答我的问题。我使用0
作为布局 - 事实上,如果我将它更改为std430
,就像我最初做的那样。这是为什么?我的假设是,std140
为着色器的std430
缓冲区块生成的布局与编译器为我的应用程序的PointLights
结构生成的布局非常匹配(正如您在该循环中看到的那样)盲目地一个接一个地存储)。你认为是这样的吗?
现在,假设我在这个假设中是正确的,显而易见的解决方案是自己进行大小和偏移的映射,用PointLightData
和glGetUniformIndices
查询opengl(后者用{调用} {1}}和glGetActiveUniformsiv
),但我怀疑这两个人只使用Uniform Blocks而不是像我想做的那样使用Buffer Blocks。至少,当我执行以下操作时,OpenGL会发脾气,给我一个GL_UNIFORM_SIZE
错误并返回一个非常奇怪的数字作为索引(类似GL_UNIFORM_OFFSET
或其他):
1281
我是否正确地说3432898282
和const char * names[2] = {
"pos", "intensity"
};
GLuint indices[2];
GLint size[2];
GLint offset[2];
glGetUniformIndices(shaderProgram->id, 2, names, indices);
glGetActiveUniformsiv(shaderProgram->id, 2, indices, GL_UNIFORM_SIZE, size);
glGetActiveUniformsiv(shaderProgram->id, 2, indices, GL_UNIFORM_OFFSET, offset);
不适用于缓冲区块?
如果他们不这样做,或者它的工作就像我想象的那样巧合,我怎么能手动进行映射呢?我检查了编程指南的附录H,结构数组的措辞有些令人困惑。如果我无法查询OpenGL的大小/偏移量,我想我可以手动计算它们(虽然很麻烦)但我也很感激帮助。