public ShadowRenderer(Renderer renderer) { //create the render targets for (int i = 0; i < NUM_SPOT_SHADOWS; i++) { SpotShadowMapEntry entry = new SpotShadowMapEntry(); //we store the linear depth, in a float render target. We need also the HW zbuffer entry.Texture = new RenderTarget2D(renderer.GraphicsDevice, SPOT_SHADOW_RESOLUTION, SPOT_SHADOW_RESOLUTION, false, SurfaceFormat.Single, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents); entry.LightViewProjection = Matrix.Identity; _spotShadowMaps.Add(entry); } for (int i = 0; i < NUM_CSM_SHADOWS; i++) { CascadeShadowMapEntry entry = new CascadeShadowMapEntry(); entry.Texture = new RenderTarget2D(renderer.GraphicsDevice, CASCADE_SHADOW_RESOLUTION * NUM_CSM_SPLITS, CASCADE_SHADOW_RESOLUTION, false, SurfaceFormat.Single, DepthFormat.Depth24Stencil8, 0, RenderTargetUsage.DiscardContents); _cascadeShadowMaps.Add(entry); } }
public void GenerateShadowTextureDirectionalLight(Renderer renderer, object[] meshes, object[] InstancedMeshes, Light light, CascadeShadowMapEntry cascadeShadowMap, Camera.Camera camera) { //bind the render target renderer.GraphicsDevice.SetRenderTarget(cascadeShadowMap.Texture); //clear it to white, ie, far far away renderer.GraphicsDevice.Clear(Color.White); renderer.GraphicsDevice.BlendState = BlendState.Opaque; renderer.GraphicsDevice.DepthStencilState = DepthStencilState.Default; // Get the corners of the frustum camera.Frustum.GetCorners(frustumCornersWS); Matrix eyeTransform = camera.View; Vector3.Transform(frustumCornersWS, ref eyeTransform, frustumCornersVS); float near = camera.NearPlane, far = MathHelper.Min(camera.FarPlane, light.ShadowDistance); splitDepthsTmp[0] = near; splitDepthsTmp[NUM_CSM_SPLITS] = far; //compute each distance the way you like... for (int i = 1; i < splitDepthsTmp.Length - 1; i++) splitDepthsTmp[i] = near + (far - near) * (float)Math.Pow((i / (float)NUM_CSM_SPLITS), 3); Viewport splitViewport = new Viewport(); Vector3 lightDir = -Vector3.Normalize(light.Transform.Forward); BoundingFrustum frustum = new BoundingFrustum(Matrix.Identity); for (int i = 0; i < NUM_CSM_SPLITS; i++) { cascadeShadowMap.LightClipPlanes[i].X = -splitDepthsTmp[i]; cascadeShadowMap.LightClipPlanes[i].Y = -splitDepthsTmp[i + 1]; cascadeShadowMap.LightViewProjectionMatrices[i] = CreateLightViewProjectionMatrix(lightDir, far, camera, splitDepthsTmp[i], splitDepthsTmp[i + 1], i); Matrix viewProj = cascadeShadowMap.LightViewProjectionMatrices[i]; // Set the viewport for the current split splitViewport.MinDepth = 0; splitViewport.MaxDepth = 1; splitViewport.Width = CASCADE_SHADOW_RESOLUTION; splitViewport.Height = CASCADE_SHADOW_RESOLUTION; splitViewport.X = i * CASCADE_SHADOW_RESOLUTION; splitViewport.Y = 0; renderer.GraphicsDevice.Viewport = splitViewport; frustum.Matrix = viewProj; foreach (object mesh in meshes) { if (mesh is List<Models>) for (int index = 0; index < ((List<Models>)mesh).Count; index++) { Models m = ((List<Models>)mesh)[index]; //cull meshes outside the light volume // if (!frustum.Intersects(m.BoundingSphere)) // continue; //render it m.RenderShadowMap(ref viewProj, renderer.GraphicsDevice); } if (mesh is Models) { //cull meshes outside the light volume // if (!frustum.Intersects(((Models)mesh).BoundingSphere)) // continue; //render it ((Models)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice); } if (mesh is CarPlayer) { ((CarPlayer)mesh).RenderShadowMap(ref viewProj, renderer.GraphicsDevice); } if (mesh is Terrain.Terrain) { for (int index = 0; index < ((Terrain.Terrain)mesh).QuadTrees.Count; index++) { //cull meshes outside the light volume // if (!frustum.Intersects(((Terrain.Terrain)mesh).QuadTrees[index].BoundingSphere)) // continue; //render it ((Terrain.Terrain)mesh).QuadTrees[index].RenderShadowMap(ref viewProj, renderer.GraphicsDevice); } } } foreach (object mesh in InstancedMeshes) { if (mesh is Billboards.Billboard) { ((Billboards.Billboard)mesh).TreePreDraw(); for (int lod = 0; lod < ((Billboards.Billboard)mesh).LOD; lod++) if (((Billboards.Billboard)mesh).instanceTransforms[lod].Length != 0) ((Billboards.Billboard)mesh).trunck[lod][0].RenderShadowMap(ref viewProj, renderer.GraphicsDevice); if (((Billboards.Billboard)mesh).Leaves) for (int tree = 0; tree < ((Billboards.Billboard)mesh).NoTrees; tree++) { if (((Billboards.Billboard)mesh).LeavesAreVisible[tree]) for (int j = 0; j < ((Billboards.Billboard)mesh).NoLeaves; j++) { ((Billboards.Billboard)mesh).leaves[tree][j].UpdateTransformationMatrix(((Billboards.Billboard)mesh).instanceTransforms1[tree]); if (j == 0) ((Billboards.Billboard)mesh).leaves[tree][j].RenderShadowMap(ref viewProj, renderer.GraphicsDevice); } } } } } }