internal void PreDraw(int swapchainIndex) { float aspect = (float)colorTarget.Size.X / colorTarget.Size.Y; var cameraData = CameraData.FromCamera(scene.Camera, aspect); cameraBuffer.Write(cameraData, offset: CameraData.SIZE * swapchainIndex); }
internal void PreDraw(int swapchainIndex, Float3 sunDirection, float shadowDistance) { //Get the 'normal' scene projections for current camera and aspect CameraData sceneCameraData = CameraData.FromCamera(scene.Camera, swapchainAspect); //Rotation from world to 'sun' direction Float4x4 rotationMatrix = Float4x4.CreateRotationFromAxis(sunDirection, Float3.Forward); //Calculate a sphere in 'lightspace' that fits the frustum of the camera //using a sphere so that the size stays constant when the camera rotates, this avoids //the shimmering when the shadow map is resized all the time FloatSphere shadowSphere = GetShadowSphere( sceneCameraData.InverseViewProjectionMatrix, rotationMatrix.Invert(), shadowDistance); //Derive the projection values from the sphere Float3 shadowCenter = shadowSphere.Center; float radius = shadowSphere.Radius.Round(); float shadowSize = radius * 2f; float shadowNearClip = -radius; float shadowFarClip = radius; //Calculate the matrices for the shadow projection Float4x4 cameraMatrix = rotationMatrix * Float4x4.CreateTranslation(shadowCenter); Float4x4 viewMatrix = cameraMatrix.Invert(); Float4x4 projectionMatrix = Float4x4.CreateOrthographicProjection( shadowSize.XX(), shadowNearClip, shadowFarClip); Float4x4 viewProjectionMatrix = projectionMatrix * viewMatrix; //Calculate a rounding matrix to fix shadow 'shimmering' as objects constantly 'switch' //between pixels in the shadowmap float targetHalfSize = targetSize / 2f; Float2 shadowOrigin = viewProjectionMatrix.TransformPoint((0f, 0f, 0f)).XY *targetHalfSize; Float2 rounding = (shadowOrigin.Round() - shadowOrigin) / targetHalfSize; Float4x4 roundingMat = Float4x4.CreateTranslation(rounding.XY0); //Apply rounding projectionMatrix = roundingMat * projectionMatrix; viewProjectionMatrix = roundingMat * viewProjectionMatrix; //Update shadow projection data in the buffer cameraBuffer.Write(new CameraData( cameraMatrix, viewMatrix, projectionMatrix, viewProjectionMatrix, viewProjectionMatrix.Invert(), shadowNearClip, shadowFarClip), offset: CameraData.SIZE * swapchainIndex); }