24 |
24 |
25 function NewTexture(width, height: Longword; buf: Pointer): PTexture; |
25 function NewTexture(width, height: Longword; buf: Pointer): PTexture; |
26 procedure Surface2GrayScale(surf: PSDL_Surface); |
26 procedure Surface2GrayScale(surf: PSDL_Surface); |
27 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; |
27 function Surface2Tex(surf: PSDL_Surface; enableClamp: boolean): PTexture; |
28 procedure FreeTexture(tex: PTexture); |
28 procedure FreeTexture(tex: PTexture); |
|
29 procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect); |
29 |
30 |
30 procedure initModule; |
31 procedure initModule; |
31 procedure freeModule; |
32 procedure freeModule; |
32 |
33 |
33 implementation |
34 implementation |
45 end; |
46 end; |
46 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
47 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
47 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) |
48 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR) |
48 end; |
49 end; |
49 |
50 |
|
51 procedure ComputeTexcoords(texture: PTexture; r: PSDL_Rect; tb: PVertexRect); |
|
52 var x0, y0, x1, y1: Real; |
|
53 w, h, aw, ah: LongInt; |
|
54 const texelOffset = 0.0; |
|
55 begin |
|
56 aw:=texture^.atlas^.w; |
|
57 ah:=texture^.atlas^.h; |
|
58 if texture^.isRotated then |
|
59 begin |
|
60 w:=r^.h; |
|
61 h:=r^.w; |
|
62 end |
|
63 else |
|
64 begin |
|
65 w:=r^.w; |
|
66 h:=r^.h; |
|
67 end; |
|
68 |
|
69 x0:= (r^.x + texelOffset)/aw; |
|
70 x1:= (r^.x + w - texelOffset)/aw; |
|
71 y0:= (r^.y + texelOffset)/ah; |
|
72 y1:= (r^.y + h - texelOffset)/ah; |
|
73 |
|
74 tb^[0].X:= x0; |
|
75 tb^[0].Y:= y0; |
|
76 tb^[1].X:= x1; |
|
77 tb^[1].Y:= y0; |
|
78 tb^[2].X:= x1; |
|
79 tb^[2].Y:= y1; |
|
80 tb^[3].X:= x0; |
|
81 tb^[3].Y:= y1 |
|
82 end; |
|
83 |
50 procedure ResetVertexArrays(texture: PTexture); |
84 procedure ResetVertexArrays(texture: PTexture); |
|
85 var r: TSDL_Rect; |
51 begin |
86 begin |
52 with texture^ do |
87 with texture^ do |
53 begin |
88 begin |
54 vb[0].X:= 0; |
89 vb[0].X:= 0; |
55 vb[0].Y:= 0; |
90 vb[0].Y:= 0; |
56 vb[1].X:= w; |
91 vb[1].X:= w; |
57 vb[1].Y:= 0; |
92 vb[1].Y:= 0; |
58 vb[2].X:= w; |
93 vb[2].X:= w; |
59 vb[2].Y:= h; |
94 vb[2].Y:= h; |
60 vb[3].X:= 0; |
95 vb[3].X:= 0; |
61 vb[3].Y:= h; |
96 vb[3].Y:= h; |
62 |
97 end; |
63 tb[0].X:= 0; |
98 |
64 tb[0].Y:= 0; |
99 r.x:= 0; |
65 tb[1].X:= rx; |
100 r.y:= 0; |
66 tb[1].Y:= 0; |
101 r.w:= texture^.w; |
67 tb[2].X:= rx; |
102 r.h:= texture^.h; |
68 tb[2].Y:= ry; |
103 ComputeTexcoords(texture, @r, @texture^.tb); |
69 tb[3].X:= 0; |
|
70 tb[3].Y:= ry |
|
71 end; |
|
72 end; |
104 end; |
73 |
105 |
74 function NewTexture(width, height: Longword; buf: Pointer): PTexture; |
106 function NewTexture(width, height: Longword; buf: Pointer): PTexture; |
75 begin |
107 begin |
76 new(NewTexture); |
108 new(NewTexture); |
82 TextureList^.PrevTexture:= NewTexture; |
114 TextureList^.PrevTexture:= NewTexture; |
83 NewTexture^.NextTexture:= TextureList |
115 NewTexture^.NextTexture:= TextureList |
84 end; |
116 end; |
85 TextureList:= NewTexture; |
117 TextureList:= NewTexture; |
86 |
118 |
87 NewTexture^.w:= width; |
119 |
88 NewTexture^.h:= height; |
120 // Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite |
89 NewTexture^.rx:= 1.0; |
121 new(NewTexture^.atlas); |
90 NewTexture^.ry:= 1.0; |
122 NewTexture^.atlas^.w:=width; |
|
123 NewTexture^.atlas^.h:=height; |
|
124 NewTexture^.x:=0; |
|
125 NewTexture^.y:=0; |
|
126 NewTexture^.w:=width; |
|
127 NewTexture^.h:=height; |
|
128 NewTexture^.isRotated:=false; |
91 |
129 |
92 ResetVertexArrays(NewTexture); |
130 ResetVertexArrays(NewTexture); |
93 |
131 |
94 glGenTextures(1, @NewTexture^.id); |
132 glGenTextures(1, @NewTexture^.atlas^.id); |
95 |
133 |
96 glBindTexture(GL_TEXTURE_2D, NewTexture^.id); |
134 glBindTexture(GL_TEXTURE_2D, NewTexture^.atlas^.id); |
97 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
135 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
98 |
136 |
99 SetTextureParameters(true); |
137 SetTextureParameters(true); |
100 end; |
138 end; |
101 |
139 |
134 TextureList^.PrevTexture:= Surface2Tex; |
172 TextureList^.PrevTexture:= Surface2Tex; |
135 Surface2Tex^.NextTexture:= TextureList |
173 Surface2Tex^.NextTexture:= TextureList |
136 end; |
174 end; |
137 TextureList:= Surface2Tex; |
175 TextureList:= Surface2Tex; |
138 |
176 |
|
177 // Atlas allocation happens here later on. For now we just allocate one exclusive atlas per sprite |
|
178 new(Surface2Tex^.atlas); |
|
179 |
139 Surface2Tex^.w:= surf^.w; |
180 Surface2Tex^.w:= surf^.w; |
140 Surface2Tex^.h:= surf^.h; |
181 Surface2Tex^.h:= surf^.h; |
|
182 Surface2Tex^.x:=0; |
|
183 Surface2Tex^.y:=0; |
|
184 Surface2Tex^.isRotated:=false; |
|
185 |
141 |
186 |
142 if (surf^.format^.BytesPerPixel <> 4) then |
187 if (surf^.format^.BytesPerPixel <> 4) then |
143 begin |
188 begin |
144 TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true); |
189 TryDo(false, 'Surface2Tex failed, expecting 32 bit surface', true); |
145 Surface2Tex^.id:= 0; |
190 Surface2Tex^.atlas^.id:= 0; |
146 exit |
191 exit |
147 end; |
192 end; |
148 |
193 |
149 |
194 |
150 glGenTextures(1, @Surface2Tex^.id); |
195 glGenTextures(1, @Surface2Tex^.atlas^.id); |
151 |
196 |
152 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.id); |
197 glBindTexture(GL_TEXTURE_2D, Surface2Tex^.atlas^.id); |
153 |
198 |
154 if SDL_MustLock(surf) then |
199 if SDL_MustLock(surf) then |
155 SDLTry(SDL_LockSurface(surf) >= 0, true); |
200 SDLTry(SDL_LockSurface(surf) >= 0, true); |
156 |
201 |
157 fromP4:= Surf^.pixels; |
202 fromP4:= Surf^.pixels; |
162 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then |
207 if (not SupportNPOTT) and (not (isPowerOf2(Surf^.w) and isPowerOf2(Surf^.h))) then |
163 begin |
208 begin |
164 tw:= toPowerOf2(Surf^.w); |
209 tw:= toPowerOf2(Surf^.w); |
165 th:= toPowerOf2(Surf^.h); |
210 th:= toPowerOf2(Surf^.h); |
166 |
211 |
167 Surface2Tex^.rx:= Surf^.w / tw; |
212 Surface2Tex^.atlas^.w:=tw; |
168 Surface2Tex^.ry:= Surf^.h / th; |
213 Surface2Tex^.atlas^.h:=th; |
169 |
214 |
170 GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel); |
215 GetMem(tmpp, tw * th * surf^.format^.BytesPerPixel); |
171 |
216 |
172 fromP4:= Surf^.pixels; |
217 fromP4:= Surf^.pixels; |
173 toP4:= tmpp; |
218 toP4:= tmpp; |
193 |
238 |
194 FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel) |
239 FreeMem(tmpp, tw * th * surf^.format^.BytesPerPixel) |
195 end |
240 end |
196 else |
241 else |
197 begin |
242 begin |
198 Surface2Tex^.rx:= 1.0; |
243 Surface2Tex^.atlas^.w:=Surf^.w; |
199 Surface2Tex^.ry:= 1.0; |
244 Surface2Tex^.atlas^.h:=Surf^.h; |
200 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels); |
245 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, surf^.w, surf^.h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surf^.pixels); |
201 end; |
246 end; |
202 |
247 |
203 ResetVertexArrays(Surface2Tex); |
248 ResetVertexArrays(Surface2Tex); |
204 |
249 |
212 // if nil is passed nothing is done |
257 // if nil is passed nothing is done |
213 procedure FreeTexture(tex: PTexture); |
258 procedure FreeTexture(tex: PTexture); |
214 begin |
259 begin |
215 if tex <> nil then |
260 if tex <> nil then |
216 begin |
261 begin |
|
262 // Atlas cleanup happens here later on. For now we just free as each sprite has one atlas |
|
263 Dispose(tex^.atlas); |
|
264 |
217 if tex^.NextTexture <> nil then |
265 if tex^.NextTexture <> nil then |
218 tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; |
266 tex^.NextTexture^.PrevTexture:= tex^.PrevTexture; |
219 if tex^.PrevTexture <> nil then |
267 if tex^.PrevTexture <> nil then |
220 tex^.PrevTexture^.NextTexture:= tex^.NextTexture |
268 tex^.PrevTexture^.NextTexture:= tex^.NextTexture |
221 else |
269 else |
222 TextureList:= tex^.NextTexture; |
270 TextureList:= tex^.NextTexture; |
223 glDeleteTextures(1, @tex^.id); |
271 glDeleteTextures(1, @tex^.atlas^.id); |
224 Dispose(tex); |
272 Dispose(tex); |
225 end |
273 end |
226 end; |
274 end; |
227 |
275 |
228 procedure initModule; |
276 procedure initModule; |
234 begin |
282 begin |
235 if TextureList <> nil then |
283 if TextureList <> nil then |
236 WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem'); |
284 WriteToConsole('FIXME FIXME FIXME. App shutdown without full cleanup of texture list; read game0.log and please report this problem'); |
237 while TextureList <> nil do |
285 while TextureList <> nil do |
238 begin |
286 begin |
239 AddFileLog('Texture not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.priority*1000))); |
287 AddFileLog('Sprite not freed: width='+inttostr(LongInt(TextureList^.w))+' height='+inttostr(LongInt(TextureList^.h))+' priority='+inttostr(round(TextureList^.atlas^.priority*1000))); |
240 FreeTexture(TextureList); |
288 FreeTexture(TextureList); |
241 end |
289 end |
242 end; |
290 end; |
243 |
291 |
244 end. |
292 end. |