Complete.Org: Mailing Lists: Archives: freeciv-dev: December 2004:
[Freeciv-Dev] Re: (PR#11433) Fog of War rendering improvement
Home

[Freeciv-Dev] Re: (PR#11433) Fog of War rendering improvement

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: andrearo@xxxxxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#11433) Fog of War rendering improvement
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 11 Dec 2004 14:16:52 -0800
Reply-to: bugs@xxxxxxxxxxx

<URL: http://bugs.freeciv.org/Ticket/Display.html?id=11433 >

Andreas Røsdal wrote:

> Excellent. I tested the patch in iso-view, and it actually seems to be
> faster than the unpatched client.

It should be, because there's less drawing being done (on the other hand 
it consumes more memory so if this pushes you into swap it could be slower).

Here's a new version of the patch.  I followed Vasco's instructions to 
automatically disable better-fog if the drawable isn't truecolor.

-jason

Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.164
diff -u -r1.164 mapview_common.c
--- client/mapview_common.c     9 Dec 2004 21:28:53 -0000       1.164
+++ client/mapview_common.c     11 Dec 2004 22:14:06 -0000
@@ -1311,14 +1311,8 @@
                  int canvas_x, int canvas_y, bool citymode)
 {
   if (tile_get_known(ptile) != TILE_UNKNOWN) {
-    struct drawn_sprite tile_sprs[80];
-
-    int count = fill_sprite_array(tile_sprs, ptile,
-                                 get_drawable_unit(ptile, citymode),
-                                 map_get_city(ptile), citymode);
-
-    put_drawn_sprites(pcanvas, canvas_x, canvas_y,
-                     count, tile_sprs, FALSE);
+    /* FIXME: These two functions should be merged. */
+    put_one_tile_iso(pcanvas, ptile, canvas_x, canvas_y, citymode);
   } else {
     /* tile is unknown */
     canvas_put_rectangle(pcanvas, COLOR_STD_BLACK,
@@ -1464,7 +1458,8 @@
   int count = fill_sprite_array(tile_sprs, ptile,
                                get_drawable_unit(ptile, citymode),
                                ptile->city, citymode);
-  bool fog = ptile->known == TILE_KNOWN_FOGGED && draw_fog_of_war;
+  bool fog = (ptile->known == TILE_KNOWN_FOGGED && draw_fog_of_war
+             && fogstyle == 0);
 
   /*** Draw terrain and specials ***/
   put_drawn_sprites(pcanvas, canvas_x, canvas_y, count, tile_sprs, fog);
Index: client/tilespec.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.c,v
retrieving revision 1.218
diff -u -r1.218 tilespec.c
--- client/tilespec.c   9 Dec 2004 02:21:46 -0000       1.218
+++ client/tilespec.c   11 Dec 2004 22:14:06 -0000
@@ -85,6 +85,7 @@
 int num_tiles_explode_unit=0;
 
 static int roadstyle;
+int fogstyle;
 static int flag_offset_x, flag_offset_y;
 
 #define NUM_CORNER_DIRS 4
@@ -846,6 +847,8 @@
 
   roadstyle = secfile_lookup_int_default(file, is_isometric ? 0 : 1,
                                         "tilespec.roadstyle");
+  fogstyle = secfile_lookup_int_default(file, 0,
+                                       "tilespec.fogstyle");
   darkness_style = secfile_lookup_int(file, "tilespec.darkness_style");
   if (darkness_style < DARKNESS_NONE
       || darkness_style > DARKNESS_CARD_FULL
@@ -1896,7 +1899,7 @@
    sprs->type = DRAWN_SPRITE,                                  \
    sprs->data.sprite.style = draw_style,                       \
    sprs->data.sprite.sprite = s,                               \
-   sprs->data.sprite.foggable = draw_fog,                      \
+   sprs->data.sprite.foggable = (draw_fog && fogstyle == 0),   \
    sprs->data.sprite.offset_x = x_offset,                      \
    sprs->data.sprite.offset_y = y_offset,                      \
    sprs++)
@@ -2754,9 +2757,9 @@
     }
   }
 
-  if (!is_isometric && draw_fog_of_war
+  if (fogstyle == 1 && draw_fog_of_war
       && ptile && tile_get_known(ptile) == TILE_KNOWN_FOGGED) {
-    /* Fogging in non-iso is done this way. */
+    /* With fogstyle 1, fog is done this way. */
     ADD_SPRITE_SIMPLE(sprites.tx.fog);
   }
 
Index: client/tilespec.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/tilespec.h,v
retrieving revision 1.92
diff -u -r1.92 tilespec.h
--- client/tilespec.h   3 Dec 2004 09:39:39 -0000       1.92
+++ client/tilespec.h   11 Dec 2004 22:14:06 -0000
@@ -266,6 +266,7 @@
 };
 
 extern struct named_sprites sprites;
+extern int fogstyle;
 
 struct Sprite *get_citizen_sprite(struct citizen_type type,
                                  int citizen_index,
Index: client/gui-gtk-2.0/graphics.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/graphics.c,v
retrieving revision 1.28
diff -u -r1.28 graphics.c
--- client/gui-gtk-2.0/graphics.c       23 Nov 2004 15:44:10 -0000      1.28
+++ client/gui-gtk-2.0/graphics.c       11 Dec 2004 22:14:07 -0000
@@ -290,7 +290,7 @@
     SPRITE *mysprite = fc_malloc(sizeof(SPRITE));
 
     mysprite->pixmap   = mypixmap;
-
+    mysprite->fogged = NULL;
     mysprite->mask = mask;
 
     mysprite->width    = width;
@@ -352,6 +352,7 @@
   mysprite->height    = h;
 
   mysprite->pixbuf    = NULL;
+  mysprite->fogged = NULL;
 
   g_object_unref(im);
 
@@ -374,6 +375,9 @@
   if (s->pixbuf) {
     g_object_unref(s->pixbuf);
   }
+  if (s->fogged) {
+    g_object_unref(s->fogged);
+  }
   free(s);
 }
 
@@ -457,7 +461,7 @@
   mysprite->height    = new_h;
 
   mysprite->pixbuf    = NULL;
-
+  mysprite->fogged = NULL;
   g_object_unref(im);
 
   return mysprite;
Index: client/gui-gtk-2.0/graphics.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/graphics.h,v
retrieving revision 1.9
diff -u -r1.9 graphics.h
--- client/gui-gtk-2.0/graphics.h       20 Nov 2004 08:17:37 -0000      1.9
+++ client/gui-gtk-2.0/graphics.h       11 Dec 2004 22:14:07 -0000
@@ -21,6 +21,7 @@
 struct Sprite
 {
   GdkPixmap *pixmap;
+  GdkPixmap *fogged;
   GdkBitmap *mask;
   int       width;
   int       height;
Index: client/gui-gtk-2.0/gui_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.c,v
retrieving revision 1.98
diff -u -r1.98 gui_main.c
--- client/gui-gtk-2.0/gui_main.c       7 Dec 2004 22:38:59 -0000       1.98
+++ client/gui-gtk-2.0/gui_main.c       11 Dec 2004 22:14:07 -0000
@@ -86,6 +86,7 @@
 bool fullscreen_mode = TRUE;
 bool enable_tabs = TRUE;
 bool solid_unit_icon_bg = FALSE;
+bool better_fog = TRUE;
 
 GtkWidget *toplevel;
 GdkWindow *root_window;
@@ -178,7 +179,13 @@
                  N_("If this is enabled then units will be shown in the "
                     "city dialog production tab with a color-coded "
                     "solid background."),
-                 COC_INTERFACE)
+                 COC_INTERFACE),
+  GEN_BOOL_OPTION(better_fog,
+                 N_("Better fog-of-war drawing"),
+                 N_("If this is enabled then a better method is used for "
+                    "drawing fog-of-war.  It is not any slower but will "
+                    "consume about twice as much memory."),
+                 COC_GRAPHICS)
 };
 const int num_gui_options = ARRAY_SIZE(gui_options);
 
Index: client/gui-gtk-2.0/gui_main.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/gui_main.h,v
retrieving revision 1.18
diff -u -r1.18 gui_main.h
--- client/gui-gtk-2.0/gui_main.h       23 Nov 2004 15:44:10 -0000      1.18
+++ client/gui-gtk-2.0/gui_main.h       11 Dec 2004 22:14:07 -0000
@@ -44,6 +44,7 @@
 extern bool fullscreen_mode;
 extern bool enable_tabs;
 extern bool solid_unit_icon_bg;
+extern bool better_fog;
 
 extern GdkGC *          civ_gc;
 extern GdkGC *          mask_fg_gc;
Index: client/gui-gtk-2.0/mapview.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/gui-gtk-2.0/mapview.c,v
retrieving revision 1.147
diff -u -r1.147 mapview.c
--- client/gui-gtk-2.0/mapview.c        1 Nov 2004 03:39:45 -0000       1.147
+++ client/gui-gtk-2.0/mapview.c        11 Dec 2004 22:14:07 -0000
@@ -25,15 +25,17 @@
 #include <gtk/gtk.h>
 
 #include "fcintl.h"
-#include "game.h"
-#include "government.h"                /* government_graphic() */
-#include "map.h"
+#include "log.h"
 #include "mem.h"
-#include "player.h"
 #include "rand.h"
 #include "support.h"
 #include "timing.h"
 
+#include "game.h"
+#include "government.h"                /* government_graphic() */
+#include "map.h"
+#include "player.h"
+
 #include "civclient.h"
 #include "climap.h"
 #include "climisc.h"
@@ -866,6 +868,58 @@
 }
 
 /**************************************************************************
+  Created a fogged version of the sprite.  This can fail on older systems
+  in which case the callers needs a fallback.
+**************************************************************************/
+static void fog_sprite(struct Sprite *sprite)
+{
+  int x, y;
+  GdkImage* ftile;
+
+  if (gdk_drawable_get_visual(sprite->pixmap)->type
+      != GDK_VISUAL_TRUE_COLOR) {
+    /* In this case the below code won't work. */
+    return;
+  }
+
+  ftile = gdk_drawable_get_image(sprite->pixmap,
+                                0, 0, sprite->width, sprite->height);
+
+  /* Iterate over all pixels, reducing brightness by 50%. */
+  for (x = 0; x < sprite->width; x++) {
+    for (y = 0; y < sprite->height; y++) {
+      guint32 pixel =  gdk_image_get_pixel(ftile, x, y);
+
+      guint8 red = (((pixel & ftile->visual->red_mask) << 
+                    (32 - ftile->visual->red_shift 
+                     - ftile->visual->red_prec)) >> 24) / 2; 
+      guint8 green = (((pixel & ftile->visual->green_mask) <<
+                      (32 - ftile->visual->green_shift 
+                       - ftile->visual->green_prec)) >> 24) / 2;
+      guint8 blue = (((pixel & ftile->visual->blue_mask) <<
+                     (32 - ftile->visual->blue_shift 
+                      - ftile->visual->blue_prec)) >> 24) / 2;
+      guint32 result = red << ftile->visual->red_shift
+       | green << ftile->visual->green_shift          
+       | blue << ftile->visual->blue_shift;
+
+      gdk_image_put_pixel(ftile, x , y, result);
+    }
+  }
+
+  /* Convert the image back to a pixmap, since pixmaps are much faster
+   * to draw. */
+  sprite->fogged = gdk_pixmap_new(root_window,
+                                 sprite->width, sprite->height, -1);
+  gdk_gc_set_clip_origin(fill_tile_gc, 0, 0);
+  gdk_gc_set_clip_mask(fill_tile_gc, sprite->mask);
+  gdk_draw_image(sprite->fogged, fill_tile_gc, ftile,
+                0, 0, 0, 0, sprite->width, sprite->height);
+  gdk_gc_set_clip_mask(fill_tile_gc, NULL);
+  g_object_unref(ftile);
+}
+
+/**************************************************************************
 Only used for isometric view.
 **************************************************************************/
 static void pixmap_put_overlay_tile_draw(GdkDrawable *pixmap,
@@ -877,6 +931,29 @@
     return;
   }
 
+  if (fog && better_fog && !ssprite->fogged) {
+    fog_sprite(ssprite);
+    if (!ssprite->fogged) {
+      freelog(LOG_NORMAL,
+             _("Better fog will only work in truecolor.  Disabling it"));
+      better_fog = FALSE;
+    }
+  }
+
+  if (fog && better_fog) {
+    gdk_gc_set_clip_origin(fill_tile_gc, canvas_x, canvas_y);
+    gdk_gc_set_clip_mask(fill_tile_gc, ssprite->mask);
+
+    gdk_draw_drawable(pixmap, fill_tile_gc,
+                     ssprite->fogged,
+                     0, 0,
+                     canvas_x, canvas_y,
+                     ssprite->width, ssprite->height);
+    gdk_gc_set_clip_mask(fill_tile_gc, NULL);
+
+    return;
+  }
+
   pixmap_put_sprite(pixmap, canvas_x, canvas_y, ssprite,
                    0, 0, ssprite->width, ssprite->height);
 
Index: data/isophex.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isophex.tilespec,v
retrieving revision 1.2
diff -u -r1.2 isophex.tilespec
--- data/isophex.tilespec       24 Oct 2004 23:44:22 -0000      1.2
+++ data/isophex.tilespec       11 Dec 2004 22:14:09 -0000
@@ -19,6 +19,9 @@
 ; Use roadstyle 0 (old iso style)
 roadstyle = 0
 
+; Use fogstyle 0 (old iso style)
+fogstyle = 0
+
 ; Use darkness style 1 (single-sprite)
 darkness_style = 2
  
Index: data/isotrident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/isotrident.tilespec,v
retrieving revision 1.22
diff -u -r1.22 isotrident.tilespec
--- data/isotrident.tilespec    1 Dec 2004 19:21:17 -0000       1.22
+++ data/isotrident.tilespec    11 Dec 2004 22:14:09 -0000
@@ -21,6 +21,9 @@
 ; Use roadstyle 0 (old iso style)
 roadstyle = 0
 
+; Use fogstyle  (old iso style)
+fogstyle = 0
+
 ; Use darkness style 1 (single-sprite)
 darkness_style = 1
  
Index: data/trident.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident.tilespec,v
retrieving revision 1.26
diff -u -r1.26 trident.tilespec
--- data/trident.tilespec       1 Dec 2004 19:21:17 -0000       1.26
+++ data/trident.tilespec       11 Dec 2004 22:14:09 -0000
@@ -21,6 +21,9 @@
 ; Use roadstyle 1 (old non-iso style)
 roadstyle = 1
 
+; Use fogstyle 1 (old non-iso style)
+fogstyle = 0
+
 ; Use darkness style 3 (15 sprites)
 darkness_style = 3
  
Index: data/trident_shields.tilespec
===================================================================
RCS file: /home/freeciv/CVS/freeciv/data/trident_shields.tilespec,v
retrieving revision 1.16
diff -u -r1.16 trident_shields.tilespec
--- data/trident_shields.tilespec       3 Nov 2004 03:34:54 -0000       1.16
+++ data/trident_shields.tilespec       11 Dec 2004 22:14:11 -0000
@@ -25,6 +25,9 @@
 ; Do not blend hills and mountains together.
 is_mountainous = 0
 
+; Use fogstyle 1 (old non-iso style)
+fogstyle = 0
+
 ; Use roadstyle 1 (old non-iso style)
 roadstyle = 1
 
Index: doc/README.graphics
===================================================================
RCS file: /home/freeciv/CVS/freeciv/doc/README.graphics,v
retrieving revision 1.13
diff -u -r1.13 README.graphics
--- doc/README.graphics 1 Dec 2004 19:21:17 -0000       1.13
+++ doc/README.graphics 11 Dec 2004 22:14:11 -0000
@@ -104,6 +104,14 @@
                           2 : One sprite is drawn to show roads in all
                               directions.  There are thus 256 road and 256
                               rail sprites (64 for a hex tileset).
+  fogstyle              : Specifies how fog is drawn.
+                          0 : A single fog sprite is drawn on top of all
+                              other sprites for fogged tiles.  The
+                              tx.fog sprite is used for this.
+                          1 : Each sprite for a fogged tile is drawn fogged.
+                              The tx.fog sprite may be used for the fog
+                              drawing (but clipped by the mask of the
+                              underlying sprite).
   darkness_style        : Specifies how "encroaching darkness" is drawn.
                           0 : No darkness.
                           1 : A single sprite can be split into 4 parts, each

[Prev in Thread] Current Thread [Next in Thread]