Hi. I created a “Matrix4x4” class. Now I need to pass it to “glUniformMatrix4fv”. When I read the documentation, is said that the last value shall be a pointer to a float. From what I saw, if it was a primitive array, like: “float a ”, the right thing to pass would be: “a&”
I imagine that OpenGL can deduce the array structure and hence know where the other variables are stored.
However, my “Matrix4x4” is composed of four “Vec4f” objects, each one made of four floats.
So my question is? Is there a way to pass it to glUniformMatrix4fv, or I will have to redesign my class? If there is not, how do you recommend for me to redesign it? Thank you.
No, the driver implementing glUniformMatrix4fv() doesn’t deduce anything. It requires that the pointer passed in point to the first of 16 consecutive floats which comprise a 4x4 matrix in column major order (if transpose == false).
On your side, you can use any struct/class/array or combination you want to hold this, so long as it yields that representation in memory. float m and Vec4f m are often valid examples, as they typically result in the component floats being tightly packed in memory.
OpenGL will start from row 1 first float, go the second (that for it will be the first element of row 2), until reachs row1.w, which I wanted to be the last element of row1, but for Ogl will the element 1 of row4. And Then what? It will proceed to row2, that wil see as “column2” ?
What if I add a float “trouble” between row1 and row2 declarations?
Is there any disavantage in using row-major ordering?
Anyway, it shall work if I pass &model_view_projection.row1.x ?
I find awkward that this will just work given that is not a primititive type. I mean, how I can be sure that the four Vec4f will be ordered in memory as a 16 consecutive floats which comprises a matrix in column or row major order ?
Then you will have changed your type’s layout and therefore its ability to interface with code that expects a specific layout.
Because it works for everyone else. You’re not going to get a guarantee of a specific layout. But since lots of programs that interface with low-level systems will hard-code certain layout expectations, C++ compilers will generally avoid doing surprising things. If you have two adjacent floats in a struct, then one float will generally be directly next to the next one. The compiler could hypothetically insert padding between them, but it won’t because that would break lots of code.
Not for uniforms; if there is a performance cost, it will be negligible. Vertex shader inputs (attributes) which are matrices treat each column as a distinct attribute, so you’d have to perform an explicit transpose in the vertex shader if you wanted to use row-major matrices.
The members of a structure are guaranteed to be stored in the order that they occur in the structure definition. Nothing in the C/C++ standard guarantees that there won’t be padding between elements, although I’m fairly sure that the C ABIs for any platform you’re interested in will guarantee this. And while C++ doesn’t usually have a formal ABI, it generally follows the C ABI for features which aren’t specific to C++.