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