fix: shadow map re-bind after DrawModelEx + transpose lightViewProj
- Bind shadow map on MaterialMapIndex.Emission (unit 1) per entity - Re-bind via Rlgl.ActiveTextureSlot(1)+EnableTexture after DrawModelEx (DrawModelEx resets texture state internally) - Transpose lightViewProj matrix (Raylib row-major → OpenGL column-major) - 66/66 tests, 145 FPS
This commit is contained in:
@@ -14,7 +14,7 @@ Size=250,398
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=740,357
|
Pos=740,354
|
||||||
Size=300,400
|
Size=300,403
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +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)
|
||||||
lightViewProj = Rlgl.GetMatrixModelview() * Rlgl.GetMatrixProjection();
|
// Raylib matrices are row-major, need to transpose for OpenGL (column-major)
|
||||||
|
var lv = Rlgl.GetMatrixModelview();
|
||||||
|
var lp = Rlgl.GetMatrixProjection();
|
||||||
|
lightViewProj = Matrix4x4.Transpose(lv * lp);
|
||||||
|
|
||||||
// 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) =>
|
||||||
@@ -175,17 +178,12 @@ public sealed class RaylibRenderer : IRenderer
|
|||||||
if (hasDirectionalLight && _lightViewProjLoc >= 0)
|
if (hasDirectionalLight && _lightViewProjLoc >= 0)
|
||||||
{
|
{
|
||||||
Raylib.SetShaderValueMatrix(_shader, _lightViewProjLoc, lightViewProj);
|
Raylib.SetShaderValueMatrix(_shader, _lightViewProjLoc, lightViewProj);
|
||||||
// Bind shadow map on texture unit 1, tell shader sampler to use it
|
|
||||||
if (_shadowMapLoc >= 0)
|
|
||||||
{
|
|
||||||
Rlgl.ActiveTextureSlot(1);
|
|
||||||
Rlgl.EnableTexture(_shadowDepthTex);
|
|
||||||
Raylib.SetShaderValue(_shader, _shadowMapLoc, 1, ShaderUniformDataType.Int);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Rlgl.DisableBackfaceCulling();
|
Rlgl.DisableBackfaceCulling();
|
||||||
|
|
||||||
|
var shadowTex = new Texture2D { Id = _shadowDepthTex, Width = ShadowMapSize, Height = ShadowMapSize, Mipmaps = 1, Format = PixelFormat.UncompressedR16 };
|
||||||
|
|
||||||
world.Each((Entity e, ref EngineMesh mesh, ref EngineTransform transform) =>
|
world.Each((Entity e, ref EngineMesh mesh, ref EngineTransform transform) =>
|
||||||
{
|
{
|
||||||
if (e.Name() == "Grid")
|
if (e.Name() == "Grid")
|
||||||
@@ -199,7 +197,23 @@ 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
|
||||||
|
if (hasDirectionalLight && _shadowMapLoc >= 0)
|
||||||
|
{
|
||||||
|
unsafe { Raylib.SetMaterialTexture(ref model.Materials[0], MaterialMapIndex.Emission, shadowTex); }
|
||||||
|
}
|
||||||
|
|
||||||
Raylib.DrawModelEx(model, position, axis, angle * 180.0f / MathF.PI, scale, Color.White);
|
Raylib.DrawModelEx(model, position, axis, angle * 180.0f / MathF.PI, scale, Color.White);
|
||||||
|
|
||||||
|
// Re-bind shadow map on unit 1 after DrawModelEx (it may have reset texture state)
|
||||||
|
if (hasDirectionalLight && _shadowMapLoc >= 0)
|
||||||
|
{
|
||||||
|
Rlgl.ActiveTextureSlot(1);
|
||||||
|
Rlgl.EnableTexture(_shadowDepthTex);
|
||||||
|
Raylib.SetShaderValue(_shader, _shadowMapLoc, 1, ShaderUniformDataType.Int);
|
||||||
|
Rlgl.ActiveTextureSlot(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user