Ejemplo n.º 1
0
        private void AddMaterialToArrayAndDictionary(ScatteringParameters scatteringParameters, uint materialArrayIndex)
        {
            // "SetScatteringWidth()" throws an exception if the range is exceeded. // TODO: How to handle this? Don't throw at all?
            SubsurfaceScatteringBlurEffect.SetScatteringWidth(materialArrayIndex, scatteringParameters.ScatteringWidth); // Add the scattering width to the scattering width array.
            if (scatteringParameters.ScatteringKernel != null)
            {
                // TODO: STABILITY: What to do if the scattering width is present but no kernel? The post-process wouldn't be able to handle that correctly.
                //                  Maybe just save a dummy kernel?
                SubsurfaceScatteringBlurEffect.SetScatteringKernel(materialArrayIndex, scatteringParameters.ScatteringKernel);
            }

            scatteringParametersToArrayIndexDictionary[scatteringParameters] = materialArrayIndex; // Add the material to the dictionary and save its associated index in the scattering width array.
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public override void Prepare(RenderDrawContext context)
        {
            if (DeduplicateMaterialParameters)
            {
                scatteringParametersToArrayIndexDictionary.Clear();
            }

            // TODO: Generate a material array per view? This could in some cases limit the number of materials present in the array.
            //       In case every object is visible from every view, it wouldn't save us anything though.

            uint materialArrayIndexCounter = 1; // We start at index 1 instead of 0 because we use index 0 to flag (and discard) non-scattering materials.

            // TODO: Not sure if the following line is even necessary, because we don't use any material parameters of material 0 anyway. I mean not even the kernel of material 0 is set. So either set both or none.
            SubsurfaceScatteringBlurEffect.SetScatteringWidth(0, 0.0f);    // This element is unused because a material index of 0 means the material is not a subsurface scattering material and therefore will be skipped by the post-process.

            // Generate the material dictionary that contains only scattering materials:
            //Dispatcher.ForEach(((RootEffectRenderFeature)RootRenderFeature).RenderNodes, (ref RenderNode renderNode) =>   // TODO: PERFORMANCE: Use this instead?
            foreach (RenderNode renderNode in ((RootEffectRenderFeature)RootRenderFeature).RenderNodes)
            {
                var perDrawLayout = renderNode.RenderEffect?.Reflection?.PerDrawLayout;
                if (perDrawLayout == null)
                {
                    continue;
                }

                var  renderMesh         = (RenderMesh)renderNode.RenderObject;
                uint materialArrayIndex = 0; // If the mesh doesn't have a scattering kernel we write index 0 into the constant buffer.

                if (HasScatteringKernel(renderMesh.MaterialPass))
                {
                    materialArrayIndex = AddMaterialToDictionaryAndGetArrayIndex(renderMesh, ref materialArrayIndexCounter);
                }

                WriteMaterialIndexIntoRenderNodeConstantBuffer(perDrawLayout, renderNode, materialArrayIndex);
            }

            bool scatteringMaterialsAreVisible = (materialArrayIndexCounter > 1);

            SubsurfaceScatteringBlurEffect.Enabled = scatteringMaterialsAreVisible;   // Disable the post-process if no scattering objects are visible (to save performance).
        }
Ejemplo n.º 3
0
        protected virtual void DrawView(RenderContext context, RenderDrawContext drawContext, int eyeIndex, int eyeCount)
        {
            var renderSystem = context.RenderSystem;

            PrepareVRConstantBuffer(context, eyeIndex, eyeCount);

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

            if (lightProbes)
            {
                // Note: Baking lightprobe 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 == 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;
                }

                // Shafts if we have them
                if (LightShafts != null)
                {
                    using (drawContext.QueryManager.BeginProfile(Color.Green, CompositingProfilingKeys.LightShafts))
                    {
                        LightShafts.Draw(drawContext, depthStencil, renderTargets[colorTargetIndex]);
                    }
                }

                if (PostEffects != null)
                {
                    // Run post effects
                    // 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);
                }
            }
        }