1 module des.gl.base.render; 2 3 import des.math.linear; 4 import des.gl.base; 5 import des.il; 6 7 /// Render to FBO 8 class GLRender : DesObject 9 { 10 mixin DES; 11 mixin ClassLogger; 12 protected: 13 14 /// 15 GLFrameBuffer fbo; 16 17 /// 18 GLTexture depth_buf; 19 20 /// 21 GLTexture[uint] color_bufs; 22 23 uivec2 buf_size; 24 int[4] last_vp; 25 26 public: 27 28 /// 29 this() { fbo = newEMM!GLFrameBuffer; } 30 31 /// 32 GLTexture defaultDepth( uint unit ) 33 { 34 auto tex = createDefaultTexture( unit ); 35 tex.image( ivec2(1,1), GLTexture.InternalFormat.DEPTH32F, 36 GLTexture.Format.DEPTH, GLTexture.Type.FLOAT ); 37 return tex; 38 } 39 40 /// 41 GLTexture defaultColor( uint unit ) 42 { 43 auto tex = createDefaultTexture( unit ); 44 tex.image( ivec2(1,1), GLTexture.InternalFormat.RGBA, 45 GLTexture.Format.RGBA, GLTexture.Type.FLOAT ); 46 return tex; 47 } 48 49 /// 50 GLTexture getDepth() { return depth_buf; } 51 52 /// 53 void setDepth( GLTexture buf ) 54 in{ assert( buf !is null ); } body 55 { 56 if( depth_buf is buf ) 57 { 58 // TODO: warning 59 return; 60 } 61 62 removeIfChild( depth_buf ); 63 registerChildEMM( buf, true ); 64 depth_buf = buf; 65 fbo.setDepth( buf ); 66 fbo.check(); 67 } 68 69 /// get buffer setted to color attachment N 70 GLTexture getColor( uint N ) 71 { return color_bufs.get( N, null ); } 72 73 /// set buf to color attachment N 74 void setColor( GLTexture buf, uint N ) 75 in{ assert( buf !is null ); } body 76 { 77 if( auto tmp = color_bufs.get( N, null ) ) 78 { 79 if( tmp is buf ) 80 { 81 // TODO: warning 82 return; 83 } 84 removeIfChild( tmp ); 85 } 86 87 registerChildEMM( buf, true ); 88 color_bufs[N] = buf; 89 fbo.setColor( buf, N ); 90 fbo.check(); 91 } 92 93 /// 94 void resize( uivec2 sz ) 95 { 96 if( sz == buf_size ) return; 97 if( depth_buf ) depth_buf.resize( sz ); 98 foreach( col; color_bufs ) col.resize( sz ); 99 buf_size = sz; 100 logger.Debug( "[%d,%d]", sz.x, sz.y ); 101 } 102 103 /// 104 void resize( uint w, uint h ) 105 { resize( uivec2( w, h ) ); } 106 107 /// 108 void bind() 109 { 110 fbo.bind(); 111 checkGLCall!glGetIntegerv( GL_VIEWPORT, last_vp.ptr ); 112 checkGLCall!glViewport( 0, 0, buf_size.x, buf_size.y ); 113 } 114 115 /// 116 void unbind() 117 { 118 fbo.unbind(); 119 checkGLCall!glViewport( last_vp[0], last_vp[1], last_vp[2], last_vp[3] ); 120 } 121 122 protected: 123 124 auto createDefaultTexture( uint unit ) 125 { 126 auto tex = new GLTexture( GLTexture.Target.T2D, unit ); 127 tex.setWrapS( GLTexture.Wrap.CLAMP_TO_EDGE ); 128 tex.setWrapT( GLTexture.Wrap.CLAMP_TO_EDGE ); 129 tex.setMinFilter( GLTexture.Filter.NEAREST ); 130 tex.setMagFilter( GLTexture.Filter.NEAREST ); 131 return tex; 132 } 133 134 void removeIfChild( GLTexture t ) 135 { 136 if( depth_buf && findInChildsEMM( depth_buf ) ) 137 { 138 depth_buf.destroy(); 139 detachChildsEMM( depth_buf ); 140 } 141 } 142 143 override void selfDestroy() { fbo.unbind(); } 144 }