1 module polyplex.core.render.gl.renderbuf; 2 import core = polyplex.core.render; 3 import polyplex.core.render.gl.gloo; 4 import polyplex.core.render.gl.gloo : RBO = Renderbuffer, FBO = Framebuffer; 5 import core.memory : GC; 6 7 enum Attachment { 8 Color0=GL_COLOR_ATTACHMENT0, 9 Color1=GL_COLOR_ATTACHMENT1, 10 Color2=GL_COLOR_ATTACHMENT2, 11 Color3=GL_COLOR_ATTACHMENT3, 12 Color4=GL_COLOR_ATTACHMENT4, 13 Color5=GL_COLOR_ATTACHMENT5, 14 Color6=GL_COLOR_ATTACHMENT6, 15 Color7=GL_COLOR_ATTACHMENT7, 16 Color8=GL_COLOR_ATTACHMENT8, 17 Color9=GL_COLOR_ATTACHMENT9, 18 Color10=GL_COLOR_ATTACHMENT10, 19 Color11=GL_COLOR_ATTACHMENT11, 20 Color12=GL_COLOR_ATTACHMENT12, 21 Color13=GL_COLOR_ATTACHMENT13, 22 Color14=GL_COLOR_ATTACHMENT14, 23 Color15=GL_COLOR_ATTACHMENT15, 24 Depth=GL_DEPTH_ATTACHMENT 25 } 26 27 public class Framebuffer { 28 private: 29 int width; 30 int height; 31 FBO fbo; 32 RBO rbo; 33 Texture[] renderTextures; 34 GLenum[] drawBufs; 35 36 void bufferTexture() { 37 fbo.Bind(); 38 39 // Prepare textures. 40 foreach(to; renderTextures) { 41 if (to is null) continue; 42 to.Bind(TextureType.Tex2D); 43 to.Image2D(TextureType.Tex2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null); 44 to.SetParameter(TextureType.Tex2D, TextureParameter.MagFilter, GL.Nearest); 45 to.SetParameter(TextureType.Tex2D, TextureParameter.MinFilter, GL.Nearest); 46 to.Unbind(); 47 } 48 49 rbo.Bind(); 50 rbo.Storage(GL_DEPTH_COMPONENT, width, height); 51 fbo.Renderbuffer(FramebufferType.Multi, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo.Id); 52 53 // Attach textures. 54 foreach(i, to; renderTextures) { 55 to.Bind(TextureType.Tex2D); 56 fbo.Texture(GL_FRAMEBUFFER, drawBufs[i], to.Id, 0); 57 to.Unbind(); 58 } 59 GL.DrawBuffers(cast(int)drawBufs.length, drawBufs.ptr); 60 } 61 62 void updateTextureBuffer() { 63 64 } 65 66 public: 67 @property int Width() { 68 return width; 69 } 70 71 @property int Height() { 72 return height; 73 } 74 75 this(int width, int height, int colorAttachments = 1) { 76 this.width = width; 77 this.height = height; 78 79 fbo = new FBO(); 80 rbo = new RBO(); 81 82 // Add color attachment textures 83 foreach(i; 0..colorAttachments) { 84 drawBufs ~= GL_COLOR_ATTACHMENT0+cast(uint)i; 85 renderTextures ~= new Texture(); 86 } 87 88 // Setup framebuffer 89 bufferTexture(); 90 fbo.Unbind(); 91 } 92 ~this() { 93 destroy(fbo); 94 destroy(renderTextures); 95 destroy(rbo); 96 } 97 98 Texture[] OutTextures() { 99 return renderTextures; 100 } 101 102 /** 103 Resize destroys the current framebuffer and recreates it with the specified size. 104 */ 105 void Resize(int width, int height) { 106 immutable(size_t) colorAttachments = renderTextures.length; 107 destroy(rbo); 108 destroy(fbo); 109 destroy(renderTextures); 110 destroy(drawBufs); 111 GC.collect(); 112 113 114 this.width = width; 115 this.height = height; 116 117 fbo = new FBO(); 118 rbo = new RBO(); 119 120 // TODO: Optimize this. 121 renderTextures = new Texture[colorAttachments]; 122 foreach(i; 0..colorAttachments) { 123 drawBufs ~= GL_COLOR_ATTACHMENT0+cast(uint)i; 124 renderTextures[i] = new Texture(); 125 } 126 127 // Setup framebuffer 128 bufferTexture(); 129 fbo.Unbind(); 130 } 131 132 void Begin() { 133 fbo.Bind(); 134 GL.Viewport(0, 0, width, height); 135 } 136 137 void End() { 138 GL.BindFramebuffer(GL_FRAMEBUFFER, 0); 139 fbo.Unbind(); 140 } 141 }