Stable CSM Snapping + Camera MVP Computation

Here is a small snippet to snap the cascades so there is no flickering while moving. It requires a Directional Light, and you have to adjust it a bit to match your project, however it took some time for me to figure, so I thought I’d post it.

# Do this for every cascade:

# This is the position of the shadow camera of the current cascade. 
# You usually compute it yourself already, this is just an example
destPos = focusPoint + lightDirection * 300.0

# Place the shadow map camera at the position and look at the focusPoint
# Compute your MVP matrix of the shadow camera here
mvp = Mat4( ... )

# Find out how big one texel is (insert your shadow map resolution here)
texelSize = 1.0 / float(Shadow_Map_Resolution)
# Project the Point (0,0,0) to shadow map space
basePoint = mvp.xform(Point4(0,0,0,1))
basePoint *= 0.5 
basePoint += Vec4(0.5)

# Find out how much the shadow map is off-placed
offsetX = basePoint.x % texelSize
offsetY = basePoint.y % texelSize

# To reproject the position, we need the inverse mvp, so just invert it

# Reproject the corrected point to world space
newBase = mvp.xform(Point4( (basePoint.x - offsetX) * 2.0 - 1.0, (basePoint.y - offsetY) * 2.0 - 1.0, (basePoint.z) * 2.0 - 1.0, 1))

# Offset the camera position by that offset
destPos -= Vec3(newBase.x, newBase.y, newBase.z)

# Now set the shadow camera to that position, but keep the rotation

You can compute the MVP (ModelViewProjectionMatrix) with code like this:

def computeMVP(lens, cameraNode):
        projMat = Mat4.convertMat(CSYupRight, lens.getCoordinateSystem()) * lens.getProjectionMat()
        modelViewMat = TransformState.makeMat(
        return modelViewMat * projMat