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); } }
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); }
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(); }
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); }
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; }