/// <summary> /// Create the projection matrices /// </summary> /// <param name="camera"></param> /// <param name="meshMaterialLibrary"></param> /// <param name="entities"></param> private void UpdateViewProjection(Camera camera, MeshMaterialLibrary meshMaterialLibrary, List <BasicEntity> entities) { _viewProjectionHasChanged = camera.HasChanged; //If the camera didn't do anything we don't need to update this stuff if (_viewProjectionHasChanged) { //We have processed the change, now setup for next frame as false camera.HasChanged = false; camera.HasMoved = false; //View matrix _view = Matrix.CreateLookAt(camera.Position, camera.Lookat, camera.Up); _inverseView = Matrix.Invert(_view); _projection = Matrix.CreatePerspectiveFieldOfView(camera.FieldOfView, GameSettings.g_ScreenWidth / (float)GameSettings.g_ScreenHeight, 1, GameSettings.g_FarPlane); Shaders.GBufferEffectParameter_Camera.SetValue(camera.Position); _viewProjection = _view * _projection; //this is the unjittered viewProjection. For some effects we don't want the jittered one _staticViewProjection = _viewProjection; //Transformation for TAA - from current view back to the old view projection _currentViewToPreviousViewProjection = Matrix.Invert(_view) * _previousViewProjection; _previousViewProjection = _viewProjection; _inverseViewProjection = Matrix.Invert(_viewProjection); if (_boundingFrustum == null) { _boundingFrustum = new BoundingFrustum(_staticViewProjection); } else { _boundingFrustum.Matrix = _staticViewProjection; } Matrix id = Matrix.Identity; } //We need to update whether or not entities are in our boundingFrustum and then cull them or not! meshMaterialLibrary.FrustumCulling(entities, _boundingFrustum, _viewProjectionHasChanged, camera.Position); //Performance Profiler if (GameSettings.d_profiler) { long performanceCurrentTime = _performanceTimer.ElapsedTicks; GameStats.d_profileUpdateViewProjection = performanceCurrentTime - _performancePreviousTime; _performancePreviousTime = performanceCurrentTime; } }
/// <summary> /// Only one shadow map needed for a directional light /// </summary> /// <param name="light"></param> /// <param name="shadowResolution"></param> /// <param name="meshMaterialLibrary"></param> /// <param name="entities"></param> private void CreateShadowMapDirectionalLight(GraphicsDevice graphicsDevice, DirectionalLight light, int shadowResolution, MeshMaterialLibrary meshMaterialLibrary, List <BasicEntity> entities) { //Create a renderTarget if we don't have one yet if (light.ShadowMap == null) { //if (lightSource.ShadowFiltering != DirectionalLightSource.ShadowFilteringTypes.VSM) //{ light.ShadowMap = new RenderTarget2D(graphicsDevice, shadowResolution, shadowResolution, false, SurfaceFormat.Single, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents); //} //else //For a VSM shadowMap we need 2 components //{ // lightSource.ShadowMap = new RenderTarget2D(_graphicsDevice, shadowResolution, shadowResolution, false, // SurfaceFormat.Vector2, DepthFormat.Depth24, 0, RenderTargetUsage.DiscardContents); //} } if (light.HasChanged) { Matrix lightProjection = Matrix.CreateOrthographic(light.ShadowSize, light.ShadowSize, -light.ShadowDepth, light.ShadowDepth); Matrix lightView = Matrix.CreateLookAt(light.Position, light.Position + light.Direction, Vector3.Down); light.LightView = lightView; light.LightViewProjection = lightView * lightProjection; _boundingFrustumShadow = new BoundingFrustum(light.LightViewProjection); graphicsDevice.SetRenderTarget(light.ShadowMap); graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.White, 1, 0); meshMaterialLibrary.FrustumCulling(entities, _boundingFrustumShadow, true, light.Position); // Rendering! _FarClip.SetValue(light.ShadowDepth); _SizeBias.SetValue(GameSettings.ShadowBias * 2048 / light.ShadowResolution); meshMaterialLibrary.Draw(MeshMaterialLibrary.RenderType.ShadowLinear, light.LightViewProjection, light.HasChanged, false, false, 0, light.LightView, renderModule: this); } else { _boundingFrustumShadow = new BoundingFrustum(light.LightViewProjection); bool hasAnyObjectMoved = meshMaterialLibrary.FrustumCulling(entities: entities, boundingFrustrum: _boundingFrustumShadow, hasCameraChanged: false, cameraPosition: light.Position); if (!hasAnyObjectMoved) { return; } meshMaterialLibrary.FrustumCulling(entities: entities, boundingFrustrum: _boundingFrustumShadow, hasCameraChanged: true, cameraPosition: light.Position); graphicsDevice.SetRenderTarget(light.ShadowMap); graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.White, 1, 0); _FarClip.SetValue(light.ShadowDepth); _SizeBias.SetValue(GameSettings.ShadowBias * 2048 / light.ShadowResolution); meshMaterialLibrary.Draw(MeshMaterialLibrary.RenderType.ShadowLinear, light.LightViewProjection, false, true, false, 0, light.LightView, renderModule: this); } //Blur! //if (lightSource.ShadowFiltering == DirectionalLightSource.ShadowFilteringTypes.VSM) //{ // lightSource.ShadowMap = _gaussianBlur.DrawGaussianBlur(lightSource.ShadowMap); //} }
/// <summary> /// Create the shadow map for each cubemapside, then combine into one cubemap /// </summary> /// <param name="light"></param> /// <param name="size"></param> /// <param name="meshMaterialLibrary"></param> /// <param name="entities"></param> private void CreateShadowCubeMap(GraphicsDevice graphicsDevice, PointLight light, int size, MeshMaterialLibrary meshMaterialLibrary, List <BasicEntity> entities) { //For VSM we need 2 channels, -> Vector2 //todo: check if we need preserve contents if (light.ShadowMap == null) { light.ShadowMap = new RenderTarget2D(graphicsDevice, size, size * 6, false, SurfaceFormat.HalfSingle, DepthFormat.Depth24, 0, RenderTargetUsage.PreserveContents); } Matrix lightViewProjection = new Matrix(); CubeMapFace cubeMapFace; // = CubeMapFace.NegativeX; if (light.HasChanged) { graphicsDevice.SetRenderTarget(light.ShadowMap); Matrix lightProjection = Matrix.CreatePerspectiveFieldOfView((float)(Math.PI / 2), 1, 1, light.Radius); Matrix lightView; // = identity //Reset the blur array light.faceBlurCount = new int[6]; graphicsDevice.SetRenderTarget(light.ShadowMap); graphicsDevice.Clear(Color.Black); for (int i = 0; i < 6; i++) { // render the scene to all cubemap faces cubeMapFace = (CubeMapFace)i; switch (cubeMapFace) { case CubeMapFace.PositiveX: { lightView = Matrix.CreateLookAt(light.Position, light.Position + Vector3.UnitX, Vector3.UnitZ); lightViewProjection = lightView * lightProjection; light.LightViewProjectionPositiveX = lightViewProjection; break; } case CubeMapFace.NegativeX: { lightView = Matrix.CreateLookAt(light.Position, light.Position - Vector3.UnitX, Vector3.UnitZ); lightViewProjection = lightView * lightProjection; light.LightViewProjectionNegativeX = lightViewProjection; break; } case CubeMapFace.PositiveY: { lightView = Matrix.CreateLookAt(light.Position, light.Position + Vector3.UnitY, Vector3.UnitZ); lightViewProjection = lightView * lightProjection; light.LightViewProjectionPositiveY = lightViewProjection; break; } case CubeMapFace.NegativeY: { lightView = Matrix.CreateLookAt(light.Position, light.Position - Vector3.UnitY, Vector3.UnitZ); lightViewProjection = lightView * lightProjection; light.LightViewProjectionNegativeY = lightViewProjection; break; } case CubeMapFace.PositiveZ: { lightView = Matrix.CreateLookAt(light.Position, light.Position + Vector3.UnitZ, Vector3.UnitX); lightViewProjection = lightView * lightProjection; light.LightViewProjectionPositiveZ = lightViewProjection; break; } case CubeMapFace.NegativeZ: { lightView = Matrix.CreateLookAt(light.Position, light.Position - Vector3.UnitZ, Vector3.UnitX); lightViewProjection = lightView * lightProjection; light.LightViewProjectionNegativeZ = lightViewProjection; break; } } if (_boundingFrustumShadow != null) { _boundingFrustumShadow.Matrix = lightViewProjection; } else { _boundingFrustumShadow = new BoundingFrustum(lightViewProjection); } meshMaterialLibrary.FrustumCulling(entities, _boundingFrustumShadow, true, light.Position); // Rendering! graphicsDevice.Viewport = new Viewport(0, light.ShadowResolution * (int)cubeMapFace, light.ShadowResolution, light.ShadowResolution); //_graphicsDevice.ScissorRectangle = new Rectangle(0, light.ShadowResolution* (int) cubeMapFace, light.ShadowResolution, light.ShadowResolution); _FarClip.SetValue(light.Radius); _LightPositionWS.SetValue(light.Position); graphicsDevice.ScissorRectangle = new Rectangle(0, light.ShadowResolution * (int)cubeMapFace, light.ShadowResolution, light.ShadowResolution); meshMaterialLibrary.Draw(renderType: MeshMaterialLibrary.RenderType.ShadowOmnidirectional, viewProjection: lightViewProjection, lightViewPointChanged: true, hasAnyObjectMoved: light.HasChanged, renderModule: this); } } else { bool draw = false; for (int i = 0; i < 6; i++) { // render the scene to all cubemap faces cubeMapFace = (CubeMapFace)i; switch (cubeMapFace) { case CubeMapFace.NegativeX: lightViewProjection = light.LightViewProjectionNegativeX; break; case CubeMapFace.NegativeY: lightViewProjection = light.LightViewProjectionNegativeY; break; case CubeMapFace.NegativeZ: lightViewProjection = light.LightViewProjectionNegativeZ; break; case CubeMapFace.PositiveX: lightViewProjection = light.LightViewProjectionPositiveX; break; case CubeMapFace.PositiveY: lightViewProjection = light.LightViewProjectionPositiveY; break; case CubeMapFace.PositiveZ: lightViewProjection = light.LightViewProjectionPositiveZ; break; } if (_boundingFrustumShadow != null) { _boundingFrustumShadow.Matrix = lightViewProjection; } else { _boundingFrustumShadow = new BoundingFrustum(lightViewProjection); } bool hasAnyObjectMoved = meshMaterialLibrary.FrustumCulling(entities, _boundingFrustumShadow, false, light.Position); if (!hasAnyObjectMoved) { continue; } if (!draw) { graphicsDevice.SetRenderTarget(light.ShadowMap); draw = true; } graphicsDevice.Viewport = new Viewport(0, light.ShadowResolution * (int)cubeMapFace, light.ShadowResolution, light.ShadowResolution); //_graphicsDevice.Clear(Color.TransparentBlack); //_graphicsDevice.Clear(ClearOptions.DepthBuffer, Color.White, 0, 0); graphicsDevice.ScissorRectangle = new Rectangle(0, light.ShadowResolution * (int)cubeMapFace, light.ShadowResolution, light.ShadowResolution); meshMaterialLibrary.Draw(renderType: MeshMaterialLibrary.RenderType.ShadowOmnidirectional, viewProjection: lightViewProjection, lightViewPointChanged: light.HasChanged, hasAnyObjectMoved: true, renderModule: this); } } }