Quick answer: Declare UBO blocks identically across shaders. Use layout(std140, binding = N) consistently. Place the block definition in a shared header file.
A multi-pass renderer shares camera matrices via a UBO at binding 0. Shader A renders correctly. Shader B renders with wrong projection. Same UBO, different layouts.
The Bug
// shader A
layout(std140, binding = 0) uniform Camera {
mat4 view;
mat4 projection;
};
// shader B
layout(std140, binding = 0) uniform Camera {
mat4 projection; // swapped!
mat4 view;
};
Both shaders bind the same buffer but interpret it differently. B reads view’s memory as projection.
Fix: Shared Header
// camera_block.glsl — included in every shader
layout(std140, binding = 0) uniform Camera {
mat4 view;
mat4 projection;
vec3 cameraPos;
};
Define once, include in all shaders. GLSL doesn’t have native #include — preprocess offline or use ARB_shading_language_include if available.
std140 Padding Rules
std140 layout has strict alignment: vec3 takes 16 bytes, arrays stride to 16, etc. Common mistake:
layout(std140, binding = 0) uniform Data {
float a; // offset 0, padded to 16
vec3 b; // offset 16, occupies 12, padded to 32
float c; // offset 28!? No — std140 puts it at 28 but next aligns to 16
};
If your CPU struct doesn’t match this padding, the GPU reads garbage. Match the CPU struct using explicit alignas or careful field ordering.
CPU Side
struct alignas(16) CameraData {
glm::mat4 view;
glm::mat4 projection;
glm::vec3 cameraPos;
float _padding;
};
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cameraUBO);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(CameraData), &cameraData);
Bind once per frame. Update buffer when camera changes. Shaders auto-pick up.
Verifying
Render with both shaders displaying view matrix; both show identical scene. Edit camera in real time; both shaders update. RenderDoc UBO inspector confirms member layout.
“UBO is a memory contract between CPU and shaders. Break the contract, get visible bugs.”
For cross-shader sharing, always std140. std430 is denser but only available for SSBOs — UBOs need std140 for portability.