1 module armos.graphics.texture;
2 
3 import derelict.opengl3.gl;
4 import armos.math.vector;
5 import armos.graphics;
6 
7 /++
8     openGLのtextureを表すクラスです.
9     初期化後,allocateして利用します.
10     Example:
11     ---
12         auto texture = new Texture;
13         texture.allocate(256, 256);
14         
15         auto rect = new Mesh;
16         rect.primitiveMode = PrimitiveMode.Quads;
17         texture.begin;
18             rect.addTexCoord(0, 1);rect.addVertex(0, 0, 0);
19             rect.addTexCoord(0, 0);rect.addVertex(0, 1, 0);
20             rect.addTexCoord(1, 0);rect.addVertex(1, 1, 0);
21             rect.addTexCoord(1, 1);rect.addVertex(1, 0, 0);
22         texture.end;
23         
24         rect.addIndex(0);
25         rect.addIndex(1);
26         rect.addIndex(2);
27         rect.addIndex(3);
28         
29         texture.begin;
30             rect.drawFill();
31         texture.end;
32     ---
33 +/
34 class Texture {
35     public{
36         /++
37         +/
38         this(){
39             glEnable(GL_TEXTURE);
40             glGenTextures(1 , cast(uint*)&_id);
41         }
42 
43         ~this(){
44             glDeleteTextures(1 , cast(uint*)&_id);
45         }
46 
47         /++
48             Return the texture size.
49 
50             textureのサイズを返します.
51         +/
52         Vector2i size()const{return _size;}
53 
54         /++
55         +/
56         int width()const{
57             return size[0];
58         }
59 
60         /++
61         +/
62         int height()const{
63             return size[1];
64         }
65 
66         /++
67             Return gl texture id.
68         +/
69         int id()const{return _id;}
70 
71         /++
72             Begin to bind the texture.
73         +/
74         Texture begin(){
75             glBindTexture(GL_TEXTURE_2D , _id);
76             return this;
77         }
78 
79         /++
80             End to bind the texture.
81         +/
82         Texture end(){
83             glBindTexture(GL_TEXTURE_2D , 0);
84             return this;
85         }
86         
87         ///
88         Texture bind(){
89             glBindTexture(GL_TEXTURE_2D , _id);
90             return this;
91         };
92 
93         /++
94             Resize texture.
95         +/
96         Texture resize(in Vector2i textureSize){
97             _size = textureSize;
98             allocate;
99             return this;
100         };
101 
102         /++
103             Return pixel of texture
104             Deprecated:
105         +/
106         ubyte pixel(){
107             assert(_bitsPtr!=null);
108             return 0x00;
109         }
110 
111         /++
112             Set pixel of texture
113         +/
114         Texture pixel(in ubyte v){
115             assert(_bitsPtr!=null);
116             return this;
117         }
118 
119         /++
120             Allocate texture
121             Params:
122             w = width
123             h = height
124         +/
125         Texture allocate(in int w, in int h){
126             _size[0] = w;
127             _size[1] = h;
128             allocate;
129             return this;
130         }
131 
132         /++
133             Allocate texture
134             Params:
135             w = width
136             h = height
137         +/
138         Texture allocate(in int w, in int h, ColorFormat format){
139             _size[0] = w;
140             _size[1] = h;
141             _format = format;
142             allocate;
143             return this;
144         }
145 
146         /++
147             Allocate texture
148             Params:
149             bitmap =
150         +/
151         Texture allocate(Bitmap!(char) bitmap){
152             import std.math;
153             import std.array:appender;
154             
155             auto bitsApp = appender!(ubyte[]);
156             if(bitmap.width != bitmap.height){
157                 int side = cast( int )fmax(bitmap.width, bitmap.height);
158                 Bitmap!(char) squareBitmap;
159                 squareBitmap.allocate(side, side, bitmap.colorFormat);
160                 for (int j = 0; j < bitmap.size[1]; j++) {
161                     for (int i = 0; i < bitmap.size[0]; i++) {
162                         squareBitmap.pixel(i, j, bitmap.pixel(i, j));
163                     }
164                 }
165                 for (int j = 0; j < squareBitmap.size[1]; j++) {
166                     for (int i = 0; i < squareBitmap.size[0]; i++) {
167                         for (int k = 0; k < squareBitmap.numElements; k++) {
168                             bitsApp.put(squareBitmap.pixel(i, j).element(k));
169                         }
170                     }
171                 }
172                 allocate(bitsApp.data, squareBitmap.size[0], squareBitmap.size[1], squareBitmap.colorFormat);
173             }else{
174                 for (int j = 0; j < bitmap.size[1]; j++) {
175                     for (int i = 0; i < bitmap.size[0]; i++) {
176                         for (int k = 0; k < bitmap.numElements; k++) {
177                             bitsApp.put(bitmap.pixel(i, j).element(k));
178                         }
179                     }
180                 }
181                 allocate(bitsApp.data, bitmap.size[0], bitmap.size[1], bitmap.colorFormat);
182             }
183             return this;
184         }
185 
186         /++
187             Allocate texture
188             Params:
189             w    = width
190             h    = height
191             bits = image data
192         +/
193         Texture allocate(ubyte[] bits, in int w, in int h, in ColorFormat format){
194             _size[0] = w;
195             _size[1] = h;
196             _bitsPtr = bits.ptr;
197             allocate(format);
198             return this;
199         }
200 
201         /++
202             Allocate texture
203         +/
204         Texture allocate(in ColorFormat format){
205             _format = format;
206             allocate();
207             return this;
208         }
209 
210         /++
211             Allocate texture
212         +/
213         Texture allocate(){
214             GLuint internalFormat = getGLInternalFormat(_format);
215             begin;
216             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, _minFilter);
217             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, _magFilter);
218             glTexImage2D(
219                     GL_TEXTURE_2D, 0, internalFormat,
220                     _size[0], _size[1],
221                     0, internalFormat, GL_UNSIGNED_BYTE, cast(GLvoid*)_bitsPtr
222                     );
223             end;
224             return this;
225         }
226 
227         /++
228         +/
229         Texture minMagFilter(in TextureMinFilter minFilter, in TextureMagFilter magFilter){
230             _minFilter = minFilter;
231             _magFilter = magFilter;
232             begin; 
233             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
234             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
235             end;
236             return this;
237         }
238 
239         /++
240         +/
241         Texture minFilter(in TextureMinFilter filter){
242             _minFilter = filter;
243             begin;
244             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
245             end;
246             return this;
247         }
248         
249         ///
250         Texture magFilter(in TextureMagFilter filter){
251             _magFilter = filter;
252             begin;
253             glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
254             end;
255             return this;
256         }
257         
258         ///
259         Texture wrap(in TextureWrap p){
260             begin;
261             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, p);
262             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, p);
263             end;
264             return this;
265         }
266         
267         ///
268         Texture wrapS(in TextureWrap p){
269             begin;
270             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, p);
271             end;
272             return this;
273         }
274         
275         ///
276         Texture wrapT(in TextureWrap p){
277             begin;
278             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, p);
279             end;
280             return this;
281         }
282     }
283 
284     private{
285         int _id;
286         ubyte* _bitsPtr;
287         Vector2i _size;
288         ColorFormat _format;
289         TextureMinFilter _minFilter;
290         TextureMagFilter _magFilter;
291     }
292 }
293 
294 /++
295 +/
296 enum TextureMinFilter{
297     Linear = GL_LINEAR,
298     Nearest = GL_NEAREST, 
299     NearestMipmapNearest = GL_NEAREST_MIPMAP_NEAREST,
300     NearestMipmapLinear  = GL_NEAREST_MIPMAP_LINEAR,
301     LinearMipmapNearest  = GL_LINEAR_MIPMAP_NEAREST,
302     LinearMipmapLinear   = GL_LINEAR_MIPMAP_LINEAR,
303 }
304 
305 ///
306 enum TextureMagFilter{
307     Linear = GL_LINEAR,
308     Nearest = GL_NEAREST, 
309 }
310 
311 
312 ///
313 enum TextureWrap{
314     Clamp  = GL_CLAMP,
315     Repeat = GL_REPEAT,
316 }