I'm writing a 3d game level editor with PySide6, using Qt3d (not QML). I stumbled upon a problem - I don't know how to create a Uniform Buffer Objects with Qt3d. Basically I want to pass a list of lights to the shader programs.
Here are definitions of my UBOs:
struct SunInfo {
vec3 direction;
vec3 color;
float intensity;
}
struct LightInfo {
vec3 position;
vec3 rotation;
vec3 color;
float cone_inner;
float cone_outer;
float radius;
}
uniform SunInfo sun;
uniform LightInfo lights[MAX_NUM_LIGHTS];
I tried searching through the examples on the internet... There's only explanation on how to create single value uniforms (QParameter). I tried it on the above single block SunLight - I created a QBuffer and assigned it to a QParameter with a "sun" name, but that didn't work. No errors - just no result. The shader works, if I pass the sun parameters as single values, but that won't be possible for an array of other lights.
I figured out what my problem was - in my Python code I created a QParameter with instance name - "sun". It should be the UBO block name - "SunInfo".
Another problem I encountered was with packing of the buffer itself. I had to read up on all the layout qualifiers, but figured out that my SunInfo block (vec3, vec3, float) had to be packed to 32 bytes, with a format "3f 4x 3f f". Basically first vec3 is followed by 4 bytes of padding, whereas the latter vec3 was packed together with a float into 16 bytes.
I don't know if there is a way to query offsets of block members in Qt3d, like you can using OpenGL API itself. Therefore I switched my block definition inside shader to:
layout (std140, binding=auto) uniform SunInfo {
vec3 direction;
vec3 color;
float intensity;
}sunInfo;
which standarizes the layout. In case the layout gets different on different GPU cards.