public PlanarShadows() { InitializeComponent(); _disposables = new DisposeList(); MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args) { if (MainDXViewportView.DXScene != null) { string textureFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/10x10-texture.png"); // To load a texture from file, you can use the TextureLoader.LoadShaderResourceView (this supports loading standard image files and also loading dds files). // This method returns a ShaderResourceView and it can also set a textureInfo parameter that defines some of the properties of the loaded texture (bitmap size, dpi, format, hasTransparency). TextureInfo textureInfo; var loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.Device, textureFileName, out textureInfo); _disposables.Add(loadedShaderResourceView); // Get recommended BlendState based on HasTransparency and HasPreMultipliedAlpha values. // Possible values are: CommonStates.Opaque, CommonStates.PremultipliedAlphaBlend or CommonStates.NonPremultipliedAlphaBlend. var recommendedBlendState = MainDXViewportView.DXScene.DXDevice.CommonStates.GetRecommendedBlendState(textureInfo.HasTransparency, textureInfo.HasPremultipliedAlpha); _planarShadowRenderingProvider = new PlanarShadowRenderingProvider() { ShadowPlaneCenterPosition = new Vector3(0, 0, 0), ShadowPlaneSize = new Vector2(400, 400), ShadowPlaneNormalVector = new Vector3(0, 1, 0), ShadowPlaneHeightDirection = new Vector3(0, 0, -1), ShadowPlaneMaterial = new StandardMaterial() { DiffuseColor = Color3.White, // When DiffuseTextures are set, then DiffuseColor is used as a color filter (White means no filter) DiffuseTextures = new ShaderResourceView[] { loadedShaderResourceView }, TextureBlendState = recommendedBlendState, HasTransparency = textureInfo.HasTransparency }, ShadowPlaneBackMaterial = new StandardMaterial() { DiffuseColor = Colors.DimGray.ToColor3() }, ShadowColor = Color3.Black, ShadowTransparency = 0.65f, // Because shadow is rendered as standard 3D object, we need to offset it from the shadow plane // to prevent z-fighting problems that occur when two 3D objects are rendered to the same 3D position. // This value need to be very small so that it is not seen that the shadow is above the plane. // Default value is 0.01f. ShadowOffsetFromPlane = 0.01f, // When using PlanarShadowRenderingProvider we do not need PlanarShadowMeshCreator from Ab3d.PowerToys // to prepare a special MeshGeometry3D for us. Also PlanarShadowMeshCreator does not need to manually (on the CPU) // cut the shadow to the plane bounds but this can be done with using hardware accelerated algorithm (using stencil buffer). // But if we still want to use PlanarShadowMeshCreator we can set the following two properties to false // (for example if we wanted to use PlanarShadowRenderingProvider just to provide proper transparent shadows). ApplyShadowMatrix = true, CutShadowToPlaneBounds = true, // To use a custom light that does not illuminate the 3D scene set the CustomShadowLight. // Otherwise the first light that has DXAttributeType.IsCastingShadow attribute set to true is used. // If no light has IsCastingShadow attribute set, then the first directional or point light is used. //CustomShadowLight = new Ab3d.DirectX.Lights.DirectionalLight(new Vector3(0, -1, 1)) //CustomShadowLight = new Ab3d.DirectX.Lights.PointLight(new Vector3(0, 500, 0), 300) }; _disposables.Add(_planarShadowRenderingProvider); MainDXViewportView.DXScene.InitializeShadowRendering(_planarShadowRenderingProvider); } _lightHorizontalAngle = -60; _lightVerticalAngle = 60; _lightDistance = 500; _ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(40, 40, 40)); _shadowPointLight = new PointLight(); _shadowDirectionalLight = new DirectionalLight(); Camera1.ShowCameraLight = ShowCameraLightType.Never; // prevent adding camera's light SetShadowLight(isDirectionalLight: true); UpdateLights(); CreateSampleObjects(); }; this.PreviewKeyDown += OnPreviewKeyDown; // This will allow receiving keyboard events this.Focusable = true; this.Focus(); this.Unloaded += delegate(object sender, RoutedEventArgs args) { StopAnimation(); _disposables.Dispose(); MainDXViewportView.Dispose(); }; }
public PlanarShadowsCustomization() { InitializeComponent(); _disposables = new DisposeList(); MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args) { if (MainDXViewportView.DXScene != null) { // Load texture file into ShaderResourceView (in our case we load dds file; but we could also load png file) string textureFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Resources/GrassTexture.jpg"); var loadedShaderResourceView = Ab3d.DirectX.TextureLoader.LoadShaderResourceView(MainDXViewportView.DXScene.DXDevice.Device, textureFileName); _disposables.Add(loadedShaderResourceView); // Define DXEngine's materials for shadow plane _shadowPlaneMaterial = new StandardMaterial() { DiffuseColor = Color3.White, // When DiffuseTextures are set, then DiffuseColor is used as a color filter (White means no filter) DiffuseTextures = new ShaderResourceView[] { loadedShaderResourceView } }; _shadowPlaneBackMaterial = new StandardMaterial() { DiffuseColor = Colors.DimGray.ToColor3() }; _disposables.Add(_shadowPlaneMaterial); _disposables.Add(_shadowPlaneBackMaterial); // Define the PlanarShadowRenderingProvider _planarShadowRenderingProvider = new PlanarShadowRenderingProvider() { // We need to provide information about the position of the plane in 3D space ShadowPlaneCenterPosition = new Vector3(0, 0, 0), ShadowPlaneSize = new Vector2(400, 400), ShadowPlaneNormalVector = new Vector3(0, 1, 0), ShadowPlaneHeightDirection = new Vector3(0, 0, -1), // In case ShadowPlaneMaterial and/or ShadowPlaneBackMaterial are defined // the PlanarShadowRenderingProvider will also render the 3D plane. ShadowPlaneMaterial = _shadowPlaneMaterial, ShadowPlaneBackMaterial = _shadowPlaneBackMaterial, // Set shadow properties ShadowColor = Color3.Black, ShadowTransparency = (float)ShadowTransparencySlider.Value / 100.0f, // default value is 0.65f // Because shadow is rendered as standard 3D object, we need to offset it from the shadow plane // to prevent z-fighting problems that occur when two 3D objects are rendered to the same 3D position. // This value need to be very small so that it is not seen that the shadow is above the plane. // Default value is 0.01f. ShadowOffsetFromPlane = 0.01f, // When using PlanarShadowRenderingProvider we do not need PlanarShadowMeshCreator from Ab3d.PowerToys // to prepare a special MeshGeometry3D for us. Also PlanarShadowMeshCreator does not need to manually (on the CPU) // cut the shadow to the plane bounds but this can be done with using hardware accelerated algorithm (using stencil buffer). // But if we still want to use PlanarShadowMeshCreator we can set the following two properties to false // (for example if we wanted to use PlanarShadowRenderingProvider just to provide proper transparent shadows). ApplyShadowMatrix = true, CutShadowToPlaneBounds = true, IsCheckingIsCastingShadow = false, // Initially do not check for IsCastingShadow values (this is also a default value). See comments in LoadModel for more info. //CustomShadowLight = new Ab3d.DirectX.Lights.DirectionalLight(new Vector3(0, -1, 1)) //CustomShadowLight = new Ab3d.DirectX.Lights.PointLight(new Vector3(0, 500, 0), 300) }; _disposables.Add(_planarShadowRenderingProvider); MainDXViewportView.DXScene.InitializeShadowRendering(_planarShadowRenderingProvider); } _lightHorizontalAngle = 30; _lightVerticalAngle = 27; _lightDistance = 500; _ambientLight = new AmbientLight(System.Windows.Media.Color.FromRgb(40, 40, 40)); _shadowPointLight = new PointLight(); _shadowDirectionalLight = new DirectionalLight(); Camera1.ShowCameraLight = ShowCameraLightType.Never; // prevent adding camera's light SetShadowLight(isDirectionalLight: true); UpdateLights(); _loadedModel3D = LoadModel3D(); MainViewport.Children.Add(_loadedModel3D.CreateModelVisual3D()); }; this.PreviewKeyDown += OnPreviewKeyDown; // This will allow receiving keyboard events this.Focusable = true; this.Focus(); this.Unloaded += delegate(object sender, RoutedEventArgs args) { _disposables.Dispose(); MainDXViewportView.Dispose(); }; }