1 /**
2  * このモジュールをユーザーが直接使用することはありません。
3  */
4 
5 module grape.buffer;
6 
7 import derelict.opengl3.gl3;
8 import derelict.sdl2.sdl;
9 import derelict.sdl2.image;
10 
11 import std.stdio;
12 import std.math;
13 import std.conv;
14 
15 import grape.window;
16 import grape.file;
17 import grape.math;
18 import grape.camera;
19 import grape.surface;
20 import grape.shader;
21 
22 enum DrawMode {
23   Points = GL_POINTS,
24   Lines = GL_LINES,
25   LineLoop = GL_LINE_LOOP,
26   LineStrip = GL_LINE_STRIP,
27   Triangles = GL_TRIANGLES,
28   TriangleStrip = GL_TRIANGLE_STRIP,
29   TriangleFan = GL_TRIANGLE_FAN,
30   //Quads = GL_QUADS
31 }
32 
33 class UniformN {
34   public:
35     static this() {
36       _uniInt["1i"] = (location, value) { glUniform1i(location, value); };
37       _uniIntV["1iv"] = (location, value, num) { glUniform1iv(location, num, value.ptr); };
38       _uniIntV["2iv"] = (location, value, num) { glUniform2iv(location, num, value.ptr); };
39       _uniFloat["1f"] = (location, value) { glUniform1f(location, value); };
40       _uniFloatV["1fv"] = (location, value, num) { glUniform1fv(location, num, value.ptr); };
41       _uniFloatV["2fv"] = (location, value, num) { glUniform2fv(location, num, value.ptr); };
42       _uniFloatV["3fv"] = (location, value, num) { glUniform3fv(location, num, value.ptr); };
43       _uniFloatV["4fv"] = (location, value, num) { glUniform4fv(location, num, value.ptr); };
44       _uniFloatV["mat4fv"] = (location, value, num) { glUniformMatrix4fv(location, num, GL_FALSE, value.ptr); };
45     }
46 
47     static void locate(in string name, in int value, in string type, in int num, in GLint location) {
48       _uniInt[type](location, value);
49     }
50 
51     static void locate(in string name, in int[] value, in string type, in int num, in GLint location) {
52       _uniIntV[type](location, value, num);
53     }
54 
55     static void locate(in string name, in float value, in string type, in int num, in GLint location) {
56       _uniFloat[type](location, value);
57     }
58 
59     static void locate(in string name, in float[] value, in string type, in int num, in GLint location) {
60       _uniFloatV[type](location, value, num);
61     }
62 
63   private:
64     static void delegate(in GLint, in int)[string] _uniInt;
65     static void delegate(in GLint, in int[], in int)[string] _uniIntV;
66     static void delegate(in GLint, in float)[string] _uniFloat;
67     static void delegate(in GLint, in float[], in int)[string] _uniFloatV;
68 }
69 
70 class UniformLocationN {
71   public:
72     static void attach(T)(in GLuint program, in string name, in T value, in string type, in int num=1) {
73       auto location = glGetUniformLocation(program, cast(char*)name); 
74       _uniformN.locate(name, value, type, num, location);
75     }
76 
77   private:
78     static UniformN _uniformN;
79 }
80 
81 class AttributeLocationN {
82   public:
83     static void attach(in GLuint program, in string name, in int stride, in int i) {
84       glBindAttribLocation(program, i, cast(char*)name);
85       _location = glGetAttribLocation(program, cast(char*)name);
86       locate(stride);
87     }
88 
89   private:
90     static void locate(in int stride) {
91       glEnableVertexAttribArray(_location);
92       glVertexAttribPointer(_location, stride, GL_FLOAT, GL_FALSE, 0, null);
93     }
94 
95     static GLint _location;
96 }
97 
98 class VBO {
99   public:
100     this() {
101       glGenBuffers(1, &_id);
102     }
103 
104     ~this() {
105       glDeleteBuffers(1, &_id); 
106     }
107 
108     void set(T)(in GLuint program, in T data, in string name, in int stride, in int i) {
109       glBindBuffer(GL_ARRAY_BUFFER, _id); 
110       glBufferData(GL_ARRAY_BUFFER, data[0].sizeof*data.length, data.ptr, GL_STREAM_DRAW);
111       AttributeLocationN.attach(program, name, stride, i);
112       glBindBuffer(GL_ARRAY_BUFFER, 0); 
113     }
114 
115   private:
116     GLuint _id;
117 }
118 
119 class IBO {
120   public:
121     this() {
122       glGenBuffers(1, &_id);
123     }
124 
125     ~this() {
126       glDeleteBuffers(1, &_id);
127     }
128 
129     void create(in int[] index) { // const
130       _index = index.dup;
131       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _id); 
132       glBufferData(GL_ELEMENT_ARRAY_BUFFER, _index[0].sizeof*_index.length, _index.ptr, GL_STREAM_DRAW);
133       glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); 
134     }
135 
136     void draw(in DrawMode mode) { 
137       glDrawElements(mode, cast(int)_index.length, GL_UNSIGNED_INT, _index.ptr);
138     }
139 
140   private: 
141     GLuint _id;
142     int[] _index;
143 }
144 
145 class RBO {
146   public: 
147     this() {
148       glGenRenderbuffers(1, &_id);
149     }
150 
151     ~this() {
152       glDeleteRenderbuffers(1, &_id);
153     }
154 
155     void create(T)(in T type, in int w, in int h) {
156       glBindRenderbuffer(GL_RENDERBUFFER, _id);
157       glRenderbufferStorage(GL_RENDERBUFFER, type, w, h);
158       glBindRenderbuffer(GL_RENDERBUFFER, 0);
159     }
160 
161     void attach(T)(in T type) {
162       glBindRenderbuffer(GL_RENDERBUFFER, _id);
163       glFramebufferRenderbuffer(GL_FRAMEBUFFER, type, GL_RENDERBUFFER, _id);
164       glBindRenderbuffer(GL_RENDERBUFFER, 0);
165     }
166 
167   private:
168     GLuint _id;
169 }
170 
171 class FBO {
172   public:
173     this() {
174       glGenFramebuffers(1, &_id);
175     }
176 
177     ~this() {
178       glDeleteFramebuffers(1, &_id);
179     }
180 
181     void create(T)(in T texture, GLenum attachment = GL_COLOR_ATTACHMENT0) {
182       glBindFramebuffer(GL_FRAMEBUFFER, _id);
183       glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture, 0);
184       glBindFramebuffer(GL_FRAMEBUFFER, 0);
185     }
186 
187     void binded_scope(void delegate() dg) {
188       glBindFramebuffer(GL_FRAMEBUFFER, _id);
189       dg();
190       glBindFramebuffer(GL_FRAMEBUFFER, 0);
191     }
192 
193   // TODO Check whether fbo is certainly compiled 
194   // glCheckFramebufferStatus 
195 
196   private:
197     GLuint _id;
198 }
199 
200 class Texture {
201   public:
202     this() {
203       glGenTextures(1, &_id);
204     }
205 
206     ~this() {
207       glDeleteTextures(1, &_id);
208     }
209 
210     // TODO divide
211     void create(in int w, in int h, void* pixels, in int bytesPerPixel) {
212       set_draw_mode(bytesPerPixel);
213       _w = w;
214       _h = h;
215 
216       glActiveTexture(GL_TEXTURE0); // TODO Cover other units
217 
218       glBindTexture(GL_TEXTURE_2D, _id);
219       attach(w, h, pixels); filter();
220       glBindTexture(GL_TEXTURE_2D, 0);
221     }
222 
223     void create(Surface surf) {
224       create(surf.w, surf.h, surf.pixels, surf.bytes_per_pixel);
225     }
226 
227     // Provides a scope that a texture is enabled.
228     void texture_scope(void delegate() dg) {
229       glBindTexture(GL_TEXTURE_2D, _id);
230       glActiveTexture(GL_TEXTURE0);
231       dg();
232       glActiveTexture(GL_TEXTURE0); // Need? It's only needed if dg() changes the texture-unit.
233       glBindTexture(GL_TEXTURE_2D, 0);
234     }
235 
236     alias _id this; // TODO private
237 
238     @property {
239       int w() {
240         return _w;
241       }
242 
243       int h() {
244         return _h;
245       }
246     }
247 
248   private:
249     void set_draw_mode(in int bytesPerPixel) {
250       _mode = (bytesPerPixel == 4) ? GL_RGBA : GL_RGB;
251     }
252 
253     void attach(in int w, in int h, void* pixels) { // const
254       glTexImage2D(GL_TEXTURE_2D, 0, _mode, w, h, 0, _mode, GL_UNSIGNED_BYTE, pixels);
255     }
256 
257     void filter() {
258       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
259       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
260     }
261 
262     GLuint _id;
263     int _mode;
264     int _w;
265     int _h;
266 }
267 
268 
269 /*******************ここから************************/
270 deprecated class VBOHdr {
271   public:
272     this(in size_t num, in GLuint program) {
273       _num = num;
274       _vboList.length = _num;
275       for (int i; i<_num; ++i)
276         _vboList[i] = new OldVBO(program);
277     }
278 
279     void create_vbo(in float[][] list...) {
280       assert(list.length == _num, "Doesn't match the number of vbo attributes");
281 
282       foreach(int i, data; list)
283         _vboList[i].create(data);
284     }
285 
286     void enable_vbo(in string[] locNames, in int[] strides) {
287       assert(locNames.length == _num);
288       assert(strides.length == _num);
289 
290       foreach (int i, vbo; _vboList)
291         vbo.attach(locNames[i], strides[i], i);
292     }
293 
294     void draw(in DrawMode mode, in int num) {
295       glDrawArrays(mode, 0, num);
296     }
297 
298   private:
299     size_t _num;
300     OldVBO[] _vboList;
301 }
302 
303 deprecated class OldVBO {
304   public:
305     this(in GLuint program) {
306       _attLoc = new AttributeLocation(program);
307       glGenBuffers(1, &_id);
308     }
309 
310     ~this() {
311       glDeleteBuffers(1, &_id); 
312     }
313 
314     void create(T)(in T data) {
315       glBindBuffer(GL_ARRAY_BUFFER, _id); 
316       glBufferData(GL_ARRAY_BUFFER, data[0].sizeof*data.length, data.ptr, GL_STREAM_DRAW);
317       glBindBuffer(GL_ARRAY_BUFFER, 0); 
318     }
319 
320     void attach(in string name, in int stride, in int i) {
321       glBindBuffer(GL_ARRAY_BUFFER, _id); 
322       _attLoc.attach(name, stride, i);
323       glBindBuffer(GL_ARRAY_BUFFER, 0); 
324     }
325 
326   private:
327     GLuint _id;
328     AttributeLocation _attLoc;
329 }
330 
331 deprecated class AttributeLocation {
332   public:
333     this(in GLuint program) {
334       _program = program;
335     }
336 
337     void attach(in string name, in int stride, in int i) {
338       glBindAttribLocation(_program, i, cast(char*)name);
339       _location = glGetAttribLocation(_program, cast(char*)name);
340       locate(stride);
341     }
342 
343   private:
344     void locate(in int stride) {
345       glEnableVertexAttribArray(_location);
346       glVertexAttribPointer(_location, stride, GL_FLOAT, GL_FALSE, 0, null);
347     }
348 
349     GLuint _program;
350     GLint _location;
351 }
352 
353 deprecated class Uniform {
354   public:
355     this(){
356       init();
357     }
358 
359     this(string vShader, string fShader) {
360       this();
361       //extract(vShader, fShader);
362     }
363 
364     void locate(in string name, in int value, in string type, in int num, in GLint location) {
365       _uniInt[type](location, value);
366     }
367 
368     void locate(in string name, in float[] value, in string type, in int num, in GLint location) {
369       _uniFloatV[type](location, value, num);
370     }
371 
372   private:
373     void init() {
374       _uniInt["1i"] = (location, value) { glUniform1i(location, value); };
375       _uniFloatV["1fv"] = (location, value, num) { glUniform1fv(location, num, value.ptr); };
376       _uniFloatV["2fv"] = (location, value, num) { glUniform2fv(location, num, value.ptr); };
377       _uniFloatV["3fv"] = (location, value, num) { glUniform3fv(location, num, value.ptr); };
378       _uniFloatV["4fv"] = (location, value, num) { glUniform4fv(location, num, value.ptr); };
379       _uniFloatV["mat4fv"] = (location, value, num) { glUniformMatrix4fv(location, num, GL_FALSE, value.ptr); };
380     }
381 
382     // TODO ソースから判別
383     void extract(string vShader, string fShader) {
384     }
385 
386     void delegate(in GLint, in int)[string] _uniInt;
387     //void delegate(int[])[string] _uniIntV;
388     //void delegate(float)[string] _uniFloat;
389     void delegate(in GLint, in float[], in int)[string] _uniFloatV;
390 }
391 
392 deprecated class UniformLocation {
393   public:
394     this(in GLuint program) {
395       _program = program;
396       _uniform = new Uniform;
397     }
398 
399     void attach(T)(in string name, in T value, in string type, in int num=1) {
400       _location = glGetUniformLocation(_program, cast(char*)name); 
401       _uniform.locate(name, value, type, num, _location);
402     }
403 
404   private:
405     Uniform _uniform;
406     GLuint _program;
407     GLint _location;
408 }
409 
410 /************************ここまでいらない*************/
411