protected override void PassSetup(ParticleSystemBase p)
        {
            base.PassSetup(p);

            var particle_scale_factor = ValueProvider.Create (() => p.ParticleScaleFactor);
            var particle_count = ValueProvider.Create (() => p.PARTICLES_COUNT);

            var firstPassSolid =  RenderPassFactory.CreateSolidBox
            (
                 NormalDepth_Texture,
                 m_ParticleAttribute1_Texture,
                 Depth_Texture,
                 p.PositionBuffer,
                 p.ColorBuffer,
                 p.DimensionBuffer,
                 p.RotationLocalBuffer,
                 p.RotationBuffer,
                 particle_count,
                 particle_scale_factor,
                 p.CameraMvp
            );

            var firstPassShadow =  RenderPassFactory.CreateSolidBox
            (
                 Shadow_Texture,
                 p.PositionBuffer,
                 p.ColorBuffer,
                 p.DimensionBuffer,
                 p.RotationLocalBuffer,
                 p.RotationBuffer,
                 particle_count,
                 particle_scale_factor,
                 ValueProvider.Create ( () => "FragDepth" + SunLightImpl.ShadowmapType.ToString ()),
                 SunLightImpl.LightMvp
            );

            var aocPassSolid = RenderPassFactory.CreateAoc
            (
                 NormalDepth_Texture,
                 AOC_Texture,
                 p.CameraMvp.ModelViewProjection,
                 p.CameraMvp.ModelViewProjectionInv,
                 p.CameraMvp.Projection,
                 p.CameraMvp.ProjectionInv,
                 AocParameters
            );

            var aocBlur = RenderPassFactory.CreateBilateralFilter
            (
                 AOC_Texture, AOC_Texture_Blurred_H, AOC_Texture_Blurred_HV,
                 ValueProvider.Create(() => 20 * new Vector4(AocParameters.BlurEdgeAvoidance, AocParameters.BlurEdgeAvoidance, AocParameters.BlurEdgeAvoidance, 0))
            );

            //
            var thirdPassSolid = RenderPassFactory.CreateFullscreenQuad
            (
                 "solid3", "SolidModel",
                 ValueProvider.Create(() => new Vector2(SolidModeTextureSize, SolidModeTextureSize)),
                 (window) => { },
                 (window) =>
                 {
                    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                    GL.Disable (EnableCap.DepthTest);
                    GL.Disable (EnableCap.Blend);
                 },
                 //pass state
                 new FramebufferBindingSet{
                   { FramebufferAttachment.DepthAttachment, Depth_Texture },
                   { "color_luma", BeforeAA_Texture}
                 },
                 p.ParticleStateArrayObject,
                 m_Uniforms,
                 new TextureBindingSet
                 {
                   { "colorramp_texture", ValueProvider.Create(() => (ColorRamp ?? ColorRamps.RedBlue).Texture)},
                   { "normaldepth_texture", NormalDepth_Texture },
                   { "particle_attribute1_texture", m_ParticleAttribute1_Texture },
                   { "shadow_texture", Shadow_Texture },
                   { "aoc_texture", AOC_Texture_Blurred_HV }
                 }
            );

            var antialiasPass = RenderPassFactory.CreateFxaa3Filter
            (
                 BeforeAA_Texture, AA_Texture
            );

            var finalRender = RenderPassFactory.CreateRenderTextureToBuffer
            (
                 AA_Texture,
                 Depth_Texture,
                 ValueProvider.Create(() => p.Viewport),
                 (window) =>
                 {
                    p.SetViewport (window);
                 },
                 (window) =>
                 {
                    GL.Clear (ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                    GL.Disable (EnableCap.DepthTest);
                    GL.Disable (EnableCap.Blend);
                 },
                //TODO: BUG m_ParticleRenderingState is necessary, but it shouldn't be
                FramebufferBindingSet.Default,
                p.ParticleStateArrayObject
            );

            m_Pass = new CompoundRenderPass
            (
             firstPassSolid, firstPassShadow, aocPassSolid, aocBlur, thirdPassSolid, antialiasPass, finalRender
            );
        }
        protected virtual void PassSetup(ParticleSystemBase p)
        {
            //
            m_Uniforms = new UniformState(p.Uniforms)
            {
                {SunLightImpl.LightMvp, "light"},
                {"u_GetShadow", (ShaderType)ShaderTypeExt.ComputeShader, () => "GetShadow" + SunLightImpl.ImplementationType.ToString () },
                //{"u_ShadowmapGet", () => "ShadowmapGet" + SunLightImpl.ShadowmapType.ToString () },
                //{"u_ShadowmapGetFiltered", () => "ShadowmapGetFiltered" + SunLightImpl.ShadowmapType.ToString () },
                {"u_MaterialColorSource", ValueProvider.Create(() => MaterialType)},

                {"u_LightSize", ValueProvider.Create(() => LightSize )},
                {"u_ShadowSampleCount", ValueProvider.Create(() => ShadowSampleCount )},

                {"u_SamplingPattern", MathHelper2.RandomVectorSet (256, new Vector2 (1, 1))},
                {"sampling_pattern_len", 256},
            };

            //m_Uniforms.SetMvp("light", SunLightImpl.LightMvp);
        }
        public RenderPass GetPass(ParticleSystemBase p)
        {
            UpdateTextureResolutions();

            if(m_Pass != null)
                return m_Pass;

            ParameterSetup();
            TextureSetup();
            PassSetup(p);

            return m_Pass;
        }
        protected override void PassSetup(ParticleSystemBase p)
        {
            base.PassSetup(p);

            var particle_scale_factor = ValueProvider.Create (() => p.ParticleScaleFactor);
            var particle_count = ValueProvider.Create (() => p.PARTICLES_COUNT);

            var firstPassSolid =  RenderPassFactory.CreateSolidBox
            (
                 NormalDepth_Texture,
                 m_ParticleAttribute1_Texture,
                 Depth_Texture,
                 p.PositionBuffer,
                 p.ColorBuffer,
                 p.DimensionBuffer,
                 p.RotationLocalBuffer,
                 p.RotationBuffer,
                 particle_count,
                 particle_scale_factor,
                 p.CameraMvp
            );

            var firstPassShadow =  RenderPassFactory.CreateSolidBox
            (
                 Shadow_Texture,
                 p.PositionBuffer,
                 p.ColorBuffer,
                 p.DimensionBuffer,
                 p.RotationLocalBuffer,
                 p.RotationBuffer,
                 particle_count,
                 particle_scale_factor,
                 ValueProvider.Create ( () => "FragDepth" + SunLightImpl.ShadowmapType.ToString ()),
                 SunLightImpl.LightMvp
            );

            /*var aocPassSolid = RenderPassFactory.CreateAoc
            (
                 NormalDepth_Texture,
                 AOC_Texture,
                 p.CameraMvp.ModelViewProjection,
                 p.CameraMvp.ModelViewProjectionInv,
                 p.CameraMvp.Projection,
                 p.CameraMvp.ProjectionInv,
                 AocParameters
            );*/
            SsaoEffect.SourceNormalDepth = NormalDepth_Texture;
            SsaoEffect.Target = AOC_Texture;
            SsaoEffect.SourceMvp = p.CameraMvp;
            var aocPassSolid = RenderPassFactory.CreatePass(SsaoEffect);

            /*var aocBlur = RenderPassFactory.CreateBilateralFilter
            (
                 AOC_Texture, AOC_Texture_Blurred_H, AOC_Texture_Blurred_HV,
                 ValueProvider.Create(() => 20 * new Vector4(AocParameters.BlurEdgeAvoidance, AocParameters.BlurEdgeAvoidance, AocParameters.BlurEdgeAvoidance, 0))
            );*/
            var aocBlur = RenderPassFactory.CreatePass(new BilateralFilter { Source = AOC_Texture, SourceK = NormalDepth_Texture, Target = AOC_Texture_Blurred_HV, Width = 4 });

            string scode =
                @"
            {0}version 440
            {0}define T_LAYOUT_OUT_DEPTH {1}
            {0}define T_LAYOUT_OUT_COLORLUMA {2}

            layout(local_size_x = {3}, local_size_y = {4}) in;
            {0}line 1
            ";
            int workgroupSize = 16;
            scode = string.Format (scode, "#", ImageFormat.R32f, BeforeAA_Texture.InternalFormat, workgroupSize, workgroupSize);
            var namemodifier = string.Format ("wgsize:{0}x{0},fi:{1},fi:{2}", workgroupSize, ImageFormat.R32f, BeforeAA_Texture.InternalFormat);
            var deferredLigthing = new SeparateProgramPass
            (
                "shadingsetup.solidbox.deferredligthing",
                window => { GLExtensions.DispatchCompute ((int)Math.Ceiling((float)Depth_Texture.Width/workgroupSize), (int)Math.Ceiling((float)Depth_Texture.Height/workgroupSize), 1); },
                new Program ("shadingsetup.solidbox.deferredligthing")
                {
                    RenderPass.GetShaders ("shadingsetup", "solid3", "compute").PrependText(namemodifier, scode),
                },
                new ImageBindingSet
                {
                    {"u_TargetDepth", () => Depth_Texture },
                    {"u_TargetColorLuma", () => BeforeAA_Texture },
                },

                p.ParticleStateArrayObject,
                m_Uniforms,
                new TextureBindingSet
                {
                    { "u_ColorRampTexture", ValueProvider.Create(() => (ColorRamp ?? ColorRamps.RedBlue).Texture)},
                    { "u_NormalDepthTexture", NormalDepth_Texture },
                    { "u_ParticleAttribute1Texture", m_ParticleAttribute1_Texture },
                    { "u_ShadowTexture", Shadow_Texture },
                    { "u_SsaoTexture", AOC_Texture_Blurred_HV }
                }
            );

            var antialiasPass = RenderPassFactory.CreatePass( new Fxaa3Filter{ Source = BeforeAA_Texture, Target = AA_Texture});

            var finalRender = RenderPassFactory.CreateRenderTextureToBuffer
            (
                 AA_Texture,
                 Depth_Texture,
                 ValueProvider.Create(() => p.Viewport),
                 (window) =>
                 {
                    p.SetViewport (window);
                 },
                 (window) =>
                 {
                    GL.Clear (ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                    GL.Disable (EnableCap.DepthTest);
                    GL.Disable (EnableCap.Blend);
                 },
                //TODO: BUG m_ParticleRenderingState is necessary, but it shouldn't be
                FramebufferBindingSet.Default,
                p.ParticleStateArrayObject
            );

            m_Pass = new CompoundRenderPass
            (
                    firstPassSolid, firstPassShadow, aocPassSolid, aocBlur, deferredLigthing, antialiasPass, finalRender
            );
        }
        RenderPass IShadingSetup.GetPass(ParticleSystemBase p)
        {
            PrepareTexture();

            if(m_Pass != null)
                return m_Pass;

            m_Uniforms = new UniformState(p.Uniforms);
            m_Uniforms.Set ("particle_shape", ValueProvider.Create (() => (int)this.ParticleShape));
            m_Uniforms.Set ("particle_brightness", ValueProvider.Create (() => this.ParticleBrightness));
            m_Uniforms.Set ("smooth_shape_sharpness", ValueProvider.Create (() => this.SmoothShapeSharpness));

            //
            m_Pass = new SeparateProgramPass
            (
                 "light",
                 "SmoothShading",
                 null,
                 null,

                 //pass code
                 (window) =>
                 {
                    GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
                    GL.Disable (EnableCap.DepthTest);
                    GL.Enable (EnableCap.Blend);
                    GL.BlendFunc (BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
                    GL.BlendEquation (BlendEquationMode.FuncAdd);

                    //TODO: viewport size actually doesn't propagate to shader, because uniform state has been already activated
                    p.SetViewport (window);
                    GL.DrawArrays (BeginMode.Points, 0, p.PARTICLES_COUNT);
                 },

                 //pass state
                 FramebufferBindingSet.Default,
                 p.ParticleStateArrayObject,
                 m_Uniforms,
                 new TextureBindingSet(
                   new TextureBinding { VariableName = "custom_texture", Texture = m_Texture }
                 )
            );

            return m_Pass;
        }
        protected virtual void PassSetup(ParticleSystemBase p)
        {
            //
            m_Uniforms = new UniformState(p.Uniforms)
            {
                {SunLightImpl.LightMvp, "light"},
                {"u_GetShadow", ShaderType.FragmentShader, () => "GetShadow" + SunLightImpl.ImplementationType.ToString () },
                //{"u_ShadowmapGet", () => "ShadowmapGet" + SunLightImpl.ShadowmapType.ToString () },
                //{"u_ShadowmapGetFiltered", () => "ShadowmapGetFiltered" + SunLightImpl.ShadowmapType.ToString () },
                {"material_color_source", ValueProvider.Create(() => MaterialType)},

                {"light_size", ValueProvider.Create(() => LightSize )},

                {"light_expmap_level", ValueProvider.Create(() => ExpMapLevel )},
                {"light_expmap_range", ValueProvider.Create(() => ExpMapRange )},
                {"light_expmap_range_k", ValueProvider.Create(() => ExpMapRangeK )},
                {"light_expmap_nsamples", ValueProvider.Create(() => ExpMapNsamples )},

            //
                {"sampling_pattern", MathHelper2.RandomVectorSet (256, new Vector2 (1, 1))},
                {"sampling_pattern_len", 256},
            };

            //m_Uniforms.SetMvp("light", SunLightImpl.LightMvp);
        }