// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { // ----- Create prototype of a lava ball: // Use a sphere for physics simulation. _bodyPrototype = new RigidBody(new SphereShape(0.5f)); // Load the graphics model. var content = _services.GetInstance<ContentManager>(); _modelPrototype = content.Load<ModelNode>("LavaBall/LavaBall").Clone(); // Attach a point light to the model. The light projects the glowing lava // veins (cube map texture) onto the environment. _pointLight = new PointLight { Color = new Vector3F(1, 1, 1), DiffuseIntensity = 2, SpecularIntensity = 2, Range = 1.5f, Attenuation = 0.5f, Texture = content.Load<TextureCube>("LavaBall/LavaCubeMap"), }; var pointLightNode = new LightNode(_pointLight); _modelPrototype.Children.Add(pointLightNode); // Get the emissive color binding of the material because the emissive color // will be animated. // The model contains one mesh node with a single material. var meshNode = (MeshNode)_modelPrototype.Children[0]; var mesh = meshNode.Mesh; var material = mesh.Materials[0]; // The material contains several effect bindings. The "EmissiveColor" is applied // in the "Material" pass. // (For reference see material definition file: Samples\Media\LavaBall\Lava.drmat) _emissiveColorBinding = (ConstParameterBinding<Vector3>)material["Material"].ParameterBindings["EmissiveColor"]; // Use the animation service to animate glow intensity of the lava. var animationService = _services.GetInstance<IAnimationService>(); // Create an AnimatableProperty<float>, which stores the animation value. _glowIntensity = new AnimatableProperty<float>(); // Create sine animation and play the animation back-and-forth. var animation = new SingleFromToByAnimation { From = 0.3f, To = 3.0f, Duration = TimeSpan.FromSeconds(1), EasingFunction = new SineEase { Mode = EasingMode.EaseInOut }, }; var clip = new AnimationClip<float> { Animation = animation, Duration = TimeSpan.MaxValue, LoopBehavior = LoopBehavior.Oscillate }; animationService.StartAnimation(clip, _glowIntensity).AutoRecycle(); }
public ProjectedShadowSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService) { RenderCallback = Render, }; GraphicsService.Screens.Insert(0, delegateGraphicsScreen); // Create a new empty scene. _scene = new Scene(); Services.Register(typeof(IScene), null, _scene); // Add a custom game object which controls the camera. _cameraObject = new CameraObject(Services); _cameraObject.ResetPose(new Vector3F(-8, 6, 8), -ConstantsF.PiOver4, -0.4f); GameObjectService.Objects.Add(_cameraObject); // Add a default light setup (ambient light + 3 directional lights). var defaultLightsObject = new DefaultLightsObject(Services); GameObjectService.Objects.Add(defaultLightsObject); // Get the main directional light. _mainDirectionalLightNode = ((LightNode)_scene.GetSceneNode("KeyLight")); // Add a ground plane model to the scene graph. var grid = ContentManager.Load<ModelNode>("Ground/Ground").Clone(); grid.ScaleLocal = new Vector3F(0.3f); _scene.Children.Add(grid); // Add a tank model to the scene graph. var tank = ContentManager.Load<ModelNode>("Tank/tank").Clone(); _scene.Children.Add(tank); // Remember the mesh nodes of tank node. _tankMeshNodes = tank.GetSubtree().Where(n => n is MeshNode).ToArray(); // Create the renderers. _meshRenderer = new MeshRenderer(); var spriteFont = UIContentManager.Load<SpriteFont>("UI Themes/BlendBlue/Default"); _debugRenderer = new DebugRenderer(GraphicsService, spriteFont); _projectedShadowRenderer = new ProjectedShadowRenderer(GraphicsService) { // The plane onto which the shadows are projected. It is positioned a bit above the ground // plane to avoid z-fighting. ShadowedPlane = new Plane(new Vector3F(0, 1, 0), 0.01f), // The shadow color is a transparent black. ShadowColor = new Vector4F(0, 0, 0, 0.4f), // The light position is set in Update(). //LightPosition = ... }; }
// OnUnload() is called when the GameObject is removed from the IGameObjectService. protected override void OnUnload() { _godRayFilter.Scale = _defaultScale; if (_directionalLightNode != null) { _directionalLightNode.SceneChanged -= OnDirectionalLightNodeChanged; _directionalLightNode = null; } }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var ambientLight = new AmbientLight { //Color = new Vector3F(0.05333332f, 0.09882354f, 0.1819608f), // XNA BasicEffect Values Color = new Vector3F(0.5f), // Make ambient light brighter. Intensity = 1, HemisphericAttenuation = 1, }; _ambientLightNode = new LightNode(ambientLight); var keyLight = new DirectionalLight { Color = new Vector3F(1, 0.9607844f, 0.8078432f), DiffuseIntensity = 1, SpecularIntensity = 1, }; _keyLightNode = new LightNode(keyLight) { Name = "KeyLight", Priority = 10, // This is the most important light. PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(-0.5265408f, -0.5735765f, -0.6275069f))), }; var fillLight = new DirectionalLight { Color = new Vector3F(0.9647059f, 0.7607844f, 0.4078432f), DiffuseIntensity = 1, SpecularIntensity = 0, }; _fillLightNode = new LightNode(fillLight) { Name = "FillLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.7198464f, 0.3420201f, 0.6040227f))), }; var backLight = new DirectionalLight { Color = new Vector3F(0.3231373f, 0.3607844f, 0.3937255f), DiffuseIntensity = 1, SpecularIntensity = 1, }; _backLightNode = new LightNode(backLight) { Name = "BackLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.4545195f, -0.7660444f, 0.4545195f))), }; var scene = _services.GetInstance<IScene>(); scene.Children.Add(_ambientLightNode); scene.Children.Add(_keyLightNode); scene.Children.Add(_fillLightNode); scene.Children.Add(_backLightNode); }
public VarianceShadowSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services) { // For debugging: Disable materials and only show light buffer. DebugMode = DeferredGraphicsDebugMode.VisualizeDiffuseLightBuffer }; _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); // Create test scene. ShadowSample.CreateScene(Services, ContentManager, _graphicsScreen); // Get directional light created by the DynamicSkyObject and replace the default // shadow with our custom VSM shadow. _lightNode = _graphicsScreen.Scene.GetDescendants().OfType<LightNode>().First(n => n.Shadow is CascadedShadow); _varianceShadow = new VarianceShadow { // If a target area is set, the VSM covers the given area. // If no target area is set, the VSM covers the area in front of the camera. TargetArea = new Aabb(new Vector3F(-100, 0, -100), new Vector3F(100, 50, 100)), }; _lightNode.Shadow = _varianceShadow; // Apply a blur filter to the shadow map. _varianceShadow.Filter = new Blur(GraphicsService); _varianceShadow.Filter.InitializeGaussianBlur(11, 3, false); // Register our custom shadow map and shadow mask renderers. _graphicsScreen.ShadowMapRenderer.Renderers.Add(new VarianceShadowMapRenderer(_graphicsScreen.ShadowMapRenderer.RenderCallback)); _graphicsScreen.ShadowMaskRenderer.Renderers.Add(new VarianceShadowMaskRenderer(GraphicsService)); CreateGuiControls(); }
public int Compare(LightNode x, LightNode y) { if (x.Priority < y.Priority) { return(-1); } if (x.Priority > y.Priority) { return(+1); } return(x.SortTag.CompareTo(y.SortTag)); }
// Add light sources for standard three-point lighting. private static void AddLights(Scene scene) { var ambientLight = new AmbientLight { Color = new Vector3F(0.05333332f, 0.09882354f, 0.1819608f), Intensity = 1, HemisphericAttenuation = 0, }; scene.Children.Add(new LightNode(ambientLight)); var keyLight = new DirectionalLight { Color = new Vector3F(1, 0.9607844f, 0.8078432f), DiffuseIntensity = 1, SpecularIntensity = 1, }; var keyLightNode = new LightNode(keyLight) { Name = "KeyLight", Priority = 10, // This is the most important light. PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(-0.5265408f, -0.5735765f, -0.6275069f))), }; scene.Children.Add(keyLightNode); var fillLight = new DirectionalLight { Color = new Vector3F(0.9647059f, 0.7607844f, 0.4078432f), DiffuseIntensity = 1, SpecularIntensity = 0, }; var fillLightNode = new LightNode(fillLight) { Name = "FillLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.7198464f, 0.3420201f, 0.6040227f))), }; scene.Children.Add(fillLightNode); var backLight = new DirectionalLight { Color = new Vector3F(0.3231373f, 0.3607844f, 0.3937255f), DiffuseIntensity = 1, SpecularIntensity = 1, }; var backLightNode = new LightNode(backLight) { Name = "BackLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.4545195f, -0.7660444f, 0.4545195f))), }; scene.Children.Add(backLightNode); }
public void UpdateClipSubmesh(IGraphicsService graphicsService, LightNode node) { var clip = node.Clip; Debug.Assert(clip != null); // We have to update the submesh if it is null or disposed. // Submesh == null --> Update // Submesh != null && VertexBuffer.IsDisposed --> Update // Submesh != null && VertexBuffer == null --> This is the EmptyShape. No updated needed. if (ClipSubmesh == null || (ClipSubmesh.VertexBuffer != null && ClipSubmesh.VertexBuffer.IsDisposed)) { ShapeMeshCache.GetMesh(graphicsService, clip.Shape, out ClipSubmesh, out ClipMatrix); // Add transform of Clip. ClipMatrix = clip.Pose * Matrix44F.CreateScale(clip.Scale) * ClipMatrix; } }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var scene = (SceneNode)_services.GetInstance<IScene>(); // Find the most important directional light. _directionalLightNode = scene.GetDescendants() .OfType<LightNode>() .Where(ln => ln.Light is DirectionalLight) .OrderBy(ln => ln.Priority) .LastOrDefault(); if (_directionalLightNode != null) { // This light node defines the direction of the god rays. Handle the // SceneChanged event to update the GodRayFilter when the light node is // updated. _directionalLightNode.SceneChanged += OnDirectionalLightNodeChanged; // First time initialization: OnDirectionalLightNodeChanged(null, null); } }
public ProjectedShadowSample2(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; var delegateGraphicsScreen = new DelegateGraphicsScreen(GraphicsService) { RenderCallback = Render, }; GraphicsService.Screens.Insert(0, delegateGraphicsScreen); // The dude model uses a new ProjectedShadowSkinned.fx effect. This effect contains new // parameters 'ShadowMatrix' and 'ShadowColor' which are not yet supported. When an mesh is // loaded via the content manager, effect bindings are automatically created. This is done // by effect interpreters and effect binders. The graphics service uses several predefined // effect interpreter and binder classes to support the most common effect parameters. E.g. // the SceneEffectInterpreter and SceneEffectBinder handle parameters like 'World', 'View', // 'ViewProjection', 'CameraPosition', 'FogColor', etc. (see also class // SceneEffectParameterSemantics). // We can add new effect interpreters/binders or we can add an entry to an existing // interpreter/binder. Let's add entries to the standard SceneEffectInterpreter which creates // meta-data for the new parameters: var sceneEffectInterpreter = GraphicsService.EffectInterpreters.OfType<SceneEffectInterpreter>().First(); sceneEffectInterpreter.ParameterDescriptions.Add( "ShadowMatrix", (parameter, index) => new EffectParameterDescription(parameter, "ShadowMatrix", index, EffectParameterHint.Global)); sceneEffectInterpreter.ParameterDescriptions.Add( "ShadowColor", (parameter, index) => new EffectParameterDescription(parameter, "ShadowColor", index, EffectParameterHint.Global)); // Add entries to the standard SceneEffectBinder which create DelegateParameterBindings for // the new parameters. The delegate bindings use callback methods to compute the parameter // value. var sceneEffectBinder = GraphicsService.EffectBinders.OfType<SceneEffectBinder>().First(); sceneEffectBinder.MatrixBindings.Add( "ShadowMatrix", (effect, parameter, data) => new DelegateParameterBinding<Matrix>(effect, parameter, GetShadowMatrix)); sceneEffectBinder.Vector4Bindings.Add( "ShadowColor", (effect, parameter, data) => new DelegateParameterBinding<Vector4>(effect, parameter, GetShadowColor)); // Create a new empty scene. _scene = new Scene(); Services.Register(typeof(IScene), null, _scene); // Add a custom game object which controls the camera. _cameraObject = new CameraObject(Services); _cameraObject.ResetPose(new Vector3F(-2, 2, 2), -ConstantsF.PiOver4, -0.4f); GameObjectService.Objects.Add(_cameraObject); // Add a default light setup (ambient light + 3 directional lights). var defaultLightsObject = new DefaultLightsObject(Services); GameObjectService.Objects.Add(defaultLightsObject); // Get the main directional light. _mainDirectionalLightNode = ((LightNode)_scene.GetSceneNode("KeyLight")); // Add a ground plane model to the scene graph. var grid = ContentManager.Load<ModelNode>("Ground/Ground").Clone(); grid.ScaleLocal = new Vector3F(0.3f); _scene.Children.Add(grid); // Add a dude model to the scene graph. var dude = ContentManager.Load<ModelNode>("DudeWithProjectedShadow/Dude").Clone(); dude.PoseWorld = new Pose(Matrix33F.CreateRotationY(ConstantsF.Pi)); SampleHelper.EnablePerPixelLighting(dude); _scene.Children.Add(dude); // Start walk animation. StartDudeAnimation(dude); // Create the renderers. _meshRenderer = new MeshRenderer(); _shadowColor = new Vector4(0, 0, 0, 0.4f); }
public FacialAnimationSample(Microsoft.Xna.Framework.Game game) : base(game) { _graphicsScreen = new DeferredGraphicsScreen(Services) { DrawReticle = false }; GraphicsService.Screens.Insert(0, _graphicsScreen); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add a game object which adds some GUI controls for the deferred graphics // screen to the Options window. GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); // Use a fixed camera. var projection = new PerspectiveProjection(); projection.SetFieldOfView( ConstantsF.PiOver4, GraphicsService.GraphicsDevice.Viewport.AspectRatio, 0.1f, 10); var cameraNode = new CameraNode(new Camera(projection)); cameraNode.LookAt(new Vector3F(0.15f, 0.15f, 0.5f), new Vector3F(0.1f, 0.15f, 0), Vector3F.Up); _graphicsScreen.Scene.Children.Add(cameraNode); _graphicsScreen.ActiveCameraNode = cameraNode; // Lighting setup: var keyLight = new LightNode(new Spotlight { DiffuseIntensity = 0.6f, SpecularIntensity = 0.4f }); keyLight.LookAt(new Vector3F(-2, 2, 2), new Vector3F(), Vector3F.Up); _graphicsScreen.Scene.Children.Add(keyLight); var backLight = new LightNode(new Spotlight { DiffuseIntensity = 0.3f, SpecularIntensity = 0.3f }); backLight.LookAt(new Vector3F(1, 0.5f, -2), new Vector3F(), Vector3F.Up); _graphicsScreen.Scene.Children.Add(backLight); var fillLight = new LightNode(new AmbientLight { HemisphericAttenuation = 1, Intensity = 0.1f }); _graphicsScreen.Scene.Children.Add(fillLight); // The scene does not have a proper background. That's why the exposure is a // bit off. --> Reduce the max exposure. var hdrFilter = _graphicsScreen.PostProcessors.OfType<HdrFilter>().First(); hdrFilter.MaxExposure = 6; // Load the customized "Sintel" model (original: Durian Open Movie Project - http://www.sintel.org/). var model = ContentManager.Load<ModelNode>("Sintel/Sintel-Head").Clone(); model.PoseWorld = new Pose(new Vector3F(0, 0, 0), Matrix33F.CreateRotationY(MathHelper.ToRadians(10)) * Matrix33F.CreateRotationX(-MathHelper.ToRadians(90))); _graphicsScreen.Scene.Children.Add(model); // The model consists of a root node and a mesh node. // ModelNode "Sintel-Head" // MeshNode "Sintel" _sintel = (MeshNode)model.Children[0]; // The model contains two skeletal animations: // - "MOUTH-open" is just a single frame. // - "Test" is a short animation (250 frames). // In the Options window, we will add a slider to move the jaw. // Slider.Value = 0 ... mouth closed (default) _mouthClosedPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); // Slider.Value = 1 ... mouth open (copied from the "MOUTH-open" animation) SkeletonKeyFrameAnimation mouthOpen = _sintel.Mesh.Animations["MOUTH-open"]; _mouthOpenPose = SkeletonPose.Create(_sintel.Mesh.Skeleton); mouthOpen.GetValue(TimeSpan.Zero, ref _mouthOpenPose, ref _mouthOpenPose, ref _mouthOpenPose); // Turn the "Test" animation into an endless loop. _skeletalAnimation = new AnimationClip<SkeletonPose>(_sintel.Mesh.Animations["Test"]) { Duration = TimeSpan.MaxValue, LoopBehavior = LoopBehavior.Cycle }; // Mesh has several morph targets for facial animation, which are imported // automatically via the content pipeline. Unfortunately, the XNA content // pipeline cannot import morph target animations automatically. // In this demo, we will create a morph target animation in code. _morphingAnimation = CreateMorphingAnimation(); CreateGuiControls(); }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var contentManager = _services.GetInstance<ContentManager>(); if (_type == 1) { // A simple cube. RigidBody = new RigidBody(new BoxShape(1, 1, 1)); ModelNode = contentManager.Load<ModelNode>("RustyCube/RustyCube").Clone(); } else if (_type == 2) { // Another simple cube. RigidBody = new RigidBody(new BoxShape(1, 1, 1)); ModelNode = contentManager.Load<ModelNode>("MetalGrateBox/MetalGrateBox").Clone(); } else if (_type == 3) { // A TV-like box. RigidBody = new RigidBody(new BoxShape(1, 0.6f, 0.8f)) { UserData = "TV" }; ModelNode = contentManager.Load<ModelNode>("TVBox/TVBox"); if (ModelNode.Children.OfType<LightNode>().Count() == 0) { // This is the first time the "TVBox" is loaded. // Add a projector light to the model that projects the TV screen. The // TV screen is the emissive part of the TV mesh. var meshNode = ModelNode.Children.OfType<MeshNode>().First(); var material = meshNode.Mesh.Materials.First(m => m.Name == "TestCard"); // Get texture from material. // Note: In XNA the effect parameter type is Texture. In MonoGame it is Texture2D. Texture2D texture; EffectParameterBinding parameterBinding = material["Material"].ParameterBindings["EmissiveTexture"]; if (parameterBinding is EffectParameterBinding<Texture>) texture = (Texture2D)((EffectParameterBinding<Texture>)parameterBinding).Value; else texture = ((EffectParameterBinding<Texture2D>)parameterBinding).Value; var projection = new PerspectiveProjection(); projection.Near = 0.55f; projection.Far = 3.0f; projection.SetFieldOfView(MathHelper.ToRadians(60), 0.76f / 0.56f); var projectorLight = new ProjectorLight(texture, projection); projectorLight.Attenuation = 4; var projectorLightNode = new LightNode(projectorLight); projectorLightNode.LookAt(new Vector3F(0, 0.2f, 0), Vector3F.Zero, Vector3F.UnitZ); // Attach the projector light to the model. ModelNode.Children.Add(projectorLightNode); } ModelNode = ModelNode.Clone(); } else if (_type == 4) { // A "magic" sphere with a colored point light. RigidBody = new RigidBody(new SphereShape(0.25f)); ModelNode = contentManager.Load<ModelNode>("MagicSphere/MagicSphere"); if (ModelNode.Children.OfType<LightNode>().Count() == 0) { // This is the first time the "MagicSphere" is loaded. // Change the size of the sphere. var meshNode = ModelNode.Children.OfType<MeshNode>().First(); meshNode.ScaleLocal = new Vector3F(0.5f); // Disable shadows. (The sphere acts as a light source.) meshNode.CastsShadows = false; // Add a point light. var pointLight = new PointLight { Color = new Vector3F(1, 1, 1), DiffuseIntensity = 4, SpecularIntensity = 4, Range = 3, Attenuation = 1, Texture = contentManager.Load<TextureCube>("MagicSphere/ColorCube"), }; var pointLightNode = new LightNode(pointLight) { // The point light uses shadow mapping to cast an omnidirectional shadow. Shadow = new CubeMapShadow { PreferredSize = 64, } }; ModelNode.Children.Add(pointLightNode); } ModelNode = ModelNode.Clone(); } else if (_type == 5) { // A sphere of glass (or "bubble"). RigidBody = new RigidBody(new SphereShape(0.3f)); ModelNode = contentManager.Load<ModelNode>("Bubble/Bubble").Clone(); ModelNode.GetDescendants().OfType<MeshNode>().First().ScaleLocal = new Vector3F(0.3f); } else if (_type == 6) { // A rusty barrel with multiple levels of detail (LODs). RigidBody = new RigidBody(new CylinderShape(0.35f, 1)); ModelNode = contentManager.Load<ModelNode>("Barrel/Barrel").Clone(); } else { // A cube consisting of a frame and transparent sides. RigidBody = new RigidBody(new BoxShape(1, 1, 1)); ModelNode = contentManager.Load<ModelNode>("GlassBox/GlassBox").Clone(); } SampleHelper.EnablePerPixelLighting(ModelNode); // Set a random pose. var randomPosition = new Vector3F( RandomHelper.Random.NextFloat(-10, 10), RandomHelper.Random.NextFloat(2, 5), RandomHelper.Random.NextFloat(-20, 0)); RigidBody.Pose = new Pose(randomPosition, RandomHelper.Random.NextQuaternionF()); ModelNode.PoseWorld = RigidBody.Pose; // Add rigid body to physics simulation and model to scene. var simulation = _services.GetInstance<Simulation>(); simulation.RigidBodies.Add(RigidBody); var scene = _services.GetInstance<IScene>(); scene.Children.Add(ModelNode); }
public void Render(IList<SceneNode> occluders, LightNode lightNode, SceneNodeRenderer renderer, RenderContext context) { if (context == null) throw new ArgumentNullException("context"); context.ThrowIfCameraMissing(); // ----- Sort occluders by type: IOcclusionProxy vs. SceneNode SortOccluders(occluders, renderer, context); Statistics.Occluders = _occlusionProxies.Count + _sceneNodes.Count; // ----- Update all IOcclusionProxy in background. if (_occlusionProxies.Count > 0) { if (EnableMultithreading) _updateTask = Parallel.Start(_updateOcclusionProxies); else UpdateOcclusionProxies(); } // ----- Backup render state. var originalRenderTarget = context.RenderTarget; var originalViewport = context.Viewport; var graphicsService = context.GraphicsService; var graphicsDevice = graphicsService.GraphicsDevice; var originalRenderState = new RenderStateSnapshot(graphicsDevice); // ----- Camera properties var cameraNode = context.CameraNode; Matrix cameraView = (Matrix)cameraNode.View; var cameraProjection = cameraNode.Camera.Projection; Matrix cameraViewProjection = cameraView * cameraProjection; if (lightNode == null) { _lightHzbAvailable = false; } else { // ----- Render light HZB. _lightHzbAvailable = true; var shadow = lightNode.Shadow as CascadedShadow; if (shadow == null) throw new ArgumentException("LightNode expected to have a CascadedShadow.", "lightNode"); // Set up orthographic camera similar to CascadedShadowMapRenderer. context.CameraNode = _orthographicCameraNode; // Part of camera frustum covered by shadow map. var maxShadowDistance = shadow.Distances[shadow.NumberOfCascades - 1]; _splitVolume.SetFieldOfView(cameraProjection.FieldOfViewY, cameraProjection.AspectRatio, cameraProjection.Near, Math.Min(cameraProjection.Far, maxShadowDistance)); // Find the bounding sphere of the camera frustum. Vector3F center; float radius; GetBoundingSphere(_splitVolume, out center, out radius); Matrix33F orientation = lightNode.PoseWorld.Orientation; Vector3F lightBackward = orientation.GetColumn(2); var orthographicProjection = (OrthographicProjection)_orthographicCameraNode.Camera.Projection; // Create a tight orthographic frustum around the cascade's bounding sphere. orthographicProjection.SetOffCenter(-radius, radius, -radius, radius, 0, 2 * radius); center = cameraNode.PoseWorld.ToWorldPosition(center); Vector3F cameraPosition = center + radius * lightBackward; Pose frustumPose = new Pose(cameraPosition, orientation); // For rendering the shadow map, move near plane back by MinLightDistance // to catch occluders in front of the cascade. orthographicProjection.Near = -shadow.MinLightDistance; _orthographicCameraNode.PoseWorld = frustumPose; Pose lightView = frustumPose.Inverse; Matrix lightViewProjection = (Matrix)lightView * orthographicProjection; _parameterCameraViewProj.SetValue(lightViewProjection); _parameterCameraNear.SetValue(orthographicProjection.Near); _parameterCameraFar.SetValue(orthographicProjection.Far); RenderOccluders(renderer, context); CreateDepthHierarchy(_lightHzb, context); // Set effect parameters for use in Query(). _lightAabb = _orthographicCameraNode.Aabb; _parameterLightViewProj.SetValue(lightViewProjection); _parameterLightToCamera.SetValue(Matrix.Invert(lightViewProjection) * cameraViewProjection); context.CameraNode = cameraNode; } // ----- Render camera HZB. // Set camera parameters. (These effect parameters are also needed in Query()!) _cameraAabb = cameraNode.Aabb; _parameterCameraViewProj.SetValue(cameraViewProjection); _parameterCameraNear.SetValue(cameraProjection.Near); _parameterCameraFar.SetValue(cameraProjection.Far); var lodCameraNode = context.LodCameraNode; if (lodCameraNode != null) { // Enable distance culling. _parameterCameraPosition.SetValue((Vector3)lodCameraNode.PoseWorld.Position); float yScale = Math.Abs(lodCameraNode.Camera.Projection.ToMatrix44F().M11); _parameterNormalizationFactor.SetValue(1.0f / yScale * cameraNode.LodBias * context.LodBias); } else { // Disable distance culling. _parameterCameraPosition.SetValue(new Vector3()); _parameterNormalizationFactor.SetValue(0); } RenderOccluders(renderer, context); CreateDepthHierarchy(_cameraHzb, context); _sceneNodes.Clear(); _occlusionProxies.Clear(); // Restore render state. graphicsDevice.SetRenderTarget(null); originalRenderState.Restore(); context.RenderTarget = originalRenderTarget; context.Viewport = originalViewport; }
public void Render(IList<SceneNode> occluders, LightNode lightNode, RenderContext context) { Render(occluders, lightNode, null, context); }
public CompositeShadowSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services) { // For debugging: Disable materials and only show light buffer. DebugMode = DeferredGraphicsDebugMode.VisualizeDiffuseLightBuffer }; _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); // Create test scene. ShadowSample.CreateScene(Services, ContentManager, _graphicsScreen); // Create 3 different shadows: // The VarianceShadow covers the whole level. _vsmShadow = new VarianceShadow { Prefer16Bit = false, PreferredSize = 512, MinLightDistance = 200, MaxDistance = 200, FadeOutRange = 0, ShadowFog = 0, TargetArea = new Aabb(new Vector3F(-100, 0, -100), new Vector3F(100, 50, 100)) }; _vsmShadow.Filter = new Blur(GraphicsService); _vsmShadow.Filter.NumberOfPasses = 1; _vsmShadow.Filter.InitializeGaussianBlur(11, 3, false); // The CascadedShadow for static objects. _staticCascadedShadow = new CascadedShadow { PreferredSize = 1024, Prefer16Bit = true, Distances = new Vector4F(4, 12, 20, 80), MinLightDistance = 200, }; // The CascadedShadow for dynamic objects covering a smaller distance. _dynamicCascadedShadow = new CascadedShadow { PreferredSize = 1024, Prefer16Bit = true, NumberOfCascades = 2, Distances = new Vector4F(4, 12, 0, 0), MinLightDistance = 200, }; // Get directional light created by the DynamicSkyObject and replace the default // shadow with our a CompositeShadow. _lightNode = _graphicsScreen.Scene.GetDescendants().OfType<LightNode>().First(n => n.Shadow is CascadedShadow); _lightNode.Shadow = new CompositeShadow { Shadows = { _vsmShadow, _staticCascadedShadow, _dynamicCascadedShadow, } }; // We do not want to render the same objects into all 3 shadow maps. We use a custom // render callback to render each objects into only one of the shadow maps. _graphicsScreen.ShadowMapRenderer.RenderCallback = context => { // Query all shadow casters. var query = context.Scene.Query<ShadowCasterQuery>(context.CameraNode, context); if (query.ShadowCasters.Count == 0) return false; // Get the shadow which is currently being rendered. var shadow = context.Object; // Create a list of scene nodes for the current shadow. var list = _tempList; if (shadow == _vsmShadow) { // Get the hills and skyscrapers which have been marked with a user flag // in ShadowSample.CreateScene. foreach (var node in query.ShadowCasters) if (node.UserFlags == 1) _tempList.Add(node); } else if (shadow == _staticCascadedShadow) { // Get all static objects except the hills/skyscrapers. foreach (var node in query.ShadowCasters) if (node.UserFlags == 0 && node.IsStatic) _tempList.Add(node); } else if (shadow == _dynamicCascadedShadow) { // Get all dynamic objects. foreach (var node in query.ShadowCasters) if (!node.IsStatic) _tempList.Add(node); } else { // Other shadows of other lights. list = query.ShadowCasters; } // Render the selected objects into the shadow map. _graphicsScreen.MeshRenderer.Render(list, context); _tempList.Clear(); return true; }; // Register the custom renderers for the VarianceShadow. _graphicsScreen.ShadowMapRenderer.Renderers.Add(new VarianceShadowMapRenderer(_graphicsScreen.ShadowMapRenderer.RenderCallback)); _graphicsScreen.ShadowMaskRenderer.Renderers.Add(new VarianceShadowMaskRenderer(GraphicsService)); CreateGuiControls(); }
// OnUnload() is called when the GameObject is removed from the IGameObjectService. protected override void OnUnload() { // Clean up. _campfire.Parent.Children.Remove(_campfire); _campfire.Dispose(false); _campfire = null; _fireParticles = null; _smokeParticles = null; _light = null; _random = null; }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var content = _services.GetInstance<ContentManager>(); _skyboxNode = new SkyboxNode(content.Load<TextureCube>("Sky2")) { Color = new Vector3F(SkyExposure), }; // The ambient light. var ambientLight = new AmbientLight { Color = new Vector3F(0.9f, 0.9f, 1f), HdrScale = 0.1f, Intensity = 0.5f, HemisphericAttenuation = 0.8f, }; _ambientLightNode = new LightNode(ambientLight) { Name = "Ambient", }; // The main directional light. var sunlight = new DirectionalLight { Color = new Vector3F(1, 0.9607844f, 0.9078432f), HdrScale = 0.4f, DiffuseIntensity = 1, SpecularIntensity = 1, }; _sunlightNode = new LightNode(sunlight) { Name = "Sunlight", Priority = 10, // This is the most important light. PoseWorld = new Pose(QuaternionF.CreateRotationY(-1.4f) * QuaternionF.CreateRotationX(-0.6f)), // This light uses Cascaded Shadow Mapping. Shadow = new CascadedShadow { #if XBOX PreferredSize = 512, #else PreferredSize = 1024, #endif Prefer16Bit = true, } }; // Add a lens flare for the key light. var lensFlare = new LensFlare(true) { QuerySize = 0.2f, Size = 0.2f, Name = "Sun Flare" }; var lensFlareTexture = content.Load<Texture2D>("LensFlare/LensFlares"); var circleTexture = new PackedTexture("Circle", lensFlareTexture, new Vector2F(0, 0), new Vector2F(0.25f, 0.5f)); var glowTexture = new PackedTexture("Glow", lensFlareTexture, new Vector2F(0.25f, 0), new Vector2F(0.25f, 0.5f)); var ringTexture = new PackedTexture("Ring", lensFlareTexture, new Vector2F(0.5f, 0), new Vector2F(0.25f, 0.5f)); var haloTexture = new PackedTexture("Halo", lensFlareTexture, new Vector2F(0.75f, 0), new Vector2F(0.25f, 0.5f)); var sunTexture = new PackedTexture("Sun", lensFlareTexture, new Vector2F(0, 0.5f), new Vector2F(0.25f, 0.5f)); var streaksTexture = new PackedTexture("Streaks", lensFlareTexture, new Vector2F(0.25f, 0.5f), new Vector2F(0.25f, 0.5f)); var flareTexture = new PackedTexture("Flare", lensFlareTexture, new Vector2F(0.5f, 0.5f), new Vector2F(0.25f, 0.5f)); lensFlare.Elements.Add(new LensFlareElement(-0.2f, 0.55f, 0.0f, new Color(175, 175, 255, 20), new Vector2F(0.5f, 0.5f), circleTexture)); lensFlare.Elements.Add(new LensFlareElement(0.0f, 0.9f, 0.0f, new Color(255, 255, 255, 255), new Vector2F(0.5f, 0.5f), sunTexture)); lensFlare.Elements.Add(new LensFlareElement(0.0f, 1.8f, 0.0f, new Color(255, 255, 255, 128), new Vector2F(0.5f, 0.5f), streaksTexture)); lensFlare.Elements.Add(new LensFlareElement(0.0f, 2.6f, 0.0f, new Color(255, 255, 200, 64), new Vector2F(0.5f, 0.5f), glowTexture)); lensFlare.Elements.Add(new LensFlareElement(0.5f, 0.12f, 0.0f, new Color(60, 60, 180, 35), new Vector2F(0.5f, 0.5f), circleTexture)); lensFlare.Elements.Add(new LensFlareElement(0.55f, 0.46f, 0.0f, new Color(100, 100, 200, 60), new Vector2F(0.5f, 0.5f), circleTexture)); lensFlare.Elements.Add(new LensFlareElement(0.6f, 0.17f, 0.0f, new Color(120, 120, 220, 40), new Vector2F(0.5f, 0.5f), circleTexture)); lensFlare.Elements.Add(new LensFlareElement(0.85f, 0.2f, 0.0f, new Color(60, 60, 255, 100), new Vector2F(0.5f, 0.5f), ringTexture)); lensFlare.Elements.Add(new LensFlareElement(1.5f, 0.2f, 0.0f, new Color(255, 60, 60, 130), new Vector2F(0.5f, 0.5f), flareTexture)); lensFlare.Elements.Add(new LensFlareElement(0.15f, 0.15f, 0.0f, new Color(255, 60, 60, 90), new Vector2F(0.5f, 0.5f), flareTexture)); lensFlare.Elements.Add(new LensFlareElement(1.3f, 0.6f, 0.0f, new Color(60, 60, 255, 180), new Vector2F(0.5f, 0.5f), haloTexture)); lensFlare.Elements.Add(new LensFlareElement(1.4f, 0.2f, 0.0f, new Color(220, 80, 80, 98), new Vector2F(0.5f, 0.5f), haloTexture)); lensFlare.Elements.Add(new LensFlareElement(1.5f, 0.1f, 0.0f, new Color(220, 80, 80, 85), new Vector2F(0.5f, 0.5f), circleTexture)); lensFlare.Elements.Add(new LensFlareElement(1.6f, 0.5f, 0.0f, new Color(60, 60, 255, 80), new Vector2F(0.5f, 0.5f), haloTexture)); lensFlare.Elements.Add(new LensFlareElement(1.8f, 0.3f, 0.0f, new Color(90, 60, 255, 110), new Vector2F(0.5f, 0.5f), ringTexture)); lensFlare.Elements.Add(new LensFlareElement(1.95f, 0.5f, 0.0f, new Color(60, 60, 255, 120), new Vector2F(0.5f, 0.5f), haloTexture)); lensFlare.Elements.Add(new LensFlareElement(2.0f, 0.15f, 0.0f, new Color(60, 60, 255, 85), new Vector2F(0.5f, 0.5f), circleTexture)); // Add lens flare as a child of the sunlight. var lensFlareNode = new LensFlareNode(lensFlare); _sunlightNode.Children = new SceneNodeCollection(); _sunlightNode.Children.Add(lensFlareNode); // Add scene nodes to scene graph. var scene = _services.GetInstance<IScene>(); scene.Children.Add(_skyboxNode); scene.Children.Add(_ambientLightNode); scene.Children.Add(_sunlightNode); }
// OnUnload() is called when the GameObject is removed from the IGameObjectService. protected override void OnUnload() { _skyboxNode.Parent.Children.Remove(_skyboxNode); _skyboxNode.Dispose(false); _skyboxNode = null; _ambientLightNode.Parent.Children.Remove(_ambientLightNode); _ambientLightNode.Dispose(false); _ambientLightNode = null; _sunlightNode.Parent.Children.Remove(_sunlightNode); _sunlightNode.Dispose(false); _sunlightNode = null; }
public static void AddLights(Scene scene) { if (scene == null) throw new ArgumentNullException(nameof(scene)); float hdrScale = 1; // ----- Ambient light var ambientLight = new AmbientLight { Color = new Vector3F(0.05333332f, 0.09882354f, 0.1819608f), Intensity = 1, HemisphericAttenuation = 0, HdrScale = hdrScale, }; scene.Children.Add(new LightNode(ambientLight)); // ----- Key Light with shadow map var keyLight = new DirectionalLight { Color = new Vector3F(1, 0.9607844f, 0.8078432f), DiffuseIntensity = 1, SpecularIntensity = 1, HdrScale = hdrScale, }; var keyLightNode = new LightNode(keyLight) { Name = "KeyLight", Priority = 10, // This is the most important light. PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(-0.5265408f, -0.5735765f, -0.6275069f))), // This light uses Cascaded Shadow Mapping. Shadow = new CascadedShadow { PreferredSize = 1024, NumberOfCascades = 4, Distances = new Vector4F(2, 4, 10, 20f), MinLightDistance = 8, FilterRadius = 2, NumberOfSamples = 16, CascadeSelection = ShadowCascadeSelection.BestDithered, } }; scene.Children.Add(keyLightNode); // ----- Fill light var fillLight = new DirectionalLight { Color = new Vector3F(0.9647059f, 0.7607844f, 0.4078432f), DiffuseIntensity = 1, SpecularIntensity = 0, HdrScale = hdrScale, }; var fillLightNode = new LightNode(fillLight) { Name = "FillLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.7198464f, 0.3420201f, 0.6040227f))), }; scene.Children.Add(fillLightNode); // ----- Back light var backLight = new DirectionalLight { Color = new Vector3F(0.3231373f, 0.3607844f, 0.3937255f), DiffuseIntensity = 1, SpecularIntensity = 1, HdrScale = hdrScale, }; var backLightNode = new LightNode(backLight) { Name = "BackLight", PoseWorld = new Pose(QuaternionF.CreateRotation(Vector3F.Forward, new Vector3F(0.4545195f, -0.7660444f, 0.4545195f))), }; scene.Children.Add(backLightNode); }
public EnvironmentLightSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics Simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new GroundObject(Services)); GameObjectService.Objects.Add(new DudeObject(Services)); var lavaBallsObject = new LavaBallsObject(Services); GameObjectService.Objects.Add(lavaBallsObject); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new FogObject(Services)); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Barrier", 0.9f, new Pose(new Vector3F(0, 0, -2)))); GameObjectService.Objects.Add(new StaticObject(Services, "Barrier/Cylinder", 0.9f, new Pose(new Vector3F(3, 0, 0), QuaternionF.CreateRotationY(MathHelper.ToRadians(-20))))); GameObjectService.Objects.Add(new StaticSkyObject(Services)); // Add a few palm trees. Random random = new Random(12345); for (int i = 0; i < 10; i++) { Vector3F position = new Vector3F(random.NextFloat(-3, -8), 0, random.NextFloat(0, -5)); Matrix33F orientation = Matrix33F.CreateRotationY(random.NextFloat(0, ConstantsF.TwoPi)); float scale = random.NextFloat(0.5f, 1.2f); GameObjectService.Objects.Add(new StaticObject(Services, "PalmTree/palm_tree", scale, new Pose(position, orientation))); } // Add some more dynamic objects. for (int i = 0; i < 5; i++) { lavaBallsObject.Spawn(); GameObjectService.Objects.Add(new ProceduralObject(Services)); GameObjectService.Objects.Add(new DynamicObject(Services, 7)); } // To show the effect of the EnvironmentLight in isolation, disable all other light sources. //foreach (var light in _graphicsScreen.Scene.GetDescendants().OfType<LightNode>()) // light.IsEnabled = false; // Add the environment light. var environmentLight = new EnvironmentLight { Color = new Vector3F(0.1f), DiffuseIntensity = 0, SpecularIntensity = 1, EnvironmentMap = ContentManager.Load<TextureCube>("Sky2"), }; var environmentLightNode = new LightNode(environmentLight) { Name = "Environment", }; _graphicsScreen.Scene.Children.Add(environmentLightNode); // The EnvironmentLight is a new light type. We have to register a light renderer // for this light in the LightRenderer of the DeferredGraphicsScreen. _graphicsScreen.LightBufferRenderer.LightRenderer.Renderers.Add(new EnvironmentLightRenderer(GraphicsService)); // EnvironmentLight.fx uses the specular power of the materials to determine // which mip map level of the cube is reflected. // In reality, a high specular power is necessary to reflect the cube map // with all its detail. To reflect a cube map level with 512 texels size, we // need a specular power of ~200000. // To make the reflection effects more obvious, let's change some material properties // and make the more reflective. // ProceduralObject: var proceduralObjects = _graphicsScreen.Scene .GetDescendants() .OfType<MeshNode>() .Where(mn => mn.Mesh.Name == "ProceduralObject") .Select(mn => mn.Mesh); foreach (var mesh in proceduralObjects) { foreach (var material in mesh.Materials) { material["GBuffer"].Set("SpecularPower", 10000f); material["Material"].Set("DiffuseColor", new Vector3(0.01f)); material["Material"].Set("SpecularColor", new Vector3(1)); } } // Frame of GlassBox: var glassBoxes = _graphicsScreen.Scene .GetDescendants() .OfType<ModelNode>() .Where(mn => mn.Name == "GlassBox") .Select(mn => ((MeshNode)mn.Children[0]).Mesh); foreach (var mesh in glassBoxes) { foreach (var material in mesh.Materials.Where(m => m.Contains("GBuffer"))) { material["GBuffer"].Set("SpecularPower", 100000f); material["Material"].Set("DiffuseColor", new Vector3(0.0f)); material["Material"].Set("SpecularColor", new Vector3(1)); } } // LavaBall: var lavaBalls = _graphicsScreen.Scene .GetDescendants() .OfType<ModelNode>() .Where(mn => mn.Name == "LavaBall") .Select(mn => ((MeshNode)mn.Children[0]).Mesh); foreach (var mesh in lavaBalls) { foreach (var material in mesh.Materials.Where(m => m.Contains("GBuffer"))) { material["GBuffer"].Set("SpecularPower", 10000f); material["Material"].Set("DiffuseColor", new Vector3(0.0f)); material["Material"].Set("SpecularColor", new Vector3(10)); material["Material"].Set("EmissiveColor", new Vector3(0.0f)); } } // Ground plane: var groundPlanes = _graphicsScreen.Scene .GetDescendants() .OfType<ModelNode>() .Where(mn => mn.Name == "Ground") .Select(mn => ((MeshNode)mn.Children[0]).Mesh); foreach (var mesh in groundPlanes) { foreach (var material in mesh.Materials.Where(m => m.Contains("GBuffer"))) { material["GBuffer"].Set("SpecularPower", 200000.0f); material["Material"].Set("DiffuseColor", new Vector3(0.5f)); material["Material"].Set("SpecularColor", new Vector3(0.4f)); } } // Please note, XNA does not filter cube maps over cube map borders. Therefore, reflections // of low resolution mip map levels might show obvious borders between the cube map // sides. In this case you can change the EnvironmentLight.fx effect to always reflect // the mip map level 0. // This is not a problem with MonoGame because DirectX automatically filters cube map borders. }
// OnUnload() is called when the GameObject is removed from the IGameObjectService. protected override void OnUnload() { var scene = _ambientLightNode.Parent; scene.Children.Remove(_ambientLightNode); _ambientLightNode.Dispose(false); _ambientLightNode = null; scene.Children.Remove(_keyLightNode); _keyLightNode.Dispose(false); _keyLightNode = null; scene.Children.Remove(_fillLightNode); _fillLightNode.Dispose(false); _fillLightNode = null; scene.Children.Remove(_backLightNode); _backLightNode.Dispose(false); _backLightNode = null; }
private int AssignShadowMask(LightNode lightNode, RenderContext context) { // Each shadow mask has 4 8-bit channels. We must assign a shadow mask channel to // each shadow-casting light. Non-overlapping lights can use the same channel. // Overlapping lights must use different channels. If we run out of channels, // we remove some lights from the list. var scene = context.Scene; var viewport = context.Viewport; int maskWidth = viewport.Width; int maskHeight = viewport.Height; if (UseHalfResolution && Numeric.IsLessOrEqual(UpsampleDepthSensitivity, 0)) { // Half-res rendering with no upsampling. maskWidth /= 2; maskHeight /= 2; } // Loop over all bins until we find one which can be used for this light node. int binIndex; for (binIndex = 0; binIndex < _shadowMaskBins.Length; binIndex++) { var bin = _shadowMaskBins[binIndex]; // Check if the light node touches any other light nodes in this bin. bool hasContact = false; foreach (var otherLightNode in bin) { if (scene.HaveContact(lightNode, otherLightNode)) { hasContact = true; break; } } // No overlap. Use this bin. if (!hasContact) { bin.Add(lightNode); break; } } if (binIndex >= _shadowMaskBins.Length) return -1; // Light node does not fit into any bin. int shadowMaskIndex = binIndex / 4; if (_shadowMasks[shadowMaskIndex] == null) { // Create shadow mask. var shadowMaskFormat = new RenderTargetFormat(maskWidth, maskHeight, false, SurfaceFormat.Color, DepthFormat.None); _shadowMasks[shadowMaskIndex] = context.GraphicsService.RenderTargetPool.Obtain2D(shadowMaskFormat); } // Assign shadow mask to light node. lightNode.Shadow.ShadowMask = _shadowMasks[shadowMaskIndex]; lightNode.Shadow.ShadowMaskChannel = binIndex % 4; return shadowMaskIndex; }
public ShadowSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services) { // For debugging: Disable materials and only show light buffer. DebugMode = DeferredGraphicsDebugMode.VisualizeDiffuseLightBuffer }; _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; GameObjectService.Objects.Add(new GrabObject(Services)); CreateScene(Services, ContentManager, _graphicsScreen); // Disable existing lights. foreach (var lightNode in _graphicsScreen.Scene.GetDescendants().OfType<LightNode>()) lightNode.IsEnabled = false; // Add a dim ambient light. _graphicsScreen.Scene.Children.Add( new LightNode( new AmbientLight { HemisphericAttenuation = 1, Intensity = 0.001f, })); // Add some test lights with shadows. _spotlight = new Spotlight { Range = 10, FalloffAngle = 0.8f, CutoffAngle = 1f }; _standardShadow = new StandardShadow(); _spotlightNode = new LightNode(_spotlight) { PoseWorld = new Pose(new Vector3F(0, 1f, -2)), Shadow = _standardShadow, IsEnabled = true, }; _graphicsScreen.Scene.Children.Add(_spotlightNode); _cubeMapShadow = new CubeMapShadow(); _pointLight = new PointLight { Range = 10, }; _pointLightNode = new LightNode(_pointLight) { PoseWorld = new Pose(new Vector3F(0, 1f, -2)), Shadow = _cubeMapShadow, IsEnabled = false, }; _graphicsScreen.Scene.Children.Add(_pointLightNode); CreateGuiControls(); }
private void AddNode(LightNode lightNode) { Debug.Assert(lightNode.ActualIsEnabled, "Scene query contains disabled nodes."); // Ignore light if the reference position is not in the clip geometry. if (lightNode.Clip != null && _referencePosition.HasValue) { bool haveContact = HaveContact(lightNode.Clip, _referencePosition.Value); if (lightNode.InvertClip == haveContact) { return; } } // ----- Sort by estimated light contribution. // All lights except IBL will be sorted by contribution. // Note: If we have no reference node, it still makes sense to sort the objects // by their contribution. We choose to get the light contribution at the position // of each light. Vector3F position = _referencePosition ?? lightNode.PoseWorld.Position; //lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); // Or simpler: Sort light nodes by distance. --> Use for image-based lights. // (We use distance², because it is faster.) //float distance = (position - lightNode.PoseWorld.Position).LengthSquared; //lightNode.SortTag = -distance; // minus because we use descending sort. if (lightNode.Light is AmbientLight) { AmbientLights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } else if (lightNode.Light is DirectionalLight) { DirectionalLights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } else if (lightNode.Light is PointLight) { PointLights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } else if (lightNode.Light is Spotlight) { Spotlights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } else if (lightNode.Light is ProjectorLight) { ProjectorLights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } else if (lightNode.Light is ImageBasedLight) { ImageBasedLights.Add(lightNode); float distance = (position - lightNode.PoseWorld.Position).LengthSquared; lightNode.SortTag = -distance; // minus because we use descending sort. } else { OtherLights.Add(lightNode); lightNode.SortTag = lightNode.GetLightContribution(position, 0.7f); } }
// OnLoad() is called when the GameObject is added to the IGameObjectService. protected override void OnLoad() { var particleSystemService = _services.GetInstance<IParticleSystemService>(); // The campfire consists of two particle systems (fire + smoke) and a light source. // // _campfire (SceneNode) // | // +-- _fireParticles (ParticleSystemNode) // | // +-- _smokeParticles (ParticleSystemNode) // | // +-- _light (LightNode) // Use a basic scene node as the root node for the campfire. _campfire = new SceneNode { Name = "Campfire", PoseLocal = new Pose(new Vector3F(0, 0, -1)), Children = new SceneNodeCollection() }; // Add fire particles. var contentManager = _services.GetInstance<ContentManager>(); var particleSystem = CreateFire(contentManager); particleSystemService.ParticleSystems.Add(particleSystem); _fireParticles = new ParticleSystemNode(particleSystem) { // The fire effect lies in the xy plane and shoots into the forward direction (= -z axis). // Therefore we rotate the particle system to shoot upwards. PoseLocal = new Pose(new Vector3F(0, 0.2f, 0), Matrix33F.CreateRotationX(ConstantsF.PiOver2)) }; _campfire.Children.Add(_fireParticles); // Add smoke particles. particleSystem = CreateSmoke(contentManager); particleSystemService.ParticleSystems.Add(particleSystem); _smokeParticles = new ParticleSystemNode(particleSystem) { PoseLocal = new Pose(new Vector3F(0, 0.2f, 0), Matrix33F.CreateRotationX(ConstantsF.PiOver2)) }; _campfire.Children.Add(_smokeParticles); // Add a point light that illuminates the environment. var light = new PointLight { Attenuation = 0.1f, Color = new Vector3F(1, 0.2f, 0), HdrScale = 20, Range = 4 }; _light = new LightNode(light) { // Optional: We can make this light cast shadows - but this will cost performance! //Shadow = new CubeMapShadow { PreferredSize = 64, FilterRadius = 2, JitterResolution = 2048 }, PoseLocal = new Pose(new Vector3F(0, 1f, 0)) }; _campfire.Children.Add(_light); // Add campfire to scene. var scene = _services.GetInstance<IScene>(); scene.Children.Add(_campfire); // Particle effects can be added multiple times to the scene (= "instancing"). // Uncomment the following lines to add a few more instance to the scene. //for (int i = 0; i < 10; i++) //{ // var clone = _campfire.Clone(); // // Set random scale, position, orientation. // clone.ScaleLocal = _random.NextVector3F(0.5f, 1.5f); // var pose = _campfire.PoseWorld; // pose.Position.X += _random.NextFloat(-10, 10); // pose.Position.Z += _random.NextFloat(-10, 10); // pose.Orientation = Matrix33F.CreateRotationY(_random.NextFloat(-ConstantsF.PiOver2, ConstantsF.PiOver2)); // clone.PoseLocal = pose; // scene.Children.Add(clone); //} // Add GUI controls to the Options window. var sampleFramework = _services.GetInstance<SampleFramework>(); var optionsPanel = sampleFramework.AddOptions("Game Objects"); var panel = SampleHelper.AddGroupBox(optionsPanel, "CampfireObject"); SampleHelper.AddCheckBox( panel, "Enable campfire", IsEnabled, isChecked => IsEnabled = isChecked); }
public ImageBasedLightingSample(Microsoft.Xna.Framework.Game game) : base(game) { SampleFramework.IsMouseVisible = false; _graphicsScreen = new DeferredGraphicsScreen(Services); _graphicsScreen.DrawReticle = true; GraphicsService.Screens.Insert(0, _graphicsScreen); GameObjectService.Objects.Add(new DeferredGraphicsOptionsObject(Services)); Services.Register(typeof(DebugRenderer), null, _graphicsScreen.DebugRenderer); Services.Register(typeof(IScene), null, _graphicsScreen.Scene); // Add gravity and damping to the physics simulation. Simulation.ForceEffects.Add(new Gravity()); Simulation.ForceEffects.Add(new Damping()); // Add a custom game object which controls the camera. var cameraGameObject = new CameraObject(Services); GameObjectService.Objects.Add(cameraGameObject); _graphicsScreen.ActiveCameraNode = cameraGameObject.CameraNode; // Add standard game objects. GameObjectService.Objects.Add(new GrabObject(Services)); GameObjectService.Objects.Add(new DynamicSkyObject(Services, true, false, true)); GameObjectService.Objects.Add(new GroundObject(Services)); GameObjectService.Objects.Add(new ObjectCreatorObject(Services)); GameObjectService.Objects.Add(new DudeObject(Services) { Pose = new Pose(new Vector3F(-4, 0, 4)) }); GameObjectService.Objects.Add(new LavaBallsObject(Services)); // Create 3 image-based lights. for (int i = 0; i < 3; i++) { _imageBasedLights[i] = new ImageBasedLight { DiffuseIntensity = 1f, SpecularIntensity = 1f, FalloffRange = 0.2f, BlendMode = 1, // 0 = add to ambient light, 1 = replace ambient light }; } // The first IBL is infinite. _imageBasedLights[0].Shape = Shape.Infinite; // The other 2 IBLs have a box shape and use specify an AABB which is // aligned to the with scene objects (walls, barrels, palm tree line). _imageBasedLights[1].Shape = new BoxShape(7.5f, 10, 7); _imageBasedLights[1].EnableLocalizedReflection = true; _imageBasedLights[1].LocalizedReflectionBox = new Aabb(new Vector3F(-100, -2, -100), new Vector3F(3.5f, 2, 100)); _imageBasedLights[2].Shape = new BoxShape(7.5f, 10, 7); _imageBasedLights[2].EnableLocalizedReflection = true; _imageBasedLights[2].LocalizedReflectionBox = new Aabb(new Vector3F(-3, -2, -100), new Vector3F(3.5f, 2, 100)); // Add 3 light nodes to add the IBL to the scene. for (int i = 0; i < 3; i++) { _lightNodes[i] = new LightNode(_imageBasedLights[i]); _graphicsScreen.Scene.Children.Add(_lightNodes[i]); } _lightNodes[0].PoseLocal = _globalRotation * new Pose(new Vector3F(-5, 5, 5)); _lightNodes[1].PoseLocal = _globalRotation * new Pose(new Vector3F(0, 2, 0)); _lightNodes[2].PoseLocal = _globalRotation * new Pose(new Vector3F(0, 2, -4)); // Increase specular power of ground to create sharper reflections. var groundModelNode = (ModelNode)_graphicsScreen.Scene.GetSceneNode("Ground"); var groundMaterial = ((MeshNode)groundModelNode.Children[0]).Mesh.Materials[0]; groundMaterial["GBuffer"].Set("SpecularPower", 1000000.0f); // Add more test objects to the scenes. AddLightProbes(); AddTestSpheres(); AddTestObjects(); CreateGuiControls(); }