[sokol_gfx] Array of struct uniform
mathewmariani opened this issue · comments
I've been looking around for more information on passing an array of structs to my shader, but can't find a lot of information on the subject. I should mention that I'm working with OpenGLES for the time being, and I'm not using the sokol-shdc
shader compiler tool.
Here is my structure in both C++ and GLSL.
struct pointlight_t
{
float radius;
glm::vec3 color;
glm::vec3 position;
};
static pointlight_t light_data[MAX_LIGHTS];
struct PointLight {
float radius;
vec3 color;
vec3 position;
};
uniform PointLight[MAX_LIGHTS] lights;
I'm not sure if this is completely correct but this is how I'm describing the uniform block in my sg_shader_desc
. At this point, I will add that I have no compile or runtime errors.
// [...]
.uniform_blocks[1] = {
.layout = SG_UNIFORMLAYOUT_NATIVE,
.size = sizeof(pointlight_t) * MAX_LIGHTS,
.uniforms = {
[0] = {.name = "light.radius", .type = SG_UNIFORMTYPE_FLOAT, .array_count = MAX_LIGHTS},
[1] = {.name = "light.color", .type = SG_UNIFORMTYPE_FLOAT3, .array_count = MAX_LIGHTS},
[2] = {.name = "light.position", .type = SG_UNIFORMTYPE_FLOAT3, .array_count = MAX_LIGHTS},
},
},
// [...]
sg_apply_uniforms(SG_SHADERSTAGE_FS, 1, SG_RANGE(light_data));
I'm not exactly sure what is the proper way to approach this using sokol_gfx
. There are no build or runtime errors, yet I don't seem to be getting any data passed to the shader. I wasn't able to find a whole lot of information about this, hopefully, you can clarify my understanding.
Hmm... without using the sokol-shdc compiler that's most likely not possible in the GL backend. You would need to convert the struct array into a plain vec4 array.
With the sokol-shdc compiler this conversion happens automatically for the GL backend (e.g. uniform blocks are flattened into a vec4 array), and then something like this could work. TBH I never tried that though.
uniform vs_params {
PointLight lights[MAX_LIGHTS];
};
PS: maybe it doesn't work though... sokol-shdc has restrictions on what can be declared as an array because that uniform block must also be mapped to a matching C struct, and that's gnarly because of std140
alignment and padding rules, so I'm allowing arrays only for floats, vec2, vec4 and mat4.
I would probably recommend a 'structure of arrays' approach instead:
uniform vs_params {
float light_radii[MAX_LIGHTS];
vec4 light_colors[MAX_LIGHTS];
vec4 light_positions[MAX_LIGHTS];
};
(vec4 instead of vec3 because of the above mentioned alignment restrictions - this is all assuming sokol-shdc though).
Without sokol-shdc this should also work for regular uniforms, but you'd need to experiment..