CuriousGeorge
CuriousGeorge

Reputation: 7400

How to use a 4x4 matrix as a vertex attribute in GLSL?

I am trying to use a 4x4 matrix as a vertex attribute, using this code:

Mat4 matrices[numVerts];

int mtxBoneID = glGetAttribLocation(hProgram, "aMtxBone");

glEnableVertexAttribArray(mtxBoneID + 0);
glEnableVertexAttribArray(mtxBoneID + 1);
glEnableVertexAttribArray(mtxBoneID + 2);
glEnableVertexAttribArray(mtxBoneID + 3);
glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 1);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 2);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 3);

// shader:
// ...
attribute mat4 aMtxBone;
// ...

But all I get on the screen is garbage.

Upvotes: 2

Views: 4705

Answers (5)

Scr3amer
Scr3amer

Reputation: 135

Long story short OpenGL spec does not support what you want.

Vertex attribute format has a maximum of 4 components. So you are stuck with vec4 as the highest dimension input for a vertex attribute.

Cf OpenGL 4.6 specification, table 10.3, page 354.

If I were you I would store my matrices in a UBO / SSBO and consume them using gl_VertexID or a user defined index passed as a vertex attribute.

Edit: Or you can do as in the linked SO post added in one of the comments Using a matrix as vertex attribute in OpenGL3 Core Profile: You consume 4 vertex attributes, each being a vec4. I find it ugly and harder to maintain but if you can measure a perf increase for your use case then do that.

Upvotes: 0

0xbaadf00d
0xbaadf00d

Reputation: 2643

So, my answer was deleted because of reasons unknown.

Here I go again, I'll format it differently this time.

I had the EXACT same problem as the question had/has, stuff would be drawn quite messed up. At least that's the description.

What fixed it for me was calling

glDrawElementsInstancedBaseVertex(GL_TRIANGLES,
                                    d->drawCount,
                                    GL_UNSIGNED_INT,
                                    0,
                                    p_objects.size(),
                                    0);

To draw my stuff, just this and nothing more.

HOWEVER!

This MIGHT not be the only issue you have if your stuff is drawn incorrectly. The entire list of stuff you NEED to get correct it immense. So i'm going to put a link here, which has a great tutorial on how to draw lots of stuff. Also, you can get the source code and try it out yourself.

http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html

Sources here: http://ogldev.atspace.co.uk/ogldev-source.zip

Downvote me again and delete my answer, it's content hasn't changed at all from what it was.

Ban me from the site, your loss.

Upvotes: 1

sak
sak

Reputation: 3307

It looks like your offsets are off. It should be

((Vec4*)matrices) + sizeOf(Vec4)*i

instead of

((Vec4*)matrices) + i

Upvotes: -1

user1075940
user1075940

Reputation: 1125

you may try something like this in your shader use layout

layout(location=x) in mat4 <name>;

x won't be equal to glGetAttribLocation,you must maintain it by yourself.it is equal to number times you call glVertexAttribPointer. example

layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
layout(location=2) in vec4 in_Normal;

glVertexAttribPointer(0, xxxxxxxx);
glVertexAttribPointer(1, xxxxxx);
glVertexAttribPointer(2, xxxxxx);

Upvotes: 0

Anton Guryanov
Anton Guryanov

Reputation: 12467

First you need to create VBO (glGenBuffers) for your matrix, then bind it (glBindBuffer) as current, then use

glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, 0, 4);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, 0, 8);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, 0, 12);

instead of your glVertexAttribPointer calls.

Upvotes: -1

Related Questions