Exemple #1
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var output = GetOutput(context.RenderContext);
            if (output != null)
            {
                try
                {
                    // TODO GRAPHICS REFACTOR
                    //context.PushParameters(Parameters);

                    ActivateOutput(context);

                    DrawCore(context, output);
                }
                finally
                {
                    // TODO GRAPHICS REFACTOR
                    //context.PopParameters();

                    if (ResetGraphicsStates)
                    {
                        // Make sure that states are clean after this rendering
                        // TODO GRAPHICS REFACTOR
                        //context.GraphicsDevice.ResetStates();
                    }
                }
            }
        }
 public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
 {
     lock (drawLock)
     {
         DrawInternal(context, renderView, renderViewStage, startIndex, endIndex);
     }
 }
Exemple #3
0
        protected override void LoadContent()
        {
            var assetManager = Services.GetSafeServiceAs<ContentManager>();
            var graphicsContext = Services.GetSafeServiceAs<GraphicsContext>();

            // Preload the scene if it exists
            if (InitialSceneUrl != null && assetManager.Exists(InitialSceneUrl))
            {
                SceneInstance = new SceneInstance(Services, assetManager.Load<Scene>(InitialSceneUrl));
            }

            if (MainRenderFrame == null)
            {
                // TODO GRAPHICS REFACTOR Check if this is a good idea to use Presenter targets
                MainRenderFrame = RenderFrame.FromTexture(GraphicsDevice.Presenter?.BackBuffer, GraphicsDevice.Presenter?.DepthStencilBuffer);
                if (MainRenderFrame != null)
                {
                    previousWidth = MainRenderFrame.Width;
                    previousHeight = MainRenderFrame.Height;
                }
            }

            // Create the drawing context
            renderContext = RenderContext.GetShared(Services);
            renderDrawContext = new RenderDrawContext(Services, renderContext, graphicsContext);
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutationsImpl(RenderDrawContext context)
        {
            var renderEffects = RenderData.GetData(RenderEffectKey);

            foreach (var renderObject in RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                for (int i = 0; i < EffectPermutationSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * EffectPermutationSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];
                    var renderSkybox = (RenderSkybox)renderObject;

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    var parameters = renderSkybox.Background == SkyboxBackground.Irradiance ? renderSkybox.Skybox.DiffuseLightingParameters : renderSkybox.Skybox.Parameters;

                    var shader = parameters.Get(SkyboxKeys.Shader);

                    if (shader == null)
                    {
                        renderEffect.EffectValidator.ShouldSkip = true;
                    }
                    renderEffect.EffectValidator.ValidateParameter(SkyboxKeys.Shader, shader);
                }
            }

            transformRenderFeature.PrepareEffectPermutations(context);
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            if (string.IsNullOrEmpty(ShaderSourceName))
                return;

            Parameters.Set(ComputeEffectShaderKeys.ThreadNumbers, ThreadNumbers);
            Parameters.Set(ComputeEffectShaderKeys.ComputeShaderName, ShaderSourceName);
            Parameters.Set(ComputeShaderBaseKeys.ThreadGroupCountGlobal, ThreadGroupCounts);

            if (EffectInstance.UpdateEffect(GraphicsDevice) || pipelineStateDirty || previousBytecode != EffectInstance.Effect.Bytecode)
            {
                // The EffectInstance might have been updated from outside
                previousBytecode = EffectInstance.Effect.Bytecode;

                pipelineState.State.SetDefaults();
                pipelineState.State.RootSignature = EffectInstance.RootSignature;
                pipelineState.State.EffectBytecode = EffectInstance.Effect.Bytecode;
                pipelineState.Update();
                pipelineStateDirty = false;
            }

            // Apply pipeline state
            context.CommandList.SetPipelineState(pipelineState.CurrentState);

            // Apply the effect
            EffectInstance.Apply(context.GraphicsContext);

            // Draw a full screen quad
            context.CommandList.Dispatch(ThreadGroupCounts.X, ThreadGroupCounts.Y, ThreadGroupCounts.Z);

            // Un-apply
            //throw new InvalidOperationException();
            //EffectInstance.Effect.UnbindResources(GraphicsDevice);
        }
Exemple #6
0
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey);
            int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            foreach (var renderObject in RootRenderFeature.RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;
                var renderMesh = (RenderMesh)renderObject;

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    // Generate shader permuatations
                    renderEffect.EffectValidator.ValidateParameter(GameParameters.EnableBend, renderMesh.Mesh.Parameters.Get(GameParameters.EnableBend));
                    renderEffect.EffectValidator.ValidateParameter(GameParameters.EnableFog, renderMesh.Mesh.Parameters.Get(GameParameters.EnableFog));
                    renderEffect.EffectValidator.ValidateParameter(GameParameters.EnableOnflyTextureUVChange, renderMesh.Mesh.Parameters.Get(GameParameters.EnableOnflyTextureUVChange));
                }
            }
        }
        protected override void PreDrawCore(RenderDrawContext context)
        {
            base.PreDrawCore(context);

            // Default handler for parameters
            UpdateParameters();
        }
Exemple #8
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey);
            int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            foreach (var renderObject in RootRenderFeature.RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];
                    var renderMesh = (RenderMesh)renderObject;

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    if (renderMesh.Mesh.Skinning != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningPosition, renderMesh.Mesh.Parameters.Get(MaterialKeys.HasSkinningPosition));
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningNormal, renderMesh.Mesh.Parameters.Get(MaterialKeys.HasSkinningNormal));
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningTangent, renderMesh.Mesh.Parameters.Get(MaterialKeys.HasSkinningTangent));

                        var skinningBones = Math.Max(MaxBones, renderMesh.Mesh.Skinning.Bones.Length);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.SkinningMaxBones, skinningBones);
                    }
                }
            }
        }
        protected override void DrawCore(RenderDrawContext context, RenderFrame output)
        {
            var commandList = context.CommandList;

            // clear the targets
            if (output.DepthStencil != null && (ClearFlags == ClearRenderFrameFlags.ColorAndDepth || ClearFlags == ClearRenderFrameFlags.DepthOnly))
            {
                const DepthStencilClearOptions ClearOptions = DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil;
                commandList.Clear(output.DepthStencil, ClearOptions, Depth, Stencil);
            }

            if (ClearFlags == ClearRenderFrameFlags.ColorAndDepth || ClearFlags == ClearRenderFrameFlags.ColorOnly)
            {
                foreach (var renderTarget in output.RenderTargets)
                {
                    if (renderTarget != null)
                    {
                        // If color is in GammeSpace and rendertarget is either SRgb or HDR, use a linear value to clear the buffer.
                        // TODO: We will need to move this color transform code to a shareable component
                        var color = Color.ToColorSpace(ColorSpace, (renderTarget.Format.IsSRgb() || renderTarget.Format.IsHDR()) ? ColorSpace.Linear : context.GraphicsDevice.ColorSpace);
                        commandList.Clear(renderTarget, color);
                    }
                }
            }
        }
 protected override void DrawCore(RenderDrawContext context)
 {
     using (context.RenderContext.PushTagAndRestore(SceneCameraSlotCollection.Current, Cameras))
     {
         base.DrawCore(context);
     }
 }
        protected override void DrawCore(RenderDrawContext context, RenderFrame output)
        {
            var input = Input.GetSafeRenderFrame(context.RenderContext);

            // If RenderFrame input or output are null, we can't do anything
            if (input == null)
            {
                return;
            }

            // If an effect is set, we are using it
            if (Effect != null)
            {
                Effect.SetInput(0, input);
                if (input.DepthStencil != null)
                {
                    Effect.SetInput(1, input.DepthStencil);
                }
                Effect.SetOutput(output);
                Effect.Draw(context);
            }
            else if (input != output)
            {
                // Else only use a scaler if input and output don't match
                // TODO: Is this something we want by default or we just don't output anything?
                var effect = context.GetSharedEffect<ImageScaler>();
                effect.SetInput(0, input);
                effect.SetOutput(output);
                ((RendererBase)effect).Draw(context);
            }

            // Switch back last output as render target
            context.CommandList.ResourceBarrierTransition(output, GraphicsResourceState.RenderTarget);
        }
 protected override void PreDrawCore(RenderDrawContext context)
 {
     base.PreDrawCore(context);
     int value = InputCount;
     Parameters.Set(FactorCount, value);
     Parameters.Set(ColorCombinerShaderKeys.Factors, factors);
     Parameters.Set(ColorCombinerShaderKeys.ModulateRGB, ModulateRGB);
 }
Exemple #13
0
 /// <summary>
 /// Activates the output to the current <see cref="GraphicsDevice"/>.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <param name="disableDepth">if set to <c>true</c> [disable depth].</param>
 public void ActivateOutput(RenderDrawContext context, bool disableDepth = false)
 {
     var output = GetOutput(context.RenderContext);
     if (output != null)
     {
         ActivateOutputCore(context, output, disableDepth);
     }
 }
        private void RenderQuad(RenderDrawContext renderContext, RenderFrame frame)
        {
            customEffectInstance.Parameters.Set(EffectKeys.Phase, -3 * (float)Game.UpdateTime.Total.TotalSeconds);

            spriteBatch.Begin(renderContext.GraphicsContext, blendState: BlendStates.NonPremultiplied, depthStencilState: DepthStencilStates.None, effect: customEffectInstance);
            spriteBatch.Draw(Logo, new RectangleF(0, 0, 1, 1), Color.White);
            spriteBatch.End();
        }
        protected override void DrawCore(RenderDrawContext context, RenderFrame output)
        {
            var sceneInstance = GetChildSceneInstance();
            if (sceneInstance == null)
                return;

            // Draw scene recursively
            sceneInstance.Draw(context, output, GraphicsCompositorOverride);
        }
 /// <summary>
 /// Draws this renderer with the specified context.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <exception cref="System.ArgumentNullException">context</exception>
 /// <exception cref="System.InvalidOperationException">Cannot use a different context between Load and Draw</exception>
 public void Draw(RenderDrawContext context)
 {
     if (Enabled)
     {
         PreDrawCoreInternal(context);
         DrawCore(context);
         PostDrawCoreInternal(context);
     }
 }
Exemple #17
0
        /// <inheritdoc/>
        public override void Prepare(RenderDrawContext context)
        {
            base.Prepare(context);

            // Prepare each sub render feature
            foreach (var renderFeature in RenderFeatures)
            {
                renderFeature.Prepare(context);
            }
        }
        protected override void Draw(GameTime gameTime)
        {
            if (!ScreenShotAutomationEnabled)
                AdjustEffectParameters();

            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);
            DrawCustomEffect(renderDrawContext);

            base.Draw(gameTime);
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            var input = GetInput(0);
            var output = GetOutput(0);

            if (FadeOutSpeed == 0f)
            {
                // Nothing to do
                if (input != output)
                {
                    context.CommandList.Copy(input, output);
                }
                return;
            }

            if (input == output)
            {
                var newInput = NewScopedRenderTarget2D(input.Description);
                context.CommandList.Copy(input, newInput);
                input = newInput;
            }

            // Check we have a render target to hold the persistence over a few frames
            if (persistenceTexture == null || persistenceTexture.Description != output.Description)
            {
                // We need to re-allocate the texture
                if (persistenceTexture != null)
                {
                    Context.Allocator.ReleaseReference(persistenceTexture);
                }

                persistenceTexture = Context.Allocator.GetTemporaryTexture2D(output.Description);
                // Initializes to black
                context.CommandList.Clear(persistenceTexture, Color.Black);
            }

            var accumulationPersistence = NewScopedRenderTarget2D(persistenceTexture.Description);

            // For persistence, we combine the current brightness with the one of the previous frames.
            bloomAfterimageShader.Parameters.Set(BloomAfterimageShaderKeys.FadeOutSpeed, FadeOutSpeed);
            bloomAfterimageShader.Parameters.Set(BloomAfterimageShaderKeys.Sensitivity, Sensitivity / 100f);
            bloomAfterimageShader.SetInput(0, input);
            bloomAfterimageShader.SetInput(1, persistenceTexture);
            bloomAfterimageShader.SetOutput(accumulationPersistence);
            bloomAfterimageShader.Draw(context, "Afterimage persistence accumulation");

            // Keep the final brightness buffer for the following frames
            context.CommandList.Copy(accumulationPersistence, persistenceTexture);

            // Merge persistence and current bloom into the final result
            bloomAfterimageCombineShader.SetInput(0, input);
            bloomAfterimageCombineShader.SetInput(1, persistenceTexture);
            bloomAfterimageCombineShader.SetOutput(output);
            bloomAfterimageCombineShader.Draw(context, "Afterimage persistence combine");
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            var output = PrefilteredRadiance;
            if (output == null || (output.Dimension != TextureDimension.Texture2D && output.Dimension != TextureDimension.TextureCube) || output.ArraySize != 6)
                throw new NotSupportedException("Only array of 2D textures are currently supported as output");

            if (!output.IsRenderTarget)
                throw new NotSupportedException("Only render targets are supported as output");

            var input = RadianceMap;
            if (input == null || input.Dimension != TextureDimension.TextureCube)
                throw new NotSupportedException("Only cubemaps are currently supported as input");

            var roughness = 0f;
            var faceCount = output.ArraySize;
            var levelSize = new Int2(output.Width, output.Height);
            var mipCount = MipmapGenerationCount == 0 ? output.MipLevels : MipmapGenerationCount;

            for (int mipLevel = 0; mipLevel < mipCount; mipLevel++)
            {
                if (mipLevel == 0 && DoNotFilterHighestLevel && input.Width >= output.Width)
                {
                    var inputLevel = MathUtil.Log2(input.Width / output.Width);
                    for (int faceIndex = 0; faceIndex < 6; faceIndex++)
                    {
                        var inputSubresource = inputLevel + faceIndex * input.MipLevels;
                        var outputSubresource = 0 + faceIndex * output.MipLevels;
                        context.CommandList.CopyRegion(input, inputSubresource, null, output, outputSubresource);
                    }
                }
                else
                {
                    for (int faceIndex = 0; faceIndex < faceCount; faceIndex++)
                    {
                        using (var outputView = output.ToTextureView(ViewType.Single, faceIndex, mipLevel))
                        {
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.Face, faceIndex);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.Roughness, roughness);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.MipmapCount, input.MipLevels - 1);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.RadianceMap, input);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeShaderKeys.RadianceMapSize, input.Width);
                            shader.Parameters.Set(RadiancePrefilteringGGXNoComputeParams.NbOfSamplings, SamplingsCount);
                            shader.SetOutput(outputView);
                            ((RendererBase)shader).Draw(context);
                        }
                    }
                }

                if (mipCount > 1)
                {
                    roughness += 1f / (mipCount - 1);
                    levelSize /= 2;
                }
            }
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            var output = PrefilteredRadiance;
            if(output == null || (output.Dimension != TextureDimension.Texture2D && output.Dimension != TextureDimension.TextureCube) || output.ArraySize != 6)
                throw new NotSupportedException("Only array of 2D textures are currently supported as output");

            if (!output.IsUnorderedAccess || output.IsRenderTarget)
                throw new NotSupportedException("Only non-rendertarget unordered access textures are supported as output");

            var input = RadianceMap;
            if(input == null || input.Dimension != TextureDimension.TextureCube)
                throw new NotSupportedException("Only cubemaps are currently supported as input");

            var roughness = 0f;
            var faceCount = output.ArraySize;
            var levelSize = new Int2(output.Width, output.Height);
            var mipCount = MipmapGenerationCount == 0 ? output.MipLevels : MipmapGenerationCount;

            for (int l = 0; l < mipCount; l++)
            {
                if (l == 0 && DoNotFilterHighestLevel && input.Width >= output.Width)
                {
                    var inputLevel = MathUtil.Log2(input.Width / output.Width);
                    for (int f = 0; f < 6; f++)
                    {
                        var inputSubresource = inputLevel + f * input.MipLevels;
                        var outputSubresource = 0 + f * output.MipLevels;
                        context.CommandList.CopyRegion(input, inputSubresource, null, output, outputSubresource);
                    }
                }
                else
                {
                    var outputView = output.ToTextureView(ViewType.MipBand, 0, l);

                    computeShader.ThreadGroupCounts = new Int3(levelSize.X, levelSize.Y, faceCount);
                    computeShader.ThreadNumbers = new Int3(SamplingsCount, 1, 1);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.Roughness, roughness);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.MipmapCount, input.MipLevels - 1);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.RadianceMap, input);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.RadianceMapSize, input.Width);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXShaderKeys.FilteredRadiance, outputView);
                    computeShader.Parameters.Set(RadiancePrefilteringGGXParams.NbOfSamplings, SamplingsCount);
                    ((RendererBase)computeShader).Draw(context);

                    outputView.Dispose();
                }

                if (mipCount > 1)
                {
                    roughness += 1f / (mipCount - 1);
                    levelSize /= 2;
                }
            }
        }
        /// <summary>
        /// Activates the output to the current <see cref="GraphicsDevice" />.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="output">The output.</param>
        /// <param name="disableDepth">if set to <c>true</c> [disable depth].</param>
        protected virtual void ActivateOutputCore(RenderDrawContext context, RenderFrame output, bool disableDepth)
        {
            // Set default render target states
            foreach (var renderTarget in output.RenderTargets)
            {
                context.CommandList.ResourceBarrierTransition(renderTarget, GraphicsResourceState.RenderTarget);
            }
            context.CommandList.ResourceBarrierTransition(output.DepthStencil, GraphicsResourceState.DepthWrite);

            // Setup the render target
            context.CommandList.SetRenderTargetsAndViewport(disableDepth ? null : output.DepthStencil, output.RenderTargets);
        }
        protected override void DrawCore(RenderDrawContext context)
        {
            var inputTexture = GetSafeInput(0);

            // Output pixel format
            PixelFormat outputPixelFormat;
            // Scaling direction (<0 downscale, >0 upscale)
            int scalingDirection;

            // Validate and Prepare scaling 
            if (!PrepareScaling(inputTexture, out scalingDirection, out outputPixelFormat))
            {
                return;
            }

            // Make sure that we are using a clean Scaler.
            Scaler.Reset();

            var nextSize = inputTexture.Size;
            nextSize.Depth = 1;

            var previousMipMap = inputTexture;
            int matchOutputCount = 0;
            while (matchOutputCount != outputTextures.Count)
            {
                nextSize = nextSize.Mip(scalingDirection);
                var mipmap = FindOutputMatchingSize(nextSize, scalingDirection);
                if (mipmap != null)
                {
                    matchOutputCount++;

                    // The size is now the intermediate texture
                    nextSize = mipmap.Size;
                }
                else
                {
                    mipmap = NewScopedRenderTarget2D(nextSize.Width, nextSize.Height, outputPixelFormat, 1);
                }

                // Down or UpScale
                Scaler.SetInput(previousMipMap);
                Scaler.SetOutput(mipmap);
                Scaler.Draw(context, name: scalingDirection < 0 ? "Down2" : "Up2");

                previousMipMap = mipmap;
            }

            // Cleanup output textures so that we don't hold a reference
            outputTextures.Clear();
        }
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var skinningInfos = RootRenderFeature.RenderData.GetData(skinningInfoKey);

            var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey);
            int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            //foreach (var objectNodeReference in RootRenderFeature.ObjectNodeReferences)
            Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).ObjectNodeReferences, objectNodeReference =>
            {
                var objectNode = RootRenderFeature.GetObjectNode(objectNodeReference);
                var renderMesh = (RenderMesh)objectNode.RenderObject;
                var staticObjectNode = renderMesh.StaticObjectNode;

                var skinningInfo = skinningInfos[staticObjectNode];
                var parameters = renderMesh.Mesh.Parameters;
                if (parameters != skinningInfo.Parameters || parameters.PermutationCounter != skinningInfo.PermutationCounter)
                {
                    skinningInfo.Parameters = parameters;
                    skinningInfo.PermutationCounter = parameters.PermutationCounter;

                    skinningInfo.HasSkinningPosition = parameters.Get(MaterialKeys.HasSkinningPosition);
                    skinningInfo.HasSkinningNormal = parameters.Get(MaterialKeys.HasSkinningNormal);
                    skinningInfo.HasSkinningTangent = parameters.Get(MaterialKeys.HasSkinningTangent);

                    skinningInfos[staticObjectNode] = skinningInfo;
                }

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    if (renderMesh.Mesh.Skinning != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningPosition, skinningInfo.HasSkinningPosition);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningNormal, skinningInfo.HasSkinningNormal);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasSkinningTangent, skinningInfo.HasSkinningTangent);

                        var skinningBones = Math.Max(MaxBones, renderMesh.Mesh.Skinning.Bones.Length);
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.SkinningMaxBones, skinningBones);
                    }
                }
            });
        }
        /// <inheritdoc/>
        public override void PrepareEffectPermutationsImpl(RenderDrawContext context)
        {
            base.PrepareEffectPermutationsImpl(context);

            var renderEffects = RenderData.GetData(renderEffectKey);
            int effectSlotCount = EffectPermutationSlotCount;

            // Update existing materials
            foreach (var material in allMaterialInfos)
            {
                material.Key.Setup(RenderSystem.RenderContextOld);
            }

            foreach (var renderObject in RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;

                var material = renderParticleEmitter.ParticleEmitter.Material;
                var materialInfo = renderParticleEmitter.ParticleMaterialInfo;

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    if (materialInfo == null || materialInfo.Material != material)
                    {
                        // First time this material is initialized, let's create associated info
                        if (!allMaterialInfos.TryGetValue(material, out materialInfo))
                        {
                            materialInfo = new ParticleMaterialInfo(material);
                            allMaterialInfos.Add(material, materialInfo);
                        }
                        renderParticleEmitter.ParticleMaterialInfo = materialInfo;

                        // Update new materials
                        material.Setup(RenderSystem.RenderContextOld);
                    }

                    // TODO: Iterate PermuatationParameters automatically?
                    material.ValidateEffect(RenderSystem.RenderContextOld, ref renderEffect.EffectValidator);
                }
            }
        }
Exemple #26
0
 public SkyboxGeneratorContext(SkyboxAsset skybox)
 {
     if (skybox == null) throw new ArgumentNullException(nameof(skybox));
     Skybox = skybox;
     Services = new ServiceRegistry();
     Content = new ContentManager(Services);
     GraphicsDevice = GraphicsDevice.New();
     GraphicsDeviceService = new GraphicsDeviceServiceLocal(Services, GraphicsDevice);
     EffectSystem = new EffectSystem(Services);
     EffectSystem.Initialize();
     ((IContentable)EffectSystem).LoadContent();
     ((EffectCompilerCache)EffectSystem.Compiler).CompileEffectAsynchronously = false;
     RenderContext = RenderContext.GetShared(Services);
     RenderDrawContext = new RenderDrawContext(Services, RenderContext, new GraphicsContext(new CommandList(GraphicsDevice), new ResourceGroupAllocator(GraphicsDevice)));
 }
        protected override void Draw(GameTime gameTime)
        {
            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);

            GraphicsContext.CommandList.Clear(output, Color4.White);
            renderHammersley.ThreadGroupCounts = new Int3(samplesCount, 1, 1);
            renderHammersley.ThreadNumbers = new Int3(1);
            renderHammersley.Parameters.Set(HammersleyTestKeys.OutputTexture, output);
            renderHammersley.Parameters.Set(HammersleyTestKeys.SamplesCount, samplesCount);
            renderHammersley.Draw(renderDrawContext);

            GraphicsContext.DrawTexture(output);

            base.Draw(gameTime);
        }
        protected override void Draw(GameTime gameTime)
        {
            var renderDrawContext = new RenderDrawContext(Services, RenderContext.GetShared(Services), GraphicsContext);

            computeShaderEffect.Parameters.Set(ComputeShaderTestParams.NbOfIterations, ReductionRatio);
            computeShaderEffect.Parameters.Set(ComputeShaderTestKeys.input, inputTexture);
            computeShaderEffect.Parameters.Set(ComputeShaderTestKeys.output, outputTexture);
            computeShaderEffect.Draw(renderDrawContext);

            if (displayedTexture == null || spriteBatch == null)
                return;

            GraphicsContext.DrawTexture(displayedTexture);

            base.Draw(gameTime);
        }
 protected override void DrawCore(RenderDrawContext context)
 {
     var input = GetInput(0);
     var output = GetOutput(0);
     if (input == null || output == null)
     {
         return;
     }
 
     brightPassFilter.Parameters.Set(BrightFilterShaderKeys.BrightPassThreshold, Threshold);
     brightPassFilter.Parameters.Set(BrightFilterShaderKeys.ColorModulator, Color.ToColorSpace(GraphicsDevice.ColorSpace));
     
     brightPassFilter.SetInput(input);
     brightPassFilter.SetOutput(output);
     ((RendererBase)brightPassFilter).Draw(context);
 }
Exemple #30
0
        protected override void DrawCore(RenderDrawContext context)
        {
            // Make sure we keep our uniform weights in synchronization with the number of taps
            if (tapWeights == null || tapWeights.Length != tapCount)
            {
                tapWeights = DoFUtil.GetUniformWeightBlurArray(tapCount);
            }

            if (!useOptimizedPath)
            {
                DrawCoreNaive(context);
            }
            else
            {
                DrawCoreOptimized(context);
            }
        }
 public virtual void ApplyDrawParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights, ref BoundingBoxExt boundingBox)
 {
 }
Exemple #32
0
        protected override void DrawCore(RenderDrawContext context)
        {
            if (lightShaftProcessor == null || lightShaftBoundingVolumeProcessor == null)
            {
                return; // Not collected
            }
            if (LightBufferDownsampleLevel < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(LightBufferDownsampleLevel));
            }
            if (BoundingVolumeBufferDownsampleLevel < 1)
            {
                throw new ArgumentOutOfRangeException(nameof(BoundingVolumeBufferDownsampleLevel));
            }

            var lightShaftDatas = lightShaftProcessor.LightShafts;

            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 lightShaftDatas)
            {
                if (lightShaft.LightComponent == 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.LightComponent);
                SetupLight(context, lightShaft, shadowMapTexture, lightShaftsParameters);

                var boundingVolumes = lightShaftBoundingVolumeProcessor.GetBoundingVolumesForComponent(lightShaft.Component);
                if (boundingVolumes == null)
                {
                    continue;
                }

                // Check if we can pack bounding volumes together or need to draw them one by one
                var boundingVolumeLoop = lightShaft.SeparateBoundingVolumes ? 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 : boundingVolumes;
                    if (lightShaft.SeparateBoundingVolumes)
                    {
                        singleBoundingVolume[0] = 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.Light.ComputeColor(context.GraphicsDevice.ColorSpace, lightShaft.LightComponent.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 #33
0
 public void Flush(RenderDrawContext context)
 {
     RenderViewsWithShadows.Clear();
 }
Exemple #34
0
 /// <summary>
 /// Main drawing method for this renderer that must be implemented.
 /// </summary>
 /// <param name="context"></param>
 /// <param name="drawContext"></param>
 protected abstract void DrawCore(RenderContext context, RenderDrawContext drawContext);
Exemple #35
0
        protected override void DrawCore(RenderDrawContext context)
        {
            // Inputs:
            Texture colorBuffer             = GetSafeInput(0);
            Texture depthBuffer             = GetSafeInput(1);
            Texture normalsBuffer           = GetSafeInput(2);
            Texture specularRoughnessBuffer = GetSafeInput(3);

            // Output:
            Texture outputBuffer = GetSafeOutput(0);

            // Prepare
            var temporalCache = Prepare(context, outputBuffer);

            FlushCache(context.RenderContext.Time.FrameCount);

            // Get temporary buffers
            var     rayTraceBuffersSize = GetBufferResolution(outputBuffer, RayTracePassResolution);
            var     resolveBuffersSize  = GetBufferResolution(outputBuffer, ResolvePassResolution);
            Texture rayTraceBuffer      = NewScopedRenderTarget2D(rayTraceBuffersSize.Width, rayTraceBuffersSize.Height, RayTraceTargetFormat, 1);
            Texture resolveBuffer       = NewScopedRenderTarget2D(resolveBuffersSize.Width, resolveBuffersSize.Height, ReflectionsFormat, 1);

            // Check if resize depth
            Texture smallerDepthBuffer = depthBuffer;

            if (DepthResolution != ResolutionMode.Full)
            {
                // Smaller depth buffer improves ray tracing performance.

                var depthBuffersSize = GetBufferResolution(depthBuffer, DepthResolution);
                smallerDepthBuffer = NewScopedRenderTarget2D(depthBuffersSize.Width, depthBuffersSize.Height, PixelFormat.R32_Float, 1);

                depthPassShader.SetInput(0, depthBuffer);
                depthPassShader.SetOutput(smallerDepthBuffer);
                depthPassShader.Draw(context, "Downscale Depth");
            }

            // Blur Pass
            Texture blurPassBuffer;

            if (UseColorBufferMips)
            {
                // Note: using color buffer mips maps helps with reducing artifacts
                // and improves resolve pass performance (faster color texture lookups, less cache misses)
                // Also for high surface roughness values it adds more blur to the reflection tail which looks more realistic.

                // Get temp targets
                var     colorBuffersSize      = new Size2(outputBuffer.Width / 2, outputBuffer.Height / 2);
                int     colorBuffersMips      = Texture.CalculateMipMapCount(MipMapCount.Auto, colorBuffersSize.Width, colorBuffersSize.Height);
                Texture colorBuffer0          = NewScopedRenderTarget2D(colorBuffersSize.Width, colorBuffersSize.Height, ReflectionsFormat, colorBuffersMips);
                Texture colorBuffer1          = NewScopedRenderTarget2D(colorBuffersSize.Width / 2, colorBuffersSize.Height / 2, ReflectionsFormat, colorBuffersMips - 1);
                int     colorBuffer1MipOffset = 1; // For colorBuffer1 we could use one mip less (optimized)

                // Cache per color buffer mip views
                int colorBuffer0Mips = colorBuffer0.MipLevels;
                if (cachedColorBuffer0Mips == null || cachedColorBuffer0Mips.Length != colorBuffer0Mips || cachedColorBuffer0Mips[0].ParentTexture != colorBuffer0)
                {
                    cachedColorBuffer0Mips?.ForEach(view => view?.Dispose());
                    cachedColorBuffer0Mips = new Texture[colorBuffer0Mips];
                    for (int mipIndex = 0; mipIndex < colorBuffer0Mips; mipIndex++)
                    {
                        cachedColorBuffer0Mips[mipIndex] = colorBuffer0.ToTextureView(ViewType.Single, 0, mipIndex);
                    }
                }
                int colorBuffer1Mips = colorBuffer1.MipLevels;
                if (cachedColorBuffer1Mips == null || cachedColorBuffer1Mips.Length != colorBuffer1Mips || cachedColorBuffer1Mips[0].ParentTexture != colorBuffer1)
                {
                    cachedColorBuffer1Mips?.ForEach(view => view?.Dispose());
                    cachedColorBuffer1Mips = new Texture[colorBuffer1Mips];
                    for (int mipIndex = 0; mipIndex < colorBuffer1Mips; mipIndex++)
                    {
                        cachedColorBuffer1Mips[mipIndex] = colorBuffer1.ToTextureView(ViewType.Single, 0, mipIndex);
                    }
                }

                // Clone scene frame to mip 0 of colorBuffer0
                Scaler.SetInput(0, colorBuffer);
                Scaler.SetOutput(cachedColorBuffer0Mips[0]);
                Scaler.Draw(context, "Copy frame");

                // Downscale with gaussian blur
                for (int mipLevel = 1; mipLevel < colorBuffersMips; mipLevel++)
                {
                    // Blur H
                    var srcMip = cachedColorBuffer0Mips[mipLevel - 1];
                    var dstMip = cachedColorBuffer1Mips[mipLevel - colorBuffer1MipOffset];
                    blurPassShaderH.SetInput(0, srcMip);
                    blurPassShaderH.SetOutput(dstMip);
                    blurPassShaderH.Draw(context, "Blur H");

                    // Blur V
                    srcMip = dstMip;
                    dstMip = cachedColorBuffer0Mips[mipLevel];
                    blurPassShaderV.SetInput(0, srcMip);
                    blurPassShaderV.SetOutput(dstMip);
                    blurPassShaderV.Draw(context, "Blur V");
                }

                blurPassBuffer = colorBuffer0;
            }
            else
            {
                // Don't use color buffer with mip maps
                blurPassBuffer = colorBuffer;

                cachedColorBuffer0Mips?.ForEach(view => view?.Dispose());
                cachedColorBuffer1Mips?.ForEach(view => view?.Dispose());
            }

            // Ray Trace Pass
            rayTracePassShader.SetInput(0, colorBuffer);
            rayTracePassShader.SetInput(1, smallerDepthBuffer);
            rayTracePassShader.SetInput(2, normalsBuffer);
            rayTracePassShader.SetInput(3, specularRoughnessBuffer);
            rayTracePassShader.SetOutput(rayTraceBuffer);
            rayTracePassShader.Draw(context, "Ray Trace");

            // Resolve Pass
            resolvePassShader.SetInput(0, blurPassBuffer);
            resolvePassShader.SetInput(1, ResolvePassResolution == ResolutionMode.Full ? depthBuffer : smallerDepthBuffer);
            resolvePassShader.SetInput(2, normalsBuffer);
            resolvePassShader.SetInput(3, specularRoughnessBuffer);
            resolvePassShader.SetInput(4, rayTraceBuffer);
            resolvePassShader.SetOutput(resolveBuffer);
            resolvePassShader.Draw(context, "Resolve");

            // Temporal Pass
            Texture reflectionsBuffer = resolveBuffer;

            if (TemporalEffect)
            {
                var temporalSize = outputBuffer.Size;
                temporalCache.Resize(GraphicsDevice, ref temporalSize);
                Texture temporalBuffer0 = NewScopedRenderTarget2D(temporalSize.Width, temporalSize.Height, ReflectionsFormat, 1);

                temporalPassShader.SetInput(0, resolveBuffer);
                temporalPassShader.SetInput(1, temporalCache.TemporalBuffer);
                temporalPassShader.SetInput(2, depthBuffer);
                temporalPassShader.SetOutput(temporalBuffer0);
                temporalPassShader.Draw(context, "Temporal");

                context.CommandList.Copy(temporalBuffer0, temporalCache.TemporalBuffer); // TODO: use Texture.Swap from ContentStreaming branch to make it faster!

                reflectionsBuffer = temporalCache.TemporalBuffer;
            }

            // Combine Pass
            combinePassShader.SetInput(0, colorBuffer);
            combinePassShader.SetInput(1, depthBuffer);
            combinePassShader.SetInput(2, normalsBuffer);
            combinePassShader.SetInput(3, specularRoughnessBuffer);
            combinePassShader.SetInput(4, reflectionsBuffer);
            combinePassShader.SetOutput(outputBuffer);
            combinePassShader.Draw(context, "Combine");

#if SSLR_DEBUG
            if (DebugMode != DebugModes.None)
            {
                // Debug preview of temp targets
                switch (DebugMode)
                {
                case DebugModes.RayTrace:
                    Scaler.SetInput(0, rayTraceBuffer);
                    break;

                case DebugModes.Resolve:
                    Scaler.SetInput(0, resolveBuffer);
                    break;

                case DebugModes.Temporal:
                    if (temporalCache != null)
                    {
                        Scaler.SetInput(0, temporalCache.TemporalBuffer);
                    }
                    break;
                }
                Scaler.SetOutput(outputBuffer);
                Scaler.Draw(context);
            }
#endif
        }
Exemple #36
0
 public abstract void PostProcess(RenderDrawContext drawContext);
            public unsafe void AllocateBuffers(RenderDrawContext renderDrawContext, int vertexBufferSize, int requiredIndexCount)
            {
                // Build the shared vertex buffer - every frame
                if (vertexBufferSize > 0)
                {
                    {
                        vertexBufferSize--;
                        vertexBufferSize |= vertexBufferSize >> 1;
                        vertexBufferSize |= vertexBufferSize >> 2;
                        vertexBufferSize |= vertexBufferSize >> 3;
                        vertexBufferSize |= vertexBufferSize >> 8;
                        vertexBufferSize |= vertexBufferSize >> 16;
                        vertexBufferSize++;
                    }

                    VertexBufferSize = vertexBufferSize;

                    VertexBuffer = renderDrawContext.GraphicsContext.Allocator.GetTemporaryBuffer(
                        new BufferDescription(VertexBufferSize, BufferFlags.VertexBuffer, GraphicsResourceUsage.Dynamic));
                }

                // Build the shared index buffer - only when necessary
                var requiredIndexBufferSize = requiredIndexCount * IndexStride;

                if (requiredIndexBufferSize > IndexBufferSize)
                {
                    if (IndexBuffer != null)
                    {
                        renderDrawContext.GraphicsContext.Allocator.ReleaseReference(IndexBuffer);
                        IndexBuffer = null;
                    }

                    //  We start allocating from 64K (allowing 32K indices to be written at once - this is most probably going to be sufficient in all cases)
                    IndexBufferSize = requiredIndexBufferSize;
                    if (IndexBufferSize < 64 * 1024)
                    {
                        IndexBufferSize = 64 * 1024;
                    }

                    {
                        IndexBufferSize--;
                        IndexBufferSize |= IndexBufferSize >> 1;
                        IndexBufferSize |= IndexBufferSize >> 2;
                        IndexBufferSize |= IndexBufferSize >> 3;
                        IndexBufferSize |= IndexBufferSize >> 8;
                        IndexBufferSize |= IndexBufferSize >> 16;
                        IndexBufferSize++;
                    }

                    IndexBuffer = renderDrawContext.GraphicsContext.Allocator.GetTemporaryBuffer(
                        new BufferDescription(IndexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic));

                    var indexCount = IndexBufferSize / IndexStride;
                    indexCount = ((indexCount / 6) * 6);
                    {
                        var commandList = renderDrawContext.CommandList;

                        var mappedIndices = commandList.MapSubresource(IndexBuffer, 0, MapMode.WriteNoOverwrite, false, 0, IndexBufferSize);
                        var indexPointer  = mappedIndices.DataBox.DataPointer;

                        int indexStructSize = sizeof(short);
                        int verticesPerQuad = 4;

                        var k = 0;
                        for (var i = 0; i < indexCount; k += verticesPerQuad)
                        {
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 0);
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 1);
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 2);
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 0);
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 2);
                            *(short *)(indexPointer + indexStructSize * i++) = (short)(k + 3);
                        }

                        commandList.UnmapSubresource(mappedIndices);
                    }
                }
            }
Exemple #38
0
        private bool DrawBoundingVolumes(RenderDrawContext context, IReadOnlyList <LightShaftBoundingVolumeProcessor.Data> boundingVolumes, Matrix viewProjection)
        {
            var commandList = context.CommandList;

            bool effectUpdated = minmaxVolumeEffectShader.UpdateEffect(GraphicsDevice);

            if (minmaxVolumeEffectShader.Effect == null)
            {
                return(false);
            }

            var  needEffectUpdate = effectUpdated || previousMinmaxEffectBytecode != minmaxVolumeEffectShader.Effect.Bytecode;
            bool visibleMeshes    = false;

            for (int pass = 0; pass < 2; ++pass)
            {
                var minmaxPipelineState = minmaxPipelineStates[pass];

                bool pipelineDirty = false;
                if (needEffectUpdate)
                {
                    // The EffectInstance might have been updated from outside
                    previousMinmaxEffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.RootSignature  = minmaxVolumeEffectShader.RootSignature;
                    minmaxPipelineState.State.EffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.Output.RenderTargetCount   = 1;
                    minmaxPipelineState.State.Output.RenderTargetFormat0 = commandList.RenderTarget.Format;
                    pipelineDirty = true;
                }

                MeshDraw currentDraw = null;
                var      frustum     = new BoundingFrustum(ref viewProjection);
                foreach (var volume in boundingVolumes)
                {
                    if (volume.Model == null)
                    {
                        continue;
                    }

                    // Update parameters for the minmax shader
                    Matrix worldViewProjection = Matrix.Multiply(volume.World, viewProjection);
                    minmaxVolumeEffectShader.Parameters.Set(VolumeMinMaxShaderKeys.WorldViewProjection, worldViewProjection);

                    foreach (var mesh in volume.Model.Meshes)
                    {
                        // Frustum culling
                        BoundingBox meshBoundingBox;
                        Matrix      world = volume.World;
                        BoundingBox.Transform(ref mesh.BoundingBox, ref world, out meshBoundingBox);
                        var boundingBoxExt = new BoundingBoxExt(meshBoundingBox);
                        if (boundingBoxExt.Extent != Vector3.Zero &&
                            !VisibilityGroup.FrustumContainsBox(ref frustum, ref boundingBoxExt, true))
                        {
                            continue;
                        }

                        visibleMeshes = true;

                        var draw = mesh.Draw;

                        if (currentDraw != draw)
                        {
                            if (minmaxPipelineState.State.PrimitiveType != draw.PrimitiveType)
                            {
                                minmaxPipelineState.State.PrimitiveType = draw.PrimitiveType;
                                pipelineDirty = true;
                            }

                            var inputElements = draw.VertexBuffers.CreateInputElements();
                            if (inputElements.ComputeHash() != minmaxPipelineState.State.InputElements.ComputeHash())
                            {
                                minmaxPipelineState.State.InputElements = inputElements;
                                pipelineDirty = true;
                            }

                            // Update mesh
                            for (int i = 0; i < draw.VertexBuffers.Length; i++)
                            {
                                var vertexBuffer = draw.VertexBuffers[i];
                                commandList.SetVertexBuffer(i, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                            }
                            if (draw.IndexBuffer != null)
                            {
                                commandList.SetIndexBuffer(draw.IndexBuffer.Buffer, draw.IndexBuffer.Offset, draw.IndexBuffer.Is32Bit);
                            }
                            currentDraw = draw;
                        }

                        if (pipelineDirty)
                        {
                            minmaxPipelineState.Update();
                            pipelineDirty = false;
                        }

                        context.CommandList.SetPipelineState(minmaxPipelineState.CurrentState);

                        minmaxVolumeEffectShader.Apply(context.GraphicsContext);

                        // Draw
                        if (currentDraw.IndexBuffer == null)
                        {
                            commandList.Draw(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                        else
                        {
                            commandList.DrawIndexed(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                    }
                }
            }

            return(visibleMeshes);
        }
Exemple #39
0
        /// <inheritdoc/>
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // TODO: PerView data
            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            var descriptorSets = new DescriptorSet[EffectDescriptorSetSlotCount];

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

                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;
                if (renderParticleEmitter.ParticleEmitter.VertexBuilder.ResourceContext == null)
                {
                    continue;
                }

                // Generate vertices
                // TODO: Just just unmap/barrier here
                renderParticleEmitter.ParticleEmitter.BuildVertexBuffer(context.CommandList, ref viewInverse);

                // Get effect
                var renderEffect = renderNode.RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // TODO GRAPHICS REFACTOR: Extract data
                var particleSystemComponent = renderParticleEmitter.RenderParticleSystem.ParticleSystemComponent;
                var particleSystem          = particleSystemComponent.ParticleSystem;
                var vertexBuilder           = renderParticleEmitter.ParticleEmitter.VertexBuilder;

                // Bind VB
                var vertexBuffer = vertexBuilder.ResourceContext.VertexBuffer;
                var indexBuffer  = vertexBuilder.ResourceContext.IndexBuffer;
                commandList.SetVertexBuffer(0, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                commandList.SetIndexBuffer(indexBuffer.Buffer, indexBuffer.Offset, indexBuffer.Is32Bit);

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(context.CommandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSets.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSets[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSets);

                commandList.DrawIndexed(vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad, vertexBuilder.ResourceContext.IndexBufferPosition);
            }
        }
Exemple #40
0
 private bool DrawBoundingVolumeMinMax(RenderDrawContext context, IReadOnlyList <LightShaftBoundingVolumeProcessor.Data> boundingVolumes)
 {
     return(DrawBoundingVolumes(context, boundingVolumes, context.RenderContext.RenderView.ViewProjection));
 }
Exemple #41
0
        private void DrawLightShaft(RenderDrawContext context, LightShaftProcessor.Data lightShaft)
        {
            lightShaftsEffectShader.Parameters.Set(LightShaftsShaderKeys.DensityFactor, lightShaft.DensityFactor);

            lightShaftsEffectShader.Draw(context, $"Light shaft [{lightShaft.LightComponent.Entity.Name}]");
        }
 protected override void DrawCore(RenderContext context, RenderDrawContext drawContext)
 {
     drawAction(drawContext);
 }
 public virtual void ApplyViewParameters(RenderDrawContext context, ParameterCollection parameters, FastListStruct <LightDynamicEntry> currentLights)
 {
 }
 /// <inheritdoc/>
 public override void Flush(RenderDrawContext context)
 {
     // Release the temporary vertex buffer
     particleBufferContext.ReleaseBuffers(context);
 }
Exemple #45
0
 protected virtual void SpecificDrawBeforeUI(RenderDrawContext context, RenderFrame renderFrame)
 {
 }
 public override LightShaderGroupDynamic CreateLightShaderGroup(RenderDrawContext context,
                                                                ILightShadowMapShaderGroupData shadowShaderGroupData)
 {
     return(new PointLightShaderGroup(context.RenderContext, shadowShaderGroupData));
 }
Exemple #47
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var renderEffects      = RootRenderFeature.RenderData.GetData(renderEffectKey);
            var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);
            int effectSlotCount    = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            Dispatcher.ForEach(RootRenderFeature.RenderObjects, renderObject =>
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                var renderMesh          = (RenderMesh)renderObject;
                bool resetPipelineState = false;

                var material     = renderMesh.MaterialPass;
                var materialInfo = renderMesh.MaterialInfo;

                // Material use first 16 bits
                var materialHashCode      = material != null ? ((uint)material.GetHashCode() & 0x0FFF) | ((uint)material.PassIndex << 12) : 0;
                renderObject.StateSortKey = (renderObject.StateSortKey & 0x0000FFFF) | (materialHashCode << 16);

                ref var tessellationState = ref tessellationStates[staticObjectNode];

                // Update draw data if tessellation is active
                if (material.TessellationMethod != XenkoTessellationMethod.None)
                {
                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    if (tessellationState.Method != material.TessellationMethod)
                    {
                        tessellationState.Method = material.TessellationMethod;

                        var oldMeshDraw      = renderMesh.ActiveMeshDraw;
                        tessellationMeshDraw = new MeshDraw
                        {
                            VertexBuffers = oldMeshDraw.VertexBuffers,
                            IndexBuffer   = oldMeshDraw.IndexBuffer,
                            DrawCount     = oldMeshDraw.DrawCount,
                            StartLocation = oldMeshDraw.StartLocation,
                            PrimitiveType = tessellationState.Method.GetPrimitiveType(),
                        };

                        // adapt the primitive type and index buffer to the tessellation used
                        if (tessellationState.Method.PerformsAdjacentEdgeAverage())
                        {
                            renderMeshesToGenerateAEN.Add(renderMesh);
                        }
                        else
                        {
                            // Not using AEN tessellation anymore, dispose AEN indices if they were generated
                            Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                        }
                        tessellationState.MeshDraw = tessellationMeshDraw;

                        // Reset pipeline states
                        resetPipelineState = true;
                    }

                    renderMesh.ActiveMeshDraw = tessellationState.MeshDraw;
                }
                else if (tessellationState.GeneratedIndicesAEN != null)
                {
                    // Not using tessellation anymore, dispose AEN indices if they were generated
                    Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                }

                // Rebuild rasterizer state if culling mode changed
                // TODO GRAPHICS REFACTOR: Negative scaling belongs into TransformationRenderFeature
                if (materialInfo != null && (materialInfo.CullMode != material.CullMode || renderMesh.IsScalingNegative != renderMesh.IsPreviousScalingNegative))
                {
                    materialInfo.CullMode = material.CullMode;
                    renderMesh.IsPreviousScalingNegative = renderMesh.IsScalingNegative;
                    resetPipelineState = true;
                }

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect           = renderEffects[staticEffectObjectNode];

                    if (renderEffect == null)
                    {
                        continue;
                    }

                    // If any pipeline state changed, rebuild it for all effect slots
                    if (resetPipelineState)
                    {
                        renderEffect.PipelineState = null;
                    }

                    // Skip effects not used during this frame
                    if (!renderEffect.IsUsedDuringThisFrame(RenderSystem))
                    {
                        continue;
                    }

                    if (materialInfo == null || materialInfo.MaterialPass != material)
                    {
                        // First time this material is initialized, let's create associated info
                        lock (allMaterialInfos)
                        {
                            if (!allMaterialInfos.TryGetValue(material, out materialInfo))
                            {
                                materialInfo = new MaterialInfo(material);
                                allMaterialInfos.Add(material, materialInfo);
                            }
                        }
                        renderMesh.MaterialInfo = materialInfo;
                    }

                    if (materialInfo.MaterialParameters != material.Parameters || materialInfo.PermutationCounter != material.Parameters.PermutationCounter)
                    {
                        lock (materialInfo)
                        {
                            var isMaterialParametersChanged = materialInfo.MaterialParameters != material.Parameters;
                            if (isMaterialParametersChanged || // parameter fast reload?
                                materialInfo.PermutationCounter != material.Parameters.PermutationCounter)
                            {
                                materialInfo.VertexStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.VertexStageSurfaceShaders);
                                materialInfo.VertexStageStreamInitializer = material.Parameters.Get(MaterialKeys.VertexStageStreamInitializer);

                                materialInfo.DomainStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.DomainStageSurfaceShaders);
                                materialInfo.DomainStageStreamInitializer = material.Parameters.Get(MaterialKeys.DomainStageStreamInitializer);

                                materialInfo.TessellationShader = material.Parameters.Get(MaterialKeys.TessellationShader);

                                materialInfo.PixelStageSurfaceShaders    = material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders);
                                materialInfo.PixelStageStreamInitializer = material.Parameters.Get(MaterialKeys.PixelStageStreamInitializer);
                                materialInfo.HasNormalMap = material.Parameters.Get(MaterialKeys.HasNormalMap);
                                materialInfo.UsePixelShaderWithDepthPass = material.Parameters.Get(MaterialKeys.UsePixelShaderWithDepthPass);

                                materialInfo.MaterialParameters = material.Parameters;
                                materialInfo.ParametersChanged  = isMaterialParametersChanged;
                                materialInfo.PermutationCounter = material.Parameters.PermutationCounter;
                            }
                        }
                    }

                    // VS
                    if (materialInfo.VertexStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageSurfaceShaders, materialInfo.VertexStageSurfaceShaders);
                    }
                    if (materialInfo.VertexStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageStreamInitializer, materialInfo.VertexStageStreamInitializer);
                    }

                    // DS
                    if (materialInfo.DomainStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageSurfaceShaders, materialInfo.DomainStageSurfaceShaders);
                    }
                    if (materialInfo.DomainStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageStreamInitializer, materialInfo.DomainStageStreamInitializer);
                    }

                    // Tessellation
                    if (materialInfo.TessellationShader != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.TessellationShader, materialInfo.TessellationShader);
                    }

                    // PS
                    if (materialInfo.PixelStageSurfaceShaders != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageSurfaceShaders, materialInfo.PixelStageSurfaceShaders);
                    }
                    if (materialInfo.PixelStageStreamInitializer != null)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageStreamInitializer, materialInfo.PixelStageStreamInitializer);
                    }
                    if (materialInfo.HasNormalMap)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasNormalMap, materialInfo.HasNormalMap);
                    }
                    if (materialInfo.UsePixelShaderWithDepthPass)
                    {
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.UsePixelShaderWithDepthPass, materialInfo.UsePixelShaderWithDepthPass);
                    }
                }
            });
        /// <inheritdoc/>
        public override unsafe void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            var commandList = context.CommandList;

            // register all texture usage
            foreach (var renderObject in RenderObjects)
            {
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;
                Context.StreamingManager?.StreamResources(renderParticleEmitter.ParticleEmitter.Material.Parameters);
            }

            // Per view - this code was moved here from Prepare(...) so that we can apply the correct Viewport
            {
                var view        = renderView;
                var viewFeature = view.Features[Index];

                Matrix.Multiply(ref view.View, ref view.Projection, out view.ViewProjection);

                // Copy ViewProjection to PerFrame cbuffer
                foreach (var viewLayout in viewFeature.Layouts)
                {
                    var resourceGroup = viewLayout.Entries[view.Index].Resources;
                    var mappedCB      = resourceGroup.ConstantBuffer.Data;

                    // PerView constant buffer
                    var perViewOffset = viewLayout.GetConstantBufferOffset(this.perViewCBufferOffset);
                    if (perViewOffset != -1)
                    {
                        var perView = (ParticleUtilitiesPerView *)((byte *)mappedCB + perViewOffset);
                        perView->ViewMatrix           = view.View;
                        perView->ProjectionMatrix     = view.Projection;
                        perView->ViewProjectionMatrix = view.ViewProjection;
                        perView->ViewFrustum          = new Vector4(view.ViewSize.X, view.ViewSize.Y, view.NearClipPlane, view.FarClipPlane);

                        perView->Viewport = new Vector4(0,
                                                        0,
                                                        ((float)context.CommandList.Viewport.Width) / ((float)context.CommandList.RenderTarget.Width),
                                                        ((float)context.CommandList.Viewport.Height) / ((float)context.CommandList.RenderTarget.Height));
                    }
                }
            }

            var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey);

            // TODO: stackalloc?
            var descriptorSetsLocal = descriptorSets.Value;

            if (descriptorSetsLocal == null || descriptorSetsLocal.Length < EffectDescriptorSetSlotCount)
            {
                descriptorSetsLocal = descriptorSets.Value = new DescriptorSet[EffectDescriptorSetSlotCount];
            }

            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;

                // Get effect
                var renderEffect = GetRenderNode(renderNodeReference).RenderEffect;
                if (renderEffect.Effect == null)
                {
                    continue;
                }

                // Get the extra node data
                var nodeData = renderParticleNodeData[renderNodeReference];
                if (nodeData.IndexCount <= 0)
                {
                    continue;
                }

                var resourceGroupOffset = ComputeResourceGroupOffset(renderNodeReference);

                // Update cbuffer
                renderEffect.Reflection.BufferUploader.Apply(commandList, ResourceGroupPool, resourceGroupOffset);

                // Bind descriptor sets
                for (int i = 0; i < descriptorSetsLocal.Length; ++i)
                {
                    var resourceGroup = ResourceGroupPool[resourceGroupOffset++];
                    if (resourceGroup != null)
                    {
                        descriptorSetsLocal[i] = resourceGroup.DescriptorSet;
                    }
                }

                commandList.SetPipelineState(renderEffect.PipelineState);
                commandList.SetDescriptorSets(0, descriptorSetsLocal);

                // Bind the buffers and draw
                commandList.SetVertexBuffer(0, nodeData.VertexBuffer, nodeData.VertexBufferOffset, nodeData.VertexBufferStride);
                commandList.SetIndexBuffer(nodeData.IndexBuffer, nodeData.IndexBufferOffset, ParticleBufferContext.IndexStride != sizeof(short));
                commandList.DrawIndexed(nodeData.IndexCount, 0);
            }
        }
Exemple #49
0
        private TemporalFrameCache Prepare(RenderDrawContext context, Texture outputBuffer)
        {
            TemporalFrameCache cache = null;

            var     renderView                  = context.RenderContext.RenderView;
            Matrix  viewMatrix                  = renderView.View;
            Matrix  projectionMatrix            = renderView.Projection;
            Matrix  viewProjectionMatrix        = renderView.ViewProjection;
            Matrix  inverseViewMatrix           = Matrix.Invert(viewMatrix);
            Matrix  inverseViewProjectionMatrix = Matrix.Invert(viewProjectionMatrix);
            Vector4 eye       = inverseViewMatrix.Row4;
            float   nearclip  = renderView.NearClipPlane;
            float   farclip   = renderView.FarClipPlane;
            Vector4 viewInfo  = new Vector4(1.0f / projectionMatrix.M11, 1.0f / projectionMatrix.M22, farclip / (farclip - nearclip), (-farclip * nearclip) / (farclip - nearclip) / farclip);
            Vector3 cameraPos = new Vector3(eye.X, eye.Y, eye.Z);

            float temporalTime = 0;

            if (TemporalEffect)
            {
                var    gameTime = context.RenderContext.Time;
                double time     = gameTime.Total.TotalSeconds;

                // Keep time in smaller range to prevent temporal noise errors
                const double scale    = 10;
                double       integral = Math.Round(time / scale) * scale;
                time -= integral;

                temporalTime = (float)time;

                cache = GetFrameCache(gameTime.FrameCount, renderView);
            }

            var traceBufferSize = GetBufferResolution(outputBuffer, RayTracePassResolution);
            var roughnessFade   = 1 - MathUtil.Clamp(GlossinessThreshold, 0.0f, 1.0f);
            var maxTraceSamples = MathUtil.Clamp(MaxSteps, 1, 128);

            // ViewInfo :  x-1/Projection[0,0]   y-1/Projection[1,1]   z-(Far / (Far - Near)   w-(-Far * Near) / (Far - Near) / Far)

            rayTracePassShader.Parameters.Set(SSLRCommonKeys.ViewFarPlane, farclip);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.RoughnessFade, roughnessFade);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.MaxTraceSamples, maxTraceSamples);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.WorldAntiSelfOcclusionBias, WorldAntiSelfOcclusionBias);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.BRDFBias, BRDFBias);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.TemporalTime, temporalTime);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.CameraPosWS, ref cameraPos);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.ViewInfo, ref viewInfo);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.V, ref viewMatrix);
            rayTracePassShader.Parameters.Set(SSLRCommonKeys.IVP, ref inverseViewProjectionMatrix);
            rayTracePassShader.Parameters.Set(SSLRRayTracePassKeys.VP, ref viewProjectionMatrix);
            rayTracePassShader.Parameters.Set(SSLRRayTracePassKeys.EdgeFadeFactor, EdgeFadeFactor);

            resolvePassShader.Parameters.Set(SSLRCommonKeys.MaxColorMiplevel, Texture.CalculateMipMapCount(0, outputBuffer.Width, outputBuffer.Height) - 1);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.TraceSizeMax, Math.Max(traceBufferSize.Width, traceBufferSize.Height) / 2.0f);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.ViewFarPlane, farclip);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.RoughnessFade, roughnessFade);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.TemporalTime, temporalTime);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.BRDFBias, BRDFBias);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.CameraPosWS, ref cameraPos);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.ViewInfo, ref viewInfo);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.V, ref viewMatrix);
            resolvePassShader.Parameters.Set(SSLRCommonKeys.IVP, ref inverseViewProjectionMatrix);
            resolvePassShader.Parameters.Set(SSLRKeys.ResolveSamples, MathUtil.Clamp(ResolveSamples, 1, 8));
            resolvePassShader.Parameters.Set(SSLRKeys.ReduceHighlights, ReduceHighlights);

            if (TemporalEffect)
            {
                temporalPassShader.Parameters.Set(SSLRTemporalPassKeys.IVP, ref inverseViewProjectionMatrix);
                temporalPassShader.Parameters.Set(SSLRTemporalPassKeys.TemporalResponse, TemporalResponse);
                temporalPassShader.Parameters.Set(SSLRTemporalPassKeys.TemporalScale, TemporalScale);

                if (cache != null)
                {
                    temporalPassShader.Parameters.Set(SSLRTemporalPassKeys.prevVP, ref cache.PrevViewProjection);
                    cache.PrevViewProjection = viewProjectionMatrix;
                }
            }

            combinePassShader.Parameters.Set(SSLRCommonKeys.ViewFarPlane, farclip);
            combinePassShader.Parameters.Set(SSLRCommonKeys.CameraPosWS, ref cameraPos);
            combinePassShader.Parameters.Set(SSLRCommonKeys.ViewInfo, ref viewInfo);
            combinePassShader.Parameters.Set(SSLRCommonKeys.V, ref viewMatrix);
            combinePassShader.Parameters.Set(SSLRCommonKeys.IVP, ref inverseViewProjectionMatrix);

            return(cache);
        }
Exemple #50
0
 public override LightShaderGroupDynamic CreateLightShaderGroup(RenderDrawContext context, ILightShadowMapShaderGroupData shadowGroup)
 {
     return(new SpotLightShaderGroup(shadowGroup));
 }
Exemple #51
0
        protected virtual void DrawView(RenderContext context, RenderDrawContext drawContext)
        {
            var renderSystem = context.RenderSystem;

            // Z-Prepass
            var lightProbes = LightProbes && GBufferRenderStage != null;

            if (lightProbes)
            {
                // NOTE: Baking light probes before GBuffer prepass because we are updating some cbuffer parameters needed by Opaque pass that GBuffer pass might upload early
                PrepareLightprobeConstantBuffer(context);

                // TODO: Temporarily using ShadowMap shader
                using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.GBuffer))
                    using (drawContext.PushRenderTargetsAndRestore())
                    {
                        drawContext.CommandList.Clear(drawContext.CommandList.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer);
                        drawContext.CommandList.SetRenderTarget(drawContext.CommandList.DepthStencilBuffer, null);

                        // Draw [Main view | Z-Prepass stage]
                        renderSystem.Draw(drawContext, context.RenderView, GBufferRenderStage);
                    }

                // Bake lightprobes against Z-buffer
                BakeLightProbes(context, drawContext);
            }

            using (drawContext.PushRenderTargetsAndRestore())
            {
                // Draw [Main view | Main stage]
                if (OpaqueRenderStage != null)
                {
                    using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.Opaque))
                    {
                        renderSystem.Draw(drawContext, context.RenderView, OpaqueRenderStage);
                    }
                }

                Texture depthStencilSRV = null;

                // Draw [Main view | SubSurface Scattering Post-process]
                if (SubsurfaceScatteringBlurEffect != null)
                {
                    var materialIndex = OpaqueRenderStage?.OutputValidator.Find <MaterialIndexTargetSemantic>() ?? -1;
                    if (materialIndex != -1)
                    {
                        using (drawContext.PushRenderTargetsAndRestore())
                        {
                            depthStencilSRV = ResolveDepthAsSRV(drawContext);

                            var renderTarget = drawContext.CommandList.RenderTargets[0];
                            var materialIndexRenderTarget = drawContext.CommandList.RenderTargets[materialIndex];

                            SubsurfaceScatteringBlurEffect.Draw(drawContext, renderTarget, materialIndexRenderTarget, depthStencilSRV, renderTarget);
                        }
                    }
                }

                // Draw [Main view | Transparent stage]
                if (TransparentRenderStage != null)
                {
                    // Some transparent shaders will require the depth as a shader resource - resolve it only once and set it here
                    using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.Transparent))
                        using (drawContext.PushRenderTargetsAndRestore())
                        {
                            if (depthStencilSRV is null)
                            {
                                depthStencilSRV = ResolveDepthAsSRV(drawContext);
                            }

                            renderSystem.Draw(drawContext, context.RenderView, TransparentRenderStage);
                        }
                }

                var colorTargetIndex = OpaqueRenderStage?.OutputValidator.Find(typeof(ColorTargetSemantic)) ?? -1;
                if (colorTargetIndex == -1)
                {
                    return;
                }

                // Resolve MSAA targets
                var renderTargets = currentRenderTargets;
                var depthStencil  = currentDepthStencil;
                if (actualMultisampleCount != MultisampleCount.None)
                {
                    using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.MsaaResolve))
                    {
                        ResolveMSAA(drawContext);
                    }

                    renderTargets = currentRenderTargetsNonMSAA;
                    depthStencil  = currentDepthStencilNonMSAA;
                }

                // Draw [Main view | Light Shafts]
                if (LightShafts != null)
                {
                    using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.LightShafts))
                    {
                        LightShafts.Draw(drawContext, depthStencil, renderTargets[colorTargetIndex]);
                    }
                }

                // Draw Post-Processing effects
                if (PostEffects != null)
                {
                    // NOTE: OpaqueRenderStage can't be null otherwise colorTargetIndex would be -1
                    PostEffects.Draw(drawContext, OpaqueRenderStage.OutputValidator, renderTargets.Items, depthStencil, viewOutputTarget);
                }
                else
                {
                    if (actualMultisampleCount != MultisampleCount.None)
                    {
                        using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.MsaaResolve))
                        {
                            drawContext.CommandList.Copy(renderTargets[colorTargetIndex], viewOutputTarget);
                        }
                    }
                }

                // Free the depth texture since we won't need it anymore
                if (depthStencilSRV != null)
                {
                    drawContext.Resolver.ReleaseDepthStenctilAsShaderResource(depthStencilSRV);
                }
            }
        }
        public static Texture GenerateCubemap(IServiceRegistry services, RenderDrawContext renderDrawContext, Texture input, int outputSize)
        {
            var pixelFormat = input.Format.IsHDR() ? PixelFormat.R16G16B16A16_Float : input.Format.IsSRgb() ? PixelFormat.R8G8B8A8_UNorm_SRgb : PixelFormat.R8G8B8A8_UNorm;

            return(GenerateCubemap(new CubemapFromTextureRenderer(services, renderDrawContext, input, outputSize, pixelFormat), Vector3.Zero));
        }
            public override unsafe void ApplyViewParameters(RenderDrawContext context, int viewIndex, ParameterCollection parameters)
            {
                // Note: no need to fill CurrentLights since we have no shadow maps
                base.ApplyViewParameters(context, viewIndex, parameters);

                var renderView    = renderViews[viewIndex];
                var viewSize      = renderView.ViewSize;
                var clusterCountX = ((int)viewSize.X + ClusterSize - 1) / ClusterSize;
                var clusterCountY = ((int)viewSize.Y + ClusterSize - 1) / ClusterSize;

                // TODO: Additional culling on x/y (to remove corner clusters)
                // Prepare planes for culling
                //var viewProjection = renderView.ViewProjection;
                //Array.Resize(ref zPlanes, ClusterSlices + 1);
                //for (int z = 0; z <= ClusterSlices; ++z)
                //{
                //    var zFactor = (float)z / (float)ClusterSlices;
                //
                //    // Build planes between nearplane and -farplane (see BoundingFrustum code)
                //    zPlanes[z] = new Plane(
                //        viewProjection.M13 - zFactor * viewProjection.M14,
                //        viewProjection.M23 - zFactor * viewProjection.M24,
                //        viewProjection.M33 - zFactor * viewProjection.M34,
                //        viewProjection.M43 - zFactor * viewProjection.M44);
                //
                //    zPlanes[z].Normalize();
                //}

                if (pointGroupRenderer.lightClusters == null || lightClustersValues.Length != clusterCountX * clusterCountY * ClusterSlices)
                {
                    // First time?
                    pointGroupRenderer.lightClusters?.Dispose();
                    pointGroupRenderer.lightClusters = Texture.New3D(context.GraphicsDevice, clusterCountX, clusterCountY, 8, PixelFormat.R32G32_UInt);
                    lightClustersValues = new Int2[clusterCountX * clusterCountY * ClusterSlices];
                }

                // Initialize cluster with no light (-1)
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    lightNodes.Add(new LightClusterLinkedNode(LightType.Point, -1, -1));
                }

                // List of clusters moved by this light
                var movedClusters = new Dictionary <LightClusterLinkedNode, int>();

                // Try to use SpecialNearPlane to not waste too much slices in very small depth
                // Make sure we don't go to more than 10% of max depth
                var nearPlane = Math.Max(Math.Min(SpecialNearPlane, renderView.FarClipPlane * 0.1f), renderView.NearClipPlane);

                //var sliceBias = ((renderView.NearClipPlane * renderView.Projection.M33) + renderView.Projection.M43) / (renderView.NearClipPlane * renderView.Projection.M34);
                // Compute scale and bias so that near_plane..special_near fits in slice 0, then grow exponentionally
                //   log2(specialNear * scale + bias) == 1.0
                //   log2(far * scale + bias) == ClusterSlices
                // as a result:
                clusterDepthScale = (float)(Math.Pow(2.0f, ClusterSlices) - 2.0f) / (renderView.FarClipPlane - nearPlane);
                clusterDepthBias  = 2.0f - clusterDepthScale * nearPlane;

                //---------------- SPOT LIGHTS -------------------
                var lightRange = pointGroupRenderer.spotGroup.LightRanges[viewIndex];

                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    var light     = pointGroupRenderer.spotGroup.Lights[i].Light;
                    var spotLight = (LightSpot)light.Type;

                    // Create spot light data
                    var spotLightData = new SpotLightData
                    {
                        PositionWS  = light.Position,
                        DirectionWS = light.Direction,
                        AngleOffsetAndInvSquareRadius = new Vector3(spotLight.LightAngleScale, spotLight.LightAngleOffset, spotLight.InvSquareRange),
                        Color = light.Color,
                    };

                    // Fill list of spot lights
                    spotLights.Add(spotLightData);

                    movedClusters.Clear();

                    var radius = (float)Math.Sqrt(1.0f / spotLightData.AngleOffsetAndInvSquareRadius.Z);

                    Vector3 positionVS;
                    Vector3.TransformCoordinate(ref spotLightData.PositionWS, ref renderView.View, out positionVS);

                    // TODO: culling (first do it on PointLight, then backport it to SpotLight and improve for SpotLight case)
                    // Find x/y ranges
                    Vector2 clipMin, clipMax;
                    ComputeClipRegion(positionVS, radius, ref renderView.Projection, out clipMin, out clipMax);

                    var tileStartX = MathUtil.Clamp((int)((clipMin.X * 0.5f + 0.5f) * viewSize.X / ClusterSize), 0, clusterCountX);
                    var tileEndX   = MathUtil.Clamp((int)((clipMax.X * 0.5f + 0.5f) * viewSize.X / ClusterSize) + 1, 0, clusterCountX);
                    var tileStartY = MathUtil.Clamp((int)((-clipMax.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize), 0, clusterCountY);
                    var tileEndY   = MathUtil.Clamp((int)((-clipMin.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize) + 1, 0, clusterCountY);

                    // Find z range (project using Projection matrix)
                    var startZ = -positionVS.Z - radius;
                    var endZ   = -positionVS.Z + radius;

                    var tileStartZ = MathUtil.Clamp((int)Math.Log(startZ * clusterDepthScale + clusterDepthBias, 2.0f), 0, ClusterSlices);
                    var tileEndZ   = MathUtil.Clamp((int)Math.Log(endZ * clusterDepthScale + clusterDepthBias, 2.0f) + 1, 0, ClusterSlices);

                    for (int z = tileStartZ; z < tileEndZ; ++z)
                    {
                        for (int y = tileStartY; y < tileEndY; ++y)
                        {
                            for (int x = tileStartX; x < tileEndX; ++x)
                            {
                                AddLightToCluster(movedClusters, LightType.Spot, i - lightRange.Start, x + (y + z * clusterCountY) * clusterCountX);
                            }
                        }
                    }
                }

                //---------------- POINT LIGHTS -------------------
                lightRange = LightRanges[viewIndex];
                for (int i = lightRange.Start; i < lightRange.End; ++i)
                {
                    var light      = Lights[i].Light;
                    var pointLight = (LightPoint)light.Type;

                    // Create point light data
                    var pointLightData = new PointLightData
                    {
                        PositionWS      = light.Position,
                        InvSquareRadius = pointLight.InvSquareRadius,
                        Color           = light.Color,
                    };

                    // Fill list of point lights
                    pointLights.Add(pointLightData);

                    movedClusters.Clear();

                    var radius = (float)Math.Sqrt(1.0f / pointLightData.InvSquareRadius);

                    Vector3 positionVS;
                    Vector3.TransformCoordinate(ref pointLightData.PositionWS, ref renderView.View, out positionVS);

                    //Vector3 positionScreen;
                    //Vector3.TransformCoordinate(ref pointLightData.PositionWS, ref renderView.ViewProjection, out positionScreen);

                    // Find x/y ranges
                    Vector2 clipMin, clipMax;
                    ComputeClipRegion(positionVS, radius, ref renderView.Projection, out clipMin, out clipMax);

                    var tileStartX = MathUtil.Clamp((int)((clipMin.X * 0.5f + 0.5f) * viewSize.X / ClusterSize), 0, clusterCountX);
                    var tileEndX   = MathUtil.Clamp((int)((clipMax.X * 0.5f + 0.5f) * viewSize.X / ClusterSize) + 1, 0, clusterCountX);
                    var tileStartY = MathUtil.Clamp((int)((-clipMax.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize), 0, clusterCountY);
                    var tileEndY   = MathUtil.Clamp((int)((-clipMin.Y * 0.5f + 0.5f) * viewSize.Y / ClusterSize) + 1, 0, clusterCountY);

                    // Find z range (project using Projection matrix)
                    var startZ = -positionVS.Z - radius;
                    var endZ   = -positionVS.Z + radius;

                    //var centerZ = (int)(positionVS.Z * ClusterDepthScale + ClusterDepthBias);
                    var tileStartZ = MathUtil.Clamp((int)Math.Log(startZ * clusterDepthScale + clusterDepthBias, 2.0f), 0, ClusterSlices);
                    var tileEndZ   = MathUtil.Clamp((int)Math.Log(endZ * clusterDepthScale + clusterDepthBias, 2.0f) + 1, 0, ClusterSlices);

                    for (int z = tileStartZ; z < tileEndZ; ++z)
                    {
                        // TODO: Additional culling on x/y (to remove corner clusters)
                        // See "Practical Clustered Shading" for details
                        //if (z != centerZ)
                        //{
                        //    var plane = z < centerZ ? zPlanes[z + 1] : -zPlanes[z];
                        //
                        //    positionScreen = Plane.DotCoordinate(ref plane, ref positionScreen, out )
                        //}

                        for (int y = tileStartY; y < tileEndY; ++y)
                        {
                            for (int x = tileStartX; x < tileEndX; ++x)
                            {
                                AddLightToCluster(movedClusters, LightType.Point, i - lightRange.Start, x + (y + z * clusterCountY) * clusterCountX);
                            }
                        }
                    }
                }

                // Finish clusters by making their last element unique and building clusterInfos
                movedClusters.Clear();
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    FinishCluster(movedClusters, i);
                }

                // Prepare light clusters
                for (int i = 0; i < clusterCountX * clusterCountY * ClusterSlices; ++i)
                {
                    var clusterId = lightNodes[i].NextNode;
                    lightClustersValues[i] = clusterId != -1 ? clusterInfos[clusterId] : new Int2(0, 0);
                }

                // Upload data to texture
                using (context.LockCommandList())
                {
                    fixed(Int2 *dataPtr = lightClustersValues)
                    context.CommandList.UpdateSubresource(pointGroupRenderer.lightClusters, 0, new DataBox((IntPtr)dataPtr, sizeof(Int2) * clusterCountX, sizeof(Int2) * clusterCountX * clusterCountY));

                    // PointLights: Ensure size and update
                    if (pointLights.Count > 0)
                    {
                        if (pointGroupRenderer.pointLightsBuffer == null || pointGroupRenderer.pointLightsBuffer.SizeInBytes < pointLights.Count * sizeof(PointLightData))
                        {
                            pointGroupRenderer.pointLightsBuffer?.Dispose();
                            pointGroupRenderer.pointLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(pointLights.Count * sizeof(PointLightData)), 0, BufferFlags.ShaderResource, PixelFormat.R32G32B32A32_Float);
                        }
                        fixed(PointLightData *pointLightsPtr = pointLights.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.pointLightsBuffer, 0, new DataBox((IntPtr)pointLightsPtr, 0, 0), new ResourceRegion(0, 0, 0, pointLights.Count * sizeof(PointLightData), 1, 1));
                    }

                    // SpotLights: Ensure size and update
                    if (spotLights.Count > 0)
                    {
                        if (pointGroupRenderer.spotLightsBuffer == null || pointGroupRenderer.spotLightsBuffer.SizeInBytes < spotLights.Count * sizeof(SpotLightData))
                        {
                            pointGroupRenderer.spotLightsBuffer?.Dispose();
                            pointGroupRenderer.spotLightsBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(spotLights.Count * sizeof(SpotLightData)), 0, BufferFlags.ShaderResource, PixelFormat.R32G32B32A32_Float);
                        }
                        fixed(SpotLightData *spotLightsPtr = spotLights.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.spotLightsBuffer, 0, new DataBox((IntPtr)spotLightsPtr, 0, 0), new ResourceRegion(0, 0, 0, spotLights.Count * sizeof(SpotLightData), 1, 1));
                    }

                    // LightIndices: Ensure size and update
                    if (lightIndices.Count > 0)
                    {
                        if (pointGroupRenderer.lightIndicesBuffer == null || pointGroupRenderer.lightIndicesBuffer.SizeInBytes < lightIndices.Count * sizeof(int))
                        {
                            pointGroupRenderer.lightIndicesBuffer?.Dispose();
                            pointGroupRenderer.lightIndicesBuffer = Buffer.New(context.GraphicsDevice, MathUtil.NextPowerOfTwo(lightIndices.Count * sizeof(int)), 0, BufferFlags.ShaderResource, PixelFormat.R32_UInt);
                        }
                        fixed(int *lightIndicesPtr = lightIndices.Items)
                        context.CommandList.UpdateSubresource(pointGroupRenderer.lightIndicesBuffer, 0, new DataBox((IntPtr)lightIndicesPtr, 0, 0), new ResourceRegion(0, 0, 0, lightIndices.Count * sizeof(int), 1, 1));
                    }
                }

                // Clear data
                pointLights.Clear();
                spotLights.Clear();
                lightIndices.Clear();
                lightNodes.Clear();
                clusterInfos.Clear();

                // Set resources
                parameters.Set(LightClusteredPointGroupKeys.PointLights, pointGroupRenderer.pointLightsBuffer);
                parameters.Set(LightClusteredSpotGroupKeys.SpotLights, pointGroupRenderer.spotLightsBuffer);
                parameters.Set(LightClusteredKeys.LightIndices, pointGroupRenderer.lightIndicesBuffer);
                parameters.Set(LightClusteredKeys.LightClusters, pointGroupRenderer.lightClusters);

                parameters.Set(LightClusteredKeys.ClusterDepthScale, clusterDepthScale);
                parameters.Set(LightClusteredKeys.ClusterDepthBias, clusterDepthBias);
            }
Exemple #54
0
        // Naive approach: 6 passes
        protected void DrawCoreNaive(RenderDrawContext context)
        {
            var originalTexture = GetSafeInput(0);
            var outputTexture   = GetSafeOutput(0);

            if (rhombiTapOffsetsDirty)
            {
                calculateRhombiOffsets();
            }

            var tapNumber = 2 * tapCount - 1;

            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurKeys.Count, tapCount);
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurKeys.TotalTap, tapNumber);
            directionalBlurEffect.EffectInstance.UpdateEffect(context.GraphicsDevice);
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Radius, Radius);
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.TapWeights, tapWeights);
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.CoCReference, CoCStrength);

            // Vertical blur
            var blurAngle = MathUtil.PiOverTwo + Phase;

            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Direction, new Vector2((float)Math.Cos(blurAngle), (float)Math.Sin(blurAngle)));

            var verticalBlurTexture = NewScopedRenderTarget2D(originalTexture.Description);

            directionalBlurEffect.SetInput(0, originalTexture);
            directionalBlurEffect.SetOutput(verticalBlurTexture);
            directionalBlurEffect.Draw(context, "TripleRhombiBokeh_RhombiABVertical_tap{0}_radius{1}", tapNumber, (int)Radius);

            // Rhombi A (top left)
            blurAngle = 7f * MathUtil.Pi / 6f + Phase;
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Direction, new Vector2((float)Math.Cos(blurAngle), (float)Math.Sin(blurAngle)));

            var rhombiA = NewScopedRenderTarget2D(originalTexture.Description);

            directionalBlurEffect.SetInput(0, verticalBlurTexture);
            directionalBlurEffect.SetOutput(rhombiA);
            directionalBlurEffect.Draw(context, "TripleRhombiBokeh_RhombiA_tap{0}_radius{1}", tapNumber, (int)Radius);

            // Rhombi B (top right)
            blurAngle = -MathUtil.Pi / 6f + Phase;
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Direction, new Vector2((float)Math.Cos(blurAngle), (float)Math.Sin(blurAngle)));

            var rhombiB = NewScopedRenderTarget2D(originalTexture.Description);

            directionalBlurEffect.SetInput(0, verticalBlurTexture);
            directionalBlurEffect.SetOutput(rhombiB);
            directionalBlurEffect.Draw(context, "TripleRhombiBokeh_RhombiB_tap{0}_radius{1}", tapNumber, (int)Radius);

            //Rhombi C (bottom)
            blurAngle = 7f * MathUtil.Pi / 6f + Phase;
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Direction, new Vector2((float)Math.Cos(blurAngle), (float)Math.Sin(blurAngle)));

            var rhombiCTmp = NewScopedRenderTarget2D(originalTexture.Description);

            directionalBlurEffect.SetInput(0, originalTexture);
            directionalBlurEffect.SetOutput(rhombiCTmp);
            directionalBlurEffect.Draw(context, "TripleRhombiBokeh_RhombiCTmp_tap{0}_radius{1}", tapNumber, (int)Radius);

            blurAngle = -MathUtil.Pi / 6f + Phase;
            directionalBlurEffect.Parameters.Set(DepthAwareDirectionalBlurUtilKeys.Direction, new Vector2((float)Math.Cos(blurAngle), (float)Math.Sin(blurAngle)));

            var rhombiC = NewScopedRenderTarget2D(originalTexture.Description);

            directionalBlurEffect.SetInput(0, rhombiCTmp);
            directionalBlurEffect.SetOutput(rhombiC);
            directionalBlurEffect.Draw(context, "TripleRhombiBokeh_RhombiC_tap{0}_radius{1}", tapNumber, (int)Radius);

            // Final pass outputting the average of the 3 blurs
            finalCombineEffect.SetInput(0, rhombiA);
            finalCombineEffect.SetInput(1, rhombiB);
            finalCombineEffect.SetInput(2, rhombiC);
            finalCombineEffect.SetOutput(outputTexture);
            finalCombineEffect.Parameters.Set(TripleRhombiCombineShaderKeys.RhombiTapOffsets, rhombiTapOffsets);
            finalCombineEffect.Draw(context, name: "TripleRhombiBokehCombine");
        }
Exemple #55
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var currentRenderFrame = context.RenderContext.Tags.Get(RenderFrame.Current);

            var uiProcessor = renderView.SceneInstance.GetProcessor <UIRenderProcessor>();

            if (uiProcessor == null)
            {
                return;
            }

            //foreach (var uiRoot in uiProcessor.UIRoots)
            //{
            //    // Perform culling on group and accept
            //    if (!renderView.SceneCameraRenderer.CullingMask.Contains(uiRoot.UIComponent.Entity.Group))
            //        continue;

            //    // skips empty UI elements
            //    if (uiRoot.UIComponent.RootElement == null)
            //        continue;

            //    // Project the position
            //    // TODO: This code is duplicated from SpriteComponent -> unify it at higher level?
            //    var worldPosition = new Vector4(uiRoot.TransformComponent.WorldMatrix.TranslationVector, 1.0f);

            //    float projectedZ;
            //    if (uiRoot.UIComponent.IsFullScreen)
            //    {
            //        projectedZ = -uiRoot.TransformComponent.WorldMatrix.M43;
            //    }
            //    else
            //    {
            //        Vector4 projectedPosition;
            //        var cameraComponent = renderView.Camera;
            //        if (cameraComponent == null)
            //            continue;

            //        Vector4.Transform(ref worldPosition, ref cameraComponent.ViewProjectionMatrix, out projectedPosition);
            //        projectedZ = projectedPosition.Z / projectedPosition.W;
            //    }

            //    transparentList.Add(new RenderItem(this, uiRoot, projectedZ));
            //}

            // build the list of the UI elements to render
            uiElementStates.Clear();
            for (var index = startIndex; index < endIndex; index++)
            {
                var renderNodeReference = renderViewStage.SortedRenderNodes[index].RenderNode;
                var renderNode          = GetRenderNode(renderNodeReference);
                var renderElement       = (RenderUIElement)renderNode.RenderObject;

                uiElementStates.Add(renderElement);
            }

            // evaluate the current draw time (game instance is null for thumbnails)
            var drawTime = game != null ? game.DrawTime : new GameTime();

            // update the rendering context
            renderingContext.GraphicsContext = context.GraphicsContext;
            renderingContext.Time            = drawTime;
            renderingContext.RenderTarget    = currentRenderFrame.RenderTargets[0]; // TODO: avoid hardcoded index 0

            var viewport = context.CommandList.Viewport;

            // cache the ratio between viewport and target.
            var viewportSize = viewport.Size;

            viewportTargetRatio = new Vector2(viewportSize.X / renderingContext.RenderTarget.Width, viewportSize.Y / renderingContext.RenderTarget.Height);
            viewportOffset      = new Vector2(viewport.X / viewport.Width, viewport.Y / viewport.Height);

            // compact all the pointer events that happened since last frame to avoid performing useless hit tests.
            CompactPointerEvents();

            // allocate temporary graphics resources if needed
            Texture scopedDepthBuffer = null;

            foreach (var uiElement in uiElementStates)
            {
                if (uiElement.UIComponent.IsFullScreen)
                {
                    var renderTarget = renderingContext.RenderTarget;
                    var description  = TextureDescription.New2D(renderTarget.Width, renderTarget.Height, PixelFormat.D24_UNorm_S8_UInt, TextureFlags.DepthStencil);
                    scopedDepthBuffer = context.RenderContext.Allocator.GetTemporaryTexture(description);
                    break;
                }
            }

            // render the UI elements of all the entities
            foreach (var uiElementState in uiElementStates)
            {
                var uiComponent = uiElementState.UIComponent;
                var rootElement = uiComponent.RootElement;
                if (rootElement == null)
                {
                    continue;
                }

                var updatableRootElement = (IUIElementUpdate)rootElement;

                // calculate the size of the virtual resolution depending on target size (UI canvas)
                var virtualResolution = uiComponent.Resolution;

                if (uiComponent.IsFullScreen)
                {
                    //var targetSize = viewportSize;
                    var targetSize = new Vector2(renderingContext.RenderTarget.Width, renderingContext.RenderTarget.Height);

                    // update the virtual resolution of the renderer
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedWidthAdaptableHeight)
                    {
                        virtualResolution.Y = virtualResolution.X * targetSize.Y / targetSize.X;
                    }
                    if (uiComponent.ResolutionStretch == ResolutionStretch.FixedHeightAdaptableWidth)
                    {
                        virtualResolution.X = virtualResolution.Y * targetSize.X / targetSize.Y;
                    }

                    viewParameters.Update(uiComponent.Entity, virtualResolution);
                }
                else
                {
                    var cameraComponent = context.RenderContext.Tags.Get(CameraComponentRendererExtensions.Current);
                    if (cameraComponent != null)
                    {
                        viewParameters.Update(uiComponent.Entity, cameraComponent);
                    }
                }

                // Analyze the input and trigger the UI element touch and key events
                // Note: this is done before measuring/arranging/drawing the element in order to avoid one frame latency on clicks.
                //       But by doing so the world matrices taken for hit test are the ones calculated during last frame.
                using (Profiler.Begin(UIProfilerKeys.TouchEventsUpdate))
                {
                    foreach (var uiState in uiElementStates)
                    {
                        if (uiState.UIComponent.RootElement == null)
                        {
                            continue;
                        }

                        UpdateMouseOver(uiState);
                        UpdateTouchEvents(uiState, drawTime);
                    }
                }

                // update the rendering context values specific to this element
                renderingContext.Resolution           = virtualResolution;
                renderingContext.ViewMatrix           = viewParameters.ViewMatrix;
                renderingContext.ProjectionMatrix     = viewParameters.ProjectionMatrix;
                renderingContext.ViewProjectionMatrix = viewParameters.ViewProjectionMatrix;
                renderingContext.DepthStencilBuffer   = uiComponent.IsFullScreen ? scopedDepthBuffer : currentRenderFrame.DepthStencil;
                renderingContext.ShouldSnapText       = uiComponent.SnapText;

                // calculate an estimate of the UI real size by projecting the element virtual resolution on the screen
                var virtualOrigin            = viewParameters.ViewProjectionMatrix.Row4;
                var virtualWidth             = new Vector4(virtualResolution.X / 2, 0, 0, 1);
                var virtualHeight            = new Vector4(0, virtualResolution.Y / 2, 0, 1);
                var transformedVirtualWidth  = Vector4.Zero;
                var transformedVirtualHeight = Vector4.Zero;
                for (var i = 0; i < 4; i++)
                {
                    transformedVirtualWidth[i]  = virtualWidth[0] * viewParameters.ViewProjectionMatrix[0 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                    transformedVirtualHeight[i] = virtualHeight[1] * viewParameters.ViewProjectionMatrix[4 + i] + viewParameters.ViewProjectionMatrix[12 + i];
                }
                var projectedOrigin        = virtualOrigin.XY() / virtualOrigin.W;
                var projectedVirtualWidth  = viewportSize * (transformedVirtualWidth.XY() / transformedVirtualWidth.W - projectedOrigin);
                var projectedVirtualHeight = viewportSize * (transformedVirtualHeight.XY() / transformedVirtualHeight.W - projectedOrigin);

                // Set default services
                rootElement.UIElementServices = new UIElementServices {
                    Services = RenderSystem.Services
                };

                // set default resource dictionary
                rootElement.ResourceDictionary = uiSystem.DefaultResourceDictionary;

                // update layouting context.
                layoutingContext.VirtualResolution          = virtualResolution;
                layoutingContext.RealResolution             = viewportSize;
                layoutingContext.RealVirtualResolutionRatio = new Vector2(projectedVirtualWidth.Length() / virtualResolution.X, projectedVirtualHeight.Length() / virtualResolution.Y);
                rootElement.LayoutingContext = layoutingContext;

                // perform the time-based updates of the UI element
                updatableRootElement.Update(drawTime);

                // update the UI element disposition
                rootElement.Measure(virtualResolution);
                rootElement.Arrange(virtualResolution, false);

                // update the UI element hierarchical properties
                var rootMatrix = Matrix.Translation(-virtualResolution / 2); // UI world is rotated of 180degrees along Ox
                updatableRootElement.UpdateWorldMatrix(ref rootMatrix, rootMatrix != uiElementState.LastRootMatrix);
                updatableRootElement.UpdateElementState(0);
                uiElementState.LastRootMatrix = rootMatrix;

                // clear and set the Depth buffer as required
                if (uiComponent.IsFullScreen)
                {
                    context.CommandList.Clear(renderingContext.DepthStencilBuffer, DepthStencilClearOptions.DepthBuffer | DepthStencilClearOptions.Stencil);
                }
                context.CommandList.SetRenderTarget(renderingContext.DepthStencilBuffer, renderingContext.RenderTarget);

                // start the image draw session
                renderingContext.StencilTestReferenceValue = 0;
                batch.Begin(context.GraphicsContext, ref viewParameters.ViewProjectionMatrix, BlendStates.AlphaBlend, uiSystem.KeepStencilValueState, renderingContext.StencilTestReferenceValue);

                // Render the UI elements in the final render target
                ReccursiveDrawWithClipping(context, rootElement);

                // end the image draw session
                batch.End();
            }

            // clear the list of compacted pointer events of time frame
            ClearPointerEvents();

            // revert the depth stencil buffer to the default value
            context.CommandList.SetRenderTargets(currentRenderFrame.DepthStencil, currentRenderFrame.RenderTargets);

            // Release scroped texture
            if (scopedDepthBuffer != null)
            {
                context.RenderContext.Allocator.ReleaseReference(scopedDepthBuffer);
            }
        }
Exemple #56
0
        protected override void DrawCore(RenderDrawContext context)
        {
            var originalColorBuffer = GetSafeInput(0);
            var originalDepthBuffer = GetSafeInput(1);

            var outputTexture = GetSafeOutput(0);

            var camera = context.RenderContext.GetCurrentCamera();

            //---------------------------------
            // 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);

            if (camera != null)
            {
                // Set Near/Far pre-calculated factors to speed up the linear depth reconstruction
                aoRawImageEffect.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(camera.NearClipPlane, camera.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      = camera.ProjectionMatrix.M11;
                var     p11      = camera.ProjectionMatrix.M22;
                var     p02      = camera.ProjectionMatrix.M13;
                var     p12      = camera.ProjectionMatrix.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);
                }

                if (camera != null)
                {
                    // Set Near/Far pre-calculated factors to speed up the linear depth reconstruction
                    blurH.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(camera.NearClipPlane, camera.FarClipPlane));
                    blurV.Parameters.Set(CameraKeys.ZProjection, CameraKeys.ZProjectionACalculate(camera.NearClipPlane, camera.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 #57
0
        public override void Prepare(RenderDrawContext context)
        {
            renderVoxelVolumeData = Context.VisibilityGroup.Tags.Get(CurrentProcessedVoxelVolumes);
            if (renderVoxelVolumeData is null)
            {
                return;
            }

            foreach (var processedVolumeKeyValue in renderVoxelVolumeData)
            {
                var processedVolume = processedVolumeKeyValue.Value;
                foreach (VoxelizationPass pass in processedVolume.passList.passes)
                {
                    var viewFeature = pass.view.Features[RootRenderFeature.Index];

                    // Find a PerView layout from an effect in normal state
                    ViewResourceGroupLayout firstViewLayout = null;
                    foreach (var viewLayout in viewFeature.Layouts)
                    {
                        // Only process view layouts in normal state
                        if (viewLayout.State != RenderEffectState.Normal)
                        {
                            continue;
                        }

                        var viewLighting = viewLayout.GetLogicalGroup(VoxelizerStorerCasterKey);
                        if (viewLighting.Hash != ObjectId.Empty)
                        {
                            firstViewLayout = viewLayout;
                            break;
                        }
                    }

                    // Nothing found for this view (no effects in normal state)
                    if (firstViewLayout is null)
                    {
                        continue;
                    }

                    var viewParameters = new ParameterCollection();

                    var firstViewLighting = firstViewLayout.GetLogicalGroup(VoxelizerStorerCasterKey);

                    // Prepare layout (should be similar for all PerView)
                    {
                        // Generate layout
                        var viewParameterLayout = new ParameterCollectionLayout();
                        viewParameterLayout.ProcessLogicalGroup(firstViewLayout, ref firstViewLighting);

                        viewParameters.UpdateLayout(viewParameterLayout);
                    }

                    ParameterCollection VSViewParameters = viewParameters;

                    pass.storer.ApplyVoxelizationParameters(VSViewParameters);
                    foreach (var attr in processedVolume.Attributes)
                    {
                        attr.Attribute.ApplyVoxelizationParameters(VSViewParameters);
                    }

                    foreach (var viewLayout in viewFeature.Layouts)
                    {
                        if (viewLayout.State != RenderEffectState.Normal)
                        {
                            continue;
                        }

                        var voxelizerStorer = viewLayout.GetLogicalGroup(VoxelizerStorerCasterKey);
                        if (voxelizerStorer.Hash == ObjectId.Empty)
                        {
                            continue;
                        }

                        if (voxelizerStorer.Hash != firstViewLighting.Hash)
                        {
                            throw new InvalidOperationException("PerView VoxelizerStorer layout differs between different RenderObject in the same RenderView.");
                        }

                        var resourceGroup = viewLayout.Entries[pass.view.Index].Resources;
                        resourceGroup.UpdateLogicalGroup(ref voxelizerStorer, VSViewParameters);
                    }
                }
            }
        }
        /// <inheritdoc/>
        public override unsafe void Prepare(RenderDrawContext context)
        {
            // Inspect each RenderObject (= ParticleEmitter) to determine if its required vertex buffer size has changed
            foreach (var renderObject in RenderObjects)
            {
                var renderParticleEmitter = (RenderParticleEmitter)renderObject;
                renderParticleEmitter.ParticleEmitter.PrepareForDraw(out renderParticleEmitter.HasVertexBufferChanged,
                                                                     out renderParticleEmitter.VertexSize, out renderParticleEmitter.VertexCount);

                // TODO: ParticleMaterial should set this up
                var materialInfo = (ParticleMaterialInfo)renderParticleEmitter.ParticleMaterialInfo;
                var colorShade   = renderParticleEmitter.Color.ToColorSpace(context.GraphicsDevice.ColorSpace);
                materialInfo?.Material.Parameters.Set(ParticleBaseKeys.ColorScale, colorShade);
            }

            // Calculate the total vertex buffer size required
            int totalVertexBufferSize  = 0;
            int highestIndexCount      = 0;
            var renderParticleNodeData = RenderData.GetData(renderParticleNodeKey);

            // Reset pipeline states if necessary
            for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++)
            {
                var renderNode            = RenderNodes[renderNodeIndex];
                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;

                if (renderParticleEmitter.HasVertexBufferChanged)
                {
                    // Reset pipeline state, so input layout is regenerated
                    if (renderNode.RenderEffect != null)
                    {
                        renderNode.RenderEffect.PipelineState = null;
                    }
                }

                // Write some attributes back which we will need for rendering later
                var vertexBuilder = renderParticleEmitter.ParticleEmitter.VertexBuilder;
                var newNodeData   = new RenderAttributesPerNode
                {
                    VertexBufferOffset = totalVertexBufferSize,
                    VertexBufferSize   = renderParticleEmitter.VertexSize * renderParticleEmitter.VertexCount,
                    VertexBufferStride = renderParticleEmitter.VertexSize,
                    IndexCount         = vertexBuilder.LivingQuads * vertexBuilder.IndicesPerQuad,
                };

                renderParticleNodeData[new RenderNodeReference(renderNodeIndex)] = newNodeData;

                totalVertexBufferSize += newNodeData.VertexBufferSize;
                if (newNodeData.IndexCount > highestIndexCount)
                {
                    highestIndexCount = newNodeData.IndexCount;
                }
            }

            base.Prepare(context);

            // Assign descriptor sets to each render node
            var resourceGroupPool = ResourceGroupPool;

            for (int renderNodeIndex = 0; renderNodeIndex < RenderNodes.Count; renderNodeIndex++)
            {
                var renderNodeReference   = new RenderNodeReference(renderNodeIndex);
                var renderNode            = RenderNodes[renderNodeIndex];
                var renderParticleEmitter = (RenderParticleEmitter)renderNode.RenderObject;

                // Ignore fallback effects
                if (renderNode.RenderEffect.State != RenderEffectState.Normal)
                {
                    continue;
                }

                // Collect materials and create associated MaterialInfo (includes reflection) first time
                // TODO: We assume same material will generate same ResourceGroup (i.e. same resources declared in same order)
                // Need to offer some protection if this invariant is violated (or support it if it can actually happen in real scenario)
                var material           = renderParticleEmitter.ParticleEmitter.Material;
                var materialInfo       = renderParticleEmitter.ParticleMaterialInfo;
                var materialParameters = material.Parameters;

                if (!MaterialRenderFeature.UpdateMaterial(RenderSystem, context, materialInfo, perMaterialDescriptorSetSlot.Index, renderNode.RenderEffect, materialParameters))
                {
                    continue;
                }

                var descriptorSetPoolOffset = ComputeResourceGroupOffset(renderNodeReference);
                resourceGroupPool[descriptorSetPoolOffset + perMaterialDescriptorSetSlot.Index] = materialInfo.Resources;
            }

            particleBufferContext.AllocateBuffers(context, totalVertexBufferSize, highestIndexCount);

            BuildParticleBuffers(context);
        }
Exemple #59
0
 public void Draw(RenderDrawContext drawContext, Texture inputDepthStencil, Texture output)
 {
     SetInput(0, inputDepthStencil);
     SetOutput(output);
     Draw(drawContext);
 }
Exemple #60
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage, int startIndex, int endIndex)
        {
            base.Draw(context, renderView, renderViewStage, startIndex, endIndex);

            var isMultisample = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount != MultisampleCount.None;

            var batchContext = threadContext.Value;

            Matrix viewInverse;

            Matrix.Invert(ref renderView.View, out viewInverse);

            uint previousBatchState = uint.MaxValue;

            //TODO string comparison ...?
            var isPicking = RenderSystem.RenderStages[renderViewStage.Index].Name == "Picking";

            bool hasBegin = false;

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

                var renderSprite = (RenderSprite)renderNode.RenderObject;

                var sprite = renderSprite.Sprite;
                if (sprite == null)
                {
                    continue;
                }

                // TODO: this should probably be moved to Prepare()
                // Project the position
                // TODO: This could be done in a SIMD batch, but we need to figure-out how to plugin in with RenderMesh object
                var worldPosition = new Vector4(renderSprite.WorldMatrix.TranslationVector, 1.0f);

                Vector4 projectedPosition;
                Vector4.Transform(ref worldPosition, ref renderView.ViewProjection, out projectedPosition);
                var projectedZ = projectedPosition.Z / projectedPosition.W;

                BlendModes     blendMode;
                EffectInstance currentEffect = null;
                if (isPicking)
                {
                    blendMode     = BlendModes.Default;
                    currentEffect = batchContext.GetOrCreatePickingSpriteEffect(RenderSystem.EffectSystem);
                }
                else
                {
                    var spriteBlend = renderSprite.BlendMode;
                    if (spriteBlend == SpriteBlend.Auto)
                    {
                        spriteBlend = sprite.IsTransparent ? SpriteBlend.AlphaBlend : SpriteBlend.None;
                    }

                    if (spriteBlend == SpriteBlend.AlphaBlend)
                    {
                        blendMode = renderSprite.PremultipliedAlpha ? BlendModes.Alpha : BlendModes.NonPremultiplied;
                    }
                    else
                    {
                        blendMode = spriteBlendToBlendMode[spriteBlend];
                    }
                }

                // Check if the current blend state has changed in any way, if not
                // Note! It doesn't really matter in what order we build the bitmask, the result is not preserved anywhere except in this method
                var currentBatchState = (uint)blendMode;
                currentBatchState = (currentBatchState << 1) + (renderSprite.IgnoreDepth ? 1U : 0U);
                currentBatchState = (currentBatchState << 1) + (renderSprite.IsAlphaCutoff ? 1U : 0U);
                currentBatchState = (currentBatchState << 2) + ((uint)renderSprite.Sampler);

                if (previousBatchState != currentBatchState)
                {
                    var blendState = blendModeToDescription[blendMode];

                    if (renderSprite.IsAlphaCutoff)
                    {
                        currentEffect = batchContext.GetOrCreateAlphaCutoffSpriteEffect(RenderSystem.EffectSystem);
                    }

                    var depthStencilState = renderSprite.IgnoreDepth ? DepthStencilStates.None : DepthStencilStates.Default;

                    var samplerState = context.GraphicsDevice.SamplerStates.LinearClamp;
                    if (renderSprite.Sampler != SpriteSampler.LinearClamp)
                    {
                        switch (renderSprite.Sampler)
                        {
                        case SpriteSampler.PointClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.PointClamp;
                            break;

                        case SpriteSampler.AnisotropicClamp:
                            samplerState = context.GraphicsDevice.SamplerStates.AnisotropicClamp;
                            break;
                        }
                    }

                    if (hasBegin)
                    {
                        lock (batchEndLocker)
                        {
                            batchContext.SpriteBatch.End();
                        }
                    }

                    var rasterizerState = RasterizerStates.CullNone;
                    if (isMultisample)
                    {
                        rasterizerState.MultisampleCount         = RenderSystem.RenderStages[renderViewStage.Index].Output.MultisampleCount;
                        rasterizerState.MultisampleAntiAliasLine = true;
                    }

                    batchContext.SpriteBatch.Begin(context.GraphicsContext, renderView.ViewProjection, SpriteSortMode.Deferred, blendState, samplerState, depthStencilState, rasterizerState, currentEffect);
                    hasBegin = true;
                }
                previousBatchState = currentBatchState;

                var sourceRegion = sprite.Region;
                var texture      = sprite.Texture;
                var color        = renderSprite.Color;
                if (isPicking) // TODO move this code corresponding to picking out of the runtime code.
                {
                    var compId = RuntimeIdHelper.ToRuntimeId(renderSprite.Source);
                    color = new Color4(compId, 0.0f, 0.0f, 0.0f);
                }

                // skip the sprite if no texture is set.
                if (texture == null)
                {
                    continue;
                }

                // determine the element world matrix depending on the type of sprite
                var worldMatrix = renderSprite.WorldMatrix;
                if (renderSprite.SpriteType == SpriteType.Billboard)
                {
                    worldMatrix = viewInverse;

                    var worldMatrixRow1 = worldMatrix.Row1;
                    var worldMatrixRow2 = worldMatrix.Row2;

                    // remove scale of the camera
                    worldMatrixRow1 /= ((Vector3)viewInverse.Row1).Length();
                    worldMatrixRow2 /= ((Vector3)viewInverse.Row2).Length();

                    // set the scale of the object
                    worldMatrixRow1 *= ((Vector3)renderSprite.WorldMatrix.Row1).Length();
                    worldMatrixRow2 *= ((Vector3)renderSprite.WorldMatrix.Row2).Length();

                    worldMatrix.Row1 = worldMatrixRow1;
                    worldMatrix.Row2 = worldMatrixRow2;

                    // set the position
                    worldMatrix.TranslationVector = renderSprite.WorldMatrix.TranslationVector;

                    // set the rotation
                    var localRotationZ = renderSprite.RotationEulerZ;
                    if (localRotationZ != 0)
                    {
                        worldMatrix = Matrix.RotationZ(localRotationZ) * worldMatrix;
                    }
                }

                // calculate normalized position of the center of the sprite (takes into account the possible rotation of the image)
                var normalizedCenter = new Vector2(sprite.Center.X / sourceRegion.Width - 0.5f, 0.5f - sprite.Center.Y / sourceRegion.Height);
                if (sprite.Orientation == ImageOrientation.Rotated90)
                {
                    var oldCenterX = normalizedCenter.X;
                    normalizedCenter.X = -normalizedCenter.Y;
                    normalizedCenter.Y = oldCenterX;
                }
                // apply the offset due to the center of the sprite
                var centerOffset = Vector2.Modulate(normalizedCenter, sprite.SizeInternal);
                worldMatrix.M41 -= centerOffset.X * worldMatrix.M11 + centerOffset.Y * worldMatrix.M21;
                worldMatrix.M42 -= centerOffset.X * worldMatrix.M12 + centerOffset.Y * worldMatrix.M22;
                worldMatrix.M43 -= centerOffset.X * worldMatrix.M13 + centerOffset.Y * worldMatrix.M23;

                // adapt the source region to match what is expected at full resolution
                if (texture.ViewType == ViewType.Full && texture.ViewWidth != texture.FullQualitySize.Width)
                {
                    var fullQualitySize = texture.FullQualitySize;
                    var horizontalRatio = texture.ViewWidth / (float)fullQualitySize.Width;
                    var verticalRatio   = texture.ViewHeight / (float)fullQualitySize.Height;
                    sourceRegion.X      *= horizontalRatio;
                    sourceRegion.Width  *= horizontalRatio;
                    sourceRegion.Y      *= verticalRatio;
                    sourceRegion.Height *= verticalRatio;
                }

                // register resource usage.
                Context.StreamingManager?.StreamResources(texture);

                // draw the sprite
                batchContext.SpriteBatch.Draw(texture, ref worldMatrix, ref sourceRegion, ref sprite.SizeInternal, ref color, sprite.Orientation, renderSprite.Swizzle, projectedZ);
            }

            if (hasBegin)
            {
                lock (batchEndLocker)
                {
                    batchContext.SpriteBatch.End();
                }
            }
        }