This is not a question but a confirmation if I'm correct about the behavior of HLSL arrays.
I'm working with a standard lighting vertex shader, HLSL plus C++, DirectX11.1 API. For storing my lights data I've setup a simple declaration, padded accordingly to match the packing requeriments of constant buffers:
// C++ side
struct LightBase {
DirectX::XMFLOAT3 pos, color;
DirectX::XMFLOAT3 color;
float intensity;
float isOn;
};
struct CBUFFER_LIGHT {
LightBase light[MAX_LIGHTS];
float numActiveLights;
float _padding[3];
};
The shader declares a "matching" cbuffer as:
// HLSL vertex shader
struct LightBase {
float3 pos;
float3 color;
float intensity;
float isOn;
};
cbuffer lights : register (b3) {
LightBase light[MAX_LIGHTS];
float numActiveLights;
}
Now, as I expected, it didnt work due to the HLSL memory organization policy regarding arrays. e.g; if I set the buffer from C++ with the following data: I get the following data when accessing struct members of light[0] from shader:
See how light[0].color
and other struct members got messed up? Seems that HLSL will organize your arrays in Vector4 elements regardless of the real type of the array element.
So the array data passed from C++ which is { -7, -1, -100, 0.44, 0.66, 0.88, 1.0, 1.0 }
will be organized by HLSL as follows:
A[0] = { -7, -1, -100, 0.44 }
A[1] = { 0.66, 0.88, 1.0, 1.0 }
A[2] = { ...}
So A[0]
contains .xyz for position and .x for color struct member. A[1]
contains .gb for color member, intensity and isOn data.
But calling light[0].color
from the shader will still try to address &light + sizeof(float3)+sizeof(float3)
as defined in the cbuffer, but you will get incorrect results due to array organization policy of HLSL.
If HLSL and DirectX are so fond of FLOAT4 values, it's not better to use all float4 variables and access members (.xyzw) as needed? Thanks.