After adding directional lights to UBO, the light is incorrect on scene. Tried to shuffle elements around, but it doesn't help. If i correct, GLSL UBO structure should be 920 bytes in size? What is wrong with this alignments/structure?
UBO structs on CPU:
MAX_POINT_LIGHTS = 10;
MAX_DIRECTIONAL_LIGHTS = 5;
struct PointLight
{
vec4 position{};
vec4 color{};
};
struct DirectionalLight {
vec4 position{0.f};
vec4 color{0.f};
vec3 shadowExtent{0.f};
// Added paddings, as try to fix problem, doesn't help
int padding{};
vec3 direction{0.f};
int padding1{};
}
struct UBO{
mat4 projection{ 1.f };
mat4 view{ 1.f };
mat4 inverseView{ 1.f };
mat4 DirectionalShadowMatrix{ 0.f };
vec4 ambientLightCol{ 0.f,0.f,0.1f,0.01f };
int numPointLight{0};
int numDirectionalLight{ 0 };
StaticArray<PointLight, MAX_POINT_LIGHTS> pointLights;
StaticArray<DirectionalLight, MAX_DIRECTIONAL_LIGHTS> DirectionalLights;
};`
UBO structs on GPU:
struct PointLight
{
vec4 position;
vec4 color;
};
struct DirectionalLight
{
vec4 position;
vec4 color;
vec3 shadowExtent;
vec3 direction;
};
layout(std140, set = 0, binding = 0) uniform UBO{
mat4 projectionMatrix;
mat4 viewMatrix;
mat4 inverseViewMatrix;
mat4 DirectionalShadowMatrix;
vec4 ambientLightCol;
int numPointLights;
int numDirectionalLights;
PointLight pointLights[10];
DirectionalLight directionalLights[5];
} ubo;
Looked on alignment, and it should be valid, so have to idea why lighting is incorect.
The rules for std140 layout in the OpenGL specification (OpenGL 4.5, Section 7.6.2.2, page 137) have the following to say about structures and arrays of structures:
- If the member is a structure, the base alignment of the structure is N , where N is the largest base alignment value of any of its members, and rounded up to the base alignment of a vec4. The individual members of this sub- structure are then assigned offsets by applying this set of rules recursively, where the base offset of the first member of the sub-structure is equal to the aligned offset of the structure. The structure may have padding at the end; the base offset of the member following the sub-structure is rounded up to the next multiple of the base alignment of the structure.
- If the member is an array of S structures, the S elements of the array are laid out in order, according to rule (9).
That means that pointLights
is aligned and assigned offsets as pointLights[0]
would. Since that is a struct containing vec4
members, the array must be aligned at 4 machine units (or 16 bytes) alignment.
You have two int
fields before pointLights
so you need to add two more to satisfy the 16-byte alignment.
As an alternative to manual padding you could add alignas(16)
to the declaration of pointLights
, or wrap your two int
fields in a nameless union
with a vec4
.