/// <summary> /// Draw all directional lights, set up some shader variables first /// </summary> /// <param name="dirLights"></param> /// <param name="cameraOrigin"></param> private void DrawDirectionalLights(List <DirectionalLight> dirLights, Vector3 cameraOrigin) { if (dirLights.Count < 1) { return; } _graphicsDevice.DepthStencilState = DepthStencilState.Default; _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; //If nothing has changed we don't need to update if (_viewProjectionHasChanged) { Shaders.deferredDirectionalLightParameterViewProjection.SetValue(_viewProjection); Shaders.deferredDirectionalLightParameterCameraPosition.SetValue(cameraOrigin); Shaders.deferredDirectionalLightParameterInverseViewProjection.SetValue(_inverseViewProjection); } _graphicsDevice.DepthStencilState = DepthStencilState.None; for (int index = 0; index < dirLights.Count; index++) { DirectionalLight light = dirLights[index]; DrawDirectionalLight(light); } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////// // HELPER FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Spawn a directional light (omni light). This light covers everything and comes from a single point from infinte distance. /// Good for something like a sun /// </summary> /// <param name="direction">The direction the light is facing in world space coordinates</param> /// <param name="intensity"></param> /// <param name="color"></param> /// <param name="position">The position is only relevant if drawing shadows</param> /// <param name="drawShadows"></param> /// <param name="shadowWorldSize">WorldSize is the width/height of the view projection for shadow mapping</param> /// <param name="shadowDepth">FarClip for shadow mapping</param> /// <param name="shadowResolution"></param> /// <param name="shadowFilteringFiltering"></param> /// <param name="screenspaceShadowBlur"></param> /// <param name="staticshadows">These shadows will not be updated once they are created, moving objects will be shadowed incorrectly</param> /// <returns></returns> private DirectionalLight AddDirectionalLight(Vector3 direction, int intensity, Color color, Vector3 position = default(Vector3), bool drawShadows = false, float shadowWorldSize = 100, float shadowDepth = 100, int shadowResolution = 512, DirectionalLight.ShadowFilteringTypes shadowFilteringFiltering = DirectionalLight.ShadowFilteringTypes.Poisson, bool screenspaceShadowBlur = false, bool staticshadows = false) { DirectionalLight light = new DirectionalLight(color: color, intensity: intensity, direction: direction, position: position, castShadows: drawShadows, shadowSize: shadowWorldSize, shadowDepth: shadowDepth, shadowResolution: shadowResolution, shadowFiltering: shadowFilteringFiltering, screenspaceshadowblur: screenspaceShadowBlur, staticshadows: staticshadows); DirectionalLights.Add(light); return(light); }
/// <summary> /// Draw the individual light, full screen effect /// </summary> /// <param name="light"></param> private void DrawDirectionalLight(DirectionalLight light) { if (!light.IsEnabled) { return; } if (_viewProjectionHasChanged) { light.DirectionViewSpace = Vector3.Transform(light.Direction, _viewIT); light.LightViewProjection_ViewSpace = _inverseView * light.LightViewProjection; light.LightView_ViewSpace = _inverseView * light.LightView; } Shaders.deferredDirectionalLightParameter_LightColor.SetValue(light.ColorV3); Shaders.deferredDirectionalLightParameter_LightDirection.SetValue(light.DirectionViewSpace); Shaders.deferredDirectionalLightParameter_LightIntensity.SetValue(light.Intensity); light.ApplyShader(); _fullScreenTriangle.Draw(_graphicsDevice); }
/// <summary> /// Main Logic for the editor part /// </summary> /// <param name="gameTime"></param> /// <param name="entities"></param> /// <param name="data"></param> public void Update(GameTime gameTime, List <BasicEntity> entities, List <Decal> decals, List <PointLight> pointLights, List <DirectionalLight> dirLights, EnvironmentSample envSample, List <DebugEntity> debugEntities, EditorReceivedData data, MeshMaterialLibrary meshMaterialLibrary) { if (!GameSettings.e_enableeditor) { return; } if (!DebugScreen.ConsoleOpen) { if (Input.WasKeyPressed(Keys.R)) { GameStats.e_gizmoMode = GizmoModes.Rotation; } if (Input.WasKeyPressed(Keys.T)) { GameStats.e_gizmoMode = GizmoModes.Translation; } if (Input.WasKeyPressed(Keys.Z)) { GameStats.e_gizmoMode = GizmoModes.Scale; } } _gizmoMode = GameStats.e_gizmoMode; int hoveredId = data.HoveredId; if (_gizmoTransformationMode) { if (Input.mouseState.LeftButton == ButtonState.Pressed) { GizmoControl(_gizmoId, data); } else { _gizmoTransformationMode = false; } } else if (Input.WasLMBClicked() && !GUIControl.UIWasUsed) { previousMouseX = Input.mouseState.X; previousMouseY = Input.mouseState.Y; //Gizmos if (hoveredId >= 1 && hoveredId <= 3) { _gizmoId = hoveredId; GizmoControl(_gizmoId, data); return; } if (hoveredId <= 0) { SelectedObject = null; return; } bool foundnew = false; //Get the selected entity! for (int index = 0; index < entities.Count; index++) { var VARIABLE = entities[index]; if (VARIABLE.Id == hoveredId) { SelectedObject = VARIABLE; foundnew = true; break; } } if (foundnew == false) { for (int index = 0; index < decals.Count; index++) { Decal decal = decals[index]; if (decal.Id == hoveredId) { SelectedObject = decal; break; } } for (int index = 0; index < pointLights.Count; index++) { PointLight pointLight = pointLights[index]; if (pointLight.Id == hoveredId) { SelectedObject = pointLight; break; } } for (int index = 0; index < dirLights.Count; index++) { DirectionalLight directionalLight = dirLights[index]; if (directionalLight.Id == hoveredId) { SelectedObject = directionalLight; break; } } { if (envSample.Id == hoveredId) { SelectedObject = envSample; } } for (int index = 0; index < debugEntities.Count; index++) { DirectionalLight debugEntity = dirLights[index]; if (debugEntity.Id == hoveredId) { SelectedObject = debugEntity; break; } } } } //Controls if (Input.WasKeyPressed(Keys.Delete)) { //Find object if (SelectedObject is BasicEntity) { entities.Remove((BasicEntity)SelectedObject); meshMaterialLibrary.DeleteFromRegistry((BasicEntity)SelectedObject); SelectedObject = null; } else if (SelectedObject is Decal) { decals.Remove((Decal)SelectedObject); SelectedObject = null; } else if (SelectedObject is PointLight) { pointLights.Remove((PointLight)SelectedObject); SelectedObject = null; } else if (SelectedObject is DirectionalLight) { dirLights.Remove((DirectionalLight)SelectedObject); SelectedObject = null; } } if (Input.WasKeyPressed(Keys.Insert) || (Input.keyboardState.IsKeyDown(Keys.LeftControl) && Input.WasKeyPressed(Keys.C))) { if (SelectedObject is BasicEntity) { BasicEntity copy = (BasicEntity)SelectedObject.Clone; copy.RegisterInLibrary(meshMaterialLibrary); entities.Add(copy); } else if (SelectedObject is Decal) { Decal copy = (Decal)SelectedObject.Clone; decals.Add(copy); } else if (SelectedObject is PointLight) { PointLight copy = (PointLight)SelectedObject.Clone; pointLights.Add(copy); } else if (SelectedObject is DirectionalLight) { DirectionalLight copy = (DirectionalLight)SelectedObject.Clone; dirLights.Add(copy); } } }
public void DrawBillboards(List <Decal> decals, List <PointLight> lights, List <DirectionalLight> dirLights, EnvironmentSample envSample, List <DebugEntity> debug, Matrix staticViewProjection, Matrix view, EditorLogic.EditorSendData sendData) { _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise; _graphicsDevice.SetVertexBuffer(_billboardBuffer.VBuffer); _graphicsDevice.Indices = (_billboardBuffer.IBuffer); Shaders.BillboardEffect.CurrentTechnique = Shaders.BillboardEffectTechnique_Billboard; Shaders.BillboardEffectParameter_IdColor.SetValue(Color.Gray.ToVector3()); //Decals Shaders.BillboardEffectParameter_Texture.SetValue(_assets.IconDecal); for (int index = 0; index < decals.Count; index++) { var decal = decals[index]; DrawBillboard(decal, staticViewProjection, view, sendData); } //Lights Shaders.BillboardEffectParameter_Texture.SetValue(_assets.IconLight); for (int index = 0; index < lights.Count; index++) { var light = lights[index]; DrawBillboard(light, staticViewProjection, view, sendData); } //DirectionalLights for (var index = 0; index < dirLights.Count; index++) { DirectionalLight light = dirLights[index]; DrawBillboard(light, staticViewProjection, view, sendData); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position + Vector3.UnitX * 10, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position - Vector3.UnitX * 10, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position + Vector3.UnitY * 10, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position - Vector3.UnitY * 10, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position + Vector3.UnitZ * 10, light.Direction * 10, 1, Color.Black, light.Color); HelperGeometryManager.GetInstance() .AddLineStartDir(light.Position - Vector3.UnitZ * 10, light.Direction * 10, 1, Color.Black, light.Color); if (light.CastShadows) { BoundingFrustum boundingFrustumShadow = new BoundingFrustum(light.LightViewProjection); HelperGeometryManager.GetInstance().CreateBoundingBoxLines(boundingFrustumShadow); } } //EnvMap Shaders.BillboardEffectParameter_Texture.SetValue(_assets.IconEnvmap); DrawBillboard(envSample, staticViewProjection, view, sendData); //Dbg for (int index = 0; index < debug.Count; index++) { var dbgEntity = debug[index]; DrawBillboard(dbgEntity, staticViewProjection, view, sendData); } }
public void Draw(GraphicsDevice graphicsDevice, MeshMaterialLibrary meshMaterialLibrary, List <BasicEntity> entities, List <PointLight> pointLights, List <DirectionalLight> dirLights, Camera camera) { _pass = Passes.Omnidirectional; //Go through all our point lights for (int index = 0; index < pointLights.Count; index++) { PointLight light = pointLights[index]; if (!light.IsEnabled) { continue; } //If we don't see the light we shouldn't update. This is actually wrong, can lead to mistakes, //if we implement it like this we should rerender once we enter visible space again. //if (_boundingFrustum.Contains(light.BoundingSphere) == ContainmentType.Disjoint) //{ // continue; //} if (light.CastShadows) { //A poing light has 6 shadow maps, add that to our stat counter. These are total shadow maps, not updated ones GameStats.shadowMaps += 6; //Update if we didn't initialize yet or if we are dynamic if (!light.StaticShadows || light.ShadowMap == null) { CreateShadowCubeMap(graphicsDevice, light, light.ShadowResolution, meshMaterialLibrary, entities); light.HasChanged = false; camera.HasChanged = true; } } } _pass = Passes.Directional; int dirLightShadowedWithSSBlur = 0; for (int index = 0; index < dirLights.Count; index++) { DirectionalLight light = dirLights[index]; if (!light.IsEnabled) { continue; } if (light.CastShadows) { GameStats.shadowMaps += 1; CreateShadowMapDirectionalLight(graphicsDevice, light, light.ShadowResolution, meshMaterialLibrary, entities); camera.HasChanged = true; light.HasChanged = false; if (light.ScreenSpaceShadowBlur) { dirLightShadowedWithSSBlur++; } } if (dirLightShadowedWithSSBlur > 1) { throw new NotImplementedException( "Only one shadowed DirectionalLight with screen space blur is supported right now"); } } }
/// <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); //} }