fix: shadow map binding before draw + correct matrix transpose

- Use BeginShaderMode/EndShaderMode around DrawModelEx to keep shader active
- Bind shadow map on texture unit 1 BEFORE DrawModelEx (not after)
- Remove manual Matrix4x4.Transpose — SetShaderValueMatrix already handles
  row-major to column-major conversion via glUniformMatrix4fv(transpose=false)
- 66/66 tests, 145 FPS
This commit is contained in:
emil28092005
2026-06-17 18:11:08 +03:00
parent 6d16287bcb
commit 573872298f
+15 -8
View File
@@ -133,10 +133,10 @@ public sealed class RaylibRenderer : IRenderer
Raylib.BeginMode3D(shadowCamera); Raylib.BeginMode3D(shadowCamera);
// Grab light view/proj matrices AFTER BeginMode3D (like official example) // Grab light view/proj matrices AFTER BeginMode3D (like official example)
// Raylib matrices are row-major, need to transpose for OpenGL (column-major) // SetShaderValueMatrix passes Matrix4x4 as-is to glUniformMatrix4fv(transpose=false)
var lv = Rlgl.GetMatrixModelview(); // which interprets row-major System.Numerics as column-major = effectively transposed.
var lp = Rlgl.GetMatrixProjection(); // So we just multiply directly (no manual transpose needed).
lightViewProj = Matrix4x4.Transpose(lv * lp); lightViewProj = Rlgl.GetMatrixModelview() * Rlgl.GetMatrixProjection();
// Draw all shadow casters with the simple shadow shader // Draw all shadow casters with the simple shadow shader
world.Each((Entity e, ref EngineMesh mesh, ref EngineTransform transform) => world.Each((Entity e, ref EngineMesh mesh, ref EngineTransform transform) =>
@@ -198,22 +198,29 @@ public sealed class RaylibRenderer : IRenderer
var (axis, angle) = QuaternionToAxisAngle(rotation); var (axis, angle) = QuaternionToAxisAngle(rotation);
SetMaterialUniforms(material, model); SetMaterialUniforms(material, model);
// Bind shadow map on Emission slot (texture unit 1) for each entity // Bind shadow map on Emission slot (texture unit 1)
if (hasDirectionalLight && _shadowMapLoc >= 0) if (hasDirectionalLight && _shadowMapLoc >= 0)
{ {
unsafe { Raylib.SetMaterialTexture(ref model.Materials[0], MaterialMapIndex.Emission, shadowTex); } unsafe { Raylib.SetMaterialTexture(ref model.Materials[0], MaterialMapIndex.Emission, shadowTex); }
} }
Raylib.DrawModelEx(model, position, axis, angle * 180.0f / MathF.PI, scale, Color.White); // Use BeginShaderMode to lock our shader, then bind shadow map on unit 1
// BEFORE DrawModelEx so it's active during the draw
// Re-bind shadow map on unit 1 after DrawModelEx (it may have reset texture state)
if (hasDirectionalLight && _shadowMapLoc >= 0) if (hasDirectionalLight && _shadowMapLoc >= 0)
{ {
Raylib.BeginShaderMode(_shader);
Rlgl.ActiveTextureSlot(1); Rlgl.ActiveTextureSlot(1);
Rlgl.EnableTexture(_shadowDepthTex); Rlgl.EnableTexture(_shadowDepthTex);
Raylib.SetShaderValue(_shader, _shadowMapLoc, 1, ShaderUniformDataType.Int); Raylib.SetShaderValue(_shader, _shadowMapLoc, 1, ShaderUniformDataType.Int);
Rlgl.ActiveTextureSlot(0); Rlgl.ActiveTextureSlot(0);
} }
Raylib.DrawModelEx(model, position, axis, angle * 180.0f / MathF.PI, scale, Color.White);
if (hasDirectionalLight && _shadowMapLoc >= 0)
{
Raylib.EndShaderMode();
}
} }
}); });