DEADSOFTWARE

fbdae7e4ee8e09cdfd307dc29365d7b322f88149
[d2df-sdl.git] / src / game / renders / opengl / r_draw.pas
1 (* Copyright (C) Doom 2D: Forever Developers
2 *
3 * This program is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation, version 3 of the License ONLY.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 *)
15 {$INCLUDE ../../../shared/a_modes.inc}
16 unit r_draw;
18 interface
20 uses
21 g_animations,
22 r_textures
23 ;
25 procedure r_Draw_Texture (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
26 procedure r_Draw_TextureRepeat (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
27 procedure r_Draw_TextureRepeatRotate (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer);
29 procedure r_Draw_MultiTextureRepeat (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
30 procedure r_Draw_MultiTextureRepeatRotate (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer);
32 procedure r_Draw_Filter (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
33 procedure r_Draw_FillRect (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
34 procedure r_Draw_InvertRect (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
36 procedure r_Draw_Text (const text: AnsiString; x, y: Integer; r, g, b, a: Byte; f: TGLFont);
37 procedure r_Draw_GetTextSize (const text: AnsiString; f: TGLFont; out w, h: Integer);
39 implementation
41 uses
42 {$IFDEF USE_GLES1}
43 GLES11,
44 {$ELSE}
45 GL, GLEXT,
46 {$ENDIF}
47 SysUtils, Classes, Math,
48 e_log, utils,
49 g_game // gScreenWidth, gScreenHeight
50 ;
52 const
53 NTR = $FF;
54 NTG = $00;
55 NTB = $00;
56 NTA = $FF;
58 procedure SetupMatrix;
59 begin
60 glScissor(0, 0, gScreenWidth, gScreenHeight);
61 glViewport(0, 0, gScreenWidth, gScreenHeight);
62 glMatrixMode(GL_PROJECTION);
63 glLoadIdentity;
64 glOrtho(0, gScreenWidth, gScreenHeight, 0, 0, 1);
65 glMatrixMode(GL_MODELVIEW);
66 glLoadIdentity;
67 end;
69 procedure DrawQuad (x, y, w, h: Integer);
70 begin
71 glBegin(GL_QUADS);
72 glVertex2i(x + w, y);
73 glVertex2i(x, y);
74 glVertex2i(x, y + h);
75 glVertex2i(x + w, y + h);
76 glEnd();
77 end;
79 procedure DrawTile (tile: TGLAtlasNode; x, y, w, h: Integer; flip: Boolean; rr, gg, bb, aa: Byte; blend: Boolean);
80 var nw, nh, ax, bx, ay, by: GLfloat; l, t, r, b: Integer;
81 begin
82 if tile = nil then
83 begin
84 glColor4ub(rr, gg, bb, aa);
85 if blend then glBlendFunc(GL_SRC_ALPHA, GL_ONE) else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
86 glDisable(GL_TEXTURE_2D);
87 glEnable(GL_BLEND);
88 DrawQuad(x, y, w, h);
89 end
90 else
91 begin
92 nw := tile.base.w;
93 nh := tile.base.h;
94 ax := IfThen(flip, tile.l, tile.r + 1) / nw;
95 bx := IfThen(flip, tile.r + 1, tile.l) / nh;
96 ay := (tile.t) / nw;
97 by := (tile.b + 1) / nh;
98 l := x; t := y; r := x + w; b := y + h;
99 glBindTexture(GL_TEXTURE_2D, tile.id);
100 glColor4ub(rr, gg, bb, aa);
101 if blend then glBlendFunc(GL_SRC_ALPHA, GL_ONE) else glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
102 glEnable(GL_TEXTURE_2D);
103 glEnable(GL_BLEND);
104 glBegin(GL_QUADS);
105 glTexCoord2f(ax, ay); glVertex2i(r, t);
106 glTexCoord2f(bx, ay); glVertex2i(l, t);
107 glTexCoord2f(bx, by); glVertex2i(l, b);
108 glTexCoord2f(ax, by); glVertex2i(r, b);
109 glEnd();
110 glDisable(GL_TEXTURE_2D);
111 glBindTexture(GL_TEXTURE_2D, 0);
112 end
113 end;
115 procedure r_Draw_Texture (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
116 var i, j, offx, offy: Integer; n: TGLAtlasNode;
117 begin
118 ASSERT(w >= 0);
119 ASSERT(h >= 0);
120 if img = nil then
121 DrawTile(nil, x, y, w, h, flip, NTR, NTB, NTG, NTA, blend)
122 else
123 begin
124 offx := 0;
125 offy := 0;
126 for j := 0 to img.lines - 1 do
127 begin
128 for i := 0 to img.cols - 1 do
129 begin
130 n := img.GetTile(i, j);
131 ASSERT(n <> nil);
132 glPushMatrix;
133 glTranslatef(x + offx, y + offy, 0);
134 glScalef(w / img.width, h / img.height, 1);
135 DrawTile(n, 0, 0, n.width, n.height, flip, r, g, b, a, blend);
136 glPopMatrix;
137 offx := offx + n.width;
138 end;
139 offx := 0;
140 offy := offy + n.height;
141 end;
142 end
143 end;
145 procedure r_Draw_TextureRepeat (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
146 var i, j: Integer;
147 begin
148 ASSERT(w >= 0);
149 ASSERT(h >= 0);
150 if img = nil then
151 r_Draw_Texture(nil, x, y, w, h, flip, NTR, NTG, NTB, NTB, blend)
152 else
153 for j := 0 to (h - 1) div img.height do
154 for i := 0 to (w - 1) div img.width do
155 r_Draw_Texture(img, x + i * img.width, y + j * img.height, img.width, img.height, flip, r, g, b, a, blend);
156 end;
158 procedure r_Draw_TextureRepeatRotate (img: TGLTexture; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer);
159 begin
160 ASSERT(w >= 0);
161 ASSERT(h >= 0);
162 if a <> 0 then
163 begin
164 glPushMatrix;
165 glTranslatef(x + rx, y + ry, 0);
166 glRotatef(angle, 0, 0, 1);
167 glTranslatef(-(x + rx), -(y + ry), 0);
168 r_Draw_TextureRepeat(img, x, y, w, h, flip, r, g, b, a, blend);
169 glPopMatrix;
170 end
171 else
172 r_Draw_TextureRepeat(img, x, y, w, h, flip, r, g, b, a, blend);
173 end;
175 procedure r_Draw_MultiTextureRepeat (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean);
176 var img: TGLTexture; cur, total, i: Integer;
177 begin
178 ASSERT(anim.IsValid());
179 if m = nil then
180 r_Draw_TextureRepeat(nil, x, y, w, h, flip, NTR, NTG, NTB, NTB, blend)
181 else
182 begin
183 if m.BackAnim then
184 begin
185 total := m.count * 2 - 1;
186 cur := anim.CurrentFrame mod total;
187 if cur < m.count then i := cur else i := total - cur - 1;
188 end
189 else
190 i := anim.CurrentFrame mod m.count;
191 img := m.GetTexture(i);
192 r_Draw_TextureRepeat(img, x, y, w, h, flip, r, g, b, a, blend);
193 end
194 end;
196 procedure r_Draw_MultiTextureRepeatRotate (m: TGLMultiTexture; const anim: TAnimState; x, y, w, h: Integer; flip: Boolean; r, g, b, a: Byte; blend: Boolean; rx, ry, angle: Integer);
197 begin
198 ASSERT(w >= 0);
199 ASSERT(h >= 0);
200 if a <> 0 then
201 begin
202 glPushMatrix;
203 glTranslatef(x + rx, y + ry, 0);
204 glRotatef(angle, 0, 0, 1);
205 glTranslatef(-(x + rx), -(y + ry), 0);
206 r_Draw_MultiTextureRepeat(m, anim, x, y, w, h, flip, r, g, b, a, blend);
207 glPopMatrix;
208 end
209 else
210 r_Draw_MultiTextureRepeat(m, anim, x, y, w, h, flip, r, g, b, a, blend);
211 end;
213 procedure r_Draw_Filter (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
214 begin
215 ASSERT(r >= l);
216 ASSERT(b >= t);
217 glEnable(GL_BLEND);
218 glBlendFunc(GL_ZERO, GL_SRC_COLOR);
219 glDisable(GL_TEXTURE_2D);
220 glColor4ub(rr, gg, bb, aa);
221 glBegin(GL_QUADS);
222 glVertex2i(l, t);
223 glVertex2i(r, t);
224 glVertex2i(r, b);
225 glVertex2i(l, b);
226 glEnd;
227 end;
229 procedure r_Draw_FillRect (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
230 begin
231 ASSERT(r >= l);
232 ASSERT(b >= t);
233 glEnable(GL_BLEND);
234 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
235 glDisable(GL_TEXTURE_2D);
236 glColor4ub(rr, gg, bb, aa);
237 glBegin(GL_QUADS);
238 glVertex2i(l, t);
239 glVertex2i(r, t);
240 glVertex2i(r, b);
241 glVertex2i(l, b);
242 glEnd;
243 end;
245 procedure r_Draw_InvertRect (l, t, r, b: Integer; rr, gg, bb, aa: Byte);
246 begin
247 ASSERT(r >= l);
248 ASSERT(b >= t);
249 glEnable(GL_BLEND);
250 glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
251 glDisable(GL_TEXTURE_2D);
252 glColor4ub(rr, gg, bb, aa);
253 glBegin(GL_QUADS);
254 glVertex2i(l, t);
255 glVertex2i(r, t);
256 glVertex2i(r, b);
257 glVertex2i(l, b);
258 glEnd;
259 end;
261 procedure r_Draw_Text (const text: AnsiString; x, y: Integer; r, g, b, a: Byte; f: TGLFont);
262 var i, xoff, spc: Integer; t: TGLTexture; ch: AnsiChar;
263 begin
264 xoff := x; spc := MAX(0, f.GetSpace());
265 for i := 1 to Length(text) do
266 begin
267 ch := text[i];
268 t := f.GetChar(ch);
269 if t <> nil then
270 r_Draw_Texture(t, xoff, y, t.width, t.height, false, r, g, b, a, false);
271 Inc(xoff, f.GetWidth(ch) + spc);
272 end;
273 end;
275 procedure r_Draw_GetTextSize (const text: AnsiString; f: TGLFont; out w, h: Integer);
276 var i, spc, len: Integer;
277 begin
278 w := 0;
279 h := f.GetMaxHeight();
280 len := Length(text);
281 if len > 0 then
282 begin
283 spc := MAX(0, f.GetSpace());
284 for i := 1 to len - 1 do
285 Inc(w, f.GetWidth(text[i]) + spc);
286 Inc(w, f.GetWidth(text[len]));
287 end;
288 end;
290 end.