DEADSOFTWARE

gl: draw sky with parallax
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 10 Jun 2022 16:41:01 +0000 (19:41 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 9 Jun 2023 08:42:32 +0000 (11:42 +0300)
src/game/renders/opengl/r_draw.pas
src/game/renders/opengl/r_map.pas

index e836b30d1190e7923f536587de66c616106fd3e0..07d805cf45b928df653a611b675c963197dcd1d2 100644 (file)
@@ -116,8 +116,6 @@ implementation
       DrawTile(nil, x, y, w, h, flip, NTR, NTB, NTG, NTA, blend)
     else
     begin
-      glPushMatrix;
-      glScalef(w / img.width, h / img.height, 1);
       offx := 0;
       offy := 0;
       for j := 0 to img.lines - 1 do
@@ -126,13 +124,16 @@ implementation
         begin
           n := img.GetTile(i, j);
           ASSERT(n <> nil);
-          DrawTile(n, x + offx, y + offy, n.width, n.height, flip, r, g, b, a, blend);
+          glPushMatrix;
+          glTranslatef(x + offx, y + offy, 0);
+          glScalef(w / img.width, h / img.height, 1);
+          DrawTile(n, 0, 0, n.width, n.height, flip, r, g, b, a, blend);
+          glPopMatrix;
           offx := offx + n.width;
         end;
         offx := 0;
         offy := offy + n.height;
       end;
-      glPopMatrix;
     end
   end;
 
index 3ef4979ad1fadf181c8879a2cb7106b445fb863f..3364f1f3ddd94830a9bb4d387d58168302527ad6 100644 (file)
@@ -1155,8 +1155,56 @@ implementation
   end;
 {$ENDIF}
 
+  procedure r_Map_CalcAspect (ow, oh, nw, nh: LongInt; horizontal: Boolean; out ww, hh: LongInt);
+  begin
+    if horizontal then
+    begin
+      ww := nw;
+      hh := nw * oh div ow;
+    end
+    else
+    begin
+      ww := nh * ow div oh;
+      hh := nh;
+    end;
+  end;
+
+  procedure r_Map_CalcSkyParallax (cx, cy, vw, vh, sw, sh, mw, mh: LongInt; out x, y, w, h: LongInt);
+    const
+      factor = 120; (* size ratio between view and sky (120%) *)
+      limit = 100;  (* max speed for parallax *)
+    var
+      msw, msh, mvw, mvh, svw, svh: LongInt;
+  begin
+    msw := vw * factor div 100;
+    msh := vh * factor div 100;
+    r_Map_CalcAspect(sw, sh, msw, msh, (sw / sh) <= (msw / msh), w, h);
+
+    (* calc x parallax or sky center on speed limit *)
+    mvw := MAX(1, mw - vw);
+    svw := w - vw;
+    if 100 * svw div mvw <= limit then
+      x := -cx * svw div mvw
+    else
+      x := -svw div 2;
+
+    (* calc y parallax or sky center on speed limit *)
+    mvh := MAX(1, mh - vh);
+    svh := h - vh;
+    if 100 * svh div mvh <= limit then
+      y := -cy * svh div mvh
+    else
+      y := -svh div 2;
+
+    (* handle out of map bounds *)
+    if x > 0 then x := 0;
+    if y > 0 then y := 0;
+    if x < -svw then x := -svw;
+    if y < -svh then y := -svh;
+  end;
+
   procedure r_Map_Draw (x, y, w, h, camx, camy: Integer; player: TPlayer);
-    var iter: TPanelGrid.Iter; p: PPanel; cx, cy, xx, yy, ww, hh: Integer;
+    var iter: TPanelGrid.Iter; p: PPanel; cx, cy, xx, yy, ww, hh: Integer; sx, sy, sw, sh: LongInt;
   begin
     cx := camx - w div 2;
     cy := camy - h div 2;
@@ -1179,9 +1227,11 @@ implementation
       cy := yy - y;
     end;
 
-    // TODO draw paralax
     if SkyTexture <> nil then
-      r_Draw_Texture(SkyTexture, x, y, w, h, false, 255, 255, 255, 255, false);
+    begin
+      r_Map_CalcSkyParallax(cx, cy, ww, hh, SkyTexture.width, SkyTexture.height, gMapInfo.Width, gMapInfo.Height, sx, sy, sw, sh);
+      r_Draw_Texture(SkyTexture, x + sx, y + sy, sw, sh, false, 255, 255, 255, 255, false);
+    end;
 
     plist.Clear;
     iter := mapGrid.ForEachInAABB(xx, yy, ww, hh, GridDrawableMask);