예제 #1
0
        public override void Initialize()
        {
            base.Initialize();

            boundingBoxPass   = new RenderPass("BoundingBoxPass");
            minMaxPass        = new RenderPass("MinmaxPass");
            lightShaftPass    = new RenderPass("LightShaftPass");
            filterUpscalePass = new RenderPass("UpscalePass");
            RenderPass.AddPass(boundingBoxPass, minMaxPass, lightShaftPass, filterUpscalePass);

            var useUpScaling = false;

            var bbRenderTargetPlugin = new RenderTargetsPlugin("BoundingBoxRenderTargetPlugin")
            {
                EnableSetTargets  = true,
                EnableClearTarget = true,
                RenderPass        = boundingBoxPass,
                Services          = Services,
            };

            var minMaxEffectBuilder = this.EffectSystemOld.BuildEffect("MinMax")
                                      .Using(new MinMaxShaderPlugin("MinMaxShaderPlugin")
            {
                RenderPassPlugin = bbRenderTargetPlugin
            })
                                      .Using(new BasicShaderPlugin("TransformationWVP")
            {
                RenderPassPlugin = bbRenderTargetPlugin
            });


            var minmaxEffectBuilder = this.EffectSystemOld.BuildEffect("LightShaftsMinMax")
                                      .Using(new PostEffectSeparateShaderPlugin()
            {
                RenderPass = minMaxPass
            })
                                      .Using(new BasicShaderPlugin("ForwardShadowMapBase")
            {
                RenderPass = minMaxPass
            })
                                      .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectMinMax", "ShadowMapUtils.shadowMapTexture", "PointSampler", 4, 4, 0.0, 1.0))
            {
                RenderPass = minMaxPass
            });

            var lightShaftsEffectBuilder = this.EffectSystemOld.BuildEffect("LightShafts")
                                           .Using(new PostEffectSeparateShaderPlugin()
            {
                RenderPass = lightShaftPass
            })
                                           .Using(new StateShaderPlugin()
            {
                UseBlendState = !useUpScaling, RenderPass = lightShaftPass
            })
                                           //.Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectLightShafts", Debug ? 1 : 0, RenderContext.IsZReverse ? 1 : 0, StepCount)) { RenderPass = lightShaftPass });
                                           .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectLightShafts", Debug ? 1 : 0, false ? 1 : 0, StepCount))
            {
                RenderPass = lightShaftPass
            });

            if (OfflineCompilation)
            {
                minMaxEffectBuilder.InstantiatePermutation();
                minmaxEffectBuilder.InstantiatePermutation();
                lightShaftsEffectBuilder.InstantiatePermutation();
                return;
            }

            Parameters.AddSources(ViewParameters);
            Parameters.Set(RenderTargetKeys.DepthStencilSource, DepthStencil.Texture);
            Parameters.Set(TexturingKeys.Sampler, GraphicsDevice.SamplerStates.PointClamp);

            // BoundingBox prepass
            var gbufferDesc    = RenderTarget.Description;
            var bbRenderTarget = Texture2D.New(GraphicsDevice, gbufferDesc.Width / 8, gbufferDesc.Height / 8, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);

            // Use MinMax Plugin
            bbRenderTargetPlugin.RenderTarget = bbRenderTarget.ToRenderTarget();
            bbRenderTargetPlugin.Parameters.AddSources(Parameters);
            bbRenderTargetPlugin.Apply();

            EffectOld minMaxEffect = minMaxEffectBuilder.InstantiatePermutation();

            // Add meshes
            foreach (var bbMeshData in BoundingBoxes)
            {
                // Mesh for MinPass
                var bbMesh = new EffectMesh(minMaxEffect, bbMeshData).KeepAliveBy(this);
                // Add mesh
                // boundingBoxPass.AddPass(bbMesh.EffectMeshPasses[0].EffectPass);
                RenderSystem.GlobalMeshes.AddMesh(bbMesh);
            }

            // MinMax render target
            var minMaxRenderTarget = Texture2D.New(GraphicsDevice, 256, 256, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);

            minMaxPass.Parameters = new ParameterCollection(null);
            minMaxPass.Parameters.AddSources(ShadowMap.Parameters);
            minMaxPass.Parameters.AddSources(Parameters);
            minMaxPass.Parameters.AddDynamic(PostEffectMinMaxKeys.MinMaxCoords, ParameterDynamicValue.New(LightingPlugin.CascadeTextureCoords, (ref Vector4[] cascadeTextureCoords, ref Vector4 output) =>
            {
                output = cascadeTextureCoords[0];
            }, autoCheckDependencies: false));

            EffectOld minmaxEffect = minmaxEffectBuilder.InstantiatePermutation();

            var minMaxMesh = new EffectMesh(minmaxEffect).KeepAliveBy(this);

            minMaxMesh.Parameters.Set(RenderTargetKeys.RenderTarget, minMaxRenderTarget.ToRenderTarget());
            RenderSystem.GlobalMeshes.AddMesh(minMaxMesh);

            // Light Shafts effect
            var blendStateDesc = new BlendStateDescription();

            blendStateDesc.SetDefaults();
            blendStateDesc.AlphaToCoverageEnable        = false;
            blendStateDesc.IndependentBlendEnable       = false;
            blendStateDesc.RenderTargets[0].BlendEnable = true;

            blendStateDesc.RenderTargets[0].AlphaBlendFunction    = BlendFunction.Add;
            blendStateDesc.RenderTargets[0].AlphaSourceBlend      = Blend.One;
            blendStateDesc.RenderTargets[0].AlphaDestinationBlend = Blend.One;

            blendStateDesc.RenderTargets[0].ColorBlendFunction    = BlendFunction.Add;
            blendStateDesc.RenderTargets[0].ColorSourceBlend      = Blend.One;
            blendStateDesc.RenderTargets[0].ColorDestinationBlend = Blend.One;

            blendStateDesc.RenderTargets[0].ColorWriteChannels = ColorWriteChannels.All;

            var additiveBlending = BlendState.New(GraphicsDevice, blendStateDesc);

            additiveBlending.Name = "LightShaftAdditiveBlend";

            var shaftRenderTarget = useUpScaling ? Texture2D.New(GraphicsDevice, gbufferDesc.Width / 2, gbufferDesc.Height / 2, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget() : RenderTarget;


            lightShaftPass.Parameters = new ParameterCollection();
            lightShaftPass.Parameters.AddSources(ShadowMap.Parameters);
            lightShaftPass.Parameters.AddSources(Parameters);

            this.lightShaftsEffect = lightShaftsEffectBuilder.InstantiatePermutation();


            var mesh = new EffectMesh(lightShaftsEffect).KeepAliveBy(this);

            mesh.Parameters.Set(TexturingKeys.Texture0, minMaxRenderTarget);
            mesh.Parameters.Set(TexturingKeys.Texture1, bbRenderTarget);
            mesh.Parameters.Set(RenderTargetKeys.RenderTarget, shaftRenderTarget);

            if (!useUpScaling)
            {
                mesh.Parameters.Set(EffectPlugin.BlendStateKey, additiveBlending);
            }
            RenderSystem.GlobalMeshes.AddMesh(mesh);

            // Bilateral Gaussian filtering for up-sampling
            if (useUpScaling)
            {
                var bbRenderTargetUpScaleH = Texture2D.New(GraphicsDevice, gbufferDesc.Width, gbufferDesc.Height / 2, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
                var bbRenderTargetUpScaleV = RenderTarget;
                //var bbRenderTargetUpScaleV = GraphicsDevice.RenderTarget2D.New(gbufferDesc.Width, gbufferDesc.Height, PixelFormat.HalfVector4);

                var blurEffects = new EffectOld[] {
                    this.EffectSystemOld.BuildEffect("BilateralGaussianFiltering")
                    .Using(new PostEffectSeparateShaderPlugin())
                    .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectBilateralGaussian", 0))),
                    this.EffectSystemOld.BuildEffect("BilateralGaussianFiltering")
                    .Using(new StateShaderPlugin()
                    {
                        UseBlendState = true
                    })
                    .Using(new PostEffectSeparateShaderPlugin())
                    .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectBilateralGaussian", 1))),
                };

                Texture2D    textureSourceH = (Texture2D)shaftRenderTarget.Texture;
                Texture2D    textureSourceV = bbRenderTargetUpScaleH;
                RenderTarget renderTargetH  = bbRenderTargetUpScaleH.ToRenderTarget();
                RenderTarget renderTargetV  = bbRenderTargetUpScaleV;

                var blurQuadMesh = new EffectMesh[2];
                for (int i = 0; i < 2; ++i)
                {
                    blurQuadMesh[i] = new EffectMesh(blurEffects[i]).KeepAliveBy(this);
                    filterUpscalePass.AddPass(blurQuadMesh[i].EffectPass);
                    RenderSystem.GlobalMeshes.AddMesh(blurQuadMesh[i]);
                }

                blurQuadMesh[0].Parameters.Set(TexturingKeys.Texture0, textureSourceH);
                blurQuadMesh[1].Parameters.Set(TexturingKeys.Texture0, textureSourceV);
                blurQuadMesh[0].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetH);
                blurQuadMesh[1].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetV);

                // Additive blending for 2nd render target
                blurQuadMesh[1].Parameters.Set(EffectPlugin.BlendStateKey, additiveBlending);
            }
        }
예제 #2
0
        public override void Load()
        {
            base.Load();

            if (OfflineCompilation)
            {
                return;
            }

            // Declare post render pass
            PostPass = new RenderPass("PostPass").KeepAliveBy(ActiveObjects);
            RenderPass.AddPass(PostPass);


            var depthStencilTexture = Texture.New2D(GraphicsDevice, AtlasSize, AtlasSize, PixelFormat.D32_Float, TextureFlags.DepthStencil | TextureFlags.ShaderResource).KeepAliveBy(ActiveObjects);
            var depthStencilBuffer  = depthStencilTexture.ToDepthStencilBuffer(false);

            ShadowMapDepth = depthStencilBuffer;

            //MainTargetPlugin.Parameters.Set(ShadowMapKeys.Texture0, ShadowMapDepth);

            // Setup clear of this target
            var renderTargetPlugin = new RenderTargetsPlugin
            {
                Services         = Services,
                EnableClearDepth = true,
                EnableSetTargets = false,
                RenderPass       = RenderPass,
                RenderTarget     = null,
                DepthStencil     = depthStencilBuffer,
            };

            renderTargetPlugin.Apply();

            // Use Default ZTest for GBuffer
            depthStencilStateZStandard      = DepthStencilState.New(GraphicsDevice, new DepthStencilStateDescription().Default()).KeepAliveBy(ActiveObjects);
            depthStencilStateZStandard.Name = "ZStandard";

            Parameters.Set(EffectPlugin.DepthStencilStateKey, depthStencilStateZStandard);

            casterRasterizerState = RasterizerState.New(GraphicsDevice, new RasterizerStateDescription(CullMode.Back)).KeepAliveBy(ActiveObjects);

            // Variance Shadow Mapping
            // Create the blur temporary texture
            var shadowMapTextureDesc = ShadowMapDepth.Description;
            var shadowMapBlurH       = Texture.New2D(GraphicsDevice, shadowMapTextureDesc.Width, shadowMapTextureDesc.Height, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).KeepAliveBy(ActiveObjects);
            var shadowMapBlurV       = Texture.New2D(GraphicsDevice, shadowMapTextureDesc.Width, shadowMapTextureDesc.Height, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).KeepAliveBy(ActiveObjects);

            Texture2D    textureSourceH = ShadowMapDepth.Texture;
            Texture2D    textureSourceV = shadowMapBlurH;
            RenderTarget renderTargetH  = shadowMapBlurH.ToRenderTarget();
            RenderTarget renderTargetV  = shadowMapBlurV.ToRenderTarget();

            var blurQuadMesh = new EffectMesh[2];

            for (int j = 0; j < BlurCount; j++)
            {
                for (int i = 0; i < 2; ++i)
                {
                    blurQuadMesh[i] = new EffectMesh(j > 0 ? blurEffects[1] : blurEffects[i]).KeepAliveBy(ActiveObjects);
                    blurQuadMesh[i].Parameters.Set(PostEffectBlurKeys.Coefficients, new[] { 0.2270270270f, 0.3162162162f, 0.3162162162f, 0.0702702703f, 0.0702702703f });
                    var unit = i == 0 ? Vector2.UnitX : Vector2.UnitY;
                    blurQuadMesh[i].Parameters.Set(PostEffectBlurKeys.Offsets, new[] { Vector2.Zero, unit * -1.3846153846f, unit * +1.3846153846f, unit * -3.2307692308f, unit * +3.2307692308f });

                    PostPass.AddPass(blurQuadMesh[i].EffectPass);

                    RenderSystem.GlobalMeshes.AddMesh(blurQuadMesh[i]);
                }

                blurQuadMesh[0].Parameters.Set(TexturingKeys.Texture0, textureSourceH);
                blurQuadMesh[1].Parameters.Set(TexturingKeys.Texture0, textureSourceV);
                blurQuadMesh[0].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetH);
                blurQuadMesh[1].Parameters.Set(RenderTargetKeys.RenderTarget, renderTargetV);

                textureSourceH = shadowMapBlurV;
                textureSourceV = shadowMapBlurH;
            }

            ShadowMapVsm = shadowMapBlurV;

            // Final texture for VSM is result of blur
            //MainTargetPlugin.Parameters.Set(ShadowMapKeys.Texture0, shadowMapBlurV);
        }
예제 #3
0
        private void OnFrameUpdate(ThreadContext context)
        {
            updatePasses.Enabled = true; //!RenderContext.IsPaused;

            // Add new updater to the current list
            foreach (var particleUpdater in Updaters)
            {
                ParticleUpdaterState particleUpdaterState = null;
                foreach (ParticleUpdaterState state in currentUpdaters)
                {
                    if (ReferenceEquals(state.UserState, particleUpdater))
                    {
                        particleUpdaterState = state;
                        break;
                    }
                }
                if (particleUpdaterState == null)
                {
                    currentUpdaters.Add(new ParticleUpdaterState()
                    {
                        UserState = particleUpdater, StructureSize = StructureSize
                    });
                }
            }

            // Get updater to remove from current list
            foreach (var particleUpdater in currentUpdaters)
            {
                ParticleEmitterComponent particleUpdaterState = null;
                foreach (ParticleEmitterComponent state in Updaters)
                {
                    if (ReferenceEquals(state, particleUpdater.UserState))
                    {
                        particleUpdaterState = state;
                        break;
                    }
                }
                if (particleUpdaterState == null)
                {
                    updatersToRemove.Add(particleUpdater);
                }
            }

            // Remove from the current list
            foreach (var particleUpdaterState in updatersToRemove)
            {
                currentUpdaters.Remove(particleUpdaterState);

                // Remove the mesh to be rendered
                meshesToRender.RemoveMesh(particleUpdaterState.MeshUpdater);

                // Dispose the previous particule updater as it is no longer used
                particleUpdaterState.DisposeBuffers();
            }

            // Reallocate global buffers if needed
            if (updatersCount > capacityCount)
            {
                CapacityCount = updatersCount;
                OnCapacityCountChange();
            }

            int particleUpdaterIndex = 1;

            currentParticleCount = 0;
            // Update start index into global buffers for all CPU/GPU static buffers.
            int startIndex = 0;

            for (int i = 0; i < currentUpdaters.Count; i++)
            {
                var currentState = currentUpdaters[i];
                var userState    = currentState.UserState;

                if (!userState.IsDynamicEmitter)
                {
                    // If there is a change from dynamic type to CPU/GPU static buffer, we need to deallocate previous Append/ConsumeBuffers
                    if (currentState.IsDynamicEmitter)
                    {
                        currentState.DisposeBuffers();
                    }
                }
                else if (userState.Count > currentState.Count)
                {
                    // This is a dynamic buffer and the new buffer is larger than previous one
                    // or we simply need to allocate new consume/append buffers
                    currentState.AllocateBuffers(context.GraphicsDevice);
                }

                // Create Effect shader
                if (!ReferenceEquals(userState.Shader, currentState.Shader) || currentState.Count != userState.Count)
                {
                    // Remove the effect pass
                    updatePasses.RemovePass(currentState.EffectPass);

                    // Dispose previous effects
                    currentState.DisposeEffects();

                    // Remove mesh
                    if (currentState.MeshUpdater != null)
                    {
                        meshesToRender.RemoveMesh(currentState.MeshUpdater);
                        currentState.MeshUpdater = null;
                    }

                    // Compile new shader
                    if (userState.Shader != null)
                    {
                        string name = userState.Name ?? string.Format("{0}{1}", userState.Shader.ClassName, particleUpdaterIndex++);

                        currentState.EffectPass = new RenderPass(name);
                        updatePasses.AddPass(currentState.EffectPass);

                        // Calculate the best dispatch thread count
                        int dispatchCount = MaximumThreadPerGroup;
                        while (dispatchCount > 0)
                        {
                            // If the maximum count is a multiple of the current dispatchCount use it
                            if ((userState.Count & (dispatchCount - 1)) == 0)
                            {
                                break;
                            }
                            dispatchCount >>= 1;
                        }

                        // Compile the new shader for this count
                        currentState.EffectUpdater = this.EffectSystemOld.BuildEffect(name).Using(
                            new ComputeShaderPlugin(userState.Shader, dispatchCount, 1, 1)
                        {
                            RenderPass = currentState.EffectPass,
                            Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName) }
                        });

                        // Instantiate the mesh updater
                        var meshParams = new ParameterCollection(name);
                        currentState.MeshUpdater = new EffectMesh(currentState.EffectUpdater, new Mesh {
                            Parameters = meshParams
                        }).Dispatch(userState.Count / dispatchCount, 1, 1);
                        currentState.MeshUpdater.Parameters.AddSources(Parameters);
                        currentState.MeshUpdater.Parameters.AddSources(MainPlugin.ViewParameters);
                        currentState.MeshUpdater.Parameters.AddSources(userState.Parameters);

                        // Setup Append/Consume
                        if (userState.IsDynamicEmitter)
                        {
                            currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleInputBuffer, currentState.ConsumeBuffer);
                            currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleOutputBuffer, currentState.AppendBuffer);
                            currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleStartIndex, (uint)0);
                        }
                        else
                        {
                            // Setup update on global buffer
                            currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleGlobalBuffer, globalBuffer);
                            currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleStartIndex, (uint)startIndex);
                        }

                        // Add this updater to the rendering list
                        meshesToRender.AddMesh(currentState.MeshUpdater);
                    }
                }

                // Setup Append/Consume
                if (currentState.MeshUpdater != null && !userState.IsDynamicEmitter && currentState.StartIndex != startIndex)
                {
                    // Setup update on global buffer
                    currentState.MeshUpdater.Parameters.Set(ParticleBaseKeys.ParticleStartIndex, (uint)startIndex);
                }

                // Transfer CPU buffer to GPU
                if (!ReferenceEquals(userState.ParticleData, currentState.ParticleData) ||
                    userState.UpdateNextBuffer ||
                    userState.Type == ParticleEmitterType.CpuDynamic ||
                    currentState.StartIndex != startIndex ||
                    currentState.Count != userState.Count
                    )
                {
                    // Update the data if necessary
                    userState.OnUpdateData();

                    if (userState.ParticleData != null)
                    {
                        var handle = GCHandle.Alloc(userState.ParticleData, GCHandleType.Pinned);
                        globalBuffer.SetData(context.GraphicsDevice, new DataPointer(handle.AddrOfPinnedObject(), userState.Count * StructureSize), startIndex * StructureSize);
                        handle.Free();
                    }
                    userState.UpdateNextBuffer = false;
                }

                // Replicate the shader to the current state
                currentState.Type   = userState.Type;
                currentState.Shader = userState.Shader;
                currentState.Count  = userState.Count;
                currentState.ParticleElementSize = userState.ParticleElementSize;
                currentState.ParticleData        = userState.ParticleData;
                currentState.StartIndex          = startIndex;

                // Copy Maximum count to current state
                currentParticleCount += userState.Count;

                // Update start index
                startIndex += userState.Count;
            }

            // Add mesh to the render list
            if (updatersCount > 0)
            {
                if (!isParticleRenderingEnabled)
                {
                    isParticleRenderingEnabled = true;

                    meshesToRender.AddMesh(effectMeshRender);
                    meshesToRender.AddMesh(effectMeshCopyToSortBuffer);
                }
            }
            else
            {
                isParticleRenderingEnabled = false;
                meshesToRender.RemoveMesh(effectMeshRender);
                meshesToRender.RemoveMesh(effectMeshCopyToSortBuffer);
            }

            // Prepare mesh for rendering
            PrepareForRendering();
        }
예제 #4
0
        public override void Load()
        {
            base.Load();

            RenderPass.AddPass(boundingBoxPass, heatShimmerPass, heatShimmerComposePass);

            // Use MinMax Plugin
            var bbRenderTargetPlugin = new RenderTargetsPlugin("BoundingBoxRenderTargetPlugin")
            {
                EnableSetTargets  = true,
                EnableClearTarget = true,
                RenderTarget      = null,
                RenderPass        = boundingBoxPass,
                Services          = Services
            };

            bbRenderTargetPlugin.Apply();

            Parameters.AddSources(ViewParameters);
            Parameters.SetDefault(RenderTargetKeys.DepthStencilSource);
            Parameters.SetDefault(TexturingKeys.Sampler);
            bbRenderTargetPlugin.Parameters.AddSources(Parameters);

            EffectOld minMaxEffect = this.EffectSystemOld.BuildEffect("MinMax")
                                     .Using(new MinMaxShaderPlugin("MinMaxShaderPlugin")
            {
                RenderPassPlugin = bbRenderTargetPlugin
            })
                                     .Using(new BasicShaderPlugin("TransformationWVP")
            {
                RenderPassPlugin = bbRenderTargetPlugin
            })
                                     .KeepAliveBy(ActiveObjects)
                                     .InstantiatePermutation()
                                     .KeepAliveBy(ActiveObjects);

            heatShimmerPass.Parameters = new ParameterCollection();
            heatShimmerPass.Parameters.AddSources(Parameters);
            heatShimmerPass.Parameters.AddSources(NoisePlugin.Parameters);

            EffectOld heatShimmerEffect = this.EffectSystemOld.BuildEffect("HeatShimmer")
                                          .Using(new PostEffectSeparateShaderPlugin()
            {
                RenderPass = heatShimmerPass
            })
                                          .Using(
                new BasicShaderPlugin(
                    new ShaderMixinSource()
            {
                Mixins = new List <ShaderClassSource>()
                {
                    // TODO add support for IsZReverse
                    //new ShaderClassSource("PostEffectHeatShimmer", Debug ? 1 : 0, effectSystemOld.IsZReverse ? 1 : 0, 3),
                    new ShaderClassSource("PostEffectHeatShimmer", Debug ? 1 : 0, false ? 1 : 0, 3)
                },
                Compositions = new Dictionary <string, ShaderSource>()
                {
                    { "NoiseSource", new ShaderClassSource("SimplexNoise") }
                },
            }
                    )
            {
                RenderPass = heatShimmerPass
            })
                                          .KeepAliveBy(ActiveObjects)
                                          .InstantiatePermutation()
                                          .KeepAliveBy(ActiveObjects);

            EffectOld heatShimmerDisplayEffect = this.EffectSystemOld.BuildEffect("HeatShimmer")
                                                 .Using(new PostEffectSeparateShaderPlugin()
            {
                RenderPass = heatShimmerComposePass
            })
                                                 .Using(new BasicShaderPlugin(new ShaderClassSource("PostEffectHeatShimmerDisplay", Debug ? 1 : 0))
            {
                RenderPass = heatShimmerComposePass
            })
                                                 .KeepAliveBy(ActiveObjects)
                                                 .InstantiatePermutation()
                                                 .KeepAliveBy(ActiveObjects);

            if (OfflineCompilation)
            {
                return;
            }

            Parameters.Set(RenderTargetKeys.DepthStencilSource, DepthStencil.Texture);
            Parameters.Set(TexturingKeys.Sampler, GraphicsDevice.SamplerStates.PointClamp);

            // ------------------------------------------
            // BoundingBox prepass
            // ------------------------------------------
            var renderTargetDesc = RenderSource.Description;
            var bbRenderTarget   = Texture2D.New(GraphicsDevice, renderTargetDesc.Width, renderTargetDesc.Height, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).KeepAliveBy(ActiveObjects);

            bbRenderTargetPlugin.RenderTarget = bbRenderTarget.ToRenderTarget();

            // Add meshes
            foreach (var bbMeshData in BoundingBoxes)
            {
                // Mesh for MinPass
                var bbMesh = new EffectMesh(minMaxEffect, bbMeshData).KeepAliveBy(ActiveObjects);
                // Add mesh
                // boundingBoxPass.AddPass(bbMesh.EffectMeshPasses[0].EffectPass);
                effectMeshes.Add(bbMesh);
                RenderSystem.GlobalMeshes.AddMesh(bbMesh);
            }

            // ------------------------------------------
            // Heat Compute
            // ------------------------------------------
            var shimmerTexture      = Texture2D.New(GraphicsDevice, renderTargetDesc.Width, renderTargetDesc.Height, PixelFormat.R8_UNorm, TextureFlags.ShaderResource | TextureFlags.RenderTarget);
            var shimmerRenderTarget = shimmerTexture.ToRenderTarget();

            heatShimmerPass.StartPass += context => context.GraphicsDevice.Clear(shimmerRenderTarget, Color.Black);

            var quadMesh = new EffectMesh(heatShimmerEffect).KeepAliveBy(ActiveObjects);

            quadMesh.Parameters.Set(TexturingKeys.Texture1, bbRenderTarget);
            quadMesh.Parameters.Set(RenderTargetKeys.RenderTarget, shimmerRenderTarget);

            effectMeshes.Add(quadMesh);
            RenderSystem.GlobalMeshes.AddMesh(quadMesh);

            // ------------------------------------------
            // Heat display
            // ------------------------------------------
            quadMesh = new EffectMesh(heatShimmerDisplayEffect).KeepAliveBy(ActiveObjects);
            quadMesh.Parameters.Set(TexturingKeys.Texture0, RenderSource);
            quadMesh.Parameters.Set(TexturingKeys.Texture1, shimmerTexture);
            quadMesh.Parameters.Set(RenderTargetKeys.RenderTarget, RenderTarget);

            effectMeshes.Add(quadMesh);
            RenderSystem.GlobalMeshes.AddMesh(quadMesh);
        }
예제 #5
0
        public override void Load()
        {
            base.Load();

            if (string.IsNullOrEmpty(StructureName) || StructureSize == 0)
            {
                throw new InvalidOperationException("StructureName and StructureSize must be setup on ParticlePlugin");
            }

            // Add passes to the render pass
            RenderPass.AddPass(updatePasses, copyPass, sortPass, renderPass);

            // Create effect to copy from particle buffer to sort buffer
            effectCopyToSortBuffer = this.EffectSystemOld.BuildEffect("CopyToSortBuffer").Using(
                new ComputeShaderPlugin(new ShaderClassSource("ParticleSortInitializer"), MaximumThreadPerGroup, 1, 1)
            {
                RenderPass = copyPass,
                Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName) }
            });
            effectCopyToSortBuffer.KeepAliveBy(ActiveObjects);
            effectCopyToSortBuffer.Parameters.AddSources(MainPlugin.ViewParameters);
            effectMeshCopyToSortBuffer = new EffectMesh(effectCopyToSortBuffer);

            // Clear the sort buffer
            copyPass.StartPass.AddFirst = (context) =>
            {
                if (CapacityCount > 0)
                {
                    // TODO handle progressive sorting
                    context.GraphicsDevice.ClearReadWrite(sortBuffer, new UInt4(0xFF7FFFFF));     // 0xFF7FFFFF = - float.MaxValue
                }
            };

            // Create effect for bitonic sort 1 - pass 1
            effectBitonicSort1Pass1 = this.EffectSystemOld.BuildEffect("ParticleBitonicSort1-Pass1").Using(
                new ComputeShaderPlugin(new ShaderClassSource("ParticleBitonicSort1"), MaximumThreadPerGroup, 1, 1)
            {
                RenderPass = bitonicSort1Pass1,
                Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName),
                               new ShaderMacro("PARTICLE_SORT_PASS", 0) }
            });
            effectBitonicSort1Pass1.KeepAliveBy(this);
            effectMeshSort1Pass1 = new EffectMesh(effectBitonicSort1Pass1);

            // Create effect for bitonic sort 1 - pass 2
            effectBitonicSort1Pass2 = this.EffectSystemOld.BuildEffect("ParticleBitonicSort1-Pass2").Using(
                new ComputeShaderPlugin(new ShaderClassSource("ParticleBitonicSort1"), MaximumThreadPerGroup, 1, 1)
            {
                RenderPass = bitonicSort1Pass2,
                Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName),
                               new ShaderMacro("PARTICLE_SORT_PASS", 1) }
            });
            effectBitonicSort1Pass2.KeepAliveBy(this);
            effectMeshSort1Pass2 = new EffectMesh(effectBitonicSort1Pass2);

            // Creates Effect for bitonic sort 2
            var currentDepth = MaximumDepthLevel;

            for (int i = 0; i < bitonicSort2Passes.Length; i++)
            {
                var bitonicShader = new RenderPass(string.Format("Bitonic-{0}", currentDepth));
                bitonicSort2Passes[i] = bitonicShader;

                // Compile the new shader for this count
                effectBitonicSort2[i] = this.EffectSystemOld.BuildEffect("ParticleBitonicSort2-" + currentDepth).Using(
                    new ComputeShaderPlugin(new ShaderClassSource("ParticleBitonicSort2", currentDepth), MaximumThreadPerGroup, 1, 1)
                {
                    RenderPass = bitonicShader,
                    Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName) }
                });
                effectBitonicSort2[i].KeepAliveBy(this);

                currentDepth /= 2;
            }
            effectMeshBitonicSort2 = new EffectMesh[bitonicSort2Passes.Length];
            for (int i = 0; i < effectMeshBitonicSort2.Length; i++)
            {
                effectMeshBitonicSort2[i] = new EffectMesh(effectBitonicSort2[i]);
            }

            // Creates Effect for rendering
            EffectOld particleRenderEffect = this.EffectSystemOld.BuildEffect("ParticleRender")
                                             .Using(new StateShaderPlugin()
            {
                UseBlendState = true, UseDepthStencilState = true, RenderPass = renderPass
            })
                                             .Using(new BasicShaderPlugin(RenderShader)
            {
                RenderPass = renderPass,
                Macros     = { new ShaderMacro("PARTICLE_STRUCT", StructureName) }
            });

            particleRenderEffect.KeepAliveBy(this);

            particleRenderEffect.Parameters.AddSources(this.Parameters);
            particleRenderEffect.Parameters.AddSources(MainPlugin.ViewParameters);
            particleRenderEffect.Parameters.Set(EffectPlugin.BlendStateKey, graphicsDeviceService.GraphicsDevice.BlendStates.AlphaBlend);
            particleRenderEffect.Parameters.Set(EffectPlugin.DepthStencilStateKey, MainTargetPlugin.DepthStencilState);
            particleRenderEffect.Parameters.Set(RenderTargetKeys.DepthStencilSource, MainTargetPlugin.DepthStencil.Texture);

            effectMeshRender = new EffectMesh(particleRenderEffect);

            effectMeshRender.Render += (context) =>
            {
                if (currentParticleCount > 0)
                {
                    context.GraphicsDevice.SetVertexArrayObject(null);
                    context.GraphicsDevice.SetViewport(MainTargetPlugin.Viewport);
                    //context.GraphicsDevice.SetRenderTargets(MainTargetPlugin.DepthStencil, 0, MainTargetPlugin.RenderTarget);

                    context.GraphicsDevice.SetRenderTargets((MainTargetPlugin.DepthStencilReadOnly != null) ? MainTargetPlugin.DepthStencilReadOnly : MainTargetPlugin.DepthStencil, RenderTarget);

                    // TODO HANDLE dynamic count
                    //context.GraphicsDevice.Draw(PrimitiveType.PointList, CapacityCount);
                    context.GraphicsDevice.Draw(PrimitiveType.PointList, currentParticleCount);
                }
                //context.GraphicsDevice.SetRenderTargets(null, 0, new ITexture2D[] { null } );
            };

            if (OfflineCompilation)
            {
                return;
            }

            // Allocate global buffers at register time
            // Buffers can also be reallocated at runtime
            OnCapacityCountChange();

            // Add our local meshes to render RenderContext.RenderPassEnumerators
            RenderSystem.RenderPassEnumerators.Add(meshesToRender);

            // Register update per frame
            RenderSystem.GlobalPass.StartPass += OnFrameUpdate;

            // Register sort pass
            sortPass.EndPass.Set = ComputeBitonicSort;
        }