OpenGL GLSL 统一缓冲区对象
Posted
技术标签:
【中文标题】OpenGL GLSL 统一缓冲区对象【英文标题】:OpenGL GLSL uniform buffer objects 【发布时间】:2021-12-27 10:47:33 【问题描述】:我有一个 UBO,这是片段着色器中的代码。
layout (std140,binding = 5) uniform uAmbientLights
vec4 position[10];
vec4 color[10];
vec4 intensity[10];
vec4 radius[3];
;
我的 C++ 代码是这样的。我的代码所做的是创建一个缓冲区、向量容器,最多可以容纳 10 个光数据。我将设置位置 x/y、颜色和强度 x/y/z 以及半径值。当我读到我需要做填充时,我使用了 vec4。
glCreateBuffers(1, &UBO);
std::vector<float> pos(40);
std::vector<float> clr(40);
std::vector<float> intensity(40);
std::vector<float> radius(12);
glNamedBufferData(UBO, sizeof(float) * (pos.size() + clr.size() + intensity.size() + radius.size()), NULL, GL_DYNAMIC_DRAW);
size_t posCount, clrCount, intensityCount, radiusCount, numOfAmbientLights;
for (eID curr : engine.GetSystem<sIdentifierSystem>().FindTaggedEntities(engine, "AMBIENTLIGHT"))
Transform& LTR = engine.GetComponent<Transform>(curr);
Lighting& LL = engine.GetComponent<Lighting>(curr);
pos[posCount++] = LTR.GetPosition().x;
pos[posCount] = LTR.GetPosition().y;
clr[clrCount++] = LL.getColor().x;
clr[clrCount++] = LL.getColor().y;
clr[clrCount] = LL.getColor().z;
intensity[intensityCount++] = LL.getIntensity().x;
intensity[intensityCount++] = LL.getIntensity().y;
intensity[intensityCount] = LL.getIntensity().z;
radius[radiusCount] = LL.getRadius();
posCount += 3;
clrCount += 2;
intensityCount += 2;
++radiusCount;
++numOfAmbientLights;
glNamedBufferSubData(UBO, 0, sizeof(float) * pos.size(), &pos);
glNamedBufferSubData(UBO, sizeof(float) * pos.size(), sizeof(float) * clr.size(), &clr);
glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size(), sizeof(float) * intensity.size(), &intensity);
glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size() + sizeof(float) * intensity.size(), sizeof(float) * radius.size(), &radius);
glBindBufferBase(GL_UNIFORM_BUFFER, 5, UBO);
我的值根本没有传递到着色器中。在为多个灯光使用数组之前,我的代码在它只包含 1 个灯光数据时工作。
我做错了什么?我避免使用 vec3s 和浮点数,将我所有的值存储在 vec4 中,值为 0 进行填充。我检查了我的矢量容器值是否按顺序正确。
我的 GL_MAX_UNIFORM_BLOCK_SIZE 给了我 65k 字节,而我只占用 (40+40+40+12)*4 = 528 字节
【问题讨论】:
【参考方案1】:我的坏.. 更新缓冲区时,应改为 4 行
glNamedBufferSubData(UBO, 0, sizeof(float) * pos.size(), pos.data());
glNamedBufferSubData(UBO, sizeof(float) * pos.size(), sizeof(float) * clr.size(), clr.data());
glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size(), sizeof(float) * intensity.size(), intensity.data());
glNamedBufferSubData(UBO, sizeof(float) * pos.size() + sizeof(float) * clr.size() + sizeof(float) * intensity.size(), sizeof(float) * radius.size(), radius.data());
我将地址传递给向量,而不是直接传递向量数据
【讨论】:
以上是关于OpenGL GLSL 统一缓冲区对象的主要内容,如果未能解决你的问题,请参考以下文章