1 /* 2 Copyright © 2020, Luna Nielsen 3 Distributed under the 2-Clause BSD License, see LICENSE file. 4 5 Authors: Luna Nielsen 6 */ 7 module engine.render.fbo; 8 import engine.render; 9 import engine.math; 10 import engine.core.window; 11 12 /** 13 A framebuffer 14 */ 15 class Framebuffer { 16 private: 17 Window window; 18 19 vec2i size; 20 vec2i realsize; 21 22 GLuint fbo; 23 GLuint color; 24 GLuint depth; 25 26 package(engine): 27 28 /** 29 Gets the texture ID associated with the fbo 30 */ 31 GLuint getTexId() { 32 return color; 33 } 34 35 public: 36 37 /** 38 The constructor 39 */ 40 this(Window window, vec2i size) { 41 this.window = window; 42 this.size = size; 43 this.realsize = size*2; 44 45 // Bind FBO 46 glGenFramebuffers(1, &fbo); 47 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 48 49 // Enable blending, etc. 50 glEnable(GL_BLEND); 51 glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 52 glEnable(GL_CULL_FACE); 53 glEnable(GL_DEPTH_TEST); 54 glDepthFunc(GL_LESS); 55 56 // Generate texture 57 glGenTextures(1, &color); 58 glBindTexture(GL_TEXTURE_2D, color); 59 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, realsize.x, realsize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, null); 60 61 // Set up texture parameters 62 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 63 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 64 65 // Generate depth buffer 66 glGenRenderbuffers(1, &depth); 67 glBindRenderbuffer(GL_RENDERBUFFER, depth); 68 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, realsize.x, realsize.y); 69 70 // Configure framebuffer 71 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); 72 glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, color, 0); 73 } 74 75 /** 76 Bind the framebuffer 77 */ 78 void bind() { 79 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 80 kmViewport(0, 0, realsize.x, realsize.y); 81 kmSetCameraTargetSize(size.x, size.y); 82 } 83 84 /** 85 Unbind the framebuffer 86 */ 87 void unbind() { 88 glBindFramebuffer(GL_FRAMEBUFFER, 0); 89 kmViewport(0, 0, window.width, window.height); 90 } 91 92 /** 93 Renders the framebuffer to fit in the current viewport 94 */ 95 void renderToFit() { 96 double widthScale = cast(double)kmViewportWidth / cast(double)realWidth; 97 double heightScale = cast(double)kmViewportHeight / cast(double)realHeight; 98 double scale = min(widthScale, heightScale); 99 100 vec4 bounds = vec4( 101 0, 102 0, 103 realWidth*scale, 104 realHeight*scale 105 ); 106 107 if (widthScale > heightScale) bounds.x = (kmViewportWidth-bounds.z)/2; 108 else if (heightScale > widthScale) bounds.y = (kmViewportHeight-bounds.w)/2; 109 110 GameBatch.draw(this, bounds); 111 } 112 113 /** 114 Width of framebuffer 115 */ 116 int width() { 117 return size.x; 118 } 119 120 /** 121 Height of framebuffer 122 */ 123 int height() { 124 return size.y; 125 } 126 127 /** 128 Real width of framebuffer 129 */ 130 int realWidth() { 131 return realsize.x; 132 } 133 134 /** 135 Real height of framebuffer 136 */ 137 int realHeight() { 138 return realsize.y; 139 } 140 }