1 (* Copyright (C) Doom 2D: Forever Developers
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.
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.
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/>.
15 {$INCLUDE ../../../shared/a_modes.inc}
25 procedure r_Draw_SetFilter (img
: TGLTexture
; enable
: Boolean);
27 procedure r_Draw_Texture (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
28 procedure r_Draw_TextureRepeat (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
29 procedure r_Draw_TextureRepeatRotate (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
31 procedure r_Draw_MultiTextureRepeat (m
: TGLMultiTexture
; const anim
: TAnimState
; backanim
: Boolean; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
32 procedure r_Draw_MultiTextureRepeatRotate (m
: TGLMultiTexture
; const anim
: TAnimState
; backanim
: Boolean; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
34 procedure r_Draw_Filter (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
35 procedure r_Draw_Rect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
36 procedure r_Draw_FillRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
37 procedure r_Draw_InvertRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
38 procedure r_Draw_Line (x0
, y0
, x1
, y1
: Integer; rr
, gg
, bb
, aa
: Byte);
40 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
41 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
43 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
44 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
45 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
47 procedure r_Draw_EnableTexture2D (enable
: Boolean);
48 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
53 {$I ../../../nogl/noGLuses.inc}
54 SysUtils
, Classes
, Math
,
65 sl
, st
, sr
, sb
: Integer;
66 ScreenWidth
, ScreenHeight
: Integer;
67 GameWidth
, GameHeight
: Integer;
69 enableTexture2D
: Boolean;
70 curR
, curG
, curB
, curA
: Byte;
72 procedure r_Draw_EnableTexture2D (enable
: Boolean);
74 if enable
<> enableTexture2D
then
76 if enable
then glEnable(GL_TEXTURE_2D
) else glDisable(GL_TEXTURE_2D
);
77 enableTexture2D
:= enable
;
81 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
83 if (r
<> curR
) or (g
<> curG
) or (b
<> curB
) or (curA
<> a
) then
85 glColor4ub(r
, g
, b
, a
);
93 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
95 ASSERT((sw
>= 0) and (sh
>= 0)); // screen/window size
96 ASSERT((gw
>= 0) and (gh
>= 0)); // virtual screen size
101 glScissor(0, 0, sw
, sh
);
102 glViewport(0, 0, sw
, sh
);
103 glMatrixMode(GL_PROJECTION
);
105 glOrtho(0, gw
, gh
, 0, 0, 1);
106 glMatrixMode(GL_MODELVIEW
);
108 glEnable(GL_SCISSOR_TEST
);
109 r_Draw_SetRect(0, 0, gw
- 1, gh
- 1);
112 procedure DrawQuad (x
, y
, w
, h
: Integer);
115 glVertex2i(x
+ w
, y
);
117 glVertex2i(x
, y
+ h
);
118 glVertex2i(x
+ w
, y
+ h
);
122 procedure DrawTextureError (x
, y
, w
, h
: Integer);
125 w2
:= w
div 2; h2
:= h
div 2;
126 r_Draw_FillRect(x
, y
, x
+ w2
, y
+ h2
, 255, 0, 255, 255);
127 r_Draw_FillRect(x
+ w2
, y
, x
+ w
, y
+ h2
, 255, 255, 255, 255);
128 r_Draw_FillRect(x
+ w2
, y
+ h2
, x
+ w
, y
+ h
, 255, 0, 255, 255);
129 r_Draw_FillRect(x
, y
+ h2
, x
+ w2
, y
+ h
, 255, 255, 255, 255);
130 if (w
> 2) and (h
> 2) then
131 r_Draw_Rect(x
, y
, x
+ w
, y
+ h
, 0, 255, 0, 255);
134 procedure r_Draw_SetFilter (img
: TGLTexture
; enable
: Boolean);
137 img
.filter
:= enable
;
140 procedure DrawTile (tile
: TGLAtlasNode
; x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
, filter
: Boolean);
141 var nw
, nh
, ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
145 DrawTextureError(x
, y
, w
, h
);
151 ax
:= IfThen(flip
, tile
.l
, tile
.r
+ 1) / nw
;
152 bx
:= IfThen(flip
, tile
.r
+ 1, tile
.l
) / nh
;
154 by
:= (tile
.b
+ 1) / nh
;
155 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
156 r_Textures_GL_Bind(tile
.id
);
157 if filter
<> tile
.base
.filter
then
161 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
162 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
163 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
164 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
168 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_S
, GL_REPEAT
);
169 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_WRAP_T
, GL_REPEAT
);
170 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
171 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
173 tile
.base
.filter
:= filter
;
175 r_Draw_SetColor(rr
, gg
, bb
, aa
);
176 r_Draw_EnableTexture2D(true);
177 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
180 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
181 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
182 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
183 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
188 procedure DrawHWTexture (gltex
: GLint
; nw
, nh
, x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
: Boolean);
189 var ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
191 ax
:= IfThen(flip
, 0, w
) / nw
;
192 bx
:= IfThen(flip
, w
, 0) / nh
;
195 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
196 r_Textures_GL_Bind(gltex
);
197 r_Draw_SetColor(rr
, gg
, bb
, aa
);
198 r_Draw_EnableTexture2D(true);
199 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
202 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
203 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
204 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
205 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
209 procedure r_Draw_Texture (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
210 var i
, j
, first
, last
, step
: Integer; n
: TGLAtlasNode
;
215 DrawTextureError(x
, y
, w
, h
)
218 if flip
then first
:= img
.cols
- 1 else first
:= 0;
219 if flip
then last
:= -1 else last
:= img
.cols
;
220 if flip
then step
:= -1 else step
:= +1;
222 glTranslatef(x
, y
, 0);
223 glScalef(w
/ img
.width
, h
/ img
.height
, 1);
224 for j
:= 0 to img
.lines
- 1 do
228 n
:= img
.GetTile(i
, j
);
230 DrawTile(n
, 0, 0, n
.width
, n
.height
, flip
, r
, g
, b
, a
, blend
, img
.filter
);
231 glTranslatef(n
.width
, 0, 0);
234 glTranslatef(-img
.width
, n
.height
, 0);
240 function r_Draw_IsHWRepeatable (img
: TGLTexture
): Boolean;
241 var n
: TGLAtlasNode
; a
: TGLAtlas
;
245 if (img
.cols
= 1) and (img
.lines
= 1) then
247 n
:= img
.GetTile(0, 0);
248 if (n
.width
= img
.width
) and (n
.height
= img
.height
) then
251 result
:= (a
.GetWidth() = img
.width
) and (a
.GetHeight() = img
.height
)
256 procedure r_Draw_TextureRepeat (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
262 DrawTextureError(x
, y
, w
, h
)
263 else if r_Draw_IsHWRepeatable(img
) then
264 DrawHWTexture(img
.GetTile(0, 0).base
.id
, img
.width
, img
.height
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
)
266 for j
:= 0 to (h
- 1) div img
.height
do
267 for i
:= 0 to (w
- 1) div img
.width
do
268 r_Draw_Texture(img
, x
+ i
* img
.width
, y
+ j
* img
.height
, img
.width
, img
.height
, flip
, r
, g
, b
, a
, blend
);
271 procedure r_Draw_TextureRepeatRotate (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
278 glTranslatef(x
+ rx
, y
+ ry
, 0);
279 glRotatef(angle
, 0, 0, 1);
280 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
281 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
285 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
288 procedure r_Draw_MultiTextureRepeat (m
: TGLMultiTexture
; const anim
: TAnimState
; backanim
: Boolean; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
289 var img
: TGLTexture
; frame
: LongInt;
291 ASSERT(anim
.IsValid());
293 DrawTextureError(x
, y
, w
, h
)
296 g_Anim_GetFrameFromState(anim
, backanim
, frame
);
298 ASSERT(frame
< m
.count
);
299 img
:= m
.GetTexture(frame
);
300 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
304 procedure r_Draw_MultiTextureRepeatRotate (m
: TGLMultiTexture
; const anim
: TAnimState
; backanim
: Boolean; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
311 glTranslatef(x
+ rx
, y
+ ry
, 0);
312 glRotatef(angle
, 0, 0, 1);
313 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
314 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
318 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
321 procedure r_Draw_Rect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
325 if (l
< r
) and (t
< b
) then
328 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
329 r_Draw_EnableTexture2D(false);
330 r_Draw_SetColor(rr
, gg
, bb
, aa
);
344 glVertex2i(l
+1, t
+1);
345 glVertex2i(l
+1, b
-1);
348 glVertex2i(r
-1, t
+1);
351 glVertex2i(r
-1, b
-1);
356 procedure r_Draw_FillRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
360 if (l
< r
) and (t
< b
) then
363 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
364 r_Draw_EnableTexture2D(false);
365 r_Draw_SetColor(rr
, gg
, bb
, aa
);
375 procedure r_Draw_Filter (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
379 if (l
< r
) and (t
< b
) then
382 glBlendFunc(GL_ZERO
, GL_SRC_COLOR
);
383 r_Draw_EnableTexture2D(false);
384 r_Draw_SetColor(rr
, gg
, bb
, aa
);
394 procedure r_Draw_InvertRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
398 if (l
< r
) and (t
< b
) then
401 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
402 r_Draw_EnableTexture2D(false);
403 r_Draw_SetColor(rr
, gg
, bb
, aa
);
413 procedure r_Draw_Line (x0
, y0
, x1
, y1
: Integer; rr
, gg
, bb
, aa
: Byte);
416 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
417 r_Draw_EnableTexture2D(false);
418 r_Draw_SetColor(rr
, gg
, bb
, aa
);
426 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
427 var i
, xoff
, spc
: Integer; t
: TGLTexture
; ch
: AnsiChar;
429 xoff
:= x
; spc
:= MAX(0, f
.GetSpace());
430 for i
:= 1 to Length(text) do
435 r_Draw_Texture(t
, xoff
, y
, t
.width
, t
.height
, false, r
, g
, b
, a
, false);
436 Inc(xoff
, f
.GetWidth(ch
) + spc
);
440 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
441 var i
, spc
, len
: Integer;
444 h
:= f
.GetMaxHeight();
448 spc
:= MAX(0, f
.GetSpace());
449 for i
:= 1 to len
- 1 do
450 Inc(w
, f
.GetWidth(text[i
]) + spc
);
451 Inc(w
, f
.GetWidth(text[len
]));
455 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
456 var x
, y
, w
, h
: Integer;
460 x
:= l
* ScreenWidth
div GameWidth
;
461 y
:= t
* ScreenHeight
div GameHeight
;
462 w
:= (r
- l
+ 1) * ScreenWidth
div GameWidth
;
463 h
:= (b
- t
+ 1) * ScreenHeight
div GameHeight
;
464 glScissor(x
, ScreenHeight
- h
- y
, w
, h
);
465 sl
:= l
; st
:= t
; sr
:= r
; sb
:= b
;
468 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
470 l
:= sl
; t
:= st
; r
:= sr
; b
:= sb
;