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