Пример #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(Sizei size, FramebufferAttachment[] attachments, PixelInternalFormat format, bool mipmaps = false, TextureParameter filterType = TextureParameter.Linear, PixelType pixelType = PixelType.UnsignedByte, bool renderbuffer = true, bool multisampled = false)
        {
            Size         = size;
            Attachments  = attachments;
            Format       = format;
            MipMaps      = mipmaps;
            Multisampled = multisampled;

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

            _attachementMap = new Dictionary <FramebufferAttachment, uint>();
            TextureTarget textureTarget = Multisampled ? TextureTarget.Texture2DMultisample : TextureTarget.Texture2D;

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

                if (Multisampled)
                {
                    GL.TexImage2DMultisample(textureTarget, GameSettings.MultisampleLevel, Format, Size.Width, Size.Height, true);
                }
                else
                {
                    GL.TexImage2D(textureTarget, 0, Format, Size.Width, Size.Height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                    GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);
                }

                GL.BindTexture(textureTarget, 0);
                GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, textureTarget, TextureID[0], 0);
                GL.DrawBuffer(DrawBufferMode.None);
                GL.ReadBuffer(ReadBufferMode.None);

                _attachementMap.Add(FramebufferAttachment.DepthAttachment, 0);
            }
            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, TextureID[i]);

                    if (Multisampled)
                    {
                        GL.TexImage2DMultisample(textureTarget, GameSettings.MultisampleLevel, Format, Size.Width, Size.Height, true);
                    }
                    else
                    {
                        GL.TexImage2D(textureTarget, 0, Format, Size.Width, Size.Height, 0, PixelFormat.Rgba, pixelType, IntPtr.Zero);

                        if (MipMaps)
                        {
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Linear);
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.LinearMipMapLinear);
                            GL.GenerateMipmap(Multisampled ? GenerateMipmapTarget.Texture2DMultisample : GenerateMipmapTarget.Texture2D);
                        }
                        else
                        {
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, filterType);
                            GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, filterType);
                        }
                    }

                    GL.BindTexture(textureTarget, 0);
                    GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, Attachments[i], textureTarget, TextureID[i], 0);

                    _attachementMap.Add(Attachments[i], TextureID[i]);
                }

                if (renderbuffer)
                {
                    // Create and attach a 24-bit depth buffer to the framebuffer
                    DepthID = GL.GenRenderbuffer();
                    GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, DepthID);

                    if (Multisampled)
                    {
                        GL.RenderbufferStorageMultisample(RenderbufferTarget.Renderbuffer, GameSettings.MultisampleLevel, PixelInternalFormat.Depth32fStencil8, Size.Width, Size.Height);
                    }
                    else
                    {
                        GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, PixelInternalFormat.Depth24Stencil8, Size.Width, Size.Height);
                    }

                    GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
                    GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, DepthID);

                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureMagFilter, TextureParameter.Nearest);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureMinFilter, TextureParameter.Nearest);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapS, TextureParameter.ClampToEdge);
                    //GL.TexParameteri(textureTarget, TextureParameterName.TextureWrapT, TextureParameter.ClampToEdge);

                    //GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, textureTarget, DepthID, 0);
                    //GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.StencilAttachment, textureTarget, DepthID, 0);

                    _attachementMap.Add(FramebufferAttachment.DepthStencilAttachment, DepthID);
                    //_attachementMap.Add(FramebufferAttachment.StencilAttachment, DepthID);
                }
            }

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

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

            // Make sure this framebuffer is not modified from outside
            GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);

            // Register this framebuffer as a disposable object
            ResourcesManager.AddDisposableResource(this);
        }
Пример #2
0
        /// <summary>
        /// Validate this Framebuffer.
        /// </summary>
        /// <param name="ctx">
        /// A <see cref="GraphicsContext"/> used for validating this Framebuffer.
        /// </param>
        /// <exception cref="InvalidOperationException">
        /// Exception thrown whenever this Framebuffer is not valid.
        /// </exception>
        private static void Validate(GraphicsContext ctx)
        {
            // Check frambuffer completeness
            FramebufferStatus status = Gl.CheckFramebufferStatus(FramebufferTarget.Framebuffer);

            if (status != FramebufferStatus.FramebufferComplete)
            {
                switch (status)
                {
                case FramebufferStatus.FramebufferComplete:
                    return;                                     // No error

                case FramebufferStatus.FramebufferUndefined:
                    throw new InvalidOperationException("framebuffer undefined");

                case FramebufferStatus.FramebufferIncompleteAttachment:
                    throw new InvalidOperationException("framebuffer incomplete attachment");

                case FramebufferStatus.FramebufferIncompleteMissingAttachment:
                    throw new InvalidOperationException("framebuffer incomplete missing attachment");

#if !MONODROID
                case FramebufferStatus.FramebufferIncompleteReadBuffer:
                    throw new InvalidOperationException("framebuffer incomplete read buffer");
#endif
                case FramebufferStatus.FramebufferUnsupported:
                    throw new InvalidOperationException("framebuffer unsupported");

                case FramebufferStatus.FramebufferIncompleteMultisample:
                    throw new InvalidOperationException("framebuffer incomplete multisample");

                case FramebufferStatus.FramebufferIncompleteLayerTargets:
                    throw new InvalidOperationException("framebuffer incomplete layer targets");

                default:
                    throw new InvalidOperationException(String.Format("unknown error code 0x{0}", status.ToString("X8")));
                }
            }
        }
Пример #3
0
        /// <summary>
        /// initializes the Fbo with <b>with</b> and <b>height</b>. You have to call that, when <see cref="FboHandle"/> less than 0 or when the size of the fbo has changed.
        /// </summary>
        /// <param name="Width">is the width.</param>
        /// <param name="Height">is the height.</param>
        public virtual void Init(int Width, int Height)
        {
            if (FboHandle > 0)
            {
                Dispose();
            }
            width         = Width; height = Height;
            ActiveTexture = GL.GetInteger(GetPName.TextureBinding2D);
            if (FboHandle < 0)
            {
                _GenFramebuffers(1, out _Fbo[0]);
            }
            if (FboHandle < 0)
            {
                throw new System.Exception("Can not create a frame buffer");
            }
            _BindFramebuffer(FramebufferTarget.Framebuffer, FboHandle);
            if (Depthbuffer < 0)
            {
                _GenRenderbuffers(1, out _Depth[0]);
            }


            _BindRenderbuffer(RenderbufferTarget.Renderbuffer, Depthbuffer);
            GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, width, height, 0, PixelFormat.DepthComponent, PixelType.UnsignedInt, IntPtr.Zero);
            if (GL.GetError() != OpenTK.Graphics.OpenGL.ErrorCode.NoError)
            {
                Dispose();
                throw new Exception("OutOf Memory");
            }
            //     GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent16, Width, Height);
            _RenderbufferStorage(RenderbufferTarget.Renderbuffer, RenderbufferStorage.DepthComponent16, Width, Height);
            _BindFramebuffer(FramebufferTarget.DrawFramebuffer, FboHandle);
            if (FboTexture < 0)
            {
                GL.GenTextures(1, _Texture);
            }

            GL.BindTexture(TextureTarget.Texture2D, FboTexture);
            GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, ref GL_NEAREST);
            GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, ref GL_NEAREST);
            {
                GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
                _FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, FboTexture, 0);
                _FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, RenderbufferTarget.Renderbuffer, Depthbuffer);
            }
            int status           = (int)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
            FramebufferStatus FS = (FramebufferStatus)(status - 0x8CD5);

            if (FS != FramebufferStatus.FRAMEBUFFER_COMPLETE)
            {
                int[] FB = new int[] { 1 };
                Dispose();
                throw new System.Exception(FS.ToString());
            }
            _BindFramebuffer(FramebufferTarget.Framebuffer, 0);
            _BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
            _BindRenderbuffer(RenderbufferTarget.Renderbuffer, 0);
            GL.BindTexture(TextureTarget.Texture2D, ActiveTexture);

            ;
        }