コード例 #1
0
        private void OnDXSceneViewInitialized()
        {
            if (MainDXViewportView.UsedGraphicsProfile.DriverType == GraphicsProfile.DriverTypes.Wpf3D)
            {
                HouseWithThreesWireframeVisual.RemoveDuplicateLines = true; // This is recommended setting for WPF because it reduces the number of lines
                PersonWireframeVisual.RemoveDuplicateLines          = true;
                return;
            }

            HouseWithThreesWireframeVisual.RemoveDuplicateLines = false; // Rendering lines in DXEngine is very cheap so we can skip the process of finding and removing duplicates
            PersonWireframeVisual.RemoveDuplicateLines          = false;

            // Get the SceneNodes (WpfWireframeVisual3DNode) used by DXScene
            // This way we can access some properties that are specific to DirectX and are not used in WPF WireframeVisual3D (like depth bias properties)
            _wpfHouseWithThreesWireframeVisualNode = MainDXViewportView.GetSceneNodeForWpfObject(HouseWithThreesWireframeVisual) as WpfWireframeVisual3DNode;

            if (_wpfHouseWithThreesWireframeVisualNode != null)
            {
                _wpfHouseWithThreesWireframeVisualNode.Name = "HouseWithThreesWireframeVisualNode";
            }


            _wpfPersonWireframeVisualNode = MainDXViewportView.GetSceneNodeForWpfObject(PersonWireframeVisual) as WpfWireframeVisual3DNode;

            if (_wpfPersonWireframeVisualNode != null)
            {
                _wpfPersonWireframeVisualNode.Name = "PersonWireframeVisualNode";
            }

            UpdateDepthBias();
        }
コード例 #2
0
        private SceneNode GetSceneNodeForWpfObject(object wpfObject)
        {
            if (wpfObject == null)
            {
                return(null);
            }

            SceneNode sceneNode = null;

            // Use _sceneNodesDictionary if possible
            if (_sceneNodesDictionary != null)
            {
                _sceneNodesDictionary.TryGetValue(wpfObject, out sceneNode);
            }


            // If SceneNode is not found, we an use the GetSceneNodeForWpfObject method.
            // Note that this method is very slow because it goes through each SceneNode in the scene
            // and for each SceneNode calls IsMyWpfObject method.
            if (sceneNode == null)
            {
                sceneNode = MainDXViewportView.GetSceneNodeForWpfObject(wpfObject);
            }

            return(sceneNode);
        }
コード例 #3
0
        private void SetIsHitTestVisible(ModelVisual3D modelVisual3D, bool isHitTestVisible)
        {
            var sceneNode = MainDXViewportView.GetSceneNodeForWpfObject(modelVisual3D);

            if (sceneNode == null)
            {
                return;
            }

            sceneNode.IsHitTestVisible = isHitTestVisible;
        }
コード例 #4
0
        private void UpdateSelectedMaps()
        {
            if (!this.IsLoaded)
            {
                return;
            }

            bool isChanged = UpdateMap(_multiMapMaterial, (DiffuseMapCheckBox.IsChecked ?? false), TextureMapTypes.DiffuseColor, _diffuseShaderResourceView);

            isChanged |= UpdateMap(_multiMapMaterial, (NormalMapCheckBox.IsChecked ?? false), TextureMapTypes.NormalMap, _normalShaderResourceView);
            isChanged |= UpdateMap(_multiMapMaterial, (SpecularMapCheckBox.IsChecked ?? false), TextureMapTypes.SpecularColor, _specularShaderResourceView);

            if (isChanged)
            {
                // When we change DXEngine's material, we need to notify the SceneNode that is using the material about the change.
                var plane1SceneNode = MainDXViewportView.GetSceneNodeForWpfObject(Plane1);
                if (plane1SceneNode != null)
                {
                    plane1SceneNode.NotifySceneNodeChange(SceneNode.SceneNodeDirtyFlags.MaterialChanged);
                }
            }
        }
コード例 #5
0
        public ShadowRenderingSample()
        {
            InitializeComponent();

            // Default values can be get before Loaded event
            _shadowMapSize          = 512;
            _shadowDepthBluringSize = 4;
            _shadowTreshold         = 0.2f;


            CreateCustomScene();
            CreateLights();
            CreateLightSphere();


            _isShadowEnabled = true;

            UpdateCastingShadowLight();


            MainDXViewportView.DXSceneInitialized += delegate(object sender, EventArgs args)
            {
                if (MainDXViewportView.DXScene == null)
                {
                    return; // Probably WPF 3D rendering
                }
                // The DXScene.InitializeShadowRendering method must be called with the VarianceShadowRenderingProvider.
                // The VarianceShadowRenderingProvider controls the rendering of shadows.
                //
                // Variance shadow rendering technique can produce nice shadows with soft edges and without the artifacts that are common for some other shadow rendering (Peter panning or Self shadowing).
                // More info can be read in the GPU Gems3 "Chapter 8. Summed-Area Variance Shadow Maps" (https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch08.html)
                _varianceShadowRenderingProvider = new VarianceShadowRenderingProvider();


                // ShadowMapSize represents the size of a shadow depth map texture. For example value 512 means that a 512 x 512 texture will be used.
                // The shadow depth map texture is used to store depth information - distance of a pixel from the light.
                // Bigger texture will produce more detailed shadows but will be slower to render.
                // Also, to bigger texture will require bigger blur amount to achieve nice soft edges.
                // NOTE: Changing the ShadowMapSize after the VarianceShadowRenderingProvider has been initialized has no effect - see UpdateShadowSettings method in this file to see how to change the value
                _varianceShadowRenderingProvider.ShadowMapSize = _shadowMapSize;

                // ShadowDepthBluringSize specifies the blur amount that is applied on the shadow depth map and can produce shadows with nice soft edges.
                // Default value is 4.
                _varianceShadowRenderingProvider.ShadowDepthBluringSize = _shadowDepthBluringSize;

                // ShadowTreshold is a float value that helps prevent light bleeding (having areas that should be in shadow fully illuminated) for variance shadow mapping.
                // The value is used to map all shadow values from 0 ... ShadowTreshold to 0 and then linearly rescale the values from ShadowTreshold to 1 into 0 to 1.
                // For more info see "Shadow bleeding" in "Chapter 8. Summed-Area Variance Shadow Maps" (https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch08.html)
                _varianceShadowRenderingProvider.ShadowTreshold = _shadowTreshold;


                // Initialize shadow rendering
                MainDXViewportView.DXScene.InitializeShadowRendering(_varianceShadowRenderingProvider);



                // When the scene is initialized, we can get the SceneNode that is created from WPF teapot model.
                // This will be used later (in OnObjectsFilterValueChanged) to enable or disable casting and receiving shadow.
                _teapotSceneNode = MainDXViewportView.GetSceneNodeForWpfObject(_teapotModel) as WpfGeometryModel3DNode;


                // To use FilterObjectsFunction to filter which objects are casting and receiving shadow, uncomment the lines below (see comment in OnObjectsFilterValueChanged method for more info):
                //_varianceShadowRenderingProvider.RenderShadowDepthRenderingStep.FilterObjectsFunction = FilterNonTeapotObjectsFunction;
                //_varianceShadowRenderingProvider.RenderNonShadowObjectsRenderingStep.FilterObjectsFunction = FilterTeapotObjectsFunction;
                //MainDXViewportView.DXScene.DefaultRenderObjectsRenderingStep.FilterObjectsFunction = FilterNonTeapotObjectsFunction;

                // IMPORTANT:
                // Af least one light need to set to cast shadow. This can be done with the following code:
                //_directionalLight.SetDXAttribute(DXAttributeType.IsCastingShadow, true);
            };


            StartLightAnimation();

            this.Unloaded += delegate(object sender, RoutedEventArgs args)
            {
                StopLightAnimation();

                if (_varianceShadowRenderingProvider != null)
                {
                    _varianceShadowRenderingProvider.Dispose();
                }

                MainDXViewportView.Dispose();
            };



            this.PreviewKeyDown += OnPreviewKeyDown;

            // This will allow receiving keyboard events
            this.Focusable = true;
            this.Focus();
        }
コード例 #6
0
        private void ProcessMouseHit(System.Windows.Point mousePosition)
        {
            bool isVertexColorDataChanged;

            RayMeshGeometry3DHitTestResult hitTestResult;

            if (double.IsNaN(mousePosition.X)) // if mousePosition.X is NaN, then we consider this as mouse did not hit the model
            {
                hitTestResult = null;
            }
            else
            {
                hitTestResult = VisualTreeHelper.HitTest(MainViewport, mousePosition) as RayMeshGeometry3DHitTestResult;

                BeamLine1.X2         = mousePosition.X;
                BeamLine1.Y2         = mousePosition.Y;
                BeamLine1.Visibility = Visibility.Visible;

                BeamLine2.X2         = mousePosition.X;
                BeamLine2.Y2         = mousePosition.Y;
                BeamLine2.Visibility = Visibility.Visible;
            }

            if (hitTestResult != null)
            {
                var hitPoint3D = hitTestResult.PointHit;

                // Update the _positionColorsArray (array of colors for each vertex) so that each color is calculated as distance from the hitPoint3D.
                // Colors are set to the distances between 0 and 50; after 50 the lase color (light blue) is assigned.
                CalculatePositionColorsFromDistance(_objectGeometry3D.Positions, hitPoint3D, 50, _positionColorsArray);

                isVertexColorDataChanged = true;
                _isLastMousePositionHit  = true;

                BeamLine1.Stroke = Brushes.Red;
                BeamLine2.Stroke = Brushes.Red;
            }
            else
            {
                // Show Gray line for missed position

                BeamLine1.Stroke = Brushes.Gray;
                BeamLine2.Stroke = Brushes.Gray;

                if (_isLastMousePositionHit)
                {
                    // If before the mouse position hit the 3D mode, then the 3D model was colored
                    // But now the position do not hit the 3D mode any more - so we need to color the 3D mode with the last color - the one that is used for the biggest beam distance (light blue)
                    var lastColor = _gradientColor4Array[_gradientColor4Array.Length - 1];
                    FillPositionColorsArray(lastColor);

                    isVertexColorDataChanged = true;
                }
                else
                {
                    isVertexColorDataChanged = false;
                }

                _isLastMousePositionHit = false;
            }

            if (isVertexColorDataChanged)
            {
                //_vertexColorMaterial.PositionColors = _positionColorsArray; // PositionColors property was already set before

                // Update method on the VertexColorMaterial will update the underlying DirectX vertex buffer that
                // is created from PositionColors array and is sent to graphics card to render the 3D model.
                _vertexColorMaterial.Update();

                // Because we have manually updated the DXEngine material we need to notify the DXEngine's SceneNode that is using this material about the change.
                var sceneNode = MainDXViewportView.GetSceneNodeForWpfObject(_vertexColorGeometryModel3D);
                if (sceneNode != null)
                {
                    sceneNode.NotifySceneNodeChange(SceneNode.SceneNodeDirtyFlags.MaterialChanged);
                }
            }
        }