DEADSOFTWARE

gl: implement split screen
[d2df-sdl.git] / src / game / renders / opengl / r_render.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_render;
18 interface
20 uses
21 {$IFDEF ENABLE_MENU}
22 g_gui,
23 {$ENDIF}
24 g_base // TRectWH
25 ;
27 (* render startup *)
28 procedure r_Render_Initialize;
29 procedure r_Render_Finalize;
31 (* load globally used textures *)
32 procedure r_Render_Load;
33 procedure r_Render_Free;
35 (* load map specific textures *)
36 procedure r_Render_LoadTextures;
37 procedure r_Render_FreeTextures;
39 procedure r_Render_Update;
40 procedure r_Render_Draw;
42 procedure r_Render_Resize (w, h: Integer);
43 procedure r_Render_Apply;
45 function r_Render_WriteScreenShot (filename: String): Boolean;
47 {$IFDEF ENABLE_GIBS}
48 function r_Render_GetGibRect (m, id: Integer): TRectWH;
49 {$ENDIF}
51 {$IFDEF ENABLE_GFX}
52 procedure r_Render_QueueEffect (AnimType, X, Y: Integer);
53 {$ENDIF}
55 {$IFDEF ENABLE_TOUCH}
56 // touch screen button location and size
57 procedure r_Render_GetKeyRect (key: Integer; out x, y, w, h: Integer; out founded: Boolean);
58 {$ENDIF}
60 {$IFDEF ENABLE_MENU}
61 procedure r_Render_GetControlSize (ctrl: TGUIControl; out w, h: Integer);
62 procedure r_Render_GetLogoSize (out w, h: Integer);
63 procedure r_Render_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
64 procedure r_Render_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
65 {$ENDIF}
67 procedure r_Render_DrawLoading (force: Boolean); // !!! remove it
69 implementation
71 uses
72 {$IFDEF USE_GLES1}
73 GLES11,
74 {$ELSE}
75 GL, GLEXT,
76 {$ENDIF}
77 {$IFDEF ENABLE_MENU}
78 r_gui,
79 {$ENDIF}
80 {$IFDEF ENABLE_SYSTEM}
81 g_system,
82 {$ENDIF}
83 SysUtils, Classes, Math,
84 e_log, utils,
85 g_game, g_options, g_console, g_player, g_weapons, g_language,
86 g_net,
87 r_draw, r_textures, r_fonts, r_common, r_console, r_map
88 ;
90 type
91 TBasePoint = (
92 BP_LEFTUP, BP_UP, BP_RIGHTUP,
93 BP_LEFT, BP_CENTER, BP_RIGHT,
94 BP_LEFTDOWN, BP_DOWN, BP_RIGHTDOWN
95 );
97 var
98 menuBG: TGLTexture;
100 hud, hudbg: TGLTexture;
101 hudhp: array [Boolean] of TGLTexture;
102 hudap: TGLTexture;
103 hudwp: array [0..WP_LAST] of TGLTexture;
104 hudkey: array [0..2] of TGLTexture;
105 hudair: TGLTexture;
106 hudjet: TGLTexture;
108 procedure r_Render_LoadTextures;
109 begin
110 r_Map_LoadTextures;
111 end;
113 procedure r_Render_FreeTextures;
114 begin
115 r_Map_FreeTextures;
116 end;
118 procedure r_Render_Load;
119 const
120 WeapName: array [0..WP_LAST] of AnsiString = ('KASTET', 'SAW', 'PISTOL', 'SHOTGUN1', 'SHOTGUN2', 'MGUN', 'RLAUNCHER', 'PGUN', 'BFG', 'SPULEMET', 'FLAMETHROWER');
121 var
122 i: Integer;
123 begin
124 r_Common_Load;
125 menuBG := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/TITLE');
126 hud := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/HUD');
127 hudbg := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/HUDBG');
128 hudhp[false] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/MED2');
129 hudhp[true] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/BMED');
130 hudap := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/ARMORHUD');
131 for i := 0 to WP_LAST do
132 hudwp[i] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/' + WeapName[i]);
133 hudkey[0] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/KEYR');
134 hudkey[1] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/KEYG');
135 hudkey[2] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/KEYB');
136 hudair := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/AIRBAR');
137 hudjet := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/JETBAR');
138 r_Console_Load;
139 r_Map_Load;
140 {$IFDEF ENABLE_MENU}
141 r_GUI_Load;
142 {$ENDIF}
143 end;
145 procedure r_Render_Free;
146 var i: Integer;
147 begin
148 {$IFDEF ENABLE_MENU}
149 r_GUI_Free;
150 {$ENDIF}
151 r_Map_Free;
152 r_Console_Free;
153 hudjet.Free;
154 hudair.Free;
155 hudkey[0].Free;
156 hudkey[1].Free;
157 hudkey[2].Free;
158 for i := 0 to WP_LAST do
159 begin
160 if hudwp[i] <> nil then
161 hudwp[i].Free;
162 hudwp[i] := nil;
163 end;
164 hudap.Free;
165 hudhp[true].Free;
166 hudhp[false].Free;
167 hudbg.Free;
168 hud.Free;
169 menuBG.Free;
170 r_Common_Free;
171 end;
173 {$IFDEF ENABLE_SYSTEM}
174 function GetInfo (): TGLDisplayInfo;
175 var info: TGLDisplayInfo;
176 begin
177 info := Default(TGLDisplayInfo);
178 info.w := Max(1, gRC_Width);
179 info.h := Max(1, gRC_Height);
180 info.bpp := Max(1, gBPP);
181 info.fullscreen := gRC_FullScreen;
182 info.maximized := gRC_Maximized;
183 info.major := 1;
184 info.minor := 1;
185 info.profile := TGLProfile.Compat;
186 result := info;
187 end;
188 {$ENDIF}
190 procedure r_Render_Initialize;
191 begin
192 {$IFDEF ENABLE_SYSTEM}
193 if sys_SetDisplayModeGL(GetInfo()) = False then
194 raise Exception.Create('Failed to set videomode on startup.');
195 sys_EnableVSync(gVSync);
196 {$ENDIF}
197 r_Textures_Initialize;
198 r_Console_Initialize;
199 r_Map_Initialize;
200 end;
202 procedure r_Render_Finalize;
203 begin
204 r_Map_Finalize;
205 r_Console_Finalize;
206 r_Textures_Finalize;
207 end;
209 procedure r_Render_Update;
210 begin
211 r_Console_Update;
212 r_Map_Update;
213 end;
215 procedure r_Render_GetBasePoint (x, y, w, h: Integer; p: TBasePoint; out xx, yy: Integer);
216 begin
217 case p of
218 TBasePoint.BP_LEFTUP, TBasePoint.BP_LEFT, TBasePoint.BP_LEFTDOWN: xx := x;
219 TBasePoint.BP_UP, TBasePoint.BP_CENTER, TBasePoint.BP_DOWN: xx := x - w div 2;
220 TBasePoint.BP_RIGHTUP, TBasePoint.BP_RIGHT, TBasePoint.BP_RIGHTDOWN: xx := x - w;
221 end;
222 case p of
223 TBasePoint.BP_LEFTUP, TBasePoint.BP_UP, TBasePoint.BP_RIGHTUP: yy := y;
224 TBasePoint.BP_LEFT, TBasePoint.BP_CENTER, TBasePoint.BP_RIGHT: yy := y - h div 2;
225 TBasePoint.BP_LEFTDOWN, TBasePoint.BP_DOWN, TBasePoint.BP_RIGHTDOWN: yy := y - h;
226 end;
227 end;
229 procedure r_Render_DrawText (const text: AnsiString; x, y: Integer; r, g, b, a: Byte; f: TGLFont; p: TBasePoint);
230 var w, h: Integer;
231 begin
232 if p <> TBasePoint.BP_LEFTUP then
233 begin
234 r_Draw_GetTextSize(text, f, w, h);
235 r_Render_GetBasePoint(x, y, w, h, p, x, y);
236 end;
237 r_Draw_Text(text, x, y, r, g, b, a, f);
238 end;
240 procedure r_Render_DrawTexture (img: TGLTexture; x, y, w, h: Integer; p: TBasePoint);
241 begin
242 r_Render_GetBasePoint(x, y, w, h, p, x, y);
243 r_Draw_TextureRepeat(img, x, y, w, h, false, 255, 255, 255, 255, false);
244 end;
246 procedure r_Render_DrawHUD (x, y: Integer; p: TPlayer);
247 var t: TGLTexture; s: AnsiString;
248 begin
249 ASSERT(p <> nil);
251 // hud area is 196 x 240 pixels
252 r_Render_DrawTexture(hud, x, y, hud.width, hud.height, TBasePoint.BP_LEFTUP);
253 r_Render_DrawText(p.name, x + 98, y + 16, 255, 0, 0, 255, smallfont, TBasePoint.BP_CENTER);
255 t := hudhp[R_BERSERK in p.FRulez];
256 r_Render_DrawTexture(t, x + 51, y + 61, t.width, t.height, TBasePoint.BP_CENTER);
257 r_Render_DrawTexture(hudap, x + 50, y + 85, hudap.width, hudap.height, TBasePoint.BP_CENTER);
259 r_Render_DrawText(IntToStr(MAX(0, p.health)), x + 174, y + 56, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
260 r_Render_DrawText(IntToStr(MAX(0, p.armor)), x + 174, y + 84, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
262 case p.CurrWeap of
263 WEAPON_KASTET, WEAPON_SAW: s := '--';
264 else s := IntToStr(p.GetAmmoByWeapon(p.CurrWeap));
265 end;
266 r_Render_DrawText(s, x + 174, y + 174, 255, 0, 0, 255, menufont, TBasePoint.BP_RIGHT);
268 if p.CurrWeap <= WP_LAST then
269 begin
270 t := hudwp[p.CurrWeap];
271 r_Render_DrawTexture(t, x + 18, y + 160, t.width, t.height, TBasePoint.BP_LEFTUP);
272 end;
274 if R_KEY_RED in p.FRulez then
275 r_Render_DrawTexture(hudkey[0], x + 76, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
276 if R_KEY_GREEN in p.FRulez then
277 r_Render_DrawTexture(hudkey[1], x + 93, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
278 if R_KEY_BLUE in p.FRulez then
279 r_Render_DrawTexture(hudkey[2], x + 110, y + 214, 16, 16, TBasePoint.BP_LEFTUP);
281 if p.JetFuel > 0 then
282 begin
283 r_Render_DrawTexture(hudair, x, y + 116, hudair.width, hudair.height, TBasePoint.BP_LEFTUP);
284 if p.air > 0 then
285 r_Draw_FillRect(x + 14, y + 116 + 4, x + 14 + 168 * p.air div AIR_MAX, y + 116 + 4 + 4, 0, 0, 196, 255);
286 r_Render_DrawTexture(hudjet, x, y + 126, hudjet.width, hudjet.height, TBasePoint.BP_LEFTUP);
287 r_Draw_FillRect(x + 14, y + 126 + 4, x + 14 + 168 * p.JetFuel div JET_MAX, y + 126 + 4 + 4, 208, 0, 0, 255);
288 end
289 else
290 begin
291 r_Render_DrawTexture(hudair, x, y + 124, hudair.width, hudair.height, TBasePoint.BP_LEFTUP);
292 if p.air > 0 then
293 r_Draw_FillRect(x + 14, y + 124 + 4, x + 14 + 168 * p.air div AIR_MAX, y + 124 + 4 + 4, 0, 0, 196, 255);
294 end;
295 end;
297 procedure r_Render_DrawHUDArea (x, y, w, h: Integer; p: TPlayer);
298 var s: AnsiString;
299 begin
300 r_Render_DrawTexture(hudbg, x, y, w, h, TBasePoint.BP_LEFTUP);
302 if p <> nil then
303 r_Render_DrawHUD(x + w - 196 + 2, y, p);
305 if gShowPing and g_Game_IsClient then
306 begin
307 s := _lc[I_GAME_PING_HUD] + IntToStr(NetPeer.lastRoundTripTime) + _lc[I_NET_SLIST_PING_MS];
308 r_Render_DrawText(s, x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
309 end;
311 if p.Spectator then
312 begin
313 r_Render_DrawText(_lc[I_PLAYER_SPECT], x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
314 r_Render_DrawText(_lc[I_PLAYER_SPECT2], x + 4, y + 258, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
315 r_Render_DrawText(_lc[I_PLAYER_SPECT1], x + 4, y + 274, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
316 if p.NoRespawn then
317 r_Render_DrawText(_lc[I_PLAYER_SPECT1S], x + 4, y + 290, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
318 end;
319 end;
321 procedure r_Render_DrawView (x, y, w, h: Integer; p: TPlayer);
322 var l, t, r, b: Integer;
323 begin
324 r_Draw_GetRect(l, t, r, b);
325 r_Draw_SetRect(x, y, x + w, y + h);
327 if p <> nil then
328 r_Map_Draw(x, y, w, h, p.obj.x + PLAYER_RECT_CX, p.obj.y + PLAYER_RECT_CY, p)
329 else
330 r_Map_Draw(x, y, w, h, 0, 0, nil);
332 // TODO draw stats
334 if p <> nil then
335 begin
336 if p.Spectator and p.NoRespawn then
337 r_Render_DrawText(_lc[I_PLAYER_SPECT4], x div 2 + w div 2, y div 2 + h div 2, 255, 255, 255, 255, stdfont, TBasePoint.BP_CENTER);
338 end;
340 r_Draw_SetRect(l, t, r, b);
341 end;
343 procedure r_Render_DrawPlayerView (x, y, w, h: Integer; p: TPlayer);
344 var l, t, r, b: Integer;
345 begin
346 r_Draw_GetRect(l, t, r, b);
347 r_Draw_SetRect(x, y, x + w, y + h);
348 r_Render_DrawView(x, y, w - 196, h, p);
349 r_Render_DrawHUDArea(x + w - 196, y, 196, h, p);
350 r_Draw_SetRect(l, t, r, b);
351 end;
353 procedure r_Render_Draw;
354 begin
355 if gExit = EXIT_QUIT then
356 exit;
358 r_Draw_Setup(gScreenWidth, gScreenHeight);
360 glClearColor(0.0, 0.0, 0.0, 0.0);
361 glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
363 glColor4ub(255, 255, 255, 255);
364 glEnable(GL_SCISSOR_TEST);
365 r_Draw_SetRect(0, 0, gScreenWidth, gScreenHeight);
367 //e_LogWritefln('r_render_draw: %sx%s', [gScreenWidth, gScreenHeight]);
369 if gGameOn or (gState = STATE_FOLD) then
370 begin
371 // TODO setup player view
372 // TODO setup sectator mode
373 // TODO setup player hear point
374 // TODO setup player view siz
376 // TODO draw player view + setup screen coords
377 if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
378 begin
379 r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight div 2 - 2, gPlayer1);
380 r_Render_DrawPlayerView(0, gScreenHeight div 2 + 2, gScreenWidth, gScreenHeight div 2, gPlayer2);
381 end
382 else
383 begin
384 r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, gPlayer1);
385 end;
387 // TODO draw holmes inspector
389 // TODO draw messages
390 // TODO draw stats (?)
391 // TODO draw spectator hud
392 end;
394 if gPauseMain and gGameOn {$IFDEF ENABLE_MENU}and (g_ActiveWindow = nil){$ENDIF} then
395 begin
396 // TODO draw pause screen
397 end;
399 if not gGameOn then
400 begin
401 case gState of
402 STATE_MENU: ; // TODO draw menu bg
403 STATE_FOLD: ;
404 STATE_INTERCUSTOM: ;
405 STATE_INTERSINGLE: ;
406 STATE_ENDPIC: ;
407 STATE_SLIST: ;
408 end;
409 end;
411 {$IFDEF ENABLE_MENU}
412 if g_ActiveWindow <> nil then
413 begin
414 if gGameOn then
415 r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 0, 0, 0, 105);
416 r_GUI_Draw_Window(g_ActiveWindow);
417 end;
418 {$ENDIF}
420 r_Console_Draw(false);
422 // TODO draw holmes interface
424 glFinish();
425 glFlush();
426 sys_Repaint;
427 end;
429 procedure r_Render_Resize (w, h: Integer);
430 begin
431 gWinSizeX := w;
432 gWinSizeY := h;
433 gRC_Width := w;
434 gRC_Height := h;
435 gScreenWidth := w;
436 gScreenHeight := h;
437 end;
439 procedure r_Render_Apply;
440 begin
441 {$IFDEF ENABLE_SYSTEM}
442 if sys_SetDisplayModeGL(GetInfo()) then
443 e_LogWriteln('resolution changed')
444 else
445 e_LogWriteln('resolution not changed');
446 sys_EnableVSync(gVSync)
447 {$ENDIF}
448 end;
450 function r_Render_WriteScreenShot (filename: String): Boolean;
451 begin
452 Result := False;
453 end;
455 {$IFDEF ENABLE_GIBS}
456 function r_Render_GetGibRect (m, id: Integer): TRectWH;
457 begin
458 result := r_Map_GetGibSize(m, id);
459 end;
460 {$ENDIF}
462 {$IFDEF ENABLE_GFX}
463 procedure r_Render_QueueEffect (AnimType, X, Y: Integer);
464 begin
465 r_Map_NewGFX(AnimType, X, Y);
466 end;
467 {$ENDIF}
469 {$IFDEF ENABLE_TOUCH}
470 procedure r_Render_GetKeyRect (key: Integer; out x, y, w, h: Integer; out founded: Boolean);
471 begin
472 founded := False;
473 end;
474 {$ENDIF}
476 {$IFDEF ENABLE_MENU}
477 procedure r_Render_GetControlSize (ctrl: TGUIControl; out w, h: Integer);
478 begin
479 r_GUI_GetSize(ctrl, w, h);
480 end;
482 procedure r_Render_GetLogoSize (out w, h: Integer);
483 begin
484 r_GUI_GetLogoSize(w, h);
485 end;
487 procedure r_Render_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
488 begin
489 r_GUI_GetMaxFontSize(BigFont, w, h);
490 end;
492 procedure r_Render_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
493 begin
494 r_GUI_GetStringSize(BigFont, str, w, h);
495 end;
496 {$ENDIF}
498 procedure r_Render_DrawLoading (force: Boolean);
499 begin
500 // TODO draw loading screen
501 end;
503 end.