1 module unecht.core.assets.texture;
2 
3 import unecht.core.component;
4 import unecht.core.object;
5 import unecht.core.serialization.serializer;
6 import unecht.core.defaultInspector;
7 
8 import derelict.opengl3.gl3;
9 
10 ///
11 enum UETextureFiltering
12 {
13     linear,
14     point,
15 }
16 
17 ///
18 enum UETextureRepeat
19 {
20     clamp,
21     repeat
22 }
23 
24 ///
25 abstract class UETexture : UEObject
26 {
27     mixin(UERegisterObject!());
28 
29     ///
30     @property int width() const { return _width; }
31     ///
32     @property int height() const { return _height; }
33 
34     ///
35     @property UETextureFiltering filter() const { return _filtering; }
36     ///
37     @property UETextureRepeat repeat() const { return _repeat; }
38     ///
39     @property void filter(UETextureFiltering v) { _filtering = v; }
40     ///
41     @property void repeat(UETextureRepeat v) { _repeat = v; }
42     ///
43     @property bool isValid() const { return _glTex != 0; }
44     ///
45     @property void* driverHandle() const { return cast(void*)_glTex; }
46 
47     void bind()
48     {
49         glBindTexture(GL_TEXTURE_2D, _glTex);
50 
51         setFilter();
52 
53         auto glClamp = GL_CLAMP_TO_EDGE;
54         if(_repeat == UETextureRepeat.repeat)
55             glClamp = GL_REPEAT;        
56 
57         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
58         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
59     }
60 
61     void unbind()
62     {
63         glBindTexture(GL_TEXTURE_2D, 0);
64     }
65 
66     protected void setFilter()
67     {
68         auto glFiltering = GL_NEAREST;
69         if(_filtering == UETextureFiltering.linear)
70             glFiltering = GL_LINEAR;
71 
72         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glFiltering);
73         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glFiltering);
74     }
75 
76 protected:
77     @Serialize
78     UETextureFiltering _filtering;
79     @Serialize
80     UETextureRepeat _repeat;
81 
82     int _width;
83     int _height;
84 
85     GLuint _glTex;
86 }
87 
88 ///
89 final class UETexture2D : UETexture
90 {
91     import derelict.freeimage.freeimage;
92 
93     mixin(UERegisterObject!());
94 
95     ///
96     public void loadFromFile(string path)
97     {
98         import std..string:toStringz;
99         import std.file:exists;
100 
101         assert(exists(path));
102 
103         auto fn = toStringz(path);
104         
105         FIBITMAP* bitmap = FreeImage_Load(FreeImage_GetFileType(fn, 0), fn);
106         scope(exit) FreeImage_Unload(bitmap);
107 
108         createRaw(bitmap);
109     }
110 
111     ///
112     public void loadFromMemFile(ubyte[] mem)
113     {
114         auto memHandle = FreeImage_OpenMemory(mem.ptr, mem.length);
115         assert(memHandle);
116         scope(exit) FreeImage_CloseMemory(memHandle);
117 
118         auto format = FreeImage_GetFileTypeFromMemory(memHandle, cast(int)mem.length);
119         import unecht.core.logger;
120         import std.conv;
121         log.logf("loadFromMemFile: %s",to!string(format));
122 
123         FIBITMAP* bitmap = FreeImage_LoadFromMemory(format, memHandle);
124         assert(bitmap);
125         scope(exit) FreeImage_Unload(bitmap);
126 
127         createRaw(bitmap);
128     }
129 
130     private void createRaw(FIBITMAP* _image)
131     {
132         //TODO: check if bits are not 32 first
133         FIBITMAP* pImage = FreeImage_ConvertTo32Bits(_image);
134         scope(exit) FreeImage_Unload(pImage);
135 
136         _width = FreeImage_GetWidth(_image);
137         _height = FreeImage_GetHeight(_image);
138 
139         assert(pImage !is null);
140         assert(FreeImage_GetBPP(pImage) == 32);
141 
142         glGenTextures(1, &_glTex);
143 
144         glBindTexture(GL_TEXTURE_2D, _glTex);
145 
146         setFilter();
147         
148         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, _width, _height,
149             0, GL_BGRA, GL_UNSIGNED_BYTE, cast(void*)FreeImage_GetBits(pImage));
150     }
151 }
152 /+
153 ///
154 final class UETextureCubemap : UETexture
155 {
156     mixin(UERegisterObject!());
157 
158     this(int size)
159     {
160         super(size,size);
161     }
162 
163 private:
164     @Serialize
165     UETexture2D[6] faces;
166 }
167 +/