Beispiel #1
0
        } // RenderModelSimple

        /// <summary>
        /// Render a skinned model.
        /// </summary>
        internal void RenderModelSkinned(ref Matrix worldMatrix, Model model, Matrix[] boneTransform, Constant material, int meshIndex, int meshPart)
        {
            try
            {
                Resource.CurrentTechnique = Resource.Techniques["ConstantSkinned"];
                // Skinned
                spBones.Value = boneTransform;
                // Matrix
                Matrix worldViewProjection;
                Matrix.Multiply(ref worldMatrix, ref viewProjectionMatrix, out worldViewProjection);
                spWorldViewProjMatrix.QuickSetValue(ref worldViewProjection);
                // Diffuse
                if (material.DiffuseTexture == null)
                {
                    spDiffuseColor.Value   = material.DiffuseColor;
                    spDiffuseTexture.Value = Texture.BlackTexture;
                }
                else
                {
                    spDiffuseColor.Value   = Color.Black;
                    spDiffuseTexture.Value = material.DiffuseTexture;
                }
                spAlphaBlending.Value = material.AlphaBlending;

                Resource.CurrentTechnique.Passes[0].Apply();
                model.RenderMeshPart(meshIndex, meshPart);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Constant Material: Unable to render model.", e);
            }
        } // RenderModelSkinned
        } // Instance

        #endregion

        #region Constructor

        /// <summary>
        /// Anamorphic Lens Flare Shader.
        /// </summary>
        private AnamorphicLensFlareShader() : base("PostProcessing\\AnamorphicLensFlare")
        {
            AssetContentManager userContentManager = AssetContentManager.CurrentContentManager;

            AssetContentManager.CurrentContentManager = AssetContentManager.SystemContentManager;
            //sunObject = new Sphere(6, 6, 1);   // Algorithmically generated mesh normally sucks when optimized vertex access is needed.
            sunObject = new FileModel("Sphere"); // Exported models for the contrary are great.
            AssetContentManager.CurrentContentManager = userContentManager;
        } // AnamorphicLensFlareShader
        } // RenderModelSimple

        /// <summary>
        /// Render a skinned model.
        /// </summary>
        internal void RenderModelSkinned(ref Matrix worldMatrix, Model model, Matrix[] boneTransform, BlinnPhong material, int meshIndex, int meshPart)
        {
            try
            {
                Resource.CurrentTechnique = blinnPhongSkinnedTechnique;
                // Skinned
                spBones.Value = boneTransform;
                // Matrix
                Matrix worldViewProjection;
                Matrix.Multiply(ref worldMatrix, ref viewProjectionMatrix, out worldViewProjection);
                spWorldViewProjMatrix.QuickSetValue(ref worldViewProjection);
                spWorldMatrix.QuickSetValue(ref worldMatrix);
                // Diffuse
                if (material.DiffuseTexture == null)
                {
                    spDiffuseColor.Value   = material.DiffuseColor;
                    spDiffuseTexture.Value = Texture.BlackTexture;
                }
                else
                {
                    spDiffuseColor.Value   = Color.Black;
                    spDiffuseTexture.Value = material.DiffuseTexture;
                }
                // Specular
                spSpecularIntensity.Value = material.SpecularIntensity;
                spSpecularTexture.Value   = material.SpecularTexture ?? Texture.WhiteTexture;
                // Reflection
                if (material.ReflectionTexture != null)
                {
                    spReflectionTexture.Value = material.ReflectionTexture;
                    if (material.ReflectionTexture.IsRgbm)
                    {
                        spIsRGBM.Value   = true;
                        spMaxRange.Value = material.ReflectionTexture.RgbmMaxRange;
                    }
                    else
                    {
                        spIsRGBM.Value = false;
                    }
                    spReflectionTextured.Value = true;
                }
                else
                {
                    spReflectionTextured.Value = false;
                }

                Resource.CurrentTechnique.Passes[0].Apply();
                model.RenderMeshPart(meshIndex, meshPart);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Bling Phong Material: Unable to render model.", e);
            }
        } // RenderModelSkinned
        } // Instance

        #endregion

        #region Constructor

        /// <summary>
        /// Skybox Shader.
        /// </summary>
        private SkydomeShader() : base("Sky\\Skydome")
        {
            skydomeModel = new FileModel("Skydome");
            AssetContentManager userContentManager = AssetContentManager.CurrentContentManager;

            AssetContentManager.CurrentContentManager = AssetContentManager.SystemContentManager;
            skyTextureNight  = new Texture("Shaders\\SkyNight");
            skyTextureSunset = new Texture("Shaders\\SkySunset");
            skyTextureDay    = new Texture("Shaders\\SkyDay");
            AssetContentManager.CurrentContentManager = userContentManager;
        } // SkyboxShader
Beispiel #5
0
        } // Instance

        #endregion

        #region Constructor

        /// <summary>
        /// Light Pre Pass Spot Light Shader.
        /// </summary>
        private SpotLightShader() : base("LightPrePass\\SpotLight")
        {
            AssetContentManager userContentManager = AssetContentManager.CurrentContentManager;

            AssetContentManager.CurrentContentManager = AssetContentManager.SystemContentManager;
            //boundingLightObject = new Sphere(6, 6, 1);   // Algorithmically generated mesh normally sucks when optimized vertex access is needed.
            boundingLightObject = new FileModel("Sphere"); // Exported models for the contrary are great.
            // TODO: Export a cone.
            AssetContentManager.CurrentContentManager = userContentManager;
            interiorOfBoundingVolumeDepthStencilState = new DepthStencilState
            {
                DepthBufferEnable      = true,
                DepthBufferWriteEnable = false,
                DepthBufferFunction    = CompareFunction.Greater,
            };
        } // SpotLightShader
        } // RenderModel

        /// <summary>
        /// Render objects in light space.
        /// </summary>
        internal void RenderModelCubeShadows(ref Matrix worldMatrix, Model model, Matrix[] boneTransform)
        {
            if (model.IsSkinned) // If it is a skinned model.
            {
                spBones.Value             = boneTransform;
                Resource.CurrentTechnique = generateCubeLightDepthBufferSkinnedTechnique;
            }
            else
            {
                Resource.CurrentTechnique = generateCubeLightDepthBufferTechnique;
            }

            if (boneTransform == null || model.IsSkinned)
            {
                Matrix worldLightProjectionMatrix;
                Matrix.Multiply(ref worldMatrix, ref lightViewProjectionMatrix, out worldLightProjectionMatrix);
                spWorldViewProjMatrix.Value = worldLightProjectionMatrix;
                spWorldMatrix.Value         = worldMatrix;
                Resource.CurrentTechnique.Passes[0].Apply();
                model.Render();
            }
            else
            {
                for (int mesh = 0; mesh < model.MeshesCount; mesh++)
                {
                    Matrix boneTransformedWorldMatrix;
                    Matrix.Multiply(ref boneTransform[mesh + 1], ref worldMatrix, out boneTransformedWorldMatrix);
                    spWorldMatrix.Value = boneTransformedWorldMatrix;

                    Matrix boneTransformedWorldLighProjectionMatrix;
                    Matrix.Multiply(ref boneTransformedWorldMatrix, ref lightViewProjectionMatrix, out boneTransformedWorldLighProjectionMatrix);
                    spWorldViewProjMatrix.Value = boneTransformedWorldLighProjectionMatrix;

                    Resource.CurrentTechnique.Passes[0].Apply();
                    // Render the model's mesh.
                    int meshPartsCount = model.MeshPartsCountPerMesh[mesh];
                    for (int meshPart = 0; meshPart < meshPartsCount; meshPart++)
                    {
                        model.RenderMeshPart(mesh, meshPart);
                    }
                }
            }
        } // RenderModel
Beispiel #7
0
        } // Instance

        #endregion

        #region Constructor

        /// <summary>
        /// Light Pre Pass Point Light Shader.
        /// </summary>
        private PointLightShader() : base("LightPrePass\\PointLight")
        {
            AssetContentManager userContentManager = AssetContentManager.CurrentContentManager;

            AssetContentManager.CurrentContentManager = AssetContentManager.SystemContentManager;
            //boundingLightObject = new Sphere(6, 6, 1);   // Algorithmically generated mesh normally sucks when optimized vertex access is needed.
            boundingLightObject = new FileModel("Sphere"); // Exported models for the contrary are great.
            AssetContentManager.CurrentContentManager = userContentManager;

            stencilBlendState = new BlendState
            {
                ColorWriteChannels  = ColorWriteChannels.None,
                ColorWriteChannels1 = ColorWriteChannels.None,
            };
            lightBlendState = new BlendState
            {
                AlphaBlendFunction    = BlendFunction.Add,
                AlphaDestinationBlend = Blend.One,
                AlphaSourceBlend      = Blend.One,
                ColorBlendFunction    = BlendFunction.Add,
                ColorDestinationBlend = Blend.One,
                ColorSourceBlend      = Blend.One,
            };
            stencilDepthStencilState = new DepthStencilState
            {
                DepthBufferEnable      = true,
                DepthBufferWriteEnable = false,
                DepthBufferFunction    = CompareFunction.Less,
                StencilEnable          = true,
                StencilFunction        = CompareFunction.Always,
                StencilDepthBufferFail = StencilOperation.Replace,
                ReferenceStencil       = 1,
            };
            lightDepthStencilState = new DepthStencilState
            {
                DepthBufferEnable      = true,
                DepthBufferWriteEnable = false,
                DepthBufferFunction    = CompareFunction.Greater,
                StencilEnable          = true,
                StencilFunction        = CompareFunction.NotEqual,
                ReferenceStencil       = 1,
            };
        } // PointLightShader
Beispiel #8
0
        } // Begin

        #endregion

        #region Render

        /// <summary>
        /// Render a model.
        /// </summary>
        internal void RenderModel(ref Matrix worldMatrix, Model model, CarPaint material, int meshIndex, int meshPart)
        {
            try
            {
                // Matrices
                Matrix worldViewProjection;
                Matrix.Multiply(ref worldMatrix, ref viewProjectionMatrix, out worldViewProjection);
                spWorldViewProjMatrix.QuickSetValue(ref worldViewProjection);
                spWorldMatrix.QuickSetValue(ref worldMatrix);
                spWorldITMatrix.Value = Matrix.Transpose(Matrix.Invert(worldMatrix));
                // Surface //
                spSpecularIntensity.Value       = material.SpecularIntensity;
                spBasePaintColor.Value          = material.BasePaintColor;
                spSecondBasePaintColor.Value    = material.SecondBasePaintColor;
                spThridBasePaintColor.Value     = material.ThirdBasePaintColor;
                spFlakeLayerColor.Value         = material.FlakesColor;
                spNormalPerturbation.Value      = material.NormalPerturbation;
                spMicroflakePerturbation.Value  = material.MicroflakePerturbation;
                spMicroflakePerturbationA.Value = material.MicroflakePerturbationA;
                spReflectionTexture.Value       = material.ReflectionTexture;
                if (material.ReflectionTexture.IsRgbm)
                {
                    spIsRGBM.Value   = true;
                    spMaxRange.Value = material.ReflectionTexture.RgbmMaxRange;
                }
                else
                {
                    spIsRGBM.Value = false;
                }
                spFlakeScale.Value     = material.FlakesScale;
                spFlakesExponent.Value = material.FlakesExponent;

                Resource.CurrentTechnique.Passes[0].Apply();
                model.RenderMeshPart(meshIndex, meshPart);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Car Paint Material: Unable to render model.", e);
            }
        } // RenderModel
Beispiel #9
0
        } // Begin

        #endregion

        #region Render

        /// <summary>
        /// Render the spot light.
        /// </summary>
        public void Render(Color diffuseColor, Vector3 position, Vector3 direction, float intensity,
                           float range, float innerConeAngle, float outerConeAngle, Texture shadowTexture, Texture lightMaskTexture,
                           Matrix worldMatrix, bool renderClipVolumeInLocalSpace, Model clipVolume = null)
        {
            try
            {
                #region Set Parameters

                spLightColor.Value     = diffuseColor;
                spLightPosition.Value  = Vector3.Transform(position, viewMatrix);
                spLightIntensity.Value = intensity;
                spInvLightRadius.Value = 1 / range;
                Vector3 directionVS = Vector3.TransformNormal(direction, viewMatrix);
                directionVS.Normalize();
                spLightDirection.Value      = directionVS;
                spLightInnerConeAngle.Value = innerConeAngle * (3.141592f / 180.0f);
                spLightOuterConeAngle.Value = outerConeAngle * (3.141592f / 180.0f);

                if (lightMaskTexture != null)
                {
                    Matrix lightViewMatrix       = Matrix.CreateLookAt(position, position + direction, Vector3.Up);
                    Matrix lightProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(outerConeAngle * (float)Math.PI / 180.0f, // field of view
                                                                                       1.0f,                                     // Aspect ratio
                                                                                       1f,                                       // Near plane
                                                                                       range);                                   // Far plane
                    spViewToLightViewProjMatrix.Value = Matrix.Invert(viewMatrix) * lightViewMatrix * lightProjectionMatrix;
                    spLightMaskTexture.Value          = lightMaskTexture;
                }
                else
                {
                    spLightMaskTexture.Value = Texture.BlackTexture; // To avoid a potential exception.
                }
                // Compute the light world matrix.
                Matrix boundingLightObjectWorldMatrix;
                if (clipVolume != null)
                {
                    boundingLightObjectWorldMatrix = renderClipVolumeInLocalSpace ? Matrix.Identity : worldMatrix;
                }
                else
                {
                    // Scale according to light radius, and translate it to light position.
                    boundingLightObjectWorldMatrix = Matrix.CreateScale(range) * Matrix.CreateTranslation(position); // TODO: when the cone model is exported I have to include the rotation into consideration.
                }
                spWorldViewProjMatrix.Value = boundingLightObjectWorldMatrix * viewMatrix * projectionMatrix;
                spWorldViewMatrix.Value     = boundingLightObjectWorldMatrix * viewMatrix;

                if (shadowTexture != null)
                {
                    spShadowTexture.Value     = shadowTexture;
                    Resource.CurrentTechnique = lightMaskTexture != null ? spotLightWithShadowsWithMaskTechnique : spotLightWithShadowsTechnique;
                }
                else
                {
                    spShadowTexture.Value     = Texture.BlackTexture; // To avoid a potential exception.
                    Resource.CurrentTechnique = lightMaskTexture != null ? spotLightWithMaskTechnique : spotLightTechnique;
                }

                #endregion

                // TODO: Implement the stencil optimization.

                // Calculate the distance between the camera and light center.
                float cameraToCenter = Vector3.Distance(Matrix.Invert(viewMatrix).Translation, position) - nearPlane;
                // If we are inside the light volume, draw the sphere's inside face.
                if (cameraToCenter <= range)
                {
                    EngineManager.Device.DepthStencilState = interiorOfBoundingVolumeDepthStencilState;
                    EngineManager.Device.RasterizerState   = RasterizerState.CullClockwise;
                }
                else
                {
                    EngineManager.Device.DepthStencilState = DepthStencilState.DepthRead;
                    EngineManager.Device.RasterizerState   = RasterizerState.CullCounterClockwise;
                }

                Resource.CurrentTechnique.Passes[0].Apply();
                if (clipVolume != null)
                {
                    clipVolume.Render();
                }
                else
                {
                    boundingLightObject.Render();
                }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Light Pre Pass Spot Light: Unable to render.", e);
            }
        } // Render
Beispiel #10
0
        } // Begin

        #endregion

        #region Render Model

        /// <summary>
        /// Render a model.
        /// </summary>
        internal void RenderModel(ref Matrix worldMatrix, Model model, BlinnPhong material, int meshIndex, int meshPart,
                                  Vector3 spotLightPosition, Vector3 spotLightDirection, Color spotLightColor, float spotLightIntensity,
                                  float spotLightInnerAngle, float spotLightOuterAngle, float spotLightRange,
                                  Vector3 pointLightPos1, Color pointLightColor1, float pointLightIntensity1,
                                  float pointLightRange1, Vector3 pointLightPos2, Color pointLightColor2,
                                  float pointLightIntensity2, float pointLightRange2)
        {
            // Set Render States.
            EngineManager.Device.RasterizerState = material.BothSides ? RasterizerState.CullNone : RasterizerState.CullCounterClockwise;

            try
            {
                spWorldViewProjMatrix.Value = worldMatrix * viewprojectionMatrix;
                spWorldMatrix.Value         = worldMatrix;
                spWorldITMatrix.Value       = Matrix.Transpose(Matrix.Invert(worldMatrix));

                spSpecularIntensity.Value = material.SpecularIntensity;
                spSpecularPower.Value     = material.SpecularPower;
                spDiffuseColor.Value      = material.DiffuseColor;
                spAlphaBlending.Value     = material.AlphaBlending;

                // Diffuse
                if (material.DiffuseTexture == null)
                {
                    spDiffuseColor.Value   = material.DiffuseColor;
                    spDiffuseTexture.Value = Texture.BlackTexture;
                }
                else
                {
                    spDiffuseColor.Value   = Color.Black;
                    spDiffuseTexture.Value = material.DiffuseTexture;
                }
                // Reflection
                if (material.ReflectionTexture != null)
                {
                    spReflectionTexture.Value = material.ReflectionTexture;
                    if (material.ReflectionTexture.IsRgbm)
                    {
                        spIsRGBM.Value   = true;
                        spMaxRange.Value = material.ReflectionTexture.RgbmMaxRange;
                    }
                    else
                    {
                        spIsRGBM.Value = false;
                    }
                    spReflectionTextured.Value = true;
                }
                else
                {
                    spReflectionTextured.Value = false;
                }
                // Spot Light //
                spSpotLightDirection.Value  = spotLightDirection;
                spSpotLightPosition.Value   = spotLightPosition;
                spSpotLightColor.Value      = spotLightColor;
                spSpotLightIntensity.Value  = spotLightIntensity;
                spSpotLightInnerAngle.Value = spotLightInnerAngle * (3.141592f / 180.0f);
                spSpotLightOuterAngle.Value = spotLightOuterAngle * (3.141592f / 180.0f);
                spInvSpotLightRadius.Value  = 1 / spotLightRange;
                // Point Light //
                spPointLightPos1.Value       = pointLightPos1;
                spPointLightColor1.Value     = pointLightColor1;
                spPointLightIntensity1.Value = pointLightIntensity1;
                spInvPointLightRadius1.Value = 1 / pointLightRange1;
                spPointLightPos2.Value       = pointLightPos2;
                spPointLightColor2.Value     = pointLightColor2;
                spPointLightIntensity2.Value = pointLightIntensity2;
                spInvPointLightRadius2.Value = 1 / pointLightRange2;

                Resource.CurrentTechnique.Passes[0].Apply();
                model.RenderMeshPart(meshIndex, meshPart);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Forward Bling Phong Material: Unable to render model.", e);
            }
        }
        } // RenderModelSkinned

        /// <summary>
        /// Render a model using the parallax technique.
        /// </summary>
        internal void RenderModelParallax(ref Matrix worldMatrix, Model model, BlinnPhong material, int meshIndex, int meshPart)
        {
            try
            {
                Resource.CurrentTechnique = blinnPhongWithParrallaxTechnique;
                // Matrix
                Matrix worldViewProjection;
                Matrix.Multiply(ref worldMatrix, ref viewProjectionMatrix, out worldViewProjection);
                spWorldViewProjMatrix.QuickSetValue(ref worldViewProjection);
                spWorldMatrix.QuickSetValue(ref worldMatrix);
                // Diffuse
                if (material.DiffuseTexture == null)
                {
                    spDiffuseColor.Value   = material.DiffuseColor;
                    spDiffuseTexture.Value = Texture.BlackTexture;
                }
                else
                {
                    spDiffuseColor.Value   = Color.Black;
                    spDiffuseTexture.Value = material.DiffuseTexture;
                }
                // Specular
                spSpecularIntensity.Value = material.SpecularIntensity;
                spSpecularTexture.Value   = material.SpecularTexture ?? Texture.WhiteTexture;
                // Parallax
                spNormalTexture.Value                 = material.NormalTexture;
                spNormalTextureSize.Value             = new Vector2(material.NormalTexture.Width, material.NormalTexture.Height);
                EngineManager.Device.SamplerStates[1] = SamplerState.AnisotropicClamp;
                spLODThreshold.Value         = material.ParallaxLodThreshold;
                spMinimumNumberSamples.Value = material.ParallaxMinimumNumberSamples;
                spMaximumNumberSamples.Value = material.ParallaxMaximumNumberSamples;
                spHeightMapScale.Value       = material.ParallaxHeightMapScale;
                spWorldITMatrix.Value        = Matrix.Transpose(Matrix.Invert(worldMatrix));
                // Reflection
                if (material.ReflectionTexture != null)
                {
                    spReflectionTexture.Value = material.ReflectionTexture;
                    if (material.ReflectionTexture.IsRgbm)
                    {
                        spIsRGBM.Value   = true;
                        spMaxRange.Value = material.ReflectionTexture.RgbmMaxRange;
                    }
                    else
                    {
                        spIsRGBM.Value = false;
                    }
                    spReflectionTextured.Value = true;
                }
                else
                {
                    spReflectionTextured.Value = false;
                }

                Resource.CurrentTechnique.Passes[0].Apply();
                model.RenderMeshPart(meshIndex, meshPart);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Bling Phong Material: Unable to render model.", e);
            }
        } // RenderModelParallax
Beispiel #12
0
        } // Begin

        #endregion

        #region Render

        /// <summary>
        /// Render the point light.
        /// </summary>
        public void Render(Color diffuseColor, Vector3 position, float intensity, float radius, TextureCube shadowTexture, Matrix worldMatrix, bool renderClipVolumeInLocalSpace, Model clipVolume = null)
        {
            try
            {
                // It is possible to use the depth information and the stencil buffer to mark in a two pass rendering exactly what pixels are affected by the light.
                // This helps to reduce pixel shader load but at the same time allows implementing clip volumes.
                // With clip volumes you can put, for example, a box and the light won’t bleed outside this box even if the radius is bigger.
                // I.e. you can place lights in a wall and the opposite side of that wall won’t be illuminated.
                //
                // The problem is I don’t have the Z-Buffer available because XNA 4 does not allow sharing depth buffers between render targets.
                // However I can reconstruct the Z-Buffer with a shader and my G-Buffer.
                //
                // If you don’t use custom clip volumes (i.e. we use the default sphere) and the light is too far then we could have more vertex processing
                // than pixel processing. Some games use glow planes (a colored mask) to see the light’s bright when they are far away,
                // this is good for open environment games but not for interior games.
                // Instead games like Killzone 2 ignore the first pass on these lights and only compute the second (and this second pass still does one
                // part of the filter). Also the far plane "problem" is addressed in this optimization.
                //
                // Another optimization that I made is the use of a Softimage sphere instead of my procedural spheres.
                // Models exported in this kind of tools are optimized for accessing. For example my stress test changes from 20/21 frames to 22 frames.
                // Not a big change, but still a change nevertheless.
                //
                // I also research the possibility to use instancing with some lights.
                // But no article talk about this technique so I try to think why is not useful and it was easy to find that:
                // 1) It can be only used with spheres (not custom clip volumes).
                // 2) The dynamic buffers used for the instancing information could be too dynamic or difficult to maintain.
                // 3) The stencil optimization could be very important on interior games and could not be mixed with instancing and custom clip volumes.
                // Extra complexity added (including the use of vfetch for Xbox 360).

                // Fill the stencil buffer with 0s.
                EngineManager.Device.Clear(ClearOptions.Stencil, Color.White, 1.0f, 0);

                #region Set Parameters

                spLightColor.Value     = diffuseColor;
                spLightPosition.Value  = Vector3.Transform(position, viewMatrix);
                spLightIntensity.Value = intensity;
                spInvLightRadius.Value = 1 / radius;

                if (shadowTexture != null)
                {
                    spShadowTexture.Value  = shadowTexture;
                    spViewInverse.Value    = Matrix.Invert(Matrix.Transpose(Matrix.Invert(viewMatrix)));
                    spTextureSize.Value    = new Vector3(shadowTexture.Size, shadowTexture.Size, shadowTexture.Size);
                    spTextureSizeInv.Value = new Vector3(1.0f / shadowTexture.Size, 1.0f / shadowTexture.Size, 1.0f / shadowTexture.Size);
                }
                else
                {
                    spShadowTexture.Value = TextureCube.BlackTexture;
                }

                // Compute the light world matrix.
                Matrix boundingLightObjectWorldMatrix;
                if (clipVolume != null)
                {
                    boundingLightObjectWorldMatrix = renderClipVolumeInLocalSpace ? Matrix.Identity : worldMatrix;
                }
                else
                {
                    // Scale according to light radius, and translate it to light position.
                    boundingLightObjectWorldMatrix = Matrix.CreateScale(radius) * Matrix.CreateTranslation(position);
                }

                spWorldViewProj.Value = boundingLightObjectWorldMatrix * viewMatrix * projectionMatrix;
                spWorldView.Value     = boundingLightObjectWorldMatrix * viewMatrix;

                #endregion

                // http://en.wikipedia.org/wiki/Angular_diameter
                // The formula was inspired from Guerilla´s GDC 09 presentation.
                float distanceToCamera = Vector3.Distance(Matrix.Invert(viewMatrix).Translation, position);
                float angularDiameter  = (float)(2 * Math.Atan(radius / distanceToCamera));
                if (angularDiameter > 0.2f * (3.1416f * fieldOfView / 180.0f)) // 0.2f is the original value.
                {
                    // This only works when the clip volume does not intercept the camera´s far plane.

                    // First pass.
                    // The stencil buffer was already filled with 0 and if the back of the clip volume
                    // is in front of the geometry then it marks the pixel as useful.
                    // I prefer to do it in that way because when the clip volume intercept the camera’s near plane
                    // we don’t need to perform a special case and we still have custom volume support.
                    Resource.CurrentTechnique              = pointLightStencilTechnique;
                    EngineManager.Device.RasterizerState   = RasterizerState.CullCounterClockwise;
                    EngineManager.Device.BlendState        = stencilBlendState;
                    EngineManager.Device.DepthStencilState = stencilDepthStencilState;
                    Resource.CurrentTechnique.Passes[0].Apply();
                    if (clipVolume != null)
                    {
                        clipVolume.Render();
                    }
                    else
                    {
                        boundingLightObject.Render();
                    }

                    // Second pass.
                    // Render the clip volume back faces with the light shader.
                    // The pixel with stencil value of 1 that are in front of the geometry will be discarded.
                    Resource.CurrentTechnique              = shadowTexture != null ? pointLightWithShadowsTechnique : pointLightTechnique;
                    EngineManager.Device.RasterizerState   = RasterizerState.CullClockwise;
                    EngineManager.Device.BlendState        = lightBlendState;
                    EngineManager.Device.DepthStencilState = lightDepthStencilState;
                    Resource.CurrentTechnique.Passes[0].Apply();
                    if (clipVolume != null)
                    {
                        clipVolume.Render();
                    }
                    else
                    {
                        boundingLightObject.Render();
                    }
                }
                else // Far lights
                {
                    // Render the clip volume front faces with the light shader.
                    Resource.CurrentTechnique            = shadowTexture != null ? pointLightWithShadowsTechnique : pointLightTechnique;
                    EngineManager.Device.RasterizerState = RasterizerState.CullCounterClockwise;
                    //EngineManager.Device.BlendState = lightBlendState; // Not need to set it.
                    EngineManager.Device.DepthStencilState = DepthStencilState.DepthRead;
                    Resource.CurrentTechnique.Passes[0].Apply();
                    if (clipVolume != null)
                    {
                        clipVolume.Render();
                    }
                    else
                    {
                        boundingLightObject.Render();
                    }
                }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException("Light Pre Pass Point Light: Unable to render.", e);
            }
        } // Render