Пример #1
0
        public override void Load()
        {
            base.Load();

            Parameters.AddSources(GBufferPlugin.MainPlugin.ViewParameters);

            Lights = this.EffectSystemOld.BuildEffect("Lights").Using(new LightPlugin()).InstantiatePermutation();

            // TODO: Check if released properly.
            for (int i = 0; i < 2; ++i)
            {
                if (i == 1)
                {
                    if (!Debug)
                    {
                        continue;
                    }

                    // Add the debug as an overlay on the main pass
                    debugRenderPass = new RenderPass("LightPrePassDebug").KeepAliveBy(ActiveObjects);
                    GBufferPlugin.MainPlugin.RenderPass.AddPass(debugRenderPass);
                }

                var debug      = i == 1;
                var renderPass = i == 1 ? debugRenderPass : RenderPass;

                var lightDeferredEffectBuilder = this.EffectSystemOld.BuildEffect("LightPrePass" + (debug ? "Debug" : string.Empty)).KeepAliveBy(ActiveObjects);
                foreach (var effectPlugin in BasePlugins)
                {
                    lightDeferredEffectBuilder.Using(new BasicShaderPlugin(effectPlugin)
                    {
                        Services = Services, RenderPassPlugin = this, RenderPass = renderPass
                    });
                }
                lightDeferredEffectBuilder.Using(new LightingPrepassShaderPlugin("LightPreShaderPass" + (debug ? "Debug" : string.Empty))
                {
                    Services = Services, RenderPassPlugin = this, RenderPass = renderPass, Debug = debug
                });

                lightDeferredEffects[i] = lightDeferredEffectBuilder.InstantiatePermutation().KeepAliveBy(ActiveObjects);
            }

            if (OfflineCompilation)
            {
                return;
            }

            // Create lighting accumulation texture (that LightPlugin will use)
            var mainBackBuffer = graphicsDeviceService.GraphicsDevice.BackBuffer;
            var lightTexture   = Texture2D.New(GraphicsDevice, mainBackBuffer.Width, mainBackBuffer.Height, PixelFormat.R16G16B16A16_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget);

            lightTexture.Name = "LightTexture";
            LightTexture      = lightTexture.ToRenderTarget();

            // Set Parameters for this plugin
            Parameters.Set(LightDeferredShadingKeys.LightTexture, lightTexture);

            // Set GBuffer Texture0
            Parameters.Set(GBufferBaseKeys.GBufferTexture, (Texture2D)GBufferPlugin.RenderTarget.Texture);

            // Set parameters for MainPlugin
            GBufferPlugin.MainTargetPlugin.Parameters.Set(LightDeferredShadingKeys.LightTexture, lightTexture);

            CreatePrePassMesh(RenderPass, false);
            if (Debug)
            {
                CreatePrePassMesh(debugRenderPass, true);
            }
        }
Пример #2
0
 internal static ModelRendererState GetModelRendererState(this RenderPass pass)
 {
     return(GetOrCreateModelRendererState(pass, false));
 }
Пример #3
0
        public override void Unload()
        {
            RenderPass.RemovePass(PostPass);

            base.Unload();
        }
Пример #4
0
        private void CreatePrePassMesh(RenderPass renderPass, bool debug)
        {
            var lightDeferredEffect = lightDeferredEffects[debug ? 1 : 0];

            Tiles = new List <LightingPrepassShaderPlugin.LightData> [TileCountX * TileCountY];
            for (int i = 0; i < Tiles.Length; ++i)
            {
                Tiles[i] = new List <LightingPrepassShaderPlugin.LightData>();
            }

            renderPass.StartPass.AddLast = (threadContext) =>
            {
                // TODO THIS IS NOT ACCURATE TO TAKE THE CURRENT BACKBUFFER
                var mainBackBuffer = graphicsDeviceService.GraphicsDevice.BackBuffer;
                threadContext.GraphicsDevice.SetViewport(new Viewport(0, 0, mainBackBuffer.Width, mainBackBuffer.Height));
                if (threadContext.FirstContext)
                {
                    if (debug)
                    {
                        threadContext.GraphicsDevice.SetRenderTarget(GBufferPlugin.MainTargetPlugin.RenderTarget);
                    }
                    else
                    {
                        threadContext.GraphicsDevice.Clear(LightTexture, new Color(0.0f, 0.0f, 0.0f, 0.0f));
                        threadContext.GraphicsDevice.SetRenderTarget(LightTexture);
                    }
                }

                for (int i = 0; i < Tiles.Length; ++i)
                {
                    Tiles[i].Clear();
                }

                var lights = Lights;
                var lightAttenuationCutoff = 0.1f;

                Matrix viewMatrix;
                var    mainParameters = GBufferPlugin.MainPlugin.ViewParameters;
                mainParameters.Get(TransformationKeys.View, out viewMatrix);
                Matrix projMatrix;
                mainParameters.Get(TransformationKeys.Projection, out projMatrix);

                for (int index = 0; index < lights.Meshes.Count; index++)
                {
                    LightingPrepassShaderPlugin.LightData lightData;

                    var     lightMesh = lights.Meshes[index];
                    Vector3 lightPos;
                    lightMesh.Parameters.TryGet(LightKeys.LightPosition, out lightPos);
                    Vector3.TransformCoordinate(ref lightPos, ref viewMatrix, out lightData.LightPosVS);
                    lightMesh.Parameters.TryGet(LightKeys.LightColor, out lightData.DiffuseColor);
                    lightMesh.Parameters.TryGet(LightKeys.LightIntensity, out lightData.LightIntensity);
                    lightMesh.Parameters.TryGet(LightKeys.LightRadius, out lightData.LightRadius);

                    // ------------------------------------------------------------------------------------------
                    // TEMPORARY FIX FOR DEFERRED LIGHTS
                    // ------------------------------------------------------------------------------------------
                    //lightData2[index].DiffuseColor.Pow(1 / 4.0f);
                    //lightData2[index].LightIntensity = (float)Math.Pow(lightData2[index].LightIntensity, 1.0f / 2.2f);
                    // ------------------------------------------------------------------------------------------

                    // Linearize color
                    lightData.DiffuseColor.Pow(Color.DefaultGamma);
                    lightData.LightIntensity = (float)Math.Pow(lightData.LightIntensity, Color.DefaultGamma);

                    float lightDistanceMax = CalculateMaxDistance(lightData.LightIntensity, lightData.LightRadius, lightAttenuationCutoff);
                    var   clipRegion       = ComputeClipRegion(lightData.LightPosVS, lightDistanceMax, ref projMatrix);

                    var tileStartX = (int)((clipRegion.X * 0.5f + 0.5f) * TileCountX);
                    var tileEndX   = (int)((clipRegion.Z * 0.5f + 0.5f) * TileCountX);
                    var tileStartY = (int)((clipRegion.Y * 0.5f + 0.5f) * TileCountY);
                    var tileEndY   = (int)((clipRegion.W * 0.5f + 0.5f) * TileCountY);

                    // Check if this light is really visible (not behind us)
                    if (lightData.LightPosVS.Z + lightDistanceMax < 0.0f)
                    {
                        continue;
                    }

                    for (int y = tileStartY; y <= tileEndY; ++y)
                    {
                        if (y < 0 || y >= TileCountY)
                        {
                            continue;
                        }
                        for (int x = tileStartX; x <= tileEndX; ++x)
                        {
                            if (x < 0 || x >= TileCountX)
                            {
                                continue;
                            }
                            Tiles[y * TileCountX + x].Add(lightData);
                        }
                    }
                }
            };

            var lightDeferredMesh = new EffectMesh(lightDeferredEffect).KeepAliveBy(ActiveObjects);

            RenderSystem.GlobalMeshes.AddMesh(lightDeferredMesh);

            renderPass.EndPass.AddLast = (context) =>
            {
                // Clear thread context overridden variables.
                context.Parameters.Reset(LightingPrepassShaderPlugin.LightCount);
                context.Parameters.Reset(LightingPrepassShaderPlugin.LightInfos);
                context.Parameters.Reset(LightingPrepassShaderPlugin.TileIndex);
                context.Parameters.Reset(TransformationKeys.Projection);
                context.Parameters.Reset(RenderTargetKeys.DepthStencilSource);
            };

            var tileRenderPasses = new RenderPass[TileCountX * TileCountY];

            for (int i = 0; i < tileRenderPasses.Length; ++i)
            {
                int tileIndex = i;
                tileRenderPasses[i] = new RenderPass("Lighting Tile");
                tileRenderPasses[i].StartPass.AddLast = (context) => { context.Parameters.Set(LightingPrepassShaderPlugin.TileIndex, tileIndex); };
                throw new NotImplementedException();
                //tileRenderPasses[i].Meshes.Add(lightDeferredMesh);
            }

            throw new NotImplementedException();
            //renderPass.UpdatePasses += (RenderPass currentRenderPass, ref FastList<RenderPass> currentPasses) =>
            //    {
            //        lightDeferredEffect.Passes[0].Passes.Clear();
            //        lightDeferredEffect.Passes[0].Passes.AddRange(tileRenderPasses);
            //    };
        }
Пример #5
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 = Texture2D.New(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       = Texture2D.New(GraphicsDevice, shadowMapTextureDesc.Width, shadowMapTextureDesc.Height, PixelFormat.R32G32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).KeepAliveBy(ActiveObjects);
            var shadowMapBlurV       = Texture2D.New(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);
        }
Пример #6
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);
        }
Пример #7
0
        public override void Load()
        {
            base.Load();

            if (OfflineCompilation)
            {
                return;
            }

            var renderTargets = new RenderTarget[2];
            DepthStencilBuffer depthStencilBuffer  = null;
            Texture2D          depthStencilTexture = null;

            Parameters.AddSources(MainPlugin.ViewParameters);

            Parameters.RegisterParameter(EffectPlugin.BlendStateKey);

            var filteredPasses = new FastList <RenderPass>();

            RenderPass.UpdatePasses += updatePassesAction = (RenderPass currentRenderPass, ref FastList <RenderPass> currentPasses) =>
            {
                var originalPasses = currentPasses;
                filteredPasses.Clear();
                currentPasses = filteredPasses;

                Parameters.Set(PickingFrameIndex, ++currentPickingFrameIndex);
                Request[] requests;

                lock (pendingRequests)
                {
                    // No picking request or no mesh to pick?
                    if (pendingRequests.Count == 0)
                    {
                        return;
                    }

                    requests = pendingRequests.ToArray();
                    pendingRequests.Clear();
                }

                foreach (var request in requests)
                {
                    requestResults.Add(request);
                }

                if (originalPasses == null)
                {
                    return;
                }

                // Count mesh passes
                int meshIndex = 0;
                foreach (var pass in originalPasses)
                {
                    meshIndex += pass.Passes.Count;
                }

                // No mesh to pick?
                if (meshIndex == 0)
                {
                    return;
                }

                // Copy mesh passes and assign indices
                var meshPasses = new EffectMesh[meshIndex];
                meshIndex = 0;
                foreach (var pass in RenderPass.Passes)
                {
                    throw new NotImplementedException();
                    //foreach (var effectMeshPass in pass.Meshes)
                    //{
                    //    meshPasses[meshIndex] = (EffectMesh)effectMeshPass;
                    //    // Prefix increment so that 0 means no rendering.
                    //    effectMeshPass.Parameters.Set(PickingMeshIndex, ++meshIndex);
                    //}
                }

                // For now, it generates one rendering per picking.
                // It would be quite easy to optimize it by make Picking shader works on multiple picking points at a time.
                foreach (var request in requests)
                {
                    var pickingRenderPass = new RenderPass("Picking");

                    pickingRenderPass.StartPass.AddFirst = (threadContext) =>
                    {
                        threadContext.GraphicsDevice.Clear(renderTargets[0], Color.Black);
                        threadContext.GraphicsDevice.Clear(renderTargets[1], Color.Black);
                        threadContext.Parameters.Set(PickingScreenPosition, request.Location);
                        threadContext.GraphicsDevice.SetViewport(new Viewport(0, 0, renderTargets[0].Description.Width, renderTargets[0].Description.Height));

                        threadContext.GraphicsDevice.Clear(depthStencilBuffer, DepthStencilClearOptions.DepthBuffer);
                        threadContext.GraphicsDevice.SetRenderTargets(depthStencilBuffer, renderTargets);
                    };
                    pickingRenderPass.EndPass.AddLast = (threadContext) =>
                    {
                        threadContext.Parameters.Reset(PickingScreenPosition);
                        threadContext.GraphicsDevice.Copy(renderTargets[0].Texture, request.ResultTextures[0]);
                        threadContext.GraphicsDevice.Copy(renderTargets[1].Texture, request.ResultTextures[1]);
                    };
                    //pickingRenderPass.PassesInternal = originalPasses;
                    throw new NotImplementedException();

                    request.MeshPasses = meshPasses;

                    currentPasses.Add(pickingRenderPass);

                    request.HasResults = true;

                    // Wait 2 frames before pulling the results.
                    request.FrameCounter = 2;
                }
            };

            RenderSystem.GlobalPass.EndPass.AddLast = CheckPickingResults;

            var backBuffer = GraphicsDevice.BackBuffer;

            int pickingArea = 1 + PickingDistance * 2;

            renderTargets[0] = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32_UInt, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);
            renderTargets[1] = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.R32G32B32A32_Float, TextureFlags.ShaderResource | TextureFlags.RenderTarget).ToRenderTarget().KeepAliveBy(ActiveObjects);

            depthStencilTexture = Texture2D.New(GraphicsDevice, pickingArea, pickingArea, PixelFormat.D32_Float, TextureFlags.ShaderResource | TextureFlags.DepthStencil).KeepAliveBy(ActiveObjects);
            depthStencilBuffer  = depthStencilTexture.ToDepthStencilBuffer(false);

            Parameters.AddDynamic(PickingMatrix, ParameterDynamicValue.New(PickingScreenPosition, (ref Vector2 pickingPosition, ref Matrix picking) =>
            {
                // Move center to picked position, and zoom (it is supposed to stay per-pixel according to render target size)
                picking = Matrix.Translation(1.0f - (pickingPosition.X) / backBuffer.Width * 2.0f, -1.0f + (pickingPosition.Y) / backBuffer.Height * 2.0f, 0.0f)
                          * Matrix.Scaling((float)backBuffer.Width / (float)pickingArea, (float)backBuffer.Height / (float)pickingArea, 1.0f);
            }));
        }
Пример #8
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;
        }
Пример #9
0
 public SlotKey(RenderPass pass, string effectName)
 {
     Pass       = pass;
     EffectName = effectName;
 }