From 8994db25076be89e65c0d032977f4c7b03a41e91 Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Mon, 7 Jun 2021 23:34:07 +0300 Subject: [PATCH] render: separate panel logic and drawing --- src/game/Doom2DF.lpr | 1 + src/game/g_panel.pas | 160 +++++------------------------------- src/game/opengl/r_game.pas | 4 +- src/game/opengl/r_map.pas | 8 +- src/game/opengl/r_panel.pas | 158 +++++++++++++++++++++++++++++++++++ 5 files changed, 185 insertions(+), 146 deletions(-) create mode 100644 src/game/opengl/r_panel.pas diff --git a/src/game/Doom2DF.lpr b/src/game/Doom2DF.lpr index 86118b4..2629d70 100644 --- a/src/game/Doom2DF.lpr +++ b/src/game/Doom2DF.lpr @@ -158,6 +158,7 @@ uses r_gfx in 'opengl/r_gfx.pas', r_items in 'opengl/r_items.pas', r_map in 'opengl/r_map.pas', + r_panel in 'opengl/r_panel.pas', {$IFDEF USE_FMOD} fmod in '../lib/FMOD/fmod.pas', diff --git a/src/game/g_panel.pas b/src/game/g_panel.pas index 52722d3..7d2752c 100644 --- a/src/game/g_panel.pas +++ b/src/game/g_panel.pas @@ -29,6 +29,12 @@ type Anim: Boolean; end; + ATextureID = array of record + case Anim: Boolean of + False: (Tex: Cardinal); + True: (AnTex: TAnimation); + end; + PPanel = ^TPanel; TPanel = Class (TObject) private @@ -39,13 +45,7 @@ type FTextureHeight: Word; FAlpha: Byte; FBlending: Boolean; - FTextureIDs: Array of - record - case Anim: Boolean of - False: (Tex: Cardinal); - True: (AnTex: TAnimation); - end; - + FTextureIDs: ATextureID; mMovingSpeed: TDFPoint; mMovingStart: TDFPoint; mMovingEnd: TDFPoint; @@ -119,8 +119,6 @@ type var Textures: TLevelTextureArray; aguid: Integer); destructor Destroy(); override; - procedure Draw (hasAmbient: Boolean; constref ambColor: TDFColor); - procedure DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer); procedure Update(); procedure SetFrame(Frame: Integer; Count: Byte); procedure NextTexture(AnimLoop: Byte = 0); @@ -148,8 +146,6 @@ type function gncNeedSend (): Boolean; inline; procedure setDirty (); inline; // why `dirty`? 'cause i may introduce property `needSend` later - procedure lerp (t: Single; out tX, tY, tW, tH: Integer); - public property visvalid: Boolean read getvisvalid; // panel is "visvalid" when it's width and height are positive @@ -163,6 +159,10 @@ type property y: Integer read FY write FY; property width: Word read FWidth write FWidth; property height: Word read FHeight write FHeight; + property oldX: Integer read FOldX; + property oldY: Integer read FOldY; + property oldWidth: Word read FOldW; + property oldHeight: Word read FOldH; property panelType: Word read FPanelType write FPanelType; property enabled: Boolean read FEnabled write FEnabled; property door: Boolean read FDoor write FDoor; @@ -193,6 +193,13 @@ type property isGLift: Boolean read getIsGLift; property isGBlockMon: Boolean read getIsGBlockMon; + (* private state *) + property Alpha: Byte read FAlpha; + property TextureWidth: Word read FTextureWidth; + property TextureHeight: Word read FTextureHeight; + property Blending: Boolean read FBlending; + property TextureIDs: ATextureID read FTextureIDs; + public property movingSpeed: TDFPoint read mMovingSpeed write mMovingSpeed; property movingStart: TDFPoint read mMovingStart write mMovingStart; @@ -222,7 +229,7 @@ implementation uses {$INCLUDE ../nogl/noGLuses.inc} - e_texture, g_basic, g_map, g_game, g_gfx, e_graphics, g_weapons, g_triggers, g_items, + e_texture, g_basic, g_map, g_game, g_gfx, g_weapons, g_triggers, g_items, g_console, g_language, g_monsters, g_player, g_grid, e_log, geom, utils, xstreams; const @@ -389,24 +396,6 @@ begin Inherited; end; -procedure TPanel.lerp (t: Single; out tX, tY, tW, tH: Integer); -begin - if mMovingActive then - begin - tX := nlerp(FOldX, FX, t); - tY := nlerp(FOldY, FY, t); - tW := nlerp(FOldW, FWidth, t); - tH := nlerp(FOldH, FHeight, t); - end - else - begin - tX := FX; - tY := FY; - tW := FWidth; - tH := FHeight; - end; -end; - function TPanel.getx1 (): Integer; inline; begin result := X+Width-1; end; function TPanel.gety1 (): Integer; inline; begin result := Y+Height-1; end; function TPanel.getvisvalid (): Boolean; inline; begin result := (Width > 0) and (Height > 0); end; @@ -449,117 +438,6 @@ function TPanel.getIsGBlockMon (): Boolean; inline; begin result := ((tag and Gr function TPanel.gncNeedSend (): Boolean; inline; begin result := mNeedSend; mNeedSend := false; end; procedure TPanel.setDirty (); inline; begin mNeedSend := true; end; - -procedure TPanel.Draw (hasAmbient: Boolean; constref ambColor: TDFColor); -var - tx, ty, tw, th: Integer; - xx, yy: Integer; - NoTextureID: DWORD; - NW, NH: Word; -begin - if {Enabled and} (FCurTexture >= 0) and - (Width > 0) and (Height > 0) and (FAlpha < 255) {and - g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)} then - begin - lerp(gLerpFactor, tx, ty, tw, th); - if FTextureIDs[FCurTexture].Anim then - begin // Àíèìèðîâàííàÿ òåêñòóðà - if FTextureIDs[FCurTexture].AnTex = nil then - Exit; - - for xx := 0 to (tw div FTextureWidth)-1 do - for yy := 0 to (th div FTextureHeight)-1 do - FTextureIDs[FCurTexture].AnTex.Draw( - tx + xx*FTextureWidth, - ty + yy*FTextureHeight, TMirrorType.None); - end - else - begin // Îáû÷íàÿ òåêñòóðà - case FTextureIDs[FCurTexture].Tex of - LongWord(TEXTURE_SPECIAL_WATER): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 0, 0, 255, 0, TBlending.Filter); - LongWord(TEXTURE_SPECIAL_ACID1): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 0, 230, 0, 0, TBlending.Filter); - LongWord(TEXTURE_SPECIAL_ACID2): e_DrawFillQuad(tx, ty, tx+tw-1, ty+th-1, 230, 0, 0, 0, TBlending.Filter); - LongWord(TEXTURE_NONE): - if g_Texture_Get('NOTEXTURE', NoTextureID) then - begin - e_GetTextureSize(NoTextureID, @NW, @NH); - e_DrawFill(NoTextureID, tx, ty, tw div NW, th div NH, 0, False, False); - end - else - begin - xx := tx + (tw div 2); - yy := ty + (th div 2); - e_DrawFillQuad(tx, ty, xx, yy, 255, 0, 255, 0); - e_DrawFillQuad(xx, ty, tx+tw-1, yy, 255, 255, 0, 0); - e_DrawFillQuad(tx, yy, xx, ty+th-1, 255, 255, 0, 0); - e_DrawFillQuad(xx, yy, tx+tw-1, ty+th-1, 255, 0, 255, 0); - end; - else - begin - if not mMovingActive then - e_DrawFill(FTextureIDs[FCurTexture].Tex, tx, ty, tw div FTextureWidth, th div FTextureHeight, FAlpha, True, FBlending, hasAmbient) - else - e_DrawFillX(FTextureIDs[FCurTexture].Tex, tx, ty, tw, th, FAlpha, True, FBlending, g_dbg_scale, hasAmbient); - if hasAmbient then e_AmbientQuad(tx, ty, tw, th, ambColor.r, ambColor.g, ambColor.b, ambColor.a); - end; - end; - end; - end; -end; - -procedure TPanel.DrawShadowVolume(lightX: Integer; lightY: Integer; radius: Integer); -var - tx, ty, tw, th: Integer; - - procedure extrude (x: Integer; y: Integer); - begin - glVertex2i(x+(x-lightX)*500, y+(y-lightY)*500); - //e_WriteLog(Format(' : (%d,%d)', [x+(x-lightX)*300, y+(y-lightY)*300]), MSG_WARNING); - end; - - procedure drawLine (x0: Integer; y0: Integer; x1: Integer; y1: Integer); - begin - // does this side facing the light? - if ((x1-x0)*(lightY-y0)-(lightX-x0)*(y1-y0) >= 0) then exit; - //e_WriteLog(Format('lightpan: (%d,%d)-(%d,%d)', [x0, y0, x1, y1]), MSG_WARNING); - // this edge is facing the light, extrude and draw it - glVertex2i(x0, y0); - glVertex2i(x1, y1); - extrude(x1, y1); - extrude(x0, y0); - end; - -begin - if radius < 4 then exit; - if Enabled and (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (FAlpha < 255) {and - g_Collide(X, Y, tw, th, sX, sY, sWidth, sHeight)} then - begin - lerp(gLerpFactor, tx, ty, tw, th); - if not FTextureIDs[FCurTexture].Anim then - begin - case FTextureIDs[FCurTexture].Tex of - LongWord(TEXTURE_SPECIAL_WATER): exit; - LongWord(TEXTURE_SPECIAL_ACID1): exit; - LongWord(TEXTURE_SPECIAL_ACID2): exit; - LongWord(TEXTURE_NONE): exit; - end; - end; - if (tx+tw < lightX-radius) then exit; - if (ty+th < lightY-radius) then exit; - if (tx > lightX+radius) then exit; - if (ty > lightY+radius) then exit; - //e_DrawFill(FTextureIDs[FCurTexture].Tex, X, Y, tw div FTextureWidth, th div FTextureHeight, FAlpha, True, FBlending); - - glBegin(GL_QUADS); - drawLine(tx, ty, tx+tw, ty); // top - drawLine(tx+tw, ty, tx+tw, ty+th); // right - drawLine(tx+tw, ty+th, tx, ty+th); // bottom - drawLine(tx, ty+th, tx, ty); // left - glEnd(); - end; -end; - - procedure TPanel.positionChanged (); inline; var px, py, pw, ph: Integer; diff --git a/src/game/opengl/r_game.pas b/src/game/opengl/r_game.pas index a494e0c..abf0068 100644 --- a/src/game/opengl/r_game.pas +++ b/src/game/opengl/r_game.pas @@ -32,7 +32,7 @@ implementation g_textures, e_input, e_sound, g_language, g_console, g_menu, g_triggers, g_player, g_options, g_monsters, g_map, g_panel, g_window, g_items, g_weapons, g_gfx, g_phys, g_net, g_gui, g_netmaster, - g_game, r_console, r_gfx, r_items, r_map + g_game, r_console, r_gfx, r_items, r_map, r_panel ; var @@ -1180,7 +1180,7 @@ var begin pan := TPanel(gDrawPanelList.front()); if ((pan.tag and tagmask) = 0) then break; - if doDraw then pan.Draw(doAmbient, ambColor); + if doDraw then r_Panel_Draw(pan, doAmbient, ambColor); gDrawPanelList.popFront(); end; end diff --git a/src/game/opengl/r_map.pas b/src/game/opengl/r_map.pas index fa1f058..d7d3a85 100644 --- a/src/game/opengl/r_map.pas +++ b/src/game/opengl/r_map.pas @@ -32,7 +32,8 @@ implementation SysUtils, Classes, Math, e_graphics, g_basic, g_game, g_options, - g_panel, g_map + g_panel, g_map, + r_panel ; procedure dplClear (); @@ -52,7 +53,8 @@ procedure r_Map_DrawPanels (PanelType: Word; hasAmbient: Boolean; constref ambCo // alas, no visible set for idx := 0 to High(panels) do begin - if not (drawDoors xor panels[idx].Door) then panels[idx].Draw(hasAmbient, ambColor); + if not (drawDoors xor panels[idx].Door) then + r_Panel_Draw(panels[idx], hasAmbient, ambColor); end; end; end; @@ -89,7 +91,7 @@ var it: TPanelGrid.Iter; begin it := mapGrid.forEachInAABB(lightX-radius, lightY-radius, radius*2, radius*2, (GridTagWall or GridTagDoor)); - for mwit in it do mwit^.DrawShadowVolume(lightX, lightY, radius); + for mwit in it do r_Panel_DrawShadowVolume(mwit^, lightX, lightY, radius); it.release(); end; diff --git a/src/game/opengl/r_panel.pas b/src/game/opengl/r_panel.pas new file mode 100644 index 0000000..f6cc7cb --- /dev/null +++ b/src/game/opengl/r_panel.pas @@ -0,0 +1,158 @@ +(* Copyright (C) Doom 2D: Forever Developers + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3 of the License ONLY. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *) +{$INCLUDE ../../shared/a_modes.inc} +unit r_panel; + +interface + + uses g_panel, MAPDEF; // TPanel + TDFColor + + procedure r_Panel_Draw (constref p: TPanel; hasAmbient: Boolean; constref ambColor: TDFColor); + procedure r_Panel_DrawShadowVolume (constref p: TPanel; lightX, lightY: Integer; radius: Integer); + +implementation + + uses + {$INCLUDE ../nogl/noGLuses.inc} + SysUtils, Classes, Math, utils, + e_graphics, + g_basic, g_textures, g_game + ; + + procedure Panel_Lerp (p: TPanel; t: Single; out tX, tY, tW, tH: Integer); + begin + if p.movingActive then + begin + tX := nlerp(p.OldX, p.X, t); + tY := nlerp(p.OldY, p.Y, t); + tW := nlerp(p.OldWidth, p.Width, t); + tH := nlerp(p.OldHeight, p.Height, t); + end + else + begin + tX := p.X; + tY := p.Y; + tW := p.Width; + tH := p.Height; + end; + end; + + // TODO: remove WITH operator + + procedure r_Panel_Draw (constref p: TPanel; hasAmbient: Boolean; constref ambColor: TDFColor); + var tx, ty, tw, th, xx, yy: Integer; NoTextureID: DWORD; NW, NH: Word; + begin + with p do + begin + if {Enabled and} (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (Alpha < 255) {and g_Collide(X, Y, Width, Height, sX, sY, sWidth, sHeight)} then + begin + Panel_Lerp(p, gLerpFactor, tx, ty, tw, th); + if TextureIDs[FCurTexture].Anim then + begin + if TextureIDs[FCurTexture].AnTex = nil then + Exit; + for xx := 0 to tw div TextureWidth - 1 do + for yy := 0 to th div TextureHeight - 1 do + TextureIDs[FCurTexture].AnTex.Draw(tx + xx * TextureWidth, ty + yy * TextureHeight, TMirrorType.None); + end + else + begin + case TextureIDs[FCurTexture].Tex of + LongWord(TEXTURE_SPECIAL_WATER): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 0, 0, 255, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID1): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 0, 230, 0, 0, TBlending.Filter); + LongWord(TEXTURE_SPECIAL_ACID2): e_DrawFillQuad(tx, ty, tx + tw - 1, ty + th - 1, 230, 0, 0, 0, TBlending.Filter); + LongWord(TEXTURE_NONE): + if g_Texture_Get('NOTEXTURE', NoTextureID) then + begin + e_GetTextureSize(NoTextureID, @NW, @NH); + e_DrawFill(NoTextureID, tx, ty, tw div NW, th div NH, 0, False, False); + end + else + begin + xx := tx + (tw div 2); + yy := ty + (th div 2); + e_DrawFillQuad(tx, ty, xx, yy, 255, 0, 255, 0); + e_DrawFillQuad(xx, ty, tx + tw - 1, yy, 255, 255, 0, 0); + e_DrawFillQuad(X, yy, xx, ty + th - 1, 255, 255, 0, 0); + e_DrawFillQuad(xx, yy, tx + tw - 1, ty + th - 1, 255, 0, 255, 0); + end; + else + begin + if not movingActive then + e_DrawFill(TextureIDs[FCurTexture].Tex, tx, ty, tw div TextureWidth, th div TextureHeight, Alpha, True, Blending, hasAmbient) + else + e_DrawFillX(TextureIDs[FCurTexture].Tex, tx, ty, tw, th, Alpha, True, Blending, g_dbg_scale, hasAmbient); + if hasAmbient then + e_AmbientQuad(tx, ty, tw, th, ambColor.r, ambColor.g, ambColor.b, ambColor.a); + end + end + end + end + end + end; + + procedure r_Panel_DrawShadowVolume (constref p: TPanel; lightX, lightY: Integer; radius: Integer); + var tx, ty, tw, th: Integer; + + procedure extrude (x: Integer; y: Integer); + begin + glVertex2i(x + (x - lightX) * 500, y + (y - lightY) * 500); + //e_WriteLog(Format(' : (%d,%d)', [x + (x - lightX) * 300, y + (y - lightY) * 300]), MSG_WARNING); + end; + + procedure drawLine (x0: Integer; y0: Integer; x1: Integer; y1: Integer); + begin + // does this side facing the light? + if ((x1 - x0) * (lightY - y0) - (lightX - x0) * (y1 - y0) >= 0) then exit; + //e_WriteLog(Format('lightpan: (%d,%d)-(%d,%d)', [x0, y0, x1, y1]), MSG_WARNING); + // this edge is facing the light, extrude and draw it + glVertex2i(x0, y0); + glVertex2i(x1, y1); + extrude(x1, y1); + extrude(x0, y0); + end; + + begin + with p do + begin + if radius < 4 then exit; + if Enabled and (FCurTexture >= 0) and (Width > 0) and (Height > 0) and (Alpha < 255) {and g_Collide(X, Y, tw, th, sX, sY, sWidth, sHeight)} then + begin + Panel_Lerp(p, gLerpFactor, tx, ty, tw, th); + if not TextureIDs[FCurTexture].Anim then + begin + case TextureIDs[FCurTexture].Tex of + LongWord(TEXTURE_SPECIAL_WATER): exit; + LongWord(TEXTURE_SPECIAL_ACID1): exit; + LongWord(TEXTURE_SPECIAL_ACID2): exit; + LongWord(TEXTURE_NONE): exit; + end; + end; + if (tx + tw < lightX - radius) then exit; + if (ty + th < lightY - radius) then exit; + if (tx > lightX + radius) then exit; + if (ty > lightY + radius) then exit; + //e_DrawFill(TextureIDs[FCurTexture].Tex, X, Y, tw div TextureWidth, th div TextureHeight, Alpha, True, Blending); + glBegin(GL_QUADS); + drawLine(tx, ty, tx + tw, ty); // top + drawLine(tx + tw, ty, tx + tw, ty + th); // right + drawLine(tx + tw, ty + th, tx, ty + th); // bottom + drawLine(tx, ty + th, tx, ty); // left + glEnd; + end + end + end; + +end. -- 2.29.2