using Engine.Renderer.Pixel; using Engine.Renderer.Texture; using OpenTK.Graphics.OpenGL; namespace Engine.Renderer.Framebuffer; public class Framebuffer : OpenGlObject { public int Width { get => _width; protected set { if (value <= 0) throw new ArgumentException("Width must be greater than 0"); _width = value; } } public int Height { get => _height; protected set { if (value <= 0) throw new ArgumentException("Height must be greater than 0"); _height = value; } } public IConstTexture Texture => _texture; internal Texture.Texture TextureInternal => _texture; private int _width; private int _height; private readonly DynamicTexture _texture; private readonly Renderbuffer _renderbuffer; public Framebuffer(int width, int height) { Width = width; Height = height; GL.CreateFramebuffers(1, out int handle); Handle = handle; _texture = new DynamicTexture(width, height); GL.NamedFramebufferTexture(Handle, FramebufferAttachment.ColorAttachment0, _texture.Handle, 0); _renderbuffer = new Renderbuffer(width, height, RenderbufferStorage.Depth24Stencil8); GL.NamedFramebufferRenderbuffer(Handle, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, _renderbuffer.Handle); var status = GL.CheckNamedFramebufferStatus(Handle, FramebufferTarget.Framebuffer); if (status != FramebufferStatus.FramebufferComplete) throw new Exception($"Framebuffer is not complete: {status}"); } public void Resize(int width, int height) { if (Width == width && Height == height) return; Width = width; Height = height; _texture.Resize(width, height); _renderbuffer.Resize(width, height); } internal override void Bind() { GL.BindFramebuffer(FramebufferTarget.Framebuffer, Handle); } internal override void Unbind() { GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0); } protected override void Destroy() { GL.DeleteFramebuffer(Handle); } }