So after fixing all my lighting and shadow problems that my new terrain system showed me that I had I have an issue with my shadow maps, I have had it since my XNA days but because of my world setup, field of view and no shadow jittering fix I couldn't really see it.
I'm 90% sure its to do with the way I fix the shadow jittering, this peace of code is really old and I have never really been able to fix it. It comes from this page and I never really did much with it other than drop it in and it worked so I moved on to other parts of the engine.
Here is a pic so u can see what is going on, easier than you guys trying to work out what "a strange black peace of my shadow map".
It looks to me like there is a problem with the way the frustum is clipped but I'm not really sure so here is the light view projection code with the jitter fix, if I turn the jitter fix off then it fixes the problem but I'm left with jittery shadows.
VB.net
Private Function CreateLightViewProjectionMatrix(CASCADE_SHADOW_RESOLUTION As Single, lightDir As Vector3, minZ As Single, maxZ As Single, index As Integer, ByRef _Camera As Camera, frustumCornersWS As Vector3(), frustumCornersVS As Vector3(), _directionalClippingPlanes As Plane()) As Matrix
Dim splitFrustumCornersVS As Vector3() = New Vector3(7) {}
For i As Integer = 0 To 3
splitFrustumCornersVS(i) = frustumCornersVS(i + 4) * (minZ / _Camera.FarClip)
Next
For i As Integer = 4 To 7
splitFrustumCornersVS(i) = frustumCornersVS(i) * (maxZ / _Camera.FarClip)
Next
Dim cameraMat As Matrix = _Camera.Transform
For i As Integer = 0 To frustumCornersWS.Length - 1
Vector3.Transform(splitFrustumCornersVS(i), cameraMat, frustumCornersWS(i))
Next
Dim cameraUpVector As Vector3 = Vector3.Up
If Math.Abs(Vector3.Dot(cameraUpVector, lightDir)) > 0.9F Then
cameraUpVector = Vector3.ForwardRH
End If
Dim lightRotation As Matrix = Matrix.LookAtRH(Vector3.Zero, -lightDir, cameraUpVector)
For i As Integer = 0 To frustumCornersWS.Length - 1
Vector3.Transform(frustumCornersWS(i), lightRotation, frustumCornersWS(i))
Next
Dim mins As Vector3 = frustumCornersWS(0), maxes As Vector3 = frustumCornersWS(0)
For i As Integer = 1 To frustumCornersWS.Length - 1
Dim p As Vector3 = frustumCornersWS(i)
If p.X < mins.X Then
mins.X = p.X
End If
If p.Y < mins.Y Then
mins.Y = p.Y
End If
If p.Z < mins.Z Then
mins.Z = p.Z
End If
If p.X > maxes.X Then
maxes.X = p.X
End If
If p.Y > maxes.Y Then
maxes.Y = p.Y
End If
If p.Z > maxes.Z Then
maxes.Z = p.Z
End If
Next
Dim minsVS As Vector3 = splitFrustumCornersVS(0), maxesVS As Vector3 = splitFrustumCornersVS(0)
For i As Integer = 1 To splitFrustumCornersVS.Length - 1
Dim p As Vector3 = splitFrustumCornersVS(i)
If p.X < minsVS.X Then
minsVS.X = p.X
End If
If p.Y < minsVS.Y Then
minsVS.Y = p.Y
End If
If p.Z < minsVS.Z Then
minsVS.Z = p.Z
End If
If p.X > maxesVS.X Then
maxesVS.X = p.X
End If
If p.Y > maxesVS.Y Then
maxesVS.Y = p.Y
End If
If p.Z > maxesVS.Z Then
maxesVS.Z = p.Z
End If
Next
Dim _lightBox As New BoundingBox(mins, maxes)
If fixShadowJittering Then
Dim diagonalLength As Single = (frustumCornersWS(0) - frustumCornersWS(6)).Length()
Dim worldsUnitsPerTexel As Single = diagonalLength / CType(CASCADE_SHADOW_RESOLUTION , Single)
Dim vBorderOffset As Vector3 = (New Vector3(diagonalLength, diagonalLength, diagonalLength) - (_lightBox.Maximum - _lightBox.Minimum)) * 0.5F
_lightBox.Maximum += vBorderOffset
_lightBox.Minimum -= vBorderOffset
_lightBox.Minimum /= worldsUnitsPerTexel
_lightBox.Minimum.X = CType(Math.Floor(_lightBox.Minimum.X), Single)
_lightBox.Minimum.Y = CType(Math.Floor(_lightBox.Minimum.Y), Single)
_lightBox.Minimum.Z = CType(Math.Floor(_lightBox.Minimum.Z), Single)
_lightBox.Minimum *= worldsUnitsPerTexel
_lightBox.Maximum /= worldsUnitsPerTexel
_lightBox.Maximum.X = CType(Math.Floor(_lightBox.Maximum.X), Single)
_lightBox.Maximum.Y = CType(Math.Floor(_lightBox.Maximum.Y), Single)
_lightBox.Maximum.Z = CType(Math.Floor(_lightBox.Maximum.Z), Single)
_lightBox.Maximum *= worldsUnitsPerTexel
End If
Dim boxSize As Vector3 = _lightBox.Maximum - _lightBox.Minimum
If boxSize.X = 0 OrElse boxSize.Y = 0 OrElse boxSize.Z = 0 Then
boxSize = Vector3.One
End If
Dim halfBoxSize As Vector3 = boxSize * 0.5F
Dim lightPosition As Vector3 = _lightBox.Minimum + halfBoxSize
lightPosition.Z = _lightBox.Minimum.Z
lightPosition = Vector3.Transform(lightPosition, Matrix.Invert(lightRotation))
Dim lightView As Matrix = Matrix.LookAtRH(lightPosition, lightPosition - lightDir, cameraUpVector)
Dim lightProjection As Matrix = Matrix.OrthoRH(boxSize.X, boxSize.Y, -boxSize.Z, 0)
Dim lightDirVS As Vector3 = Vector3.TransformNormal(-lightDir, _Camera.EyeTransform)
Return lightView * lightProjection
End Function
Just the jitter fixing code:
If fixShadowJittering Then
Dim diagonalLength As Single = (frustumCornersWS(0) - frustumCornersWS(6)).Length()
Dim worldsUnitsPerTexel As Single = diagonalLength / CType(CASCADE_SHADOW_RESOLUTION , Single)
Dim vBorderOffset As Vector3 = (New Vector3(diagonalLength, diagonalLength, diagonalLength) - (_lightBox.Maximum - _lightBox.Minimum)) * 0.5F
_lightBox.Maximum += vBorderOffset
_lightBox.Minimum -= vBorderOffset
_lightBox.Minimum /= worldsUnitsPerTexel
_lightBox.Minimum.X = CType(Math.Floor(_lightBox.Minimum.X), Single)
_lightBox.Minimum.Y = CType(Math.Floor(_lightBox.Minimum.Y), Single)
_lightBox.Minimum.Z = CType(Math.Floor(_lightBox.Minimum.Z), Single)
_lightBox.Minimum *= worldsUnitsPerTexel
_lightBox.Maximum /= worldsUnitsPerTexel
_lightBox.Maximum.X = CType(Math.Floor(_lightBox.Maximum.X), Single)
_lightBox.Maximum.Y = CType(Math.Floor(_lightBox.Maximum.Y), Single)
_lightBox.Maximum.Z = CType(Math.Floor(_lightBox.Maximum.Z), Single)
_lightBox.Maximum *= worldsUnitsPerTexel
End If