/// <returns>
        /// x = Near; y = 1/(Far-Near)
        /// </returns>
        private static Vector2 GetShadowMapDepthParameters(LightShadowMapTexture shadowMapTexture)
        {
            var     lightPoint     = shadowMapTexture.Light as LightPoint;
            Vector2 clippingPlanes = GetLightClippingPlanes(lightPoint);

            return(CameraKeys.ZProjectionACalculate(clippingPlanes.X, clippingPlanes.Y));
        }
Exemple #2
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            // First do everything that doesn't change per individual render object
            var graphicsDevice  = context.GraphicsDevice;
            var graphicsContext = context.GraphicsContext;
            var commandList     = context.GraphicsContext.CommandList;

            // Refresh shader, might have changed during runtime
            _decalShader.UpdateEffect(graphicsDevice);

            // Set common shader parameters if needed
            _decalShader.Parameters.Set(TransformationKeys.ViewProjection, renderView.ViewProjection);
            _decalShader.Parameters.Set(TransformationKeys.ViewInverse, Matrix.Invert(renderView.View));

            // Important to release it at the end of the draw, otherwise you'll run out of memory!
            //var depthStencil = context.Resolver.ResolveDepthStencil(commandList.DepthStencilBuffer);
            var depthStencil = context.Resolver.ResolveDepthStencil(graphicsDevice.Presenter.DepthStencilBuffer);       // Must use the Presenter's depth buffer, otherwise it won't appear in the Game Studio

            _decalShader.Parameters.Set(DepthBaseKeys.DepthStencil, depthStencil);

            _decalShader.Parameters.Set(CameraKeys.ViewSize, renderView.ViewSize);
            _decalShader.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));
            _decalShader.Parameters.Set(CameraKeys.NearClipPlane, renderView.NearClipPlane);
            _decalShader.Parameters.Set(CameraKeys.FarClipPlane, renderView.FarClipPlane);

            for (int index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var decalRendObj        = (DecalRenderObject)renderNode.RenderObject;

                if (decalRendObj.RenderCube == null)
                {
                    continue;   // Next render object
                }

                // Assign shader parameters
                _decalShader.Parameters.Set(TransformationKeys.WorldInverse, Matrix.Invert(decalRendObj.WorldMatrix));
                _decalShader.Parameters.Set(TransformationKeys.WorldViewProjection, decalRendObj.WorldMatrix * renderView.ViewProjection);
                _decalShader.Parameters.Set(TransformationKeys.WorldView, decalRendObj.WorldMatrix * renderView.View);
                _decalShader.Parameters.Set(DecalShaderKeys.DecalTexture, decalRendObj.Texture);
                _decalShader.Parameters.Set(DecalShaderKeys.TextureScale, decalRendObj.TextureScale);
                _decalShader.Parameters.Set(DecalShaderKeys.DecalColor, decalRendObj.Color);

                decalRendObj.RenderCube.Draw(graphicsContext, _decalShader);
            }

            context.Resolver.ReleaseDepthStenctilAsShaderResource(depthStencil);
        }
        private void UpdateParameters(RenderDrawContext context, RenderView renderView)
        {
            // Compute the camera/view parameters:
            Vector2 viewSpaceDepthReconstructionParameters = CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane);

            SetValueParameterForBothShaders(CameraKeys.ZProjection, viewSpaceDepthReconstructionParameters);
            SetValueParameterForBothShaders(CameraKeys.NearClipPlane, renderView.NearClipPlane);
            SetValueParameterForBothShaders(CameraKeys.FarClipPlane, renderView.FarClipPlane);

            // Set the values required for the projected sampling radius calculation:
            Vector2 projectionSizeOnUnitPlaneInClipSpace = CalculateProjectionSizeOnPlane(renderView, 1.0f);

            SetValueParameterForBothShaders(SubsurfaceScatteringBlurShaderKeys.ProjectionSizeOnUnitPlaneInClipSpace, projectionSizeOnUnitPlaneInClipSpace);

            // Other parameters:
            SetValueParameterForBothShaders(SubsurfaceScatteringBlurShaderKeys.ViewProjectionMatrix, ref renderView.ViewProjection);    // This is used for debugging only.

            // Supply the material arrays of this frame to the shaders:
            SetValueParameterForBothShaders(SubsurfaceScatteringBlurShaderKeys.ScatteringWidths, materialScatteringWidths);  // TODO: PERFORMANCE: Only upload the actual number of elements used?
            UpdateKernelBuffer(context);
        }
        public void HandleMessages(IntPtr hWnd, NativeMethods.WindowMessage msg, IntPtr wParam, IntPtr lParam)
        {
            switch (msg)
            {
            // Handle the keyboard
            case NativeMethods.WindowMessage.KeyDown:
                CameraKeys mappedKeyDown = MapKey(wParam);
                if (mappedKeyDown != (CameraKeys)byte.MaxValue)
                {
                    // Valid key was pressed, mark it as 'down'
                    keys[(int)mappedKeyDown] = true;
                }
                break;

            case NativeMethods.WindowMessage.KeyUp:
                CameraKeys mappedKeyUp = MapKey(wParam);
                if (mappedKeyUp != (CameraKeys)byte.MaxValue)
                {
                    // Valid key was let go, mark it as 'up'
                    keys[(int)mappedKeyUp] = false;
                }
                break;

            case NativeMethods.WindowMessage.RightButtonDown:
                if (!rightMouseDown)
                {
                    lastMousePosition = System.Windows.Forms.Cursor.Position;
                }
                rightMouseDown = true;
                break;

            case NativeMethods.WindowMessage.RightButtonUp:
                rightMouseDown = false;
                break;
            }
        }
Exemple #5
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var originalColorBuffer = GetSafeInput(0);
            var originalDepthBuffer = GetSafeInput(1);

            var outputTexture = GetSafeOutput(0);

            if (configurationDirty)
            {
                SetupTechnique();
            }

            // Preparation phase: create different downscaled versions of the original image, later needed by the bokeh blur shaders.
            // TODO use ImageMultiScaler instead?
            downscaledSources.Clear();

            // First we linearize the depth and compute the CoC map based on the user lens configuration.
            // Render target will contain "CoC"(16 bits) "Linear depth"(16bits).
            var cocLinearDepthTexture = GetScopedRenderTarget(originalColorBuffer.Description, 1f, PixelFormat.R16G16_Float);

            var renderView = context.RenderContext.RenderView;
            var farPlane   = renderView.FarClipPlane;

            var depthAreas = DOFAreas;

            if (AutoFocus)
            {
                // TODO replace this by physical camera parameters (aperture, focus distance...)
                var diffToTarget = (autoFocusDistanceTarget - autoFocusDistanceCurrent);
                var maxAmplitude = farPlane * 0.2f;
                diffToTarget             = MathUtil.Clamp(diffToTarget, -maxAmplitude, maxAmplitude);
                autoFocusDistanceCurrent = autoFocusDistanceCurrent + 0.1f * diffToTarget;
                if (autoFocusDistanceCurrent < renderView.NearClipPlane * 2.0f)
                {
                    autoFocusDistanceCurrent = renderView.NearClipPlane * 2.0f;
                }
                depthAreas = new Vector4(renderView.NearClipPlane, autoFocusDistanceCurrent, autoFocusDistanceCurrent, autoFocusDistanceCurrent + farPlane * 0.5f);
            }

            coclinearDepthMapEffect.SetInput(0, originalDepthBuffer);
            coclinearDepthMapEffect.SetOutput(cocLinearDepthTexture);
            coclinearDepthMapEffect.Parameters.Set(CircleOfConfusionKeys.depthAreas, ref depthAreas);
            coclinearDepthMapEffect.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));
            coclinearDepthMapEffect.Draw(context, "CoC_LinearDepth");

            if (AutoFocus)
            {
                // Reads the center depth of the previous frame and use it as a new target
                // TODO single pixel is really small, average some disk area instead?
                pointDepthShader.Parameters.Set(PointDepthKeys.Coordinate, new Vector2(0.5f, 0.5f));
                pointDepthShader.SetInput(cocLinearDepthTexture);
                pointDepthShader.SetOutput(depthCenter1x1);
                pointDepthShader.Draw(context, "Center Depth");

                depthReadBack.SetInput(depthCenter1x1);
                depthReadBack.Draw(context, "Center_Depth_Readback");
                var centerDepth = depthReadBack.Result[0];
                autoFocusDistanceTarget = centerDepth;
            }

            // Find the smallest downscale we should go down to.
            var maxDownscale = 0;

            foreach (var cocLevel in cocLevels)
            {
                if (cocLevel.DownscaleFactor > maxDownscale)
                {
                    maxDownscale = cocLevel.DownscaleFactor;
                }
            }

            // Create a series of downscale, with anti-bleeding treatment
            for (int i = 0; i <= maxDownscale; i++)
            {
                var downSizedTexture = originalColorBuffer;
                if (i > 0)
                {
                    downSizedTexture = GetScopedRenderTarget(originalColorBuffer.Description, 1f / (float)Math.Pow(2f, i), originalColorBuffer.Description.Format);
                    textureScaler.SetInput(0, downscaledSources[i - 1]);
                    textureScaler.SetOutput(downSizedTexture);
                    textureScaler.Draw(context, "DownScale_Factor{0}", i);
                }

                downscaledSources[i] = downSizedTexture;
            }

            // We create a blurred version of the CoC map.
            // This is useful to avoid silhouettes appearing when the CoC changes abruptly.
            var blurredCoCTexture = NewScopedRenderTarget2D(cocLinearDepthTexture.Description);

            cocMapBlur.Radius = 6f / 720f * cocLinearDepthTexture.Description.Height; // 6 pixels at 720p
            cocMapBlur.SetInput(0, cocLinearDepthTexture);
            cocMapBlur.SetOutput(blurredCoCTexture);
            cocMapBlur.Draw(context, "CoC_BlurredMap");

            // Creates all the levels with different CoC strengths.
            // (Skips level with CoC 0 which is always the original buffer.)
            combineLevelsEffect.Parameters.Set(CombineLevelsFromCoCKeys.LevelCount, cocLevels.Count);
            combineLevelsEffect.SetInput(0, cocLinearDepthTexture);
            combineLevelsEffect.SetInput(1, blurredCoCTexture);
            combineLevelsEffect.SetInput(2, originalColorBuffer);

            combineLevelsFrontEffect.Parameters.Set(CombineLevelsFromCoCKeys.LevelCount, cocLevels.Count);
            combineLevelsFrontEffect.SetInput(0, cocLinearDepthTexture);
            combineLevelsFrontEffect.SetInput(1, blurredCoCTexture);
            combineLevelsFrontEffect.SetInput(2, originalColorBuffer);

            float previousCoC = 0f;

            for (int i = 1; i < cocLevels.Count; i++)
            {
                // We render a blurred version of the original scene into a downscaled render target.
                // Blur strength depends on the current level CoC value.

                var   levelConfig     = cocLevels[i];
                var   textureToBlur   = downscaledSources[levelConfig.DownscaleFactor];
                float downscaleFactor = 1f / (float)(Math.Pow(2f, levelConfig.DownscaleFactor));
                var   blurOutput      = GetScopedRenderTarget(originalColorBuffer.Description, downscaleFactor, originalColorBuffer.Description.Format);
                var   blurOutputFront = NewScopedRenderTarget2D(blurOutput.Description);
                float blurRadius      = (MaxBokehSize * BokehSizeFactor) * levelConfig.CoCValue * downscaleFactor * originalColorBuffer.Width;
                if (blurRadius < 1f)
                {
                    blurRadius = 1f;
                }

                //---------------------------------
                // Far out-of-focus
                //---------------------------------

                // Pre-process the layer for the current CoC
                // This removes areas which might wrongly bleed into our image when blurring.
                var alphaTextureToBlur = NewScopedRenderTarget2D(textureToBlur.Description);
                thresholdAlphaCoC.Parameters.Set(ThresholdAlphaCoCKeys.CoCReference, previousCoC);
                thresholdAlphaCoC.Parameters.Set(ThresholdAlphaCoCKeys.CoCCurrent, levelConfig.CoCValue);
                thresholdAlphaCoC.SetInput(0, textureToBlur);
                thresholdAlphaCoC.SetInput(1, cocLinearDepthTexture);
                thresholdAlphaCoC.SetOutput(alphaTextureToBlur);
                thresholdAlphaCoC.Draw(context, "Alphaize_Far_{0}", i);
                textureToBlur = alphaTextureToBlur;

                // TODO Quality up: make the opaque areas "bleed" into the areas we just made transparent

                // Apply the bokeh blur effect
                BokehBlur levelBlur = levelConfig.BlurEffect;
                levelBlur.CoCStrength = levelConfig.CoCValue;
                levelBlur.Radius      = blurRadius; // This doesn't generate garbage if the radius value doesn't change.
                levelBlur.SetInput(0, textureToBlur);
                levelBlur.SetOutput(blurOutput);
                levelBlur.Draw(context, "CoC_LoD_Layer_Far_{0}", i);
                combineLevelsEffect.SetInput(i + 2, blurOutput);

                //---------------------------------
                // Near out-of-focus
                //---------------------------------

                // Negates CoC values and makes background objects transparent
                thresholdAlphaCoCFront.Parameters.Set(ThresholdAlphaCoCFrontKeys.CoCReference, previousCoC);
                thresholdAlphaCoCFront.Parameters.Set(ThresholdAlphaCoCFrontKeys.CoCCurrent, levelConfig.CoCValue);
                thresholdAlphaCoCFront.SetInput(0, downscaledSources[levelConfig.DownscaleFactor]);
                thresholdAlphaCoCFront.SetInput(1, cocLinearDepthTexture);
                thresholdAlphaCoCFront.SetOutput(alphaTextureToBlur);
                thresholdAlphaCoCFront.Draw(context, "Alphaize_Near_{0}", i);
                textureToBlur = alphaTextureToBlur;

                // Apply the bokeh blur effect
                levelBlur.SetInput(0, textureToBlur);
                levelBlur.SetOutput(blurOutputFront);
                levelBlur.Draw(context, "CoC_LoD_Layer_Near_{0}", i);
                combineLevelsFrontEffect.SetInput(i + 2, blurOutputFront);

                previousCoC = levelConfig.CoCValue;
            }

            // Far out-of-focus: each pixel, depending on its CoC, interpolates its color from
            // the original color buffer and blurred buffer(s).
            combineLevelsEffect.Parameters.Set(CombineLevelsFromCoCShaderKeys.CoCLevelValues, combineShaderCocLevelValues);
            combineLevelsEffect.SetOutput(outputTexture);
            combineLevelsEffect.Draw(context, "CoCLevelCombineInterpolation");

            // Finally add front out-of-focus objects on the top of the scene

            // TODO Quality up: instead of merging all the layers for each pixel, merge only
            // the relevant layer(s) closest to the pixel CoC.
            combineLevelsFrontEffect.SetOutput(outputTexture);
            combineLevelsFrontEffect.Draw(context, "CoCLevelCombineInterpolationFront");

            // Release any reference
            downscaledSources.Clear();
        }
Exemple #6
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var originalColorBuffer = GetSafeInput(0);
            var originalDepthBuffer = GetSafeInput(1);

            var outputTexture = GetSafeOutput(0);

            var renderView = context.RenderContext.RenderView;

            //---------------------------------
            // Ambient Occlusion
            //---------------------------------

            var tempWidth  = (originalColorBuffer.Width * (int)TempSize) / (int)TemporaryBufferSize.SizeFull;
            var tempHeight = (originalColorBuffer.Height * (int)TempSize) / (int)TemporaryBufferSize.SizeFull;
            var aoTexture1 = NewScopedRenderTarget2D(tempWidth, tempHeight, PixelFormat.R8_UNorm, 1);
            var aoTexture2 = NewScopedRenderTarget2D(tempWidth, tempHeight, PixelFormat.R8_UNorm, 1);

            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOKeys.Count, NumberOfSamples > 0 ? NumberOfSamples : 9);

            // Set Near/Far pre-calculated factors to speed up the linear depth reconstruction
            aoRawImageEffect.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));

            Vector4 screenSize = new Vector4(originalColorBuffer.Width, originalColorBuffer.Height, 0, 0);

            screenSize.Z = screenSize.X / screenSize.Y;
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ScreenInfo, screenSize);

            // Projection infor used to reconstruct the View space position from linear depth
            var     p00      = renderView.Projection.M11;
            var     p11      = renderView.Projection.M22;
            var     p02      = renderView.Projection.M13;
            var     p12      = renderView.Projection.M23;
            Vector4 projInfo = new Vector4(-2.0f / (screenSize.X * p00), -2.0f / (screenSize.Y * p11), (1.0f - p02) / p00, (1.0f + p12) / p11);

            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ProjInfo, projInfo);

            //**********************************
            // User parameters
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ParamProjScale, ParamProjScale);
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ParamIntensity, ParamIntensity);
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ParamBias, ParamBias);
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ParamRadius, ParamRadius);
            aoRawImageEffect.Parameters.Set(AmbientOcclusionRawAOShaderKeys.ParamRadiusSquared, ParamRadius * ParamRadius);

            aoRawImageEffect.SetInput(0, originalDepthBuffer);
            aoRawImageEffect.SetOutput(aoTexture1);
            aoRawImageEffect.Draw(context, "AmbientOcclusionRawAO");

            for (int bounces = 0; bounces < NumberOfBounces; bounces++)
            {
                if (offsetsWeights == null)
                {
                    offsetsWeights = new[]
                    {
                        //  0.356642f, 0.239400f, 0.072410f, 0.009869f,
                        //  0.398943f, 0.241971f, 0.053991f, 0.004432f, 0.000134f, // stddev = 1.0
                        0.153170f, 0.144893f, 0.122649f, 0.092902f, 0.062970f,     // stddev = 2.0
                        //  0.111220f, 0.107798f, 0.098151f, 0.083953f, 0.067458f, 0.050920f, 0.036108f, // stddev = 3.0
                    };

                    nameGaussianBlurH = string.Format("AmbientOcclusionBlurH{0}x{0}", offsetsWeights.Length);
                    nameGaussianBlurV = string.Format("AmbientOcclusionBlurV{0}x{0}", offsetsWeights.Length);
                }

                // Set Near/Far pre-calculated factors to speed up the linear depth reconstruction
                blurH.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));
                blurV.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));

                // Update permutation parameters
                blurH.Parameters.Set(AmbientOcclusionBlurKeys.Count, offsetsWeights.Length);
                blurH.Parameters.Set(AmbientOcclusionBlurKeys.BlurScale, BlurScale);
                blurH.Parameters.Set(AmbientOcclusionBlurKeys.EdgeSharpness, EdgeSharpness);
                blurH.EffectInstance.UpdateEffect(context.GraphicsDevice);

                blurV.Parameters.Set(AmbientOcclusionBlurKeys.Count, offsetsWeights.Length);
                blurV.Parameters.Set(AmbientOcclusionBlurKeys.BlurScale, BlurScale);
                blurV.Parameters.Set(AmbientOcclusionBlurKeys.EdgeSharpness, EdgeSharpness);
                blurV.EffectInstance.UpdateEffect(context.GraphicsDevice);

                // Update parameters
                blurH.Parameters.Set(AmbientOcclusionBlurShaderKeys.Weights, offsetsWeights);
                blurV.Parameters.Set(AmbientOcclusionBlurShaderKeys.Weights, offsetsWeights);

                // Horizontal pass
                blurH.SetInput(0, aoTexture1);
                blurH.SetInput(1, originalDepthBuffer);
                blurH.SetOutput(aoTexture2);
                blurH.Draw(context, nameGaussianBlurH);

                // Vertical pass
                blurV.SetInput(0, aoTexture2);
                blurV.SetInput(1, originalDepthBuffer);
                blurV.SetOutput(aoTexture1);
                blurV.Draw(context, nameGaussianBlurV);
            }

            aoApplyImageEffect.SetInput(0, originalColorBuffer);
            aoApplyImageEffect.SetInput(1, aoTexture1);
            aoApplyImageEffect.SetOutput(outputTexture);
            aoApplyImageEffect.Draw(context, "AmbientOcclusionApply");
        }
Exemple #7
0
        protected override void DrawCore(RenderDrawContext context)
        {
            if (lightShafts == null)
            {
                return; // Not collected
            }
            if (LightBufferDownsampleLevel < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(LightBufferDownsampleLevel));
            }
            if (BoundingVolumeBufferDownsampleLevel < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(BoundingVolumeBufferDownsampleLevel));
            }

            var depthInput = GetSafeInput(0);

            // Create a min/max buffer generated from scene bounding volumes
            var targetBoundingBoxBufferSize = new Size2(Math.Max(1, depthInput.Width / BoundingVolumeBufferDownsampleLevel), Math.Max(1, depthInput.Height / BoundingVolumeBufferDownsampleLevel));
            var boundingBoxBuffer           = NewScopedRenderTarget2D(targetBoundingBoxBufferSize.Width, targetBoundingBoxBufferSize.Height, PixelFormat.R32G32_Float);

            // Buffer that holds the minimum distance in case of being inside the bounding box
            var backSideRaycastBuffer = NewScopedRenderTarget2D(1, 1, PixelFormat.R32G32_Float);

            // Create a single channel light buffer
            PixelFormat lightBufferPixelFormat = needsColorLightBuffer ? PixelFormat.R16G16B16A16_Float : PixelFormat.R16_Float;
            var         targetLightBufferSize  = new Size2(Math.Max(1, depthInput.Width / LightBufferDownsampleLevel), Math.Max(1, depthInput.Height / LightBufferDownsampleLevel));
            var         lightBuffer            = NewScopedRenderTarget2D(targetLightBufferSize.Width, targetLightBufferSize.Height, lightBufferPixelFormat);

            lightShaftsEffectShader.SetOutput(lightBuffer);
            var lightShaftsParameters = lightShaftsEffectShader.Parameters;

            lightShaftsParameters.Set(DepthBaseKeys.DepthStencil, depthInput); // Bind scene depth

            if (!Initialized)
            {
                Initialize(context.RenderContext);
            }

            var renderView  = context.RenderContext.RenderView;
            var viewInverse = Matrix.Invert(renderView.View);

            lightShaftsParameters.Set(TransformationKeys.ViewInverse, viewInverse);
            lightShaftsParameters.Set(TransformationKeys.Eye, new Vector4(viewInverse.TranslationVector, 1));

            // Setup parameters for Z reconstruction
            lightShaftsParameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(renderView.NearClipPlane, renderView.FarClipPlane));

            Matrix projectionInverse;

            Matrix.Invert(ref renderView.Projection, out projectionInverse);
            lightShaftsParameters.Set(TransformationKeys.ProjectionInverse, projectionInverse);

            applyLightEffectShader.SetOutput(GetSafeOutput(0));

            foreach (var lightShaft in lightShafts)
            {
                if (lightShaft.Light == null)
                {
                    continue; // Skip entities without a light component
                }
                // Set sample count for this light
                lightShaftsParameters.Set(LightShaftsEffectKeys.SampleCount, lightShaft.SampleCount);

                // Setup the shader group used for sampling shadows
                var shadowMapTexture = shadowMapRenderer.FindShadowMap(renderView.LightingView ?? renderView, lightShaft.Light);
                SetupLight(context, lightShaft, shadowMapTexture, lightShaftsParameters);

                // Check if we can pack bounding volumes together or need to draw them one by one
                var boundingVolumeLoop = lightShaft.SeparateBoundingVolumes ? lightShaft.BoundingVolumes.Count : 1;
                var lightBufferUsed    = false;
                for (int i = 0; i < boundingVolumeLoop; ++i)
                {
                    // Generate list of bounding volume (either all or one by one depending on SeparateBoundingVolumes)
                    var currentBoundingVolumes = (lightShaft.SeparateBoundingVolumes) ? singleBoundingVolume : lightShaft.BoundingVolumes;
                    if (lightShaft.SeparateBoundingVolumes)
                    {
                        singleBoundingVolume[0] = lightShaft.BoundingVolumes[i];
                    }

                    using (context.PushRenderTargetsAndRestore())
                    {
                        // Clear bounding box buffer
                        context.CommandList.Clear(boundingBoxBuffer, new Color4(1.0f, 0.0f, 0.0f, 0.0f));
                        context.CommandList.SetRenderTargetAndViewport(null, boundingBoxBuffer);

                        // If nothing visible, skip second part
                        if (!DrawBoundingVolumeMinMax(context, currentBoundingVolumes))
                        {
                            continue;
                        }

                        context.CommandList.Clear(backSideRaycastBuffer, new Color4(1.0f, 0.0f, 0.0f, 0.0f));
                        context.CommandList.SetRenderTargetAndViewport(null, backSideRaycastBuffer);

                        // If nothing visible, skip second part
                        DrawBoundingVolumeBackside(context, currentBoundingVolumes);
                    }

                    if (!lightBufferUsed)
                    {
                        // First pass: replace (avoid a clear and blend state)
                        lightShaftsEffectShader.BlendState = BlendStates.Opaque;
                        lightBufferUsed = true;
                    }
                    else
                    {
                        // Then: add
                        var desc = BlendStates.Additive;
                        desc.RenderTarget0.ColorSourceBlend = Blend.One; // But without multiplying alpha
                        lightShaftsEffectShader.BlendState  = desc;
                    }

                    if (lightShaft.SampleCount < 1)
                    {
                        throw new ArgumentOutOfRangeException(nameof(lightShaft.SampleCount));
                    }

                    // Set min/max input
                    lightShaftsEffectShader.SetInput(0, boundingBoxBuffer);
                    lightShaftsEffectShader.SetInput(1, backSideRaycastBuffer);

                    // Light accumulation pass (on low resolution buffer)
                    DrawLightShaft(context, lightShaft);
                }

                // Everything was outside, skip
                if (!lightBufferUsed)
                {
                    continue;
                }

                if (LightBufferDownsampleLevel != 1)
                {
                    // Blur the result
                    blur.Radius = LightBufferDownsampleLevel;
                    blur.SetInput(lightBuffer);
                    blur.SetOutput(lightBuffer);
                    blur.Draw(context);
                }

                // Additive blend pass
                Color3 lightColor = lightShaft.Light2.ComputeColor(context.GraphicsDevice.ColorSpace, lightShaft.Light.Intensity);
                applyLightEffectShader.Parameters.Set(AdditiveLightShaderKeys.LightColor, lightColor);
                applyLightEffectShader.Parameters.Set(AdditiveLightEffectKeys.Color, needsColorLightBuffer);
                applyLightEffectShader.SetInput(lightBuffer);
                applyLightEffectShader.Draw(context);
            }

            // Clean up unused render data
            unusedLights.Clear();
            foreach (var data in renderData)
            {
                if (data.Value.UsageCounter != usageCounter)
                {
                    unusedLights.Add(data.Key);
                }
            }
            foreach (var unusedLight in unusedLights)
            {
                renderData.Remove(unusedLight);
            }
            usageCounter++;
        }
Exemple #8
0
 public static void UnRegisterKeyDownEvent(CameraKeys k, OnKeyDownEvent e)
 {
     cameraEvents[k] -= e;
 }
Exemple #9
0
 public static void RegisterKeyDownEvent(CameraKeys k, OnKeyDownEvent e)
 {
     if (!cameraEvents.ContainsKey(k))
     cameraEvents[k] = e;
       else
     cameraEvents[k] += e;
 }