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