1 module grape.filter; 2 3 import derelict.opengl3.gl3; 4 import grape.buffer; 5 import grape.renderer; 6 import grape.window; 7 8 deprecated abstract class Filter { 9 public: 10 /** 11 * Filterの初期化 12 * 13 * num: Filterで使うtextureの数 14 * w: textureの幅 15 * h: textureの高さ 16 */ 17 this(in size_t num, in int w, in int h) { 18 _w = w; 19 _h = h; 20 _fbo = new FBO; 21 _renderer = new FilterRenderer; 22 23 _textures.length = num; 24 for (int i; i<num; ++i) { 25 _textures[i] = new Texture; 26 _textures[i].create(_w, _h, null, GL_RGBA); 27 } 28 } 29 30 /** 31 * ポストエフェクトの処理 32 * 33 * 実際にポストエフェクトをかける関数です。 34 * 引数部分で下記のように描画処理をすれば、ポストエフェクトがかかった状態で描画されます。 35 * 36 * Examples: 37 * --------------- 38 * Filter.filter({ 39 * Renderer.render(); 40 * }); 41 * --------------- 42 */ 43 final void filter(in void delegate() dg) { 44 black_filter(dg); 45 render(); 46 } 47 48 /** 49 * filterが処理後の最終結果をrenderするのに対し、 50 * black_filterはrenderしない。 51 */ 52 abstract void black_filter(in void delegate()); 53 54 /** 55 * ポストエフェクトがかかったテクスチャの描画 56 * 57 * 単純にテクスチャを描画するだけです。 58 * 59 * TODO: 60 * FilterRenderer所持してるけどどうするか 61 */ 62 final void render() { 63 render(_textures.length-1); 64 } 65 66 /** 67 * Filterが内部に所持しているテクスチャの描画 68 * 69 * 基本的に使うことはありません 70 * filter()の途中で生成されるtextureを確認したいときに使えます。 71 * 引数に受け取った番号のテクスチャを描画します。 72 * BlurFilterならば、 73 * 0: renderした画面を格納したtexture 74 * 1: 0を横Blurしたtexture 75 * 2: 1を縦Blurしたtexture 76 */ 77 final void render(in size_t i) { 78 assert(i < _textures.length); 79 80 glDisable(GL_DEPTH_TEST); 81 filter_scope(i, { _renderer.render(); }); // TODO Specify a drawing area }); 82 glEnable(GL_DEPTH_TEST); 83 } 84 85 /** 86 * ポストエフェクトがかかったテクスチャを適応したスコープ 87 * 88 */ 89 final void filter_scope(in size_t i, in void delegate() dg) { 90 glEnable(GL_BLEND); 91 glBlendFunc(GL_ONE, GL_ONE); 92 _textures[i].texture_scope(dg); 93 glDisable(GL_BLEND); 94 } 95 96 protected: 97 final void create_filter(in int i, in void delegate() dg) { 98 attach(i); 99 fbo_scope(dg); 100 } 101 102 private: 103 void attach(in int i) { 104 _fbo.create(_textures[i]); 105 106 // TODO RBO 107 _fbo.binded_scope({ 108 GLenum[] drawBufs = [GL_COLOR_ATTACHMENT0]; 109 glDrawBuffers(1, drawBufs.ptr); 110 }); 111 } 112 113 void fbo_scope(in void delegate() dg) { 114 _fbo.binded_scope({ 115 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 116 117 glEnable(GL_BLEND); 118 glBlendFunc(GL_ONE, GL_ZERO); // default blend 119 glViewport(0, 0, _w, _h); 120 dg(); 121 glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); 122 glDisable(GL_BLEND); 123 }); 124 } 125 126 FBO _fbo; 127 int _w, _h; 128 FilterRenderer _renderer; 129 Texture[] _textures; 130 } 131 132 deprecated class BlurFilter : Filter { 133 public: 134 this(in int w, in int h) { 135 super(3, w, h); 136 _renderer = new GaussianRenderer([w, h]); 137 } 138 139 override void black_filter(in void delegate() dg) { 140 auto raw_render = { 141 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 142 dg(); 143 }; 144 145 create_filter(0, raw_render); 146 create_filter(1, { 147 filter_scope(0, { 148 _renderer.set_type(0); 149 _renderer.render(); 150 }); 151 }); 152 create_filter(2, { 153 filter_scope(1, { 154 _renderer.set_type(1); 155 _renderer.render(); 156 }); 157 }); 158 } 159 160 private: 161 GaussianRenderer _renderer; 162 } 163 164 deprecated class GlowFilter : Filter { 165 public: 166 this(in int w, in int h) { 167 this(w, h, w, h); 168 } 169 170 this(in int w, in int h, in int w2, in int h2) { 171 super(2, w, h); 172 _blurFilter = new BlurFilter(w2, h2); 173 } 174 175 override void black_filter(in void delegate() dg) { 176 auto raw_render = { 177 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 178 dg(); 179 }; 180 181 create_filter(0, raw_render); 182 _blurFilter.black_filter(raw_render); 183 184 create_filter(1, { 185 glBlendFunc(GL_ONE, GL_ONE); 186 render(0); 187 _blurFilter.render(); 188 }); 189 } 190 191 private: 192 BlurFilter _blurFilter; 193 } 194