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_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
; backanim
: Boolean; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
30 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);
32 procedure r_Draw_Filter (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
33 procedure r_Draw_Rect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
34 procedure r_Draw_FillRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
35 procedure r_Draw_InvertRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
36 procedure r_Draw_Line (x0
, y0
, x1
, y1
: Integer; rr
, gg
, bb
, aa
: Byte);
38 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
39 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
41 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
42 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
43 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
45 procedure r_Draw_EnableTexture2D (enable
: Boolean);
46 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
51 {$I ../../../nogl/noGLuses.inc}
52 SysUtils
, Classes
, Math
,
63 sl
, st
, sr
, sb
: Integer;
64 ScreenWidth
, ScreenHeight
: Integer;
65 GameWidth
, GameHeight
: Integer;
67 enableTexture2D
: Boolean;
68 curR
, curG
, curB
, curA
: Byte;
70 procedure r_Draw_EnableTexture2D (enable
: Boolean);
72 if enable
<> enableTexture2D
then
74 if enable
then glEnable(GL_TEXTURE_2D
) else glDisable(GL_TEXTURE_2D
);
75 enableTexture2D
:= enable
;
79 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
81 if (r
<> curR
) or (g
<> curG
) or (b
<> curB
) or (curA
<> a
) then
83 glColor4ub(r
, g
, b
, a
);
91 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
93 ASSERT((sw
>= 0) and (sh
>= 0)); // screen/window size
94 ASSERT((gw
>= 0) and (gh
>= 0)); // virtual screen size
99 glScissor(0, 0, sw
, sh
);
100 glViewport(0, 0, sw
, sh
);
101 glMatrixMode(GL_PROJECTION
);
103 glOrtho(0, gw
, gh
, 0, 0, 1);
104 glMatrixMode(GL_MODELVIEW
);
106 glEnable(GL_SCISSOR_TEST
);
107 r_Draw_SetRect(0, 0, gw
- 1, gh
- 1);
110 procedure DrawQuad (x
, y
, w
, h
: Integer);
113 glVertex2i(x
+ w
, y
);
115 glVertex2i(x
, y
+ h
);
116 glVertex2i(x
+ w
, y
+ h
);
120 procedure DrawTextureError (x
, y
, w
, h
: Integer);
123 w2
:= w
div 2; h2
:= h
div 2;
124 r_Draw_FillRect(x
, y
, x
+ w2
, y
+ h2
, 255, 0, 255, 255);
125 r_Draw_FillRect(x
+ w2
, y
, x
+ w
, y
+ h2
, 255, 255, 255, 255);
126 r_Draw_FillRect(x
+ w2
, y
+ h2
, x
+ w
, y
+ h
, 255, 0, 255, 255);
127 r_Draw_FillRect(x
, y
+ h2
, x
+ w2
, y
+ h
, 255, 255, 255, 255);
128 if (w
> 2) and (h
> 2) then
129 r_Draw_Rect(x
, y
, x
+ w
, y
+ h
, 0, 255, 0, 255);
132 procedure DrawTile (tile
: TGLAtlasNode
; x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
: Boolean);
133 var nw
, nh
, ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
137 DrawTextureError(x
, y
, w
, h
);
143 ax
:= IfThen(flip
, tile
.l
, tile
.r
+ 1) / nw
;
144 bx
:= IfThen(flip
, tile
.r
+ 1, tile
.l
) / nh
;
146 by
:= (tile
.b
+ 1) / nh
;
147 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
148 r_Textures_GL_Bind(tile
.id
);
149 r_Draw_SetColor(rr
, gg
, bb
, aa
);
150 r_Draw_EnableTexture2D(true);
151 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
154 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
155 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
156 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
157 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
162 procedure DrawHWTexture (gltex
: GLint
; nw
, nh
, x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
: Boolean);
163 var ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
165 ax
:= IfThen(flip
, 0, w
) / nw
;
166 bx
:= IfThen(flip
, w
, 0) / nh
;
169 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
170 r_Textures_GL_Bind(gltex
);
171 r_Draw_SetColor(rr
, gg
, bb
, aa
);
172 r_Draw_EnableTexture2D(true);
173 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
176 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
177 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
178 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
179 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
183 procedure r_Draw_Texture (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
184 var i
, j
, first
, last
, step
: Integer; n
: TGLAtlasNode
;
189 DrawTextureError(x
, y
, w
, h
)
192 if flip
then first
:= img
.cols
- 1 else first
:= 0;
193 if flip
then last
:= -1 else last
:= img
.cols
;
194 if flip
then step
:= -1 else step
:= +1;
196 glTranslatef(x
, y
, 0);
197 glScalef(w
/ img
.width
, h
/ img
.height
, 1);
198 for j
:= 0 to img
.lines
- 1 do
202 n
:= img
.GetTile(i
, j
);
204 DrawTile(n
, 0, 0, n
.width
, n
.height
, flip
, r
, g
, b
, a
, blend
);
205 glTranslatef(n
.width
, 0, 0);
208 glTranslatef(-img
.width
, n
.height
, 0);
214 function r_Draw_IsHWRepeatable (img
: TGLTexture
): Boolean;
215 var n
: TGLAtlasNode
; a
: TGLAtlas
;
219 if (img
.cols
= 1) and (img
.lines
= 1) then
221 n
:= img
.GetTile(0, 0);
222 if (n
.width
= img
.width
) and (n
.height
= img
.height
) then
225 result
:= (a
.GetWidth() = img
.width
) and (a
.GetHeight() = img
.height
)
230 procedure r_Draw_TextureRepeat (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
236 DrawTextureError(x
, y
, w
, h
)
237 else if r_Draw_IsHWRepeatable(img
) then
238 DrawHWTexture(img
.GetTile(0, 0).base
.id
, img
.width
, img
.height
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
)
240 for j
:= 0 to (h
- 1) div img
.height
do
241 for i
:= 0 to (w
- 1) div img
.width
do
242 r_Draw_Texture(img
, x
+ i
* img
.width
, y
+ j
* img
.height
, img
.width
, img
.height
, flip
, r
, g
, b
, a
, blend
);
245 procedure r_Draw_TextureRepeatRotate (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
252 glTranslatef(x
+ rx
, y
+ ry
, 0);
253 glRotatef(angle
, 0, 0, 1);
254 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
255 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
259 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
262 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);
263 var img
: TGLTexture
; frame
: LongInt;
265 ASSERT(anim
.IsValid());
267 DrawTextureError(x
, y
, w
, h
)
270 g_Anim_GetFrameFromState(anim
, backanim
, frame
);
272 ASSERT(frame
< m
.count
);
273 img
:= m
.GetTexture(frame
);
274 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
278 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);
285 glTranslatef(x
+ rx
, y
+ ry
, 0);
286 glRotatef(angle
, 0, 0, 1);
287 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
288 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
292 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
295 procedure r_Draw_Rect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
299 if (l
< r
) and (t
< b
) then
302 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
303 r_Draw_EnableTexture2D(false);
304 r_Draw_SetColor(rr
, gg
, bb
, aa
);
318 glVertex2i(l
+1, t
+1);
319 glVertex2i(l
+1, b
-1);
322 glVertex2i(r
-1, t
+1);
325 glVertex2i(r
-1, b
-1);
330 procedure r_Draw_FillRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
334 if (l
< r
) and (t
< b
) then
337 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
338 r_Draw_EnableTexture2D(false);
339 r_Draw_SetColor(rr
, gg
, bb
, aa
);
349 procedure r_Draw_Filter (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
353 if (l
< r
) and (t
< b
) then
356 glBlendFunc(GL_ZERO
, GL_SRC_COLOR
);
357 r_Draw_EnableTexture2D(false);
358 r_Draw_SetColor(rr
, gg
, bb
, aa
);
368 procedure r_Draw_InvertRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
372 if (l
< r
) and (t
< b
) then
375 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
376 r_Draw_EnableTexture2D(false);
377 r_Draw_SetColor(rr
, gg
, bb
, aa
);
387 procedure r_Draw_Line (x0
, y0
, x1
, y1
: Integer; rr
, gg
, bb
, aa
: Byte);
390 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
391 r_Draw_EnableTexture2D(false);
392 r_Draw_SetColor(rr
, gg
, bb
, aa
);
400 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
401 var i
, xoff
, spc
: Integer; t
: TGLTexture
; ch
: AnsiChar;
403 xoff
:= x
; spc
:= MAX(0, f
.GetSpace());
404 for i
:= 1 to Length(text) do
409 r_Draw_Texture(t
, xoff
, y
, t
.width
, t
.height
, false, r
, g
, b
, a
, false);
410 Inc(xoff
, f
.GetWidth(ch
) + spc
);
414 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
415 var i
, spc
, len
: Integer;
418 h
:= f
.GetMaxHeight();
422 spc
:= MAX(0, f
.GetSpace());
423 for i
:= 1 to len
- 1 do
424 Inc(w
, f
.GetWidth(text[i
]) + spc
);
425 Inc(w
, f
.GetWidth(text[len
]));
429 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
430 var x
, y
, w
, h
: Integer;
434 x
:= l
* ScreenWidth
div GameWidth
;
435 y
:= t
* ScreenHeight
div GameHeight
;
436 w
:= (r
- l
+ 1) * ScreenWidth
div GameWidth
;
437 h
:= (b
- t
+ 1) * ScreenHeight
div GameHeight
;
438 glScissor(x
, ScreenHeight
- h
- y
, w
, h
);
439 sl
:= l
; st
:= t
; sr
:= r
; sb
:= b
;
442 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
444 l
:= sl
; t
:= st
; r
:= sr
; b
:= sb
;