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

[Freeciv-Dev] (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] (PR#11433) Fog of War rendering improvement
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 10 Dec 2004 19:09:59 -0800
Reply-to: bugs@xxxxxxxxxxx

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

Here is my grand and glorious better-fog patch.  Compare:

  http://bugs.freeciv.org/Ticket/Attachment/78666/53702/old.png
  http://bugs.freeciv.org/Ticket/Attachment/78666/53705/new.png

The patch includes the fogstyle patch (except all fogstyles are changed
to 0 to utilize better-fog).  It makes better-fog into a client option
(gtk2-client only).  The fog is done as I described before: a separate
pixmap is tracked for each foggable sprite that holds the fogged graphics.

On my client with trident this increases memory usage from 35 to 50
megabytes.  In non-iso view the drawing speed is virtually unchanged.  I
didn't test iso-view but I suspect drawing is much faster.

-jason

? core.13161
? diff
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 02:37:27 -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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:28 -0000
@@ -866,6 +866,51 @@
 }
 
 /**************************************************************************
+  Created a fogged version of the sprite.
+**************************************************************************/
+static void fog_sprite(struct Sprite *sprite)
+{
+  int x, y;
+  GdkImage* 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 +922,24 @@
     return;
   }
 
+  if (fog && better_fog) {
+    if (!ssprite->fogged) {
+      fog_sprite(ssprite);
+    }
+
+    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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:28 -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 02:37:29 -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]