Example #1
0
        private void RenderCapsule(IGraphicsService graphicsService, PrimitiveJob job)
        {
            float radius = job.Size.Radius;
            float height = job.Size.Height;

            if (DrawWireFrame)
            {
                if (_hemisphereLinePrimitive == null)
                {
                    _hemisphereLinePrimitive = MeshHelper.GetHemisphereLines(graphicsService);
                }

                Effect.World = Matrix.CreateScale(radius) * Matrix.CreateTranslation(0, height / 2 - radius, 0) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();
                _hemisphereLinePrimitive.Draw();

                Effect.World = Matrix.CreateScale(-radius, -radius, radius) * Matrix.CreateTranslation(0, -height / 2 + radius, 0) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();
                _hemisphereLinePrimitive.Draw();

                // 4 lines
                Vector3F dx     = radius * job.Pose.ToWorldDirection(new Vector3F(1, 0, 0));
                Vector3F dy     = (height / 2 - radius) * job.Pose.ToWorldDirection(new Vector3F(0, 1, 0));
                Vector3F dz     = radius * job.Pose.ToWorldDirection(new Vector3F(0, 0, 1));
                Vector3F center = job.Pose.Position;
                _lineBatch.Add(center + dy + dx, center - dy + dx, job.Color);
                _lineBatch.Add(center + dy - dx, center - dy - dx, job.Color);
                _lineBatch.Add(center + dy + dz, center - dy + dz, job.Color);
                _lineBatch.Add(center + dy - dz, center - dy - dz, job.Color);
            }
            else
            {
                if (_hemispherePrimitive == null)
                {
                    _hemispherePrimitive = MeshHelper.GetHemisphere(graphicsService);
                }

                Effect.World = Matrix.CreateScale(radius) * Matrix.CreateTranslation(0, height / 2 - radius, 0) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();
                _hemispherePrimitive.Draw();

                Effect.World = Matrix.CreateScale(-radius, -radius, radius) * Matrix.CreateTranslation(0, -height / 2 + radius, 0) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();
                _hemispherePrimitive.Draw();

                if (_uncappedCylinderPrimitive == null)
                {
                    _uncappedCylinderPrimitive = MeshHelper.GetUncappedCylinder(graphicsService);
                }

                Effect.World = Matrix.CreateScale(radius, height / 2 - radius, radius) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();

                _uncappedCylinderPrimitive.Draw();
            }
        }
Example #2
0
        private void RenderHiDef(TextureCube texture, Matrix orientation, float exposure, RenderContext context)
        {
            var graphicsDevice = context.GraphicsService.GraphicsDevice;

            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.RasterizerState   = RasterizerState.CullNone;
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
            graphicsDevice.BlendState        = BlendState.Opaque;

            var    cameraNode = context.CameraNode;
            Matrix view       = cameraNode.View;
            Matrix projection = cameraNode.Camera.Projection;

            // Cube maps are left handed --> Sample with inverted z. (Otherwise, the
            // cube map and objects or texts in it are mirrored.)
            var mirrorZ = Matrix.CreateScale(1, 1, -1);

            _parameterWorldViewProjection.SetValue(
                (Matrix)(projection * view * new Matrix(orientation, Vector3.Zero) * mirrorZ));
            _parameterExposure.SetValue(new Vector4(exposure, exposure, exposure, 1));
            _textureParameter.SetValue(texture);

            if (context.IsHdrEnabled())
            {
                _passLinear.Apply();
            }
            else
            {
                _passGamma.Apply();
            }

            _submesh.Draw();
            savedRenderState.Restore();
        }
Example #3
0
        private void RenderCylinder(IGraphicsService graphicsService, PrimitiveJob job)
        {
            float radius = job.Size.Radius;
            float height = job.Size.Height;

            Effect.World = Matrix.CreateScale(radius, height / 2, radius) * job.Pose;
            Effect.CurrentTechnique.Passes[0].Apply();

            if (DrawWireFrame)
            {
                if (_cylinderLinePrimitive == null)
                {
                    _cylinderLinePrimitive = MeshHelper.GetCylinderLines(graphicsService);
                }

                _cylinderLinePrimitive.Draw();
            }
            else
            {
                if (_cylinderPrimitive == null)
                {
                    _cylinderPrimitive = MeshHelper.GetCylinder(graphicsService);
                }

                _cylinderPrimitive.Draw();
            }
        }
Example #4
0
        public override void Paint()
        {
            TopoModel model = ActiveModel;

            if (Visible)
            {
                if (false) //**Main.main.objectPlacement.checkCutFaces.Checked)
                {
                    // int cutpos = Main.main.objectPlacement.cutPositionSlider.Value;
                    if (ForceRefresh || ctrl.updateCuts || lastRendered != 1 || activeModel != activeSubmesh ||
                        lastShowEdges != SettingsProvider.Instance.ThreeDSettings.ShowEdges || lastSelected != Selected)
                    {
                        RHVector3 normpoint = ctrl.cutPos.Add(ctrl.cutDirection);
                        RHVector3 point     = new RHVector3(0, 0, 0);
                        ReverseTransformPoint(ctrl.cutPos, point);
                        ReverseTransformPoint(normpoint, normpoint);
                        RHVector3 normal = normpoint.Subtract(point);

                        submesh.Clear();
                        model.CutMesh(submesh, normal, point,
                                      outside ? Submesh.MESHCOLOR_OUTSIDE : Submesh.MESHCOLOR_FRONTBACK);
                        submesh.selected = Selected;
                        submesh.Compress();
                        lastShowEdges = SettingsProvider.Instance.ThreeDSettings.ShowEdges;
                        lastSelected  = Selected;
                        activeSubmesh = activeModel;
                        lastRendered  = 1;
                    }
                }
                else
                {
                    if (ForceRefresh || ctrl.updateCuts || lastRendered != 0 || activeModel != activeSubmesh ||
                        lastShowEdges != SettingsProvider.Instance.ThreeDSettings.ShowEdges)
                    {
                        submesh.Clear();
                        submesh.defaultColor =
                            ProjectManager.Instance.CurrentProject.projectSettings.PrinterSettings.Extruders[ExtruderNumber].ExtruderColor;
                        model.FillMesh(submesh, outside ? Submesh.MESHCOLOR_OUTSIDE : Submesh.MESHCOLOR_FRONTBACK);
                        submesh.selected = Selected;
                        submesh.Compress();
                        lastShowEdges = SettingsProvider.Instance.ThreeDSettings.ShowEdges;
                        lastSelected  = Selected;
                        activeSubmesh = activeModel;
                        lastRendered  = 0;
                    }
                }
//            submesh.Draw(SettingsProvider.Instance.ThreeDSettings.drawMethod,ctrl.cam.EdgeTranslation());
                submesh.Draw(2, ctrl.cam.EdgeTranslation());
            }
            ForceRefresh = false;
        }
Example #5
0
        private void RenderSphere(IGraphicsService graphicsService, PrimitiveJob job, RenderContext context)
        {
            if (DrawWireFrame)
            {
                Pose      cameraPose       = context.CameraNode.PoseWorld;
                Matrix44F cameraProjection = context.CameraNode.Camera.Projection;
                if (Numeric.AreEqual(1.0f, cameraProjection.M33))
                {
                    // Orthographic projection
                    Vector3F position = job.Pose.Position;
                    Vector3F right    = cameraPose.Orientation.GetColumn(0);
                    Vector3F up       = cameraPose.Orientation.GetColumn(1);
                    Vector3F forward  = cameraPose.Orientation.GetColumn(2);
                    Matrix   pose     = new Matrix(right.X, right.Y, right.Z, 0,
                                                   up.X, up.Y, up.Z, 0,
                                                   forward.X, forward.Y, forward.Z, 0,
                                                   position.X, position.Y, position.Z, 1);
                    Effect.World = Matrix.CreateScale(job.Size.Radius) * pose;
                    Effect.CurrentTechnique.Passes[0].Apply();

                    if (_circleLinePrimitive == null)
                    {
                        _circleLinePrimitive = MeshHelper.GetCircleLines(graphicsService);
                    }

                    _circleLinePrimitive.Draw();
                }
                else
                {
                    // Perspective projection
                    Vector3F right = cameraPose.Orientation * Vector3F.Right;
                    RenderSphereOutline(job.Size.Radius, ref job.Pose.Position, ref cameraPose, ref right, ref job.Color);
                }
            }
            else
            {
                Effect.World = Matrix.CreateScale(job.Size.Radius) * job.Pose;
                Effect.CurrentTechnique.Passes[0].Apply();

                if (_icospherePrimitive == null)
                {
                    _icospherePrimitive = MeshHelper.GetIcosphere(graphicsService);
                }

                _icospherePrimitive.Draw();
            }
        }
        private void Render(RenderContext context)
        {
            var graphicsDevice = context.GraphicsService.GraphicsDevice;

            graphicsDevice.Clear(Color.CornflowerBlue);

            graphicsDevice.DepthStencilState = DepthStencilState.Default;
            graphicsDevice.RasterizerState   = RasterizerState.CullCounterClockwise;
            graphicsDevice.BlendState        = BlendState.Opaque;

            // Use the view and projection info from the camera node controlled by the
            // Player game component.
            _effect.View       = (Matrix)_cameraObject.CameraNode.View;
            _effect.Projection = _cameraObject.CameraNode.Camera.Projection;

            _effect.World           = Matrix.CreateTranslation(-1, 1, 0);
            _effect.DiffuseColor    = new Vector3(1, 0, 0);
            _effect.LightingEnabled = true;
            _effect.CurrentTechnique.Passes[0].Apply();

            // Render the submesh using the currently active shader.
            _torus.Draw();

            _effect.World        = Matrix.CreateTranslation(1, 1, 0);
            _effect.DiffuseColor = new Vector3(0, 1, 0);
            _effect.CurrentTechnique.Passes[0].Apply();
            _teapot.Draw();

            _effect.World        = Matrix.CreateScale(0.5f, 1, 0.5f) * Matrix.CreateTranslation(-2, 1, -2);
            _effect.DiffuseColor = new Vector3(0, 0, 1);
            _effect.CurrentTechnique.Passes[0].Apply();
            _sphere.Draw();

            _effect.World        = Matrix.CreateTranslation(0, 1, -2);
            _effect.DiffuseColor = new Vector3(1, 1, 0);
            _effect.CurrentTechnique.Passes[0].Apply();
            _box.Draw();

            _effect.World           = Matrix.CreateTranslation(2, 1, -2);
            _effect.DiffuseColor    = new Vector3(1, 0, 1);
            _effect.LightingEnabled = false;
            _effect.CurrentTechnique.Passes[0].Apply();
            _cone.Draw();
        }
Example #7
0
        public override void Paint()
        {
            TopoModel model = ActiveModel;

            if (Main.main.objectPlacement.checkCutFaces.Checked)
            {
                int cutpos = Main.main.objectPlacement.cutPositionSlider.Value;
                if (ForceRefresh || Main.main.threedview.updateCuts || lastRendered != 1 || activeModel != activeSubmesh || lastShowEdges != Main.threeDSettings.ShowEdges || lastSelected != Selected)
                {
                    RHVector3 normpoint = Main.main.threedview.cutPos.Add(Main.main.threedview.cutDirection);
                    RHVector3 point     = new RHVector3(0, 0, 0);
                    ReverseTransformPoint(Main.main.threedview.cutPos, point);
                    ReverseTransformPoint(normpoint, normpoint);
                    RHVector3 normal = normpoint.Subtract(point);

                    submesh.Clear();
                    model.CutMesh(submesh, normal, point, outside ? Submesh.MESHCOLOR_OUTSIDE : Submesh.MESHCOLOR_FRONTBACK);
                    submesh.selected = Selected;
                    submesh.Compress();
                    lastShowEdges = Main.threeDSettings.ShowEdges;
                    lastSelected  = Selected;
                    activeSubmesh = activeModel;
                    lastRendered  = 1;
                }
            }
            else
            {
                if (ForceRefresh || Main.main.threedview.updateCuts || lastRendered != 0 || activeModel != activeSubmesh || lastShowEdges != Main.threeDSettings.ShowEdges)
                {
                    submesh.Clear();
                    model.FillMesh(submesh, outside ? Submesh.MESHCOLOR_OUTSIDE : Submesh.MESHCOLOR_FRONTBACK);
                    submesh.selected = Selected;
                    submesh.Compress();
                    lastShowEdges = Main.threeDSettings.ShowEdges;
                    lastSelected  = Selected;
                    activeSubmesh = activeModel;
                    lastRendered  = 0;
                }
            }
            submesh.Draw(Main.threeDSettings.drawMethod, Main.main.threedview.cam.EdgeTranslation());
            ForceRefresh = false;
        }
Example #8
0
    private void RenderBox(IGraphicsService graphicsService, PrimitiveJob job)
    {
      Effect.World = Matrix.CreateScale((Vector3)job.Size.Extent) * job.Pose;
      Effect.CurrentTechnique.Passes[0].Apply();

      if (DrawWireFrame)
      {
        if (_boxLinePrimitive == null)
          _boxLinePrimitive = MeshHelper.GetBoxLines(graphicsService);

        _boxLinePrimitive.Draw();
      }
      else
      {
        if (_boxPrimitive == null)
          _boxPrimitive = MeshHelper.GetBox(graphicsService);

        _boxPrimitive.Draw();
      }
    }
        /// <inheritdoc/>
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            ThrowIfDisposed();

            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (nodes.Count == 0)
            {
                return;
            }

            context.Validate(_effect);
            context.ThrowIfCameraMissing();

            var graphicsDevice   = context.GraphicsService.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.BlendState        = BlendState.AlphaBlend;
            graphicsDevice.RasterizerState   = RasterizerState.CullNone;
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

            // Camera properties
            var    cameraNode = context.CameraNode;
            Matrix view       = (Matrix) new Matrix(cameraNode.PoseWorld.Orientation.Transposed, new Vector3());

            _parameterView.SetValue(view);
            Matrix projection = cameraNode.Camera.Projection;

            _parameterProjection.SetValue(projection);

            // Update SceneNode.LastFrame for all visible nodes.
            int frame = context.Frame;

            cameraNode.LastFrame = frame;

            for (int i = 0; i < numberOfNodes; i++)
            {
                var node = nodes[i] as ScatteringSkyNode;
                if (node == null)
                {
                    continue;
                }

                // ScatteringSkyNode is visible in current frame.
                node.LastFrame = frame;

                _parameterSunDirection.SetValue((Vector3)node.SunDirection);
                _parameterSunIntensity.SetValue((Vector3)(node.SunIntensity * node.SunColor));
                _parameterRadii.SetValue(new Vector4(
                                             node.AtmosphereHeight + node.PlanetRadius, // Atmosphere radius
                                             node.PlanetRadius,                         // Ground radius
                                             node.ObserverAltitude + node.PlanetRadius, // Observer radius
                                             node.ScaleHeight));                        // Absolute Scale height
                _parameterNumberOfSamples.SetValue(node.NumberOfSamples);
                _parameterBetaRayleigh.SetValue((Vector3)node.BetaRayleigh);
                _parameterBetaMie.SetValue((Vector3)node.BetaMie);
                _parameterGMie.SetValue(node.GMie);
                _parameterTransmittance.SetValue(node.Transmittance);

                if (node.BaseHorizonColor.IsNumericallyZero && node.BaseZenithColor.IsNumericallyZero)
                {
                    // No base color.
                    if (context.IsHdrEnabled())
                    {
                        _passLinear.Apply();
                    }
                    else
                    {
                        _passGamma.Apply();
                    }
                }
                else
                {
                    // Add base color.
                    _parameterBaseHorizonColor.SetValue((Vector4) new Vector4(node.BaseHorizonColor, node.BaseColorShift));
                    _parameterBaseZenithColor.SetValue((Vector3)node.BaseZenithColor);

                    if (context.IsHdrEnabled())
                    {
                        _passLinearWithBaseColor.Apply();
                    }
                    else
                    {
                        _passGammaWithBaseColor.Apply();
                    }
                }

                _submesh.Draw();
            }

            savedRenderState.Restore();
        }
Example #10
0
        private void RenderHiDef(SkyboxNode node, RenderContext context)
        {
            var graphicsDevice = context.GraphicsService.GraphicsDevice;

            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.RasterizerState   = RasterizerState.CullNone;
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;
            graphicsDevice.BlendState        = node.EnableAlphaBlending ? BlendState.AlphaBlend : BlendState.Opaque;

            bool sourceIsFloatingPoint = TextureHelper.IsFloatingPointFormat(node.Texture.Format);

            // Set sampler state. (Floating-point textures cannot use linear filtering. (XNA would throw an exception.))
            if (sourceIsFloatingPoint)
            {
                graphicsDevice.SamplerStates[0] = SamplerState.PointClamp;
            }
            else
            {
                graphicsDevice.SamplerStates[0] = SamplerState.LinearClamp;
            }

            var    cameraNode = context.CameraNode;
            Matrix view       = cameraNode.View;
            Matrix projection = cameraNode.Camera.Projection;

            // Cube maps are left handed --> Sample with inverted z. (Otherwise, the
            // cube map and objects or texts in it are mirrored.)
            var    mirrorZ     = Matrix.CreateScale(1, 1, -1);
            Matrix orientation = node.PoseWorld.Orientation;

            _parameterWorldViewProjection.SetValue((Matrix)(projection * view * new Matrix(orientation, Vector3.Zero) * mirrorZ));

            Vector4 color = node.EnableAlphaBlending
                      ? new Vector4((Vector3)node.Color * node.Alpha, node.Alpha) // Premultiplied
                      : new Vector4((Vector3)node.Color, 1);                      // Opaque

            _parameterColor.SetValue(color);
            _textureParameter.SetValue(node.Texture);

            if (node.Encoding is RgbEncoding)
            {
                _parameterTextureSize.SetValue(node.Texture.Size);
                if (context.IsHdrEnabled())
                {
                    _passRgbToRgb.Apply();
                }
                else
                {
                    _passRgbToSRgb.Apply();
                }
            }
            else if (node.Encoding is SRgbEncoding)
            {
                if (!sourceIsFloatingPoint)
                {
                    if (context.IsHdrEnabled())
                    {
                        _passSRgbToRgb.Apply();
                    }
                    else
                    {
                        _passSRgbToSRgb.Apply();
                    }
                }
                else
                {
                    throw new GraphicsException("sRGB encoded skybox cube maps must not use a floating point format.");
                }
            }
            else if (node.Encoding is RgbmEncoding)
            {
                float max = GraphicsHelper.ToGamma(((RgbmEncoding)node.Encoding).Max);
                _parameterRgbmMaxValue.SetValue(max);

                if (context.IsHdrEnabled())
                {
                    _passRgbmToRgb.Apply();
                }
                else
                {
                    _passRgbmToSRgb.Apply();
                }
            }
            else
            {
                throw new NotSupportedException("The SkyBoxRenderer supports only RgbEncoding, SRgbEncoding and RgbmEncoding.");
            }

            _submesh.Draw();
            savedRenderState.Restore();
        }
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            ThrowIfDisposed();

            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (nodes.Count == 0)
            {
                return;
            }

            context.Validate(_effect);
            context.ThrowIfCameraMissing();

            var graphicsDevice   = context.GraphicsService.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.BlendState        = BlendState.AlphaBlend;
            graphicsDevice.RasterizerState   = RasterizerState.CullNone;
            graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

            // Camera properties
            var    cameraNode = context.CameraNode;
            Matrix view       = (Matrix) new Matrix(cameraNode.PoseWorld.Orientation.Transposed, new Vector3());

            _parameterView.SetValue(view);
            Matrix projection = cameraNode.Camera.Projection;

            _parameterProjection.SetValue(projection);

            // Update SceneNode.LastFrame for all visible nodes.
            int frame = context.Frame;

            cameraNode.LastFrame = frame;

            for (int i = 0; i < numberOfNodes; i++)
            {
                var node = nodes[i] as GradientSkyNode;
                if (node == null)
                {
                    continue;
                }

                // GradientSkyNode is visible in current frame.
                node.LastFrame = frame;

                _parameterSunDirection.SetValue((Vector3)node.SunDirection);
                _parameterFrontColor.SetValue((Vector4)node.FrontColor);
                _parameterZenithColor.SetValue((Vector4)node.ZenithColor);
                _parameterBackColor.SetValue((Vector4)node.BackColor);
                _parameterGroundColor.SetValue((Vector4)node.GroundColor);
                _parameterShift.SetValue(new Vector4(node.FrontZenithShift, node.BackZenithShift, node.FrontGroundShift, node.BackGroundShift));

                if (node.CieSkyStrength < Numeric.EpsilonF)
                {
                    if (context.IsHdrEnabled())
                    {
                        _passLinear.Apply();
                    }
                    else
                    {
                        _passGamma.Apply();
                    }
                }
                else
                {
                    var p = node.CieSkyParameters;
                    _parameterAbcd.SetValue(new Vector4(p.A, p.B, p.C, p.D));
                    _parameterEAndStrength.SetValue(new Vector2(p.E, node.CieSkyStrength));

                    if (context.IsHdrEnabled())
                    {
                        _passCieLinear.Apply();
                    }
                    else
                    {
                        _passCieGamma.Apply();
                    }
                }

                _submesh.Draw();
            }

            savedRenderState.Restore();
        }
Example #12
0
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            ThrowIfDisposed();

            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (numberOfNodes == 0)
            {
                return;
            }

            context.Validate(_effect);
            context.ThrowIfCameraMissing();

            var graphicsDevice   = context.GraphicsService.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            // Camera properties
            int viewportHeight = graphicsDevice.Viewport.Height;
            var cameraNode     = context.CameraNode;
            var projection     = cameraNode.Camera.Projection;

            _parameterProjection.SetValue(projection);

            // Update SceneNode.LastFrame for all visible nodes.
            int frame = context.Frame;

            cameraNode.LastFrame = frame;

            for (int i = 0; i < numberOfNodes; i++)
            {
                var node = nodes[i] as CloudLayerNode;
                if (node == null)
                {
                    continue;
                }

                // CloudLayerNode is visible in current frame.
                node.LastFrame = frame;

                if (node.CloudMap.Texture == null)
                {
                    continue;
                }

                var sunDirection = node.SunDirection;
                _parameterSunDirection.SetValue((Vector3)sunDirection);
                _parameterSkyCurvature.SetValue(node.SkyCurvature);
                _parameterTextureMatrix.SetValue((Matrix) new Matrix44F(node.TextureMatrix, Vector3F.Zero));

                // The sample at the pixel counts as one, the rest are for the blur.
                // Note: We must not set -1 because a for loop like
                //   for (int i = 0; i < -1, i++)
                // crashes the AMD DX9 WP8.1 graphics driver. LOL
                _parameterNumberOfSamples.SetValue(Math.Max(0, node.NumberOfSamples - 1));

                _parameterSampleDistance.SetValue(node.SampleDistance);
                _parameterScatterParameters.SetValue(new Vector3(node.ForwardScatterExponent, node.ForwardScatterScale, node.ForwardScatterOffset));
                _parameterHorizonFade.SetValue(new Vector2(node.HorizonFade, node.HorizonBias));
                _parameterSunLight.SetValue((Vector3)node.SunLight);
                _parameterAmbientLight.SetValue(new Vector4((Vector3)node.AmbientLight, node.Alpha));
                _parameterTexture.SetValue(node.CloudMap.Texture);

                // Occlusion query.
                if (graphicsDevice.GraphicsProfile != GraphicsProfile.Reach && node.SunQuerySize >= Numeric.EpsilonF)
                {
                    bool skipQuery = false;
                    if (node.OcclusionQuery != null)
                    {
                        if (node.OcclusionQuery.IsComplete)
                        {
                            node.TryUpdateSunOcclusion();
                        }
                        else
                        {
                            // The previous query is still not finished. Do not start a new query, this would
                            // create a SharpDX warning.
                            skipQuery = true;
                        }
                    }
                    else
                    {
                        node.OcclusionQuery = new OcclusionQuery(graphicsDevice);
                    }

                    if (!skipQuery)
                    {
                        node.IsQueryPending = true;

                        float totalPixels = viewportHeight * node.SunQuerySize;
                        totalPixels   *= totalPixels;
                        node.QuerySize = totalPixels;

                        // Use a camera which looks at the sun.
                        // Get an relative up vector which is not parallel to the forward direction.
                        var lookAtUp = Vector3F.UnitY;
                        if (Vector3F.AreNumericallyEqual(sunDirection, lookAtUp))
                        {
                            lookAtUp = Vector3F.UnitZ;
                        }

                        Vector3F zAxis = -sunDirection;
                        Vector3F xAxis = Vector3F.Cross(lookAtUp, zAxis).Normalized;
                        Vector3F yAxis = Vector3F.Cross(zAxis, xAxis);

                        var lookAtSunView = new Matrix(xAxis.X, yAxis.X, zAxis.X, 0,
                                                       xAxis.Y, yAxis.Y, zAxis.Y, 0,
                                                       xAxis.Z, yAxis.Z, zAxis.Z, 0,
                                                       0, 0, 0, 1);
                        _parameterView.SetValue(lookAtSunView);

                        graphicsDevice.BlendState        = GraphicsHelper.BlendStateNoColorWrite;
                        graphicsDevice.DepthStencilState = DepthStencilState.None;
                        graphicsDevice.RasterizerState   = RasterizerState.CullNone;

                        // Create small quad shortly behind the near plane.
                        // Note: We use an "untranslated" view matrix, so we can ignore the camera position.
                        float    width  = (projection.Top - projection.Bottom) * node.SunQuerySize;
                        Vector3F right  = sunDirection.Orthonormal1 * (width / 2);
                        Vector3F up     = sunDirection.Orthonormal2 * (width / 2);
                        Vector3F center = sunDirection * (projection.Near * 1.0001f);
                        _queryGeometry[0] = center - up - right;
                        _queryGeometry[1] = center + up - right;
                        _queryGeometry[2] = center - up + right;
                        _queryGeometry[3] = center + up + right;

                        if (node.CloudMap.Texture.Format == SurfaceFormat.Alpha8)
                        {
                            _passOcclusionAlpha.Apply();
                        }
                        else
                        {
                            _passOcclusionRgb.Apply();
                        }

                        node.OcclusionQuery.Begin();
                        graphicsDevice.DrawUserPrimitives(PrimitiveType.TriangleStrip, _queryGeometry, 0, 2,
                                                          VertexPosition.VertexDeclaration);
                        node.OcclusionQuery.End();
                    }
                }
                else
                {
                    node.IsQueryPending = false;
                    node.SunOcclusion   = 0;
                }

                Matrix viewUntranslated = (Matrix) new Matrix44F(cameraNode.PoseWorld.Orientation.Transposed, new Vector3F(0));
                _parameterView.SetValue(viewUntranslated);

                // Render clouds.
                graphicsDevice.BlendState        = BlendState.AlphaBlend;
                graphicsDevice.RasterizerState   = RasterizerState.CullNone;
                graphicsDevice.DepthStencilState = DepthStencilState.DepthRead;

                if (context.IsHdrEnabled())
                {
                    if (node.CloudMap.Texture.Format == SurfaceFormat.Alpha8)
                    {
                        _passCloudAlphaLinear.Apply();
                    }
                    else
                    {
                        _passCloudRgbLinear.Apply();
                    }
                }
                else
                {
                    if (node.CloudMap.Texture.Format == SurfaceFormat.Alpha8)
                    {
                        _passCloudAlphaGamma.Apply();
                    }
                    else
                    {
                        _passCloudRgbGamma.Apply();
                    }
                }

                _submesh.Draw();
            }

            savedRenderState.Restore();
        }
        /// <inheritdoc/>
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (numberOfNodes == 0)
            {
                return;
            }

            var  cameraNode = context.CameraNode;
            var  projection = cameraNode.Camera.Projection;
            Pose view       = cameraNode.PoseWorld.Inverse;

            int frame = context.Frame;

            cameraNode.LastFrame = frame;

            var graphicsDevice = context.GraphicsService.GraphicsDevice;

            // Save render state.
            var originalRasterizerState   = graphicsDevice.RasterizerState;
            var originalDepthStencilState = graphicsDevice.DepthStencilState;
            var originalBlendState        = graphicsDevice.BlendState;

            // We render only backsides with no depth test.
            // OPTIMIZE: When camera is outside a sphere, we can render front sides with depth-read.
            graphicsDevice.RasterizerState   = RasterizerState.CullClockwise;
            graphicsDevice.DepthStencilState = DepthStencilState.None;
            graphicsDevice.BlendState        = BlendState.AlphaBlend;

            // Set global effect parameters.
            var viewport = graphicsDevice.Viewport;

            _parameterViewportSize.SetValue(new Vector2(viewport.Width, viewport.Height));
            _parameterView.SetValue(view);
            _parameterProjection.SetValue(projection);
            _parameterCameraPosition.SetValue((Vector3)cameraNode.PoseWorld.Position);
            _parameterCameraFar.SetValue(projection.Far);
            _parameterGBuffer0.SetValue(context.GBuffer0);

            for (int i = 0; i < numberOfNodes; i++)
            {
                var node = nodes[i] as FogSphereNode;
                if (node == null)
                {
                    continue;
                }

                // FogSphereNode is visible in current frame.
                node.LastFrame = frame;

                Matrix world = Matrix.CreateScale((Vector3)node.ScaleWorld) * node.PoseWorld;
                _parameterWorld.SetValue(world);
                _parameterWorldInverse.SetValue(Matrix.Invert(world));
                _parameterColor.SetValue((Vector3)node.Color);
                _parameterBlendMode.SetValue(node.BlendMode);
                _parameterDensity.SetValue(node.Density);
                _parameterFalloff.SetValue(node.Falloff);
                _parameterIntersectionSoftness.SetValue(node.IntersectionSoftness);

                _effect.CurrentTechnique.Passes[0].Apply();
                _submesh.Draw();
            }

            // Restore render states.
            graphicsDevice.RasterizerState   = originalRasterizerState;
            graphicsDevice.DepthStencilState = originalDepthStencilState;
            graphicsDevice.BlendState        = originalBlendState;
        }
Example #14
0
        public override void Render(IList <SceneNode> nodes, RenderContext context, RenderOrder order)
        {
            if (nodes == null)
            {
                throw new ArgumentNullException("nodes");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            int numberOfNodes = nodes.Count;

            if (numberOfNodes == 0)
            {
                return;
            }

            context.Validate(_effect);
            context.ThrowIfCameraMissing();

            var graphicsDevice   = _effect.GraphicsDevice;
            var savedRenderState = new RenderStateSnapshot(graphicsDevice);

            graphicsDevice.DepthStencilState = DepthStencilState.None;
            graphicsDevice.RasterizerState   = RasterizerState.CullNone;
            graphicsDevice.BlendState        = GraphicsHelper.BlendStateAdd;

            var viewport = graphicsDevice.Viewport;

            _parameterViewportSize.SetValue(new Vector2(viewport.Width, viewport.Height));
            _parameterGBuffer0.SetValue(context.GBuffer0);
            _parameterGBuffer1.SetValue(context.GBuffer1);

            var    cameraNode     = context.CameraNode;
            Pose   cameraPose     = cameraNode.PoseWorld;
            Matrix viewProjection = (Matrix)cameraNode.View * cameraNode.Camera.Projection;

            // Update SceneNode.LastFrame for all visible nodes.
            int frame = context.Frame;

            context.CameraNode.LastFrame = frame;

            bool isHdrEnabled = context.IsHdrEnabled();

            // Copy nodes to list and sort them by persistent IDs. This is necessary to avoid popping when
            // light probes overlap.
            _jobs.Clear();
            for (int i = 0; i < numberOfNodes; i++)
            {
                var lightNode = nodes[i] as LightNode;
                if (lightNode == null)
                {
                    continue;
                }

                var light = lightNode.Light as ImageBasedLight;
                if (light == null || light.Texture == null)
                {
                    continue;
                }

                // Build sort-ID - high values for lights which should be rendered last.
                ulong sortId = 0;

                // Render infinite lights first and others later.
                if (!(light.Shape is InfiniteShape))
                {
                    sortId += ((ulong)1 << 32); // Set high value above 32-bit range.
                }
                // Sort by priority. Lights with higher priority should be rendered last
                // (= over the other lights).
                // Shift priority (signed int) to positive range and add it.
                sortId += (ulong)((long)lightNode.Priority + int.MaxValue + 1);

                // Shift sortId and add light.Id in least significant bits.
                sortId = (sortId << 16) | (ushort)light.Id;

                // Add to list for sorting.
                _jobs.Add(new Job
                {
                    SortId    = sortId,
                    LightNode = lightNode,
                });
            }

            // Sort by ascending sort-ID value.
            _jobs.Sort(Comparer.Instance);

            numberOfNodes = _jobs.Count;
            for (int i = 0; i < numberOfNodes; i++)
            {
                var lightNode = _jobs[i].LightNode;
                var light     = (ImageBasedLight)lightNode.Light;

                // LightNode is visible in current frame.
                lightNode.LastFrame = frame;

                // ReSharper disable CompareOfFloatsByEqualityOperator
                bool enableDiffuse = !(Numeric.IsNaN(light.DiffuseIntensity) || (light.DiffuseIntensity == 0.0f && light.BlendMode == 0.0f));
                // ReSharper restore CompareOfFloatsByEqualityOperator

                bool enableSpecular = !Numeric.IsNaN(light.SpecularIntensity);
                if (!enableDiffuse && !enableSpecular)
                {
                    continue;
                }

                float hdrScale = isHdrEnabled ? light.HdrScale : 1;

                // We use 1x1 mipmap level for diffuse.
                // (2x2 is still okay, 4x4 already looks a bit like a specular reflection.)
                float diffuseIntensity = enableDiffuse ? light.DiffuseIntensity : 0.0f;
                _parameterParameters0.SetValue(new Vector4(
                                                   (Vector3)light.Color * diffuseIntensity * hdrScale, // DiffuseColor
                                                   Math.Max(0, light.Texture.LevelCount - 1)));        // Diffuse mip level.

                // Shader supports only RGBM.
                float rgbmMax;
                if (light.Encoding is RgbmEncoding)
                {
                    rgbmMax = GraphicsHelper.ToGamma(((RgbmEncoding)light.Encoding).Max);
                }
                else if (light.Encoding is SRgbEncoding)
                {
                    // Decoding RGBM with MaxValue 1 is equal to encoding sRGB, i.e. only
                    // gamma-to-linear is performed (assuming that the cube map alpha channel is 1).
                    rgbmMax = 1;
                }
                else
                {
                    throw new NotSupportedException(
                              "ImageBasedLight must use sRGB or RGBM encoding. Other encodings are not yet supported.");
                }

                _parameterParameters1.SetValue(new Vector4(
                                                   (Vector3)light.Color * light.SpecularIntensity * hdrScale, // SpecularColor
                                                   rgbmMax));

                // Bounding box can be a box shape or an infinite shape.
                var boundingBoxShape = lightNode.Shape as BoxShape;

                // Get extent of bounding box. For infinite shapes we simply set a large value.
                var boundingBoxExtent = boundingBoxShape != null
                              ? boundingBoxShape.Extent * lightNode.ScaleWorld
                              : new Vector3F(1e20f);

                // Falloff can only be used for box shapes but not for infinite shapes.
                float falloffRange = (boundingBoxShape != null) ? light.FalloffRange : 0;

                // AABB for localization in local space.
                // Use invalid min and max (min > max) to disable localization.
                Aabb projectionAabb = new Aabb(new Vector3F(1), new Vector3F(-1));
                if (light.EnableLocalizedReflection)
                {
                    if (light.LocalizedReflectionBox.HasValue)
                    {
                        // User defined AABB.
                        projectionAabb          = light.LocalizedReflectionBox.Value;
                        projectionAabb.Minimum *= lightNode.ScaleWorld;
                        projectionAabb.Maximum *= lightNode.ScaleWorld;
                    }
                    else if (boundingBoxShape != null)
                    {
                        // AABB is equal to the bounding box.
                        projectionAabb = new Aabb(-boundingBoxExtent / 2, boundingBoxExtent / 2);
                    }
                }

                _parameterParameters2.SetValue(new Vector4(
                                                   boundingBoxExtent.X / 2,
                                                   boundingBoxExtent.Y / 2,
                                                   boundingBoxExtent.Z / 2,
                                                   falloffRange));

                _parameterParameters3.SetValue(new Vector4(
                                                   projectionAabb.Minimum.X,
                                                   projectionAabb.Minimum.Y,
                                                   projectionAabb.Minimum.Z,
                                                   light.Texture.Size));

                _parameterParameters4.SetValue(new Vector4(
                                                   projectionAabb.Maximum.X,
                                                   projectionAabb.Maximum.Y,
                                                   projectionAabb.Maximum.Z,
                                                   light.BlendMode));

                // Precomputed value for specular reflection lookup.
                const float sqrt3 = 1.7320508075688772935274463415059f;
                _parameterPrecomputedTerm.SetValue((float)Math.Log(light.Texture.Size * sqrt3, 2.0));

                _parameterEnvironmentMap.SetValue(light.Texture);

                // Compute screen space rectangle and FrustumFarCorners.
                var rectangle           = GraphicsHelper.GetViewportRectangle(cameraNode, viewport, lightNode);
                var texCoordTopLeft     = new Vector2F(rectangle.Left / (float)viewport.Width, rectangle.Top / (float)viewport.Height);
                var texCoordBottomRight = new Vector2F(rectangle.Right / (float)viewport.Width, rectangle.Bottom / (float)viewport.Height);
                GraphicsHelper.GetFrustumFarCorners(cameraNode.Camera.Projection, texCoordTopLeft, texCoordBottomRight, _frustumFarCorners);

                // Convert frustum far corners from view space to world space.
                for (int j = 0; j < _frustumFarCorners.Length; j++)
                {
                    _frustumFarCorners[j] = (Vector3)cameraPose.ToWorldDirection((Vector3F)_frustumFarCorners[j]);
                }

                _parameterFrustumCorners.SetValue(_frustumFarCorners);

                EffectPass passLight = null;
                if (enableDiffuse && enableSpecular)
                {
                    passLight = _passDiffuseAndSpecularLight;
                }
                else if (enableDiffuse)
                {
                    // TODO: Can we disable writes to LightBuffer1?
                    passLight = _passDiffuseLight;
                }
                else
                {
                    // TODO: Can we disable writes to LightBuffer0?
                    passLight = _passSpecularLight;
                }

                // Simply render fullscreen quad if we do not have a clip shape or a bounding box.
                if (lightNode.Clip == null && boundingBoxShape == null)
                {
                    graphicsDevice.BlendState = BlendState.AlphaBlend;

                    // Transform matrix transforms from world space with camera as origin to
                    // local space. The lightNode.Scale is already in the other parameters and not
                    // used in Transform.
                    var pose = lightNode.PoseWorld;
                    pose.Position -= cameraPose.Position;
                    _parameterTransform.SetValue(pose.Inverse);

                    passLight.Apply();
                    graphicsDevice.DrawFullScreenQuad();
                    continue;
                }

                // ----- Render clip mesh.
                graphicsDevice.DepthStencilState = GraphicsHelper.DepthStencilStateOnePassStencilFail;
                graphicsDevice.BlendState        = GraphicsHelper.BlendStateNoColorWrite;
                if (lightNode.Clip != null)
                {
                    // Using user-defined clip shape.
                    var data = lightNode.RenderData as LightRenderData;
                    if (data == null)
                    {
                        data = new LightRenderData();
                        lightNode.RenderData = data;
                    }

                    data.UpdateClipSubmesh(context.GraphicsService, lightNode);
                    _parameterTransform.SetValue((Matrix)data.ClipMatrix * viewProjection);
                    _passClip.Apply();
                    data.ClipSubmesh.Draw();

                    graphicsDevice.DepthStencilState = lightNode.InvertClip
            ? GraphicsHelper.DepthStencilStateStencilEqual0
            : GraphicsHelper.DepthStencilStateStencilNotEqual0;
                }
                else
                {
                    Debug.Assert(boundingBoxShape != null);

                    // Use box submesh.
                    if (_boxSubmesh == null)
                    {
                        _boxSubmesh = MeshHelper.GetBox(context.GraphicsService);
                    }

                    Matrix44F world = lightNode.PoseWorld
                                      * Matrix44F.CreateScale(lightNode.ScaleLocal * boundingBoxShape.Extent);
                    _parameterTransform.SetValue((Matrix)world * viewProjection);

                    _passClip.Apply();
                    _boxSubmesh.Draw();

                    graphicsDevice.DepthStencilState = GraphicsHelper.DepthStencilStateStencilNotEqual0;
                }

                graphicsDevice.BlendState = BlendState.AlphaBlend;

                {
                    // Transform matrix transforms from world space with camera as origin to
                    // local space. The lightNode.Scale is already in the other parameters and not
                    // used in Transform.
                    var pose = lightNode.PoseWorld;
                    pose.Position -= cameraPose.Position;
                    _parameterTransform.SetValue(pose.Inverse);
                }

                // ----- Render full screen quad.
                passLight.Apply();
                graphicsDevice.DrawQuad(rectangle);
            }

            savedRenderState.Restore();
            _jobs.Clear();
        }