DEADSOFTWARE

gl: fix fluid textures
[d2df-sdl.git] / src / game / renders / opengl / r_map.pas
index eff895d9b528d404a0560b035f1958efe48bf619..371b13db5ac8810e30444257144ad501c272054e 100644 (file)
@@ -232,6 +232,9 @@ implementation
     TMonsterAnims = array [0..ANIM_LAST, TDirection] of TGLMultiTexture;
 
   var
+    UseAccel: Boolean;
+    DebugFrames: Boolean;
+    DebugHealth: Boolean;
     DebugCameraScale: Single;
     FillOutsizeArea: Boolean;
     SkyTexture: TGLTexture;
@@ -285,9 +288,9 @@ implementation
 
   class function TBinHeapPanelDrawCmp.less (const a, b: TPanel): Boolean; inline;
   begin
-    if a.tag < b.tag then begin result := true; exit; end;
-    if a.tag > b.tag then begin result := false; exit; end;
-    result := a.arrIdx < b.arrIdx;
+    if a.tag < b.tag then result := true
+    else if a.tag > b.tag then result := false
+    else result := a.arrIdx < b.arrIdx;
   end;
 
   procedure r_Map_Initialize;
@@ -581,20 +584,20 @@ implementation
   end;
 
   procedure r_Map_DrawPanel (p: TPanel);
-    var Texture: Integer; t: TGLMultiTexture; tex: TGLTexture; count, frame: LongInt; a: TAnimInfo;
+    var Texture, spec: Integer; t: TGLMultiTexture; count, frame: LongInt; a: TAnimInfo;
   begin
     ASSERT(p <> nil);
+    ASSERT(p.FCurTexture >= -1); (* p.FCurTexture = -1 -> invisible texture *)
     if p.FCurTexture >= 0 then
     begin
       ASSERT(p.FCurTexture <= High(p.TextureIDs));
       Texture := p.TextureIDs[p.FCurTexture].Texture;
-      t := nil;
-      ASSERT(Texture >= -1);
-      ASSERT(Texture <= High(RenTextures));
+      ASSERT(Texture >= -1); (* Texture = -1 -> texture not found *)
       if Texture >= 0 then
       begin
+        ASSERT(Texture <= High(RenTextures));
         t := RenTextures[Texture].tex;
-        if (RenTextures[Texture].spec = 0) or (t <> nil) then
+        if t <> nil then
         begin
           count := 0; frame := 0;
           if p.AnimTime <= gTime then
@@ -603,40 +606,66 @@ implementation
             a.loop := p.AnimLoop;
             g_Anim_GetFrameByTime(a, (gTime - p.AnimTime) DIV GAME_TICK, count, frame);
           end;
-          if t <> nil then
-          begin
-            tex := t.GetTexture(frame);
-            r_Draw_TextureRepeat(tex, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending);
-          end
-          else
-            r_Draw_TextureRepeat(nil, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255, false);
+          r_Draw_TextureRepeat(t.GetTexture(frame), p.x, p.y, p.width, p.height, false, 255, 255, 255, 255 - p.alpha, p.blending);
+        end
+        else if RenTextures[Texture].spec = 0 then
+        begin
+          r_Draw_TextureRepeat(nil, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255, false);
         end;
-      end;
-
-      if t = nil then
-      begin
         case RenTextures[Texture].spec of
           TEXTURE_SPECIAL_WATER: r_Draw_Filter(p.x, p.y, p.x + p.width, p.y + p.height, 0, 0, 255, 255);
           TEXTURE_SPECIAL_ACID1: r_Draw_Filter(p.x, p.y, p.x + p.width, p.y + p.height, 0, 230, 0, 255);
           TEXTURE_SPECIAL_ACID2: r_Draw_Filter(p.x, p.y, p.x + p.width, p.y + p.height, 230, 0, 0, 255);
-        end
+        end;
       end
-    end
+      else
+      begin
+        r_Draw_TextureRepeat(nil, p.x, p.y, p.width, p.height, false, 255, 255, 255, 255, false);
+      end;
+    end;
+  end;
+
+  procedure r_Map_DrawPanels (constref panels: TPanelArray; drawDoors: Boolean = false);
+    var i: Integer; p: TPanel;
+  begin
+    if panels <> nil then
+    begin
+      for i := 0 to High(panels) do
+      begin
+        p := panels[i];
+        if p.enabled and not (drawDoors xor p.door) then
+          r_Map_DrawPanel(p);
+      end;
+    end;
   end;
 
   procedure r_Map_DrawPanelType (panelTyp: DWORD);
-    var tagMask, i: Integer; p: TPanel;
+    var tagMask: Integer; p: TPanel;
   begin
-    i := 0;
-    tagMask := PanelTypeToTag(panelTyp);
-    while plist.count > 0 do
+    if UseAccel then
+    begin
+      tagMask := PanelTypeToTag(panelTyp);
+      while plist.count > 0 do
+      begin
+        p := TPanel(plist.Front());
+        if (p.tag and tagMask) = 0 then
+          break;
+        r_Map_DrawPanel(p);
+        plist.PopFront;
+      end;
+    end
+    else
     begin
-      p := TPanel(plist.Front());
-      if (p.tag and tagMask) = 0 then
-        break;
-      r_Map_DrawPanel(p);
-      Inc(i);
-      plist.PopFront
+      case panelTyp of
+        PANEL_BACK:      if g_rlayer_back then r_Map_DrawPanels(gRenderBackgrounds);
+        PANEL_STEP:      if g_rlayer_step then r_Map_DrawPanels(gSteps);
+        PANEL_WALL:      if g_rlayer_wall then r_Map_DrawPanels(gWalls);
+        PANEL_CLOSEDOOR: if g_rlayer_door then r_Map_DrawPanels(gWalls, True);
+        PANEL_ACID1:     if g_rlayer_acid1 then r_Map_DrawPanels(gAcid1);
+        PANEL_ACID2:     if g_rlayer_acid2 then r_Map_DrawPanels(gAcid2);
+        PANEL_WATER:     if g_rlayer_water then r_Map_DrawPanels(gWater);
+        PANEL_FORE:      if g_rlayer_fore then r_Map_DrawPanels(gRenderForegrounds);
+      end;
     end;
   end;
 
@@ -656,11 +685,20 @@ implementation
             r_Common_GetObjectPos(it.obj, xx, yy);
             tex := t.GetTexture(Items[it.ItemType].frame);
             r_Draw_TextureRepeat(tex, xx, yy, tex.width, tex.height, false, 255, 255, 255, 255, false);
+            if DebugFrames then
+            begin
+              r_Draw_Rect(
+                xx + it.obj.rect.x, // it.obj.x + it.obj.rect.x,
+                yy + it.obj.rect.y, // it.obj.y + it.obj.rect.y,
+                xx + it.obj.rect.x + it.obj.rect.width,  // it.obj.x + it.obj.rect.x + it.obj.rect.width,
+                yy + it.obj.rect.y + it.obj.rect.height, // it.obj.y + it.obj.rect.y + it.obj.rect.height,
+                0, 255, 0, 255
+              );
+            end;
           end;
         end;
       end;
     end;
-    // TODO draw g_debug_frames
   end;
 
   function r_Map_GetMonsterTexture (m, a: Integer; d: TDirection; out t: TGLMultiTexture; out dx, dy: Integer; out flip: Boolean): Boolean;
@@ -720,13 +758,32 @@ implementation
     a := mon.MonsterAnim;
     d := mon.GameDirection;
 
+    r_Common_GetObjectPos(mon.obj, xx, yy);
     if r_Map_GetMonsterTexture(m, a, d, t, dx, dy, flip) then
     begin
-      r_Common_GetObjectPos(mon.obj, xx, yy);
       r_Draw_MultiTextureRepeat(t, mon.DirAnim[a, d], false, xx + dx, yy + dy, t.width, t.height, flip, 255, 255, 255, 255, false);
     end;
-
-    // TODO draw g_debug_frames
+    if DebugFrames then
+    begin
+      r_Draw_Rect(
+        xx + mon.obj.rect.x, // mon.obj.x + mon.obj.rect.x,
+        yy + mon.obj.rect.y, // mon.obj.y + mon.obj.rect.y,
+        xx + mon.obj.rect.x + mon.obj.rect.width,  // mon.obj.x + mon.obj.rect.x + mon.obj.rect.width,
+        yy + mon.obj.rect.y + mon.obj.rect.height, // mon.obj.y + mon.obj.rect.y + mon.obj.rect.height,
+        0, 255, 0, 255
+      );
+    end;
+    if DebugHealth and mon.alive then
+    begin
+      r_Common_DrawText(
+        IntToStr(mon.MonsterHealth),
+        xx + mon.obj.rect.x + mon.obj.rect.width div 2,
+        yy + mon.obj.rect.y,
+        255, 255, 255, 255,
+        stdfont,
+        TBasePoint.BP_DOWN
+      );
+    end;
   end;
 
   procedure r_Map_DrawMonsters (x, y, w, h: Integer);
@@ -960,7 +1017,29 @@ implementation
 
       r_Map_DrawPlayerModel(p.Model, x, y, alpha);
     end;
-    // TODO draw g_debug_frames
+
+    if DebugFrames then
+    begin
+      r_Draw_Rect(
+        x + p.obj.rect.x, // p.obj.x + p.obj.rect.x,
+        y + p.obj.rect.y, // p.obj.y + p.obj.rect.y,
+        x + p.obj.rect.x + p.obj.rect.width,  // p.obj.x + p.obj.rect.x + p.obj.rect.width,
+        y + p.obj.rect.y + p.obj.rect.height, // p.obj.y + p.obj.rect.y + p.obj.rect.height,
+        0, 255, 0, 255
+      );
+    end;
+
+    if DebugHealth and p.alive then
+    begin
+      r_Common_DrawText(
+        IntToStr(p.health) + '/' + IntToStr(p.armor),
+        x + p.obj.rect.x + p.obj.rect.width div 2,
+        y - 24,
+        255, 255, 255, 255,
+        stdfont,
+        TBasePoint.BP_DOWN
+      );
+    end;
 
     if (gChatBubble > 0) and p.FKeys[KEY_CHAT].Pressed and (p.Ghost = false) then
       if (p.FMegaRulez[MR_INVIS] <= gTime) or ((drawed <> nil) and ((p = drawed) or (p.Team = drawed.Team) and (gGameSettings.GameMode <> GM_DM))) then
@@ -1015,7 +1094,6 @@ implementation
         end;
       end;
     end;
-    // TODO draw g_debug_frames
   end;
 {$ENDIF}
 
@@ -1035,7 +1113,6 @@ implementation
         end;
       end;
     end;
-    // TODO draw g_debug_frames
   end;
 {$ENDIF}
 
@@ -1198,11 +1275,20 @@ implementation
             g_Anim_GetFrameByTime(ShotAnim[typ].anim, (gTime - Shots[i].time) DIV GAME_TICK, count, frame);
             tex := t.GetTexture(frame);
             r_Draw_TextureRepeatRotate(tex, xx, yy, tex.width, tex.height, false, 255, 255, 255, 255, false, pX, pY, a);
+            if DebugFrames then
+            begin
+              r_Draw_Rect(
+                xx + Shots[i].obj.rect.x, // Shots[i].obj.x + Shots[i].obj.rect.x,
+                yy + Shots[i].obj.rect.y, // Shots[i].obj.y + Shots[i].obj.rect.y,
+                xx + Shots[i].obj.rect.x + Shots[i].obj.rect.width,  // Shots[i].obj.x + Shots[i].obj.rect.x + Shots[i].obj.rect.width,
+                yy + Shots[i].obj.rect.y + Shots[i].obj.rect.height, // Shots[i].obj.y + Shots[i].obj.rect.y + Shots[i].obj.rect.height,
+                0, 255, 0, 255
+              );
+            end;
           end;
         end;
       end;
     end;
-    // TODO draw g_debug_frames
   end;
 
   procedure r_Map_DrawFlags (x, y, w, h: Integer);
@@ -1219,11 +1305,20 @@ implementation
           if flip then dx := -1 else dx := +1;
           t := FlagTextures[i];
           tex := t.GetTexture(FlagFrame);
-          r_Draw_TextureRepeat(tex, xx + dx, yy + 1, tex.width, tex.height, flip, 255, 255, 255, 255, false)
+          r_Draw_TextureRepeat(tex, xx + dx, yy + 1, tex.width, tex.height, flip, 255, 255, 255, 255, false);
+          if DebugFrames then
+          begin
+            r_Draw_Rect(
+              xx + gFlags[i].obj.rect.x, // gFlags[i].obj.x + gFlags[i].obj.rect.x,
+              yy + gFlags[i].obj.rect.y, // gFlags[i].obj.y + gFlags[i].obj.rect.y,
+              xx + gFlags[i].obj.rect.x + gFlags[i].obj.rect.width,  // gFlags[i].obj.x + gFlags[i].obj.rect.x + gFlags[i].obj.rect.width,
+              yy + gFlags[i].obj.rect.y + gFlags[i].obj.rect.height, // gFlags[i].obj.y + gFlags[i].obj.rect.y + gFlags[i].obj.rect.height,
+              0, 255, 0, 255
+            );
+          end;
         end;
       end;
     end;
-    // TODO g_debug_frames
   end;
 
 {$IFDEF ENABLE_SHELLS}
@@ -1414,16 +1509,34 @@ implementation
     end;
   end;
 
+  function r_Map_GetDrawableGridMask (): Integer;
+    var mask: Integer;
+  begin
+    mask := 0;
+    if g_rlayer_back then mask := mask or GridTagBack;
+    if g_rlayer_step then mask := mask or GridTagStep;
+    if g_rlayer_wall then mask := mask or GridTagWall;
+    if g_rlayer_door then mask := mask or GridTagDoor;
+    if g_rlayer_acid1 then mask := mask or GridTagAcid1;
+    if g_rlayer_acid2 then mask := mask or GridTagAcid2;
+    if g_rlayer_water then mask := mask or GridTagWater;
+    if g_rlayer_fore then mask := mask or GridTagFore;
+    result := mask;
+  end;
+
   procedure r_Map_DrawGame (xx, yy, ww, hh: Integer; player: TPlayer);
     (* xx/yy/ww/hh are in map units *)
     var iter: TPanelGrid.Iter; p: PPanel;
   begin
-    plist.Clear;
-    iter := mapGrid.ForEachInAABB(xx, yy, ww, hh, GridDrawableMask);
-    for p in iter do
-      if ((p^.tag and GridTagDoor) <> 0) = p^.door then
-        plist.Insert(p^);
-    iter.Release;
+    if UseAccel then
+    begin
+      plist.Clear;
+      iter := mapGrid.ForEachInAABB(xx, yy, ww, hh, r_Map_GetDrawableGridMask());
+      for p in iter do
+        if ((p^.tag and GridTagDoor) <> 0) = p^.door then
+          plist.Insert(p^);
+      iter.Release;
+    end;
 
     r_Map_DrawPanelType(PANEL_BACK);
     r_Map_DrawPanelType(PANEL_STEP);
@@ -1452,8 +1565,6 @@ implementation
     r_Map_DrawPanelType(PANEL_ACID2);
     r_Map_DrawPanelType(PANEL_WATER);
     r_Map_DrawPanelType(PANEL_FORE);
-    // TODO draw monsters health bar
-    // TODO draw players health bar
   end;
 
   procedure r_Map_DrawScaled (w, h, camx, camy: Integer; player: TPlayer; out acx, acy, acw, ach, axx, ayy, aww, ahh: Integer);
@@ -1528,7 +1639,7 @@ implementation
       glTranslatef(-w div 2, -h div 2, 0);
     end;
 
-    if SkyTexture <> nil then
+    if gDrawBackGround and (SkyTexture <> nil) then
     begin
       r_Map_CalcSkyParallax(cx, cy, w, h, SkyTexture.width, SkyTexture.height, gMapInfo.Width, gMapInfo.Height, sx, sy, sw, sh);
       r_Draw_Texture(SkyTexture, sx, sy, sw, sh, false, 255, 255, 255, 255, false);
@@ -1572,8 +1683,6 @@ implementation
       r_Map_DrawPlayerIndicators(player, cx, cy, cw, ch);
     end;
 
-    // TODO draw g_debug_player
-
     //glTranslatef(-x, -y, 0);
     r_Draw_SetRect(l, t, r, b);
     glPopMatrix;
@@ -1599,8 +1708,14 @@ implementation
   end;
 
 initialization
+  conRegVar('r_sq_draw', @UseAccel, 'accelerated spatial queries in rendering', 'accelerated rendering');
   conRegVar('r_debug_camera_scale', @DebugCameraScale, 0.0001, 1000.0, '', '');
   conRegVar('r_gl_fill_outside', @FillOutsizeArea, '', '');
+  conRegVar('d_frames', @DebugFrames, '', '');
+  conRegVar('d_health', @DebugHealth, '', '');
+  UseAccel := true;
   DebugCameraScale := 1.0;
   FillOutsizeArea := true;
+  DebugFrames := false;
+  DebugHealth := false;
 end.