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]
Subject: [Freeciv-Dev] Re: (PR#11433) Fog of War rendering improvement
From: "Andreas Røsdal" <andrearo@xxxxxxxxxxxx>
Date: Sun, 12 Dec 2004 04:35:48 -0800
Reply-to: bugs@xxxxxxxxxxx

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

On Sat, 11 Dec 2004, Jason Short wrote:
> It might be possible to get this to work a little more prettily (and
> have things work, or at least not bomb out, on non-truecolor systems) by
> using GdkRGB.

I tried using GdkPixbuf instead of GdkRGB to darken the image. The result
was a little cleaner code with the same performance.

However, darkening with indexed color systems is pretty difficult. It has
to be converted to RGB and back, to darken by dividing by 2. On a
non-truecolor system it would not look much better than the old method.

Andreas
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/graphics.c 
freeciv-fow/client/gui-gtk-2.0/graphics.c
--- freeciv/client/gui-gtk-2.0/graphics.c       2004-11-23 16:44:10.000000000 
+0100
+++ freeciv-fow/client/gui-gtk-2.0/graphics.c   2004-12-12 00:30:01.000000000 
+0100
@@ -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;
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/graphics.h 
freeciv-fow/client/gui-gtk-2.0/graphics.h
--- freeciv/client/gui-gtk-2.0/graphics.h       2004-11-20 09:17:37.000000000 
+0100
+++ freeciv-fow/client/gui-gtk-2.0/graphics.h   2004-12-12 00:30:01.000000000 
+0100
@@ -21,6 +21,7 @@
 struct Sprite
 {
   GdkPixmap *pixmap;
+  GdkPixmap *fogged;
   GdkBitmap *mask;
   int       width;
   int       height;
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/gui_main.c 
freeciv-fow/client/gui-gtk-2.0/gui_main.c
--- freeciv/client/gui-gtk-2.0/gui_main.c       2004-12-07 23:38:59.000000000 
+0100
+++ freeciv-fow/client/gui-gtk-2.0/gui_main.c   2004-12-12 00:30:01.000000000 
+0100
@@ -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);
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/gui_main.h 
freeciv-fow/client/gui-gtk-2.0/gui_main.h
--- freeciv/client/gui-gtk-2.0/gui_main.h       2004-11-23 16:44:10.000000000 
+0100
+++ freeciv-fow/client/gui-gtk-2.0/gui_main.h   2004-12-12 00:30:01.000000000 
+0100
@@ -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;
diff -ruN -Xfreeciv/diff_ignore freeciv/client/gui-gtk-2.0/mapview.c 
freeciv-fow/client/gui-gtk-2.0/mapview.c
--- freeciv/client/gui-gtk-2.0/mapview.c        2004-11-01 04:39:45.000000000 
+0100
+++ freeciv-fow/client/gui-gtk-2.0/mapview.c    2004-12-12 13:15:19.000000000 
+0100
@@ -866,6 +866,38 @@
 }
 
 /**************************************************************************
+  Created a fogged version of the sprite.
+**************************************************************************/
+static void fog_sprite(struct Sprite *sprite)
+{
+  GdkPixbuf *fogged;
+  int x, y;
+  guchar *pixel;
+
+  fogged = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 
+                          sprite->width, sprite->height);
+
+  gdk_pixbuf_get_from_drawable(fogged, sprite->pixmap, NULL, 
+                              0, 0, 0, 0, sprite->width, sprite->height);
+
+  /* Iterate over all pixels, reducing brightness by 50%. */
+  for (y = 0; y < sprite->height; y++) {
+    for (x = 0; x < sprite->width; x++) {
+      pixel = gdk_pixbuf_get_pixels(fogged)
+              + y * gdk_pixbuf_get_rowstride(fogged)
+              + x * gdk_pixbuf_get_n_channels(fogged);
+      pixel[0] = pixel[0] / 2;
+      pixel[1] = pixel[1] / 2;
+      pixel[2] = pixel[2] / 2;
+    }
+  }
+
+  gdk_pixbuf_render_pixmap_and_mask(fogged, &sprite->fogged,
+                                    NULL, 0);
+  g_object_unref(fogged);
+}
+
+/**************************************************************************
 Only used for isometric view.
 **************************************************************************/
 static void pixmap_put_overlay_tile_draw(GdkDrawable *pixmap,
@@ -877,6 +909,25 @@
     return;
   }
 
+  if (fog && better_fog && (gdk_drawable_get_visual(ssprite->pixmap)->type
+      == GDK_VISUAL_TRUE_COLOR)) {
+    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);
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/mapview_common.c 
freeciv-fow/client/mapview_common.c
--- freeciv/client/mapview_common.c     2004-12-12 13:08:54.000000000 +0100
+++ freeciv-fow/client/mapview_common.c 2004-12-12 01:54:54.000000000 +0100
@@ -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);
diff -ruN -Xfreeciv/diff_ignore freeciv/client/tilespec.c 
freeciv-fow/client/tilespec.c
--- freeciv/client/tilespec.c   2004-12-12 00:07:33.000000000 +0100
+++ freeciv-fow/client/tilespec.c       2004-12-12 00:30:01.000000000 +0100
@@ -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++)
@@ -2756,9 +2759,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);
   }
 
diff -ruN -Xfreeciv/diff_ignore freeciv/client/tilespec.h 
freeciv-fow/client/tilespec.h
--- freeciv/client/tilespec.h   2004-12-03 10:39:39.000000000 +0100
+++ freeciv-fow/client/tilespec.h       2004-12-12 00:30:01.000000000 +0100
@@ -266,6 +266,7 @@
 };
 
 extern struct named_sprites sprites;
+extern int fogstyle;
 
 struct Sprite *get_citizen_sprite(struct citizen_type type,
                                  int citizen_index,
diff -ruN -Xfreeciv/diff_ignore freeciv/data/isophex.tilespec 
freeciv-fow/data/isophex.tilespec
--- freeciv/data/isophex.tilespec       2004-10-25 01:44:22.000000000 +0200
+++ freeciv-fow/data/isophex.tilespec   2004-12-12 00:30:01.000000000 +0100
@@ -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

  

diff -ruN -Xfreeciv/diff_ignore freeciv/data/isotrident.tilespec 
freeciv-fow/data/isotrident.tilespec
--- freeciv/data/isotrident.tilespec    2004-12-01 20:21:17.000000000 +0100
+++ freeciv-fow/data/isotrident.tilespec        2004-12-12 00:30:01.000000000 
+0100
@@ -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
  
diff -ruN -Xfreeciv/diff_ignore freeciv/data/trident.tilespec 
freeciv-fow/data/trident.tilespec
--- freeciv/data/trident.tilespec       2004-12-01 20:21:17.000000000 +0100
+++ freeciv-fow/data/trident.tilespec   2004-12-12 00:30:01.000000000 +0100
@@ -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
  
diff -ruN -Xfreeciv/diff_ignore freeciv/data/trident_shields.tilespec 
freeciv-fow/data/trident_shields.tilespec
--- freeciv/data/trident_shields.tilespec       2004-11-03 04:34:54.000000000 
+0100
+++ freeciv-fow/data/trident_shields.tilespec   2004-12-12 00:30:01.000000000 
+0100
@@ -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
 
diff -ruN -Xfreeciv/diff_ignore freeciv/doc/README.graphics 
freeciv-fow/doc/README.graphics
--- freeciv/doc/README.graphics 2004-12-01 20:21:17.000000000 +0100
+++ freeciv-fow/doc/README.graphics     2004-12-12 00:30:01.000000000 +0100
@@ -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]