Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[rmodels] "matModel" shader uniform is not multiplied with the push/pop matrix stack #4005

Closed
denovodavid opened this issue May 25, 2024 · 3 comments · Fixed by #4022
Closed

Comments

@denovodavid
Copy link
Contributor

Issue description

While making a transform hierarchy, I noticed that rmodels.c DrawMesh function does not set the "matModel" matrix shader uniform relative to the push/pop matrix stack. See here:

raylib/src/rmodels.c

Lines 1392 to 1398 in 9d67f47

// Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL
if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], transform);
// Accumulate several model transformations:
// transform: model transformation provided (includes DrawModel() params combined with model.transform)
// rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack
matModel = MatrixMultiply(transform, rlGetMatrixTransform());

"matModel" uniform is set to the model's local transform, then right after, a matModel variable is created, accumulated with push/pop matrix stack, and used for "matNormal" and "mvp" uniforms

This seems unintuitive, I expect "matModel" uniform to be the model space to world space transform, the same used calculate the "mvp" uniform, the same as the matModel variable.

However, I can work around this by getting the correct matModel in the shader by way of mat4 matModel = inverse(transpose(matNormal));

Issue Screenshot

Based on the Basic Lighting example, I have a player model that gets drawn after using rlPushMatrix() and rlTranslatef(player_position), it is incorrectly lit, as if it was positioned at {0, 0, 0}.

image

It should look like this:

image

@raysan5
Copy link
Owner

raysan5 commented May 29, 2024

@denovodavid Actually, the push/pop functionality was mostly intended the immediate-mode-style batching system, not for the modern VBO-based models drawing system. model.transform is actually intended for that.

Not sure if applying matModel to the model.transform could derive in some issue. If you do some testing in that regards and nothing is broken, I can consider applying that additional transformation...

denovodavid added a commit to denovodavid/raylib that referenced this issue Jun 1, 2024
@denovodavid
Copy link
Contributor Author

@denovodavid Actually, the push/pop functionality was mostly intended the immediate-mode-style batching system, not for the modern VBO-based models drawing system. model.transform is actually intended for that.

I see, though I think I can state my issue more clearly. The matrix stack is already used when calculating the model matrix used in mvp sent to the shader, matProjection and matView also come from the matrix stack. matModel (shader uniform) is just the local model.transform matrix, which means you cannot necessarily reconstruct the mvp in the shader from what should be its component parts.

// vertex shader
mvp != matProjection*matView*matModel;

This is what causes the incorrect lighting from my previous screenshots.

Not sure if applying matModel to the model.transform could derive in some issue. If you do some testing in that regards and nothing is broken, I can consider applying that additional transformation...

All I propose is to set (what I believe to be) the correct matModel value of the model matrix shader uniform.

 // Accumulate several model transformations: 
 //    transform: model transformation provided (includes DrawModel() params combined with model.transform) 
 //    rlGetMatrixTransform(): rlgl internal transform matrix due to push/pop matrix stack 
 matModel = MatrixMultiply(transform, rlGetMatrixTransform()); 

 // Model transformation matrix is sent to shader uniform location: SHADER_LOC_MATRIX_MODEL 
 if (material.shader.locs[SHADER_LOC_MATRIX_MODEL] != -1) rlSetUniformMatrix(material.shader.locs[SHADER_LOC_MATRIX_MODEL], matModel); 

I'll make a PR to show specifically.

@raysan5
Copy link
Owner

raysan5 commented Jun 2, 2024

@denovodavid thanks for the detailed explanation! I missunderstood it on my first read. And thanks for the fix!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants