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);
37 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
38 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
40 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
41 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
42 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
44 procedure r_Draw_EnableTexture2D (enable
: Boolean);
45 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
50 {$I ../../../nogl/noGLuses.inc}
51 SysUtils
, Classes
, Math
,
62 sl
, st
, sr
, sb
: Integer;
63 ScreenWidth
, ScreenHeight
: Integer;
64 GameWidth
, GameHeight
: Integer;
66 enableTexture2D
: Boolean;
67 curR
, curG
, curB
, curA
: Byte;
69 procedure r_Draw_EnableTexture2D (enable
: Boolean);
71 if enable
<> enableTexture2D
then
73 if enable
then glEnable(GL_TEXTURE_2D
) else glDisable(GL_TEXTURE_2D
);
74 enableTexture2D
:= enable
;
78 procedure r_Draw_SetColor (r
, g
, b
, a
: Byte);
80 if (r
<> curR
) or (g
<> curG
) or (b
<> curB
) or (curA
<> a
) then
82 glColor4ub(r
, g
, b
, a
);
90 procedure r_Draw_Setup (sw
, sh
, gw
, gh
: Integer);
92 ASSERT((sw
>= 0) and (sh
>= 0)); // screen/window size
93 ASSERT((gw
>= 0) and (gh
>= 0)); // virtual screen size
98 glScissor(0, 0, sw
, sh
);
99 glViewport(0, 0, sw
, sh
);
100 glMatrixMode(GL_PROJECTION
);
102 glOrtho(0, gw
, gh
, 0, 0, 1);
103 glMatrixMode(GL_MODELVIEW
);
105 glEnable(GL_SCISSOR_TEST
);
106 r_Draw_SetRect(0, 0, gw
- 1, gh
- 1);
109 procedure DrawQuad (x
, y
, w
, h
: Integer);
112 glVertex2i(x
+ w
, y
);
114 glVertex2i(x
, y
+ h
);
115 glVertex2i(x
+ w
, y
+ h
);
119 procedure DrawTextureError (x
, y
, w
, h
: Integer);
122 w2
:= w
div 2; h2
:= h
div 2;
123 r_Draw_FillRect(x
, y
, x
+ w2
, y
+ h2
, 255, 0, 255, 255);
124 r_Draw_FillRect(x
+ w2
, y
, x
+ w
, y
+ h2
, 255, 255, 255, 255);
125 r_Draw_FillRect(x
+ w2
, y
+ h2
, x
+ w
, y
+ h
, 255, 0, 255, 255);
126 r_Draw_FillRect(x
, y
+ h2
, x
+ w2
, y
+ h
, 255, 255, 255, 255);
127 if (w
> 2) and (h
> 2) then
128 r_Draw_Rect(x
, y
, x
+ w
, y
+ h
, 0, 255, 0, 255);
131 procedure DrawTile (tile
: TGLAtlasNode
; x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
: Boolean);
132 var nw
, nh
, ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
136 DrawTextureError(x
, y
, w
, h
);
142 ax
:= IfThen(flip
, tile
.l
, tile
.r
+ 1) / nw
;
143 bx
:= IfThen(flip
, tile
.r
+ 1, tile
.l
) / nh
;
145 by
:= (tile
.b
+ 1) / nh
;
146 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
147 r_Textures_GL_Bind(tile
.id
);
148 r_Draw_SetColor(rr
, gg
, bb
, aa
);
149 r_Draw_EnableTexture2D(true);
150 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
153 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
154 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
155 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
156 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
161 procedure DrawHWTexture (gltex
: GLint
; nw
, nh
, x
, y
, w
, h
: Integer; flip
: Boolean; rr
, gg
, bb
, aa
: Byte; blend
: Boolean);
162 var ax
, bx
, ay
, by
: GLfloat
; l
, t
, r
, b
: Integer;
164 ax
:= IfThen(flip
, 0, w
) / nw
;
165 bx
:= IfThen(flip
, w
, 0) / nh
;
168 l
:= x
; t
:= y
; r
:= x
+ w
; b
:= y
+ h
;
169 r_Textures_GL_Bind(gltex
);
170 r_Draw_SetColor(rr
, gg
, bb
, aa
);
171 r_Draw_EnableTexture2D(true);
172 if blend
then glBlendFunc(GL_SRC_ALPHA
, GL_ONE
) else glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
175 glTexCoord2f(ax
, ay
); glVertex2i(r
, t
);
176 glTexCoord2f(bx
, ay
); glVertex2i(l
, t
);
177 glTexCoord2f(bx
, by
); glVertex2i(l
, b
);
178 glTexCoord2f(ax
, by
); glVertex2i(r
, b
);
182 procedure r_Draw_Texture (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
183 var i
, j
, first
, last
, step
: Integer; n
: TGLAtlasNode
;
188 DrawTextureError(x
, y
, w
, h
)
191 if flip
then first
:= img
.cols
- 1 else first
:= 0;
192 if flip
then last
:= -1 else last
:= img
.cols
;
193 if flip
then step
:= -1 else step
:= +1;
195 glTranslatef(x
, y
, 0);
196 glScalef(w
/ img
.width
, h
/ img
.height
, 1);
197 for j
:= 0 to img
.lines
- 1 do
201 n
:= img
.GetTile(i
, j
);
203 DrawTile(n
, 0, 0, n
.width
, n
.height
, flip
, r
, g
, b
, a
, blend
);
204 glTranslatef(n
.width
, 0, 0);
207 glTranslatef(-img
.width
, n
.height
, 0);
213 function r_Draw_IsHWRepeatable (img
: TGLTexture
): Boolean;
214 var n
: TGLAtlasNode
; a
: TGLAtlas
;
218 if (img
.cols
= 1) and (img
.lines
= 1) then
220 n
:= img
.GetTile(0, 0);
221 if (n
.width
= img
.width
) and (n
.height
= img
.height
) then
224 result
:= (a
.GetWidth() = img
.width
) and (a
.GetHeight() = img
.height
)
229 procedure r_Draw_TextureRepeat (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean);
235 DrawTextureError(x
, y
, w
, h
)
236 else if r_Draw_IsHWRepeatable(img
) then
237 DrawHWTexture(img
.GetTile(0, 0).base
.id
, img
.width
, img
.height
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
)
239 for j
:= 0 to (h
- 1) div img
.height
do
240 for i
:= 0 to (w
- 1) div img
.width
do
241 r_Draw_Texture(img
, x
+ i
* img
.width
, y
+ j
* img
.height
, img
.width
, img
.height
, flip
, r
, g
, b
, a
, blend
);
244 procedure r_Draw_TextureRepeatRotate (img
: TGLTexture
; x
, y
, w
, h
: Integer; flip
: Boolean; r
, g
, b
, a
: Byte; blend
: Boolean; rx
, ry
, angle
: Integer);
251 glTranslatef(x
+ rx
, y
+ ry
, 0);
252 glRotatef(angle
, 0, 0, 1);
253 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
254 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
258 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
261 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);
262 var img
: TGLTexture
; frame
: LongInt;
264 ASSERT(anim
.IsValid());
266 DrawTextureError(x
, y
, w
, h
)
269 g_Anim_GetFrameFromState(anim
, backanim
, frame
);
271 ASSERT(frame
< m
.count
);
272 img
:= m
.GetTexture(frame
);
273 r_Draw_TextureRepeat(img
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
277 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);
284 glTranslatef(x
+ rx
, y
+ ry
, 0);
285 glRotatef(angle
, 0, 0, 1);
286 glTranslatef(-(x
+ rx
), -(y
+ ry
), 0);
287 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
291 r_Draw_MultiTextureRepeat(m
, anim
, backanim
, x
, y
, w
, h
, flip
, r
, g
, b
, a
, blend
);
294 procedure r_Draw_Rect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
298 if (l
< r
) and (t
< b
) then
301 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
302 r_Draw_EnableTexture2D(false);
303 r_Draw_SetColor(rr
, gg
, bb
, aa
);
317 glVertex2i(l
+1, t
+1);
318 glVertex2i(l
+1, b
-1);
321 glVertex2i(r
-1, t
+1);
324 glVertex2i(r
-1, b
-1);
329 procedure r_Draw_FillRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
333 if (l
< r
) and (t
< b
) then
336 glBlendFunc(GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
337 r_Draw_EnableTexture2D(false);
338 r_Draw_SetColor(rr
, gg
, bb
, aa
);
348 procedure r_Draw_Filter (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
352 if (l
< r
) and (t
< b
) then
355 glBlendFunc(GL_ZERO
, GL_SRC_COLOR
);
356 r_Draw_EnableTexture2D(false);
357 r_Draw_SetColor(rr
, gg
, bb
, aa
);
367 procedure r_Draw_InvertRect (l
, t
, r
, b
: Integer; rr
, gg
, bb
, aa
: Byte);
371 if (l
< r
) and (t
< b
) then
374 glBlendFunc(GL_ONE_MINUS_DST_COLOR
, GL_ZERO
);
375 r_Draw_EnableTexture2D(false);
376 r_Draw_SetColor(rr
, gg
, bb
, aa
);
386 procedure r_Draw_Text (const text: AnsiString; x
, y
: Integer; r
, g
, b
, a
: Byte; f
: TGLFont
);
387 var i
, xoff
, spc
: Integer; t
: TGLTexture
; ch
: AnsiChar;
389 xoff
:= x
; spc
:= MAX(0, f
.GetSpace());
390 for i
:= 1 to Length(text) do
395 r_Draw_Texture(t
, xoff
, y
, t
.width
, t
.height
, false, r
, g
, b
, a
, false);
396 Inc(xoff
, f
.GetWidth(ch
) + spc
);
400 procedure r_Draw_GetTextSize (const text: AnsiString; f
: TGLFont
; out w
, h
: Integer);
401 var i
, spc
, len
: Integer;
404 h
:= f
.GetMaxHeight();
408 spc
:= MAX(0, f
.GetSpace());
409 for i
:= 1 to len
- 1 do
410 Inc(w
, f
.GetWidth(text[i
]) + spc
);
411 Inc(w
, f
.GetWidth(text[len
]));
415 procedure r_Draw_SetRect (l
, t
, r
, b
: Integer);
416 var x
, y
, w
, h
: Integer;
420 x
:= l
* ScreenWidth
div GameWidth
;
421 y
:= t
* ScreenHeight
div GameHeight
;
422 w
:= (r
- l
+ 1) * ScreenWidth
div GameWidth
;
423 h
:= (b
- t
+ 1) * ScreenHeight
div GameHeight
;
424 glScissor(x
, ScreenHeight
- h
- y
, w
, h
);
425 sl
:= l
; st
:= t
; sr
:= r
; sb
:= b
;
428 procedure r_Draw_GetRect (out l
, t
, r
, b
: Integer);
430 l
:= sl
; t
:= st
; r
:= sr
; b
:= sb
;