Exemplo n.º 1
0
        /// <summary>
        /// Creates a framebuffer object and its associated resources (depth and frame buffers).
        /// </summary>
        /// <param name="size">Specifies the size (in pixels) of the framebuffer and its associated buffers.</param>
        /// <param name="attachments">Specifies the attachments to use for the frame buffer.</param>
        /// <param name="format">Specifies the internal pixel format for the frame buffer.</param>
        /// <param name="mipmaps">Specifies whether to build mipmaps after the frame buffer is unbound.</param>
        /// <param name="filterType">Specifies the type of filtering to apply to the frame buffer when bound as a texture.</param>
        /// <param name="pixelType">Specifies the pixel type to use for the underlying format of the frame buffer.</param>
        public FBO(Size size, FramebufferAttachment[] attachments, PixelInternalFormat format, bool mipmaps = false, TextureParameter filterType = TextureParameter.Linear, PixelType pixelType = PixelType.UnsignedByte)
        {
            this.Size        = size;
            this.Attachments = attachments;
            this.Format      = format;
            this.MipMaps     = mipmaps;

            // First create the framebuffer
            BufferID = Gl.GenFramebuffer();
            Gl.BindFramebuffer(FramebufferTarget.Framebuffer, BufferID);

            if (Attachments.Length == 1 && Attachments[0] == FramebufferAttachment.DepthAttachment)
            {
                // if this is a depth attachment only
                TextureID = new uint[] { Gl.GenTexture() };
                Gl.BindTexture(TextureTarget.Texture2D, TextureID[0]);

                Gl.TexImage2D(TextureTarget.Texture2D, 0, Format, Size.Width, Size.Height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);

                Gl.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureID[0], 0);
                Gl.DrawBuffer(DrawBufferMode.None);
                Gl.ReadBuffer(ReadBufferMode.None);
            }
            else
            {
                // Create n texture buffers (known by the number of attachments)
                TextureID = new uint[Attachments.Length];
                Gl.GenTextures(Attachments.Length, TextureID);

                // Bind the n texture buffers to the framebuffer
                for (int i = 0; i < Attachments.Length; i++)
                {
                    Gl.BindTexture(TextureTarget.Texture2D, TextureID[i]);
                    Gl.TexImage2D(TextureTarget.Texture2D, 0, Format, Size.Width, Size.Height, 0, PixelFormat.Rgba, pixelType, IntPtr.Zero);
                    if (MipMaps)
                    {
                        Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureParameter.Linear);
                        Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureParameter.LinearMipMapLinear);
                        Gl.GenerateMipmap(GenerateMipmapTarget.Texture2D);
                    }
                    else
                    {
                        Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, filterType);
                        Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, filterType);
                    }
                    Gl.FramebufferTexture(FramebufferTarget.Framebuffer, Attachments[i], TextureID[i], 0);
                }

                // Create and attach a 24-bit depth buffer to the framebuffer
                DepthID = Gl.GenTexture();
                Gl.BindTexture(TextureTarget.Texture2D, DepthID);

                Gl.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Depth24Stencil8, Size.Width, Size.Height, 0, PixelFormat.DepthStencil, PixelType.UnsignedInt248, IntPtr.Zero);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                Gl.TexParameteri(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);

                Gl.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, DepthID, 0);
                Gl.FramebufferTexture(FramebufferTarget.Framebuffer, FramebufferAttachment.StencilAttachment, DepthID, 0);
            }

            // Build the framebuffer and check for errors
            FramebufferErrorCode status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferErrorCode.FramebufferComplete)
            {
                Console.WriteLine("Frame buffer did not compile correctly.  Returned {0}, glError: {1}", status.ToString(), Gl.GetError().ToString());
            }

            Gl.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
        }