public void Dispose()
        {
            ShaderLibrary.Dispose();

            foreach (var pass in Passes)
            {
                pass.Dispose();
            }

            Quad.Dispose();

            CameraUniformBuffer.Dispose();
            SceneUniformBuffer.Dispose();
            MaterialUniformBuffer.Dispose();
            ToneMapUniformBuffer.Dispose();

            ShadowMapFramebuffer.Dispose();
            ShadowMapTexture.Dispose();

            ShadowMapFilteredFramebuffer.Dispose();
            ShadowMapFilteredTexture.Dispose();

            SSSDepthTexture.Dispose();
            SSSHighFramebuffer.Dispose();
            SSSHighTexture.Dispose();
            SSSMiddleFramebuffer.Dispose();
            SSSMiddleTexture.Dispose();
            SSSLowFramebuffer.Dispose();
            SSSLowTexture.Dispose();
            SSSLowFilteredFramebuffer.Dispose();
            SSSLowFilteredTexture.Dispose();

            SceneFramebuffer.Dispose();
            SceneColorTexture.Dispose();
            SceneDepthTexture.Dispose();

            ToneMapFramebuffer.Dispose();
            ToneMapColorTexture.Dispose();
        }
        public void Initialize(int width, int height)
        {
            if (ShadowMapFramebuffer == null)
            {
                {
                    ShadowMapFramebuffer = new Framebuffer(State, ShadowMapSize, ShadowMapSize);
                    ShadowMapTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.DepthComponent,
                                                       ShadowMapSize, ShadowMapSize, PixelFormat.DepthComponent, PixelType.Float);

                    GL.DrawBuffer(DrawBufferMode.None);
                    GL.ReadBuffer(ReadBufferMode.None);

                    ShadowMapFramebuffer.Attach(FramebufferAttachment.DepthAttachment, ShadowMapTexture);
                }

                {
                    ShadowMapFilteredFramebuffer = new Framebuffer(State, ShadowMapSize, ShadowMapSize);
                    ShadowMapFilteredTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.DepthComponent,
                                                               ShadowMapSize, ShadowMapSize, PixelFormat.DepthComponent, PixelType.Float);

                    GL.DrawBuffer(DrawBufferMode.None);
                    GL.ReadBuffer(ReadBufferMode.None);

                    ShadowMapFilteredFramebuffer.Attach(FramebufferAttachment.DepthAttachment, ShadowMapFilteredTexture);
                }

                {
                    SSSDepthTexture = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.DepthComponent,
                                                  SSSWidth, SSSHeight, PixelFormat.DepthComponent, PixelType.Float);

                    {
                        SSSHighFramebuffer = new Framebuffer(State, SSSWidth, SSSHeight);
                        SSSHighTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba16f,
                                                         SSSWidth, SSSHeight, PixelFormat.Rgba, PixelType.HalfFloat);

                        SSSHighFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, SSSHighTexture);
                        SSSHighFramebuffer.Attach(FramebufferAttachment.DepthAttachment, SSSDepthTexture);
                    }

                    {
                        SSSMiddleFramebuffer = new Framebuffer(State, SSSWidth / 2, SSSHeight / 2);
                        SSSMiddleTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba16f,
                                                           SSSWidth / 2, SSSHeight / 2, PixelFormat.Rgba, PixelType.HalfFloat);

                        SSSMiddleFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, SSSMiddleTexture);
                    }

                    {
                        SSSLowFramebuffer = new Framebuffer(State, SSSWidth / 4, SSSHeight / 4);
                        SSSLowTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba16f,
                                                        SSSWidth / 4, SSSHeight / 4, PixelFormat.Rgba, PixelType.HalfFloat);

                        SSSLowFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, SSSLowTexture);
                    }

                    {
                        SSSLowFilteredFramebuffer = new Framebuffer(State, SSSWidth / 4, SSSHeight / 4);
                        SSSLowFilteredTexture     = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba16f,
                                                                SSSWidth / 4, SSSHeight / 4, PixelFormat.Rgba, PixelType.HalfFloat);

                        SSSLowFilteredFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, SSSLowFilteredTexture);
                    }
                }
            }

            Width  = Math.Max(1, width);
            Height = Math.Max(1, height);

            if (SceneFramebuffer != null)
            {
                SceneFramebuffer.Dispose();
                SceneColorTexture.Dispose();
                SceneDepthTexture.Dispose();
                ToneMapFramebuffer.Dispose();
                ToneMapColorTexture.Dispose();
            }

            {
                SceneFramebuffer = new Framebuffer(State, Width, Height);

                SceneColorTexture = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba16f,
                                                Width, Height, PixelFormat.Rgba, PixelType.HalfFloat);

                SceneDepthTexture = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.DepthComponent,
                                                Width, Height, PixelFormat.DepthComponent, PixelType.Float);

                SceneFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, SceneColorTexture);
                SceneFramebuffer.Attach(FramebufferAttachment.DepthAttachment, SceneDepthTexture);
            }

            {
                ToneMapFramebuffer = new Framebuffer(State, Width, Height);

                ToneMapColorTexture = new Texture(State, TextureTarget.Texture2D, PixelInternalFormat.Rgba8,
                                                  Width, Height, PixelFormat.Rgba, PixelType.UnsignedByte);

                ToneMapFramebuffer.Attach(FramebufferAttachment.ColorAttachment0, ToneMapColorTexture);
                ToneMapFramebuffer.Attach(FramebufferAttachment.DepthAttachment, SceneDepthTexture);
            }

            foreach (var pass in Passes)
            {
                pass.Initialize(this);
            }
        }