【发布时间】:2015-07-18 05:57:57
【问题描述】:
我无法理解 GLSL 统一缓冲区对象的 std140 布局。我的印象是,在下面的统一块中,int 将从偏移量 0 开始,矩阵将从偏移量 16 开始。下面的统一给我一个错误的矩阵,显然是因为屏幕上没有任何内容。
layout (std140) uniform Camera
{
int renderMode;
mat4 projection;
} camera;
renderMode 的意思是它告诉我统一更新代码不起作用。
我有以下代码(自制)来帮助我。这是在我的 C++ 应用程序中进行 Open GL 调用的代码。这段代码在一个名为 UniformBufferObject 的类中。
#define UpdateExData(o, s, d) glBindBuffer(GL_UNIFORM_BUFFER, _uboId); \
glBufferSubData(GL_UNIFORM_BUFFER, o, s, d); \
glBindBuffer(GL_UNIFORM_BUFFER, 0);
int Alignment(int offset, int alignment)
{
int leftOver = offset % alignment;
if (leftOver > 0)
{
return offset + (alignment - leftOver);
}
else
{
return offset;
}
}
template<typename T, typename... Args>
void UpdateEx(int offset, const std::vector<T>& data, Args&... args)
{
auto mySize = sizeof(T) * data.size();
int myAlignment = Alignment(offset, 16); // fixed for vectors of vec4 for now
UpdateExData(myAlignment, mySize, data.data());
UpdateEx(myAlignment + mySize, args...);
}
template<typename... Args>
void UpdateEx(int offset, int& data, Args&... args)
{
auto mySize = sizeof(int);
int myAlignment = Alignment(offset, mySize); // assume 4 byte alignment for ints
UpdateExData(myAlignment, mySize, &data);
UpdateEx(myAlignment + mySize, args...);
}
template<typename... Args>
void UpdateEx(int offset, const glm::mat4& data, Args&... args)
{
auto mySize = sizeof(glm::mat4);
int myAlignment = Alignment(offset, 16); // assume 16-byte alignment for mat4
UpdateExData(myAlignment, mySize, &data);
UpdateEx(myAlignment + mySize, args...);
}
启动更新的代码行如下。 m 是一个整数。 cam 是 glm::mat4。这篇文章的目的是更新我的着色器中的相机。
cameraUbo->UpdateEx(0, m, cam);
如果我翻转制服以使矩阵在前,并将上面的调用更新为 cameraUbo->UpdateEx(0, cam, m),矩阵会更新但 renderMode 不再起作用。
我真的不知道出了什么问题,真正让我困惑的是 GL_UNIFORM_BLOCK_DATA_SIZE 返回的值远远超出了我预期的 80。在它所在的 5 个着色器中,我得到不同的值,超过 1000。
我确实有另一个制服,看起来工作得很好,并且在出现的两个着色器中具有相同的大小。
struct TowerLight
{
vec4 position;
vec4 color;
};
layout(std140) uniform Towers
{
int lightCount;
TowerLight lights[MaxLights];
};
使用以下代码。 count 是整数,lights 是 std::vector<struct_of_2_vec4>。
ubo->UpdateEx(0, towerCount, lights);
[编辑]
这可能是我的显卡驱动程序中的一个错误。我有一个 Radeon 6870。如果我使用默认的统一块布局或将我的着色器版本从 440 降到 430,我会在所有着色器中获得 80 的块大小。
【问题讨论】: