# 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
cameraNode.setPos(destPos)
cameraNode.lookAt(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
mvp.invertInPlace()

# 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
cameraNode.setPos(destPos)``````

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(
Mat4.convertMat(base.win.getGsg().getInternalCoordinateSystem(),
CSZupRight)).invertCompose(
render.getTransform(cameraNode)).getMat()
return modelViewMat * projMat``````