summaryrefslogtreecommitdiffstats
path: root/crawl-ref
diff options
context:
space:
mode:
authorEnne Walker <ennewalker@users.sourceforge.net>2010-01-17 19:33:07 -0500
committerEnne Walker <ennewalker@users.sourceforge.net>2010-01-17 19:53:13 -0500
commit227420e531ae481224410978e01c834507cc61d2 (patch)
tree93b0bbe0f909bb20820a61e1836df1bb03736636 /crawl-ref
parentf903462645b80653998fe987732752038be862d4 (diff)
downloadcrawl-ref-227420e531ae481224410978e01c834507cc61d2.tar.gz
crawl-ref-227420e531ae481224410978e01c834507cc61d2.zip
Tile transparency in water without overlays.
In order for jpeg's waves to work on deep water as well as shallow, we need to not use partially transparent overlays to simulate an actor or an item being submerged. Now, non-flying objects on water will be drawn transparently to blend with the water below. This should mostly look the same, except it will now work on top of waves and will not require a mask for each water type. As a nice side-effect, ghosts are now transparent again and the water on top of submerged objects now animates properly. See the comments in tilebuf.cc for details. The mask tile itself can be adjusted to change the water level, but the parameters to SubmergedTileBuffer will need to be changed to compensate depending on what the new art looks like.
Diffstat (limited to 'crawl-ref')
-rw-r--r--crawl-ref/source/rltiles/dc-misc.txt3
-rw-r--r--crawl-ref/source/rltiles/dc-misc/mask_submerged.pngbin0 -> 593 bytes
-rw-r--r--crawl-ref/source/rltiles/dc-player.txt5
-rw-r--r--crawl-ref/source/tilebuf.cc378
-rw-r--r--crawl-ref/source/tilebuf.h89
-rw-r--r--crawl-ref/source/tilemcache.cc7
-rw-r--r--crawl-ref/source/tilemcache.h2
-rw-r--r--crawl-ref/source/tilepick.cc4
-rw-r--r--crawl-ref/source/tilereg.cc97
-rw-r--r--crawl-ref/source/tilereg.h13
-rw-r--r--crawl-ref/source/tiles.h1
-rw-r--r--crawl-ref/source/tilesdl.cc55
-rw-r--r--crawl-ref/source/tilesdl.h25
-rw-r--r--crawl-ref/source/tiletex.h41
14 files changed, 533 insertions, 187 deletions
diff --git a/crawl-ref/source/rltiles/dc-misc.txt b/crawl-ref/source/rltiles/dc-misc.txt
index 8050483dcd..120c455fc1 100644
--- a/crawl-ref/source/rltiles/dc-misc.txt
+++ b/crawl-ref/source/rltiles/dc-misc.txt
@@ -65,6 +65,9 @@ mask_shallow_water_murky MASK_SHALLOW_WATER_MURKY
mask_deep_water_shoals MASK_DEEP_WATER_SHOALS
mask_shallow_water_shoals MASK_SHALLOW_WATER_SHOALS
mask_lava MASK_LAVA
+%shrink 0
+mask_submerged MASK_SUBMERGED
+%shrink 1
cursor CURSOR
cursor_red CURSOR2
cursor_green CURSOR3
diff --git a/crawl-ref/source/rltiles/dc-misc/mask_submerged.png b/crawl-ref/source/rltiles/dc-misc/mask_submerged.png
new file mode 100644
index 0000000000..4ccb0aa8ae
--- /dev/null
+++ b/crawl-ref/source/rltiles/dc-misc/mask_submerged.png
Binary files differ
diff --git a/crawl-ref/source/rltiles/dc-player.txt b/crawl-ref/source/rltiles/dc-player.txt
index a85491abe8..dba7424fbb 100644
--- a/crawl-ref/source/rltiles/dc-player.txt
+++ b/crawl-ref/source/rltiles/dc-player.txt
@@ -7,8 +7,11 @@
effect/net_trap TRAP_NET
dc-misc/cursor CURSOR
-
+%rim 0
+%shrink 0
+dc-misc/mask_submerged MASK_SUBMERGED
%rim 1
+%shrink 1
###BASE
%parts_ctg BASE
diff --git a/crawl-ref/source/tilebuf.cc b/crawl-ref/source/tilebuf.cc
index 1c9cbf2763..edaa3a4596 100644
--- a/crawl-ref/source/tilebuf.cc
+++ b/crawl-ref/source/tilebuf.cc
@@ -11,12 +11,87 @@
#include "tilebuf.h"
#include "tilefont.h"
-#include "tilesdl.h"
#include <SDL.h>
#include <SDL_opengl.h>
/////////////////////////////////////////////////////////////////////////////
+// GLState
+
+// Note: these defaults should match the OpenGL defaults
+GLState::GLState() :
+ array_vertex(false),
+ array_texcoord(false),
+ array_colour(false),
+ blend(false),
+ texture(false),
+ depthtest(false),
+ alphatest(false),
+ alpharef(0)
+{
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// GLStateManager
+
+void GLStateManager::init()
+{
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glClearColor(0.0, 0.0, 0.0, 1.0f);
+ glDepthFunc(GL_LEQUAL);
+}
+
+void GLStateManager::set(const GLState& state)
+{
+ if (state.array_vertex)
+ glEnableClientState(GL_VERTEX_ARRAY);
+ else
+ glDisableClientState(GL_VERTEX_ARRAY);
+
+ if (state.array_texcoord)
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ else
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+ if (state.array_colour)
+ {
+ glEnableClientState(GL_COLOR_ARRAY);
+ }
+ else
+ {
+ glDisableClientState(GL_COLOR_ARRAY);
+
+ // [enne] This should *not* be necessary, but the Linux OpenGL
+ // driver that I'm using sets this to the last colour of the
+ // colour array. So, we need to unset it here.
+ glColor3f(1.0f, 1.0f, 1.0f);
+ }
+
+ if (state.texture)
+ glEnable(GL_TEXTURE_2D);
+ else
+ glDisable(GL_TEXTURE_2D);
+
+ if (state.blend)
+ glEnable(GL_BLEND);
+ else
+ glDisable(GL_BLEND);
+
+ if (state.depthtest)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+
+ if (state.alphatest)
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_NOTEQUAL, state.alpharef);
+ }
+ else
+ glDisable(GL_ALPHA_TEST);
+}
+
+/////////////////////////////////////////////////////////////////////////////
// VColour
VColour VColour::white(255, 255, 255, 255);
@@ -46,6 +121,15 @@ static bool _valid(int num_verts, int prim)
#endif
template<>
+void VertBuffer<PTVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.blend = true;
+ m_state.texture = true;
+}
+
+template<>
void VertBuffer<PTVert>::draw() const
{
if (size() == 0)
@@ -54,12 +138,7 @@ void VertBuffer<PTVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_texcoord = true;
- state.blend = true;
- state.texture = true;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
m_tex->bind();
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
@@ -68,6 +147,15 @@ void VertBuffer<PTVert>::draw() const
}
template<>
+void VertBuffer<PCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = false;
+}
+
+template<>
void VertBuffer<PCVert>::draw() const
{
if (size() == 0)
@@ -76,12 +164,7 @@ void VertBuffer<PCVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(!m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_colour = true;
- state.blend = true;
- state.texture = false;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vert), &(*this)[0].col);
@@ -89,6 +172,16 @@ void VertBuffer<PCVert>::draw() const
}
template<>
+void VertBuffer<PTCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = true;
+}
+
+template<>
void VertBuffer<PTCVert>::draw() const
{
if (size() == 0)
@@ -97,13 +190,7 @@ void VertBuffer<PTCVert>::draw() const
ASSERT(_valid(size(), m_prim));
ASSERT(m_tex);
- GLState state;
- state.array_vertex = true;
- state.array_texcoord = true;
- state.array_colour = true;
- state.blend = true;
- state.texture = true;
- GLStateManager::set(state);
+ GLStateManager::set(m_state);
m_tex->bind();
glVertexPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
@@ -112,6 +199,37 @@ void VertBuffer<PTCVert>::draw() const
glDrawArrays(m_prim, 0, size());
}
+template<>
+void VertBuffer<P3TCVert>::init_state()
+{
+ m_state.array_vertex = true;
+ m_state.array_texcoord = true;
+ m_state.array_colour = true;
+ m_state.blend = true;
+ m_state.texture = true;
+ m_state.depthtest = true;
+ m_state.alphatest = true;
+ m_state.alpharef = 0;
+}
+
+template<>
+void VertBuffer<P3TCVert>::draw() const
+{
+ if (size() == 0)
+ return;
+
+ ASSERT(_valid(size(), m_prim));
+ ASSERT(m_tex);
+
+ GLStateManager::set(m_state);
+
+ m_tex->bind();
+ glVertexPointer(3, GL_FLOAT, sizeof(Vert), &(*this)[0].pos_x);
+ glTexCoordPointer(2, GL_FLOAT, sizeof(Vert), &(*this)[0].tex_x);
+ glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(Vert), &(*this)[0].col);
+ glDrawArrays(m_prim, 0, size());
+}
+
/////////////////////////////////////////////////////////////////////////////
// FontBuffer
@@ -143,23 +261,17 @@ TileBuffer::TileBuffer(const TilesTexture *t) : VertBuffer<PTVert>(t, GL_QUADS)
void TileBuffer::add_unscaled(int idx, float x, float y, int ymax)
{
- const tile_info &inf = ((TilesTexture*)m_tex)->get_info(idx);
-
- float pos_sx = x + inf.offset_x;
- float pos_sy = y + inf.offset_y;
- float pos_ex = pos_sx + (inf.ex - inf.sx);
- int ey = inf.ey;
- if (ymax > 0)
- ey = std::min(inf.sy + ymax - inf.offset_y, ey);
- float pos_ey = pos_sy + (ey - inf.sy);
-
- float fwidth = m_tex->width();
- float fheight = m_tex->height();
+ float pos_sx = x;
+ float pos_sy = y;
+ float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
+ TilesTexture *tex = (TilesTexture *)m_tex;
+ bool drawn = tex->get_coords(idx, 0, 0,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ true, -1, ymax, 1.0f, 1.0f);
- float tex_sx = inf.sx / fwidth;
- float tex_sy = inf.sy / fheight;
- float tex_ex = inf.ex / fwidth;
- float tex_ey = inf.ey / fheight;
+ if (!drawn)
+ return;
size_t last = std::vector<Vert>::size();
std::vector<Vert>::resize(last + 4);
@@ -202,8 +314,13 @@ void TileBuffer::add(int idx, int x, int y, int ox, int oy, bool centre, int yma
float pos_sy = y;
float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
TilesTexture *tex = (TilesTexture *)m_tex;
- tex->get_coords(idx, ox, oy, pos_sx, pos_sy, pos_ex, pos_ey,
- tex_sx, tex_sy, tex_ex, tex_ey, centre, ymax);
+ bool drawn = tex->get_coords(idx, ox, oy,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ centre, -1, ymax, TILE_X, TILE_Y);
+
+ if (!drawn)
+ return;
size_t last = std::vector<Vert>::size();
std::vector<Vert>::resize(last + 4);
@@ -248,6 +365,191 @@ void TileBuffer::set_tex(const TilesTexture *new_tex)
}
/////////////////////////////////////////////////////////////////////////////
+// ColouredTileBuffer
+
+ColouredTileBuffer::ColouredTileBuffer(const TilesTexture *t) :
+ VertBuffer<P3TCVert>(t, GL_QUADS)
+{
+}
+
+static unsigned char _get_alpha(float lerp, int alpha_top, int alpha_bottom)
+{
+ if (lerp < 0.0f)
+ lerp = 0.0f;
+ if (lerp > 1.0f)
+ lerp = 1.0f;
+
+ int ret = alpha_top * (1.0f - lerp) + alpha_bottom * lerp;
+
+ ret = std::min(std::max(0, ret), 255);
+ return (static_cast<unsigned char>(ret));
+}
+
+void ColouredTileBuffer::add(int idx, int x, int y, int z,
+ int ox, int oy, int ymin, int ymax,
+ int alpha_top, int alpha_bottom)
+{
+ float pos_sx = x;
+ float pos_sy = y;
+ float pos_ex, pos_ey, tex_sx, tex_sy, tex_ex, tex_ey;
+ TilesTexture *tex = (TilesTexture *)m_tex;
+ bool drawn = tex->get_coords(idx, ox, oy,
+ pos_sx, pos_sy, pos_ex, pos_ey,
+ tex_sx, tex_sy, tex_ex, tex_ey,
+ true, -1, ymax);
+
+ if (!drawn)
+ return;
+
+ float lerp_s = (pos_sy - y);
+ float lerp_e = (pos_ey - y);
+
+ // Need to calculate the alpha at the top and bottom. As the quad
+ // being drawn may not actually start on the grid boundary, we need
+ // to figure out what alpha value its vertices should use.
+ unsigned char alpha_s = _get_alpha(lerp_s, alpha_top, alpha_bottom);
+ unsigned char alpha_e = _get_alpha(lerp_e, alpha_top, alpha_bottom);
+
+ VColour col_sy(255, 255, 255, alpha_s);
+ VColour col_ey(255, 255, 255, alpha_e);
+
+ float pos_z = (float)z;
+
+ size_t last = std::vector<Vert>::size();
+ std::vector<Vert>::resize(last + 4);
+ {
+ Vert &v = (*this)[last];
+ v.pos_x = pos_sx;
+ v.pos_y = pos_sy;
+ v.pos_z = pos_z;
+ v.tex_x = tex_sx;
+ v.tex_y = tex_sy;
+ v.col = col_sy;
+ }
+
+ {
+ Vert &v = (*this)[last + 1];
+ v.pos_x = pos_sx;
+ v.pos_y = pos_ey;
+ v.pos_z = pos_z;
+ v.tex_x = tex_sx;
+ v.tex_y = tex_ey;
+ v.col = col_ey;
+ }
+
+ {
+ Vert &v = (*this)[last + 2];
+ v.pos_x = pos_ex;
+ v.pos_y = pos_ey;
+ v.pos_z = pos_z;
+ v.tex_x = tex_ex;
+ v.tex_y = tex_ey;
+ v.col = col_ey;
+ }
+
+ {
+ Vert &v = (*this)[last + 3];
+ v.pos_x = pos_ex;
+ v.pos_y = pos_sy;
+ v.pos_z = pos_z;
+ v.tex_x = tex_ex;
+ v.tex_y = tex_sy;
+ v.col = col_sy;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// SubmergedTileBuffer
+
+
+SubmergedTileBuffer::SubmergedTileBuffer(const TilesTexture *tex,
+ int mask_idx, int above_max,
+ int below_min) :
+ m_mask_idx(mask_idx),
+ m_above_max(above_max),
+ m_below_min(below_min),
+ m_max_z(-1000),
+ m_below_water(tex),
+ m_mask(tex),
+ m_above_water(tex)
+{
+ // Adjust the state of the mask buffer so that we can use it to mask out
+ // the bottom half of the tile when drawing the character a second time.
+ // See the draw() function for more details.
+ GLState &state = m_mask.state();
+ state.blend = true;
+ state.depthtest = true;
+ state.alphatest = true;
+ state.alpharef = 255;
+}
+
+void SubmergedTileBuffer::add(int idx, int x, int y, int z, bool submerged,
+ bool ghost, int ox, int oy, int ymax)
+{
+ // Keep track of the maximum z. We'll use this for drawing the mask
+ // later, to ensure it is closer than all other tiles drawn.
+ m_max_z = std::max(m_max_z, z);
+
+ // Arbitrary alpha values for the top and bottom.
+ int alpha_top = ghost ? 100 : 255;
+ int alpha_bottom = ghost ? 0 : 40;
+
+ if (submerged)
+ {
+ m_below_water.add(idx, x, y, z, ox, oy, m_below_min, ymax,
+ alpha_top, alpha_bottom);
+
+ m_mask.add(m_mask_idx, x, y, 0, 0, 0, -1, -1, 255, 255);
+ int above_max = (ymax == -1) ? m_above_max
+ : std::min(ymax, m_above_max);
+ m_above_water.add(idx, x, y, z, ox, oy, -1, above_max,
+ alpha_top, alpha_top);
+ }
+ else
+ {
+ // Unsubmerged tiles don't need a mask.
+ m_above_water.add(idx, x, y, z, ox, oy, -1, ymax, alpha_top, alpha_top);
+ }
+}
+
+void SubmergedTileBuffer::draw() const
+{
+ // First, draw anything below water. Alpha blending is turned on,
+ // so these tiles will blend with anything previously drawn.
+ m_below_water.draw();
+
+ // Second, draw all of the mask tiles. The mask is white (255,255,255,255)
+ // above water and transparent (0,0,0,0) below water.
+ //
+ // Alpha testing is turned on with a ref value of 255, so none of the
+ // white pixels will be drawn because they will culled by alpha testing.
+ // The transparent pixels below water will be "drawn", but because they
+ // are fully transparent, they will not affect any colours on screen.
+ // Instead, they will will set the z-buffer to a z-value (depth) that is
+ // greater than the closest depth in either the below or above buffers.
+ // Because all of the above water tiles are at lower z-values than this
+ // maximum, they will not draw over these transparent pixels, effectively
+ // masking them out. (My kingdom for a shader.)
+
+ glPushMatrix();
+ glTranslatef(0, 0, m_max_z + 1);
+ m_mask.draw();
+ glPopMatrix();
+
+ // Now, draw all the above water tiles. Some of these may draw over top
+ // of part of the below water tiles, but that's fine as the mask will
+ // take care of only drawing the correct parts.
+ m_above_water.draw();
+}
+
+void SubmergedTileBuffer::clear()
+{
+ m_below_water.clear();
+ m_mask.clear();
+ m_above_water.clear();
+}
+
+/////////////////////////////////////////////////////////////////////////////
// ShapeBuffer
// [enne] - GL_POINTS should probably be used here, but there's (apparently)
diff --git a/crawl-ref/source/tilebuf.h b/crawl-ref/source/tilebuf.h
index c13e9cec91..ee315a6eca 100644
--- a/crawl-ref/source/tilebuf.h
+++ b/crawl-ref/source/tilebuf.h
@@ -8,6 +8,34 @@
#include "tiles.h"
+// This struct defines all of the state that any particular rendering needs.
+// If other rendering states are needed, they should be added here so that
+// they do not introduce unneeded side effects for other parts of the code
+// that have not thought about turning that new state off.
+struct GLState
+{
+ GLState();
+
+ // vertex arrays
+ bool array_vertex;
+ bool array_texcoord;
+ bool array_colour;
+
+ // render state
+ bool blend;
+ bool texture;
+ bool depthtest;
+ bool alphatest;
+ unsigned char alpharef;
+};
+
+class GLStateManager
+{
+public:
+ static void init();
+ static void set(const GLState& state);
+};
+
class FTFont;
class formatted_string;
class GenericTexture;
@@ -41,6 +69,16 @@ struct PTCVert
VColour col;
};
+struct P3TCVert
+{
+ float pos_x;
+ float pos_y;
+ float pos_z;
+ float tex_x;
+ float tex_y;
+ VColour col;
+};
+
struct PTVert
{
float pos_x;
@@ -70,9 +108,14 @@ public:
V& get_next();
void draw() const;
+ GLState &state() { return m_state; }
+
protected:
+ void init_state();
+
const GenericTexture *m_tex;
int m_prim;
+ GLState m_state;
};
class FontBuffer : public VertBuffer<PTCVert>
@@ -99,6 +142,51 @@ public:
void set_tex(const TilesTexture *tex);
};
+class ColouredTileBuffer : public VertBuffer<P3TCVert>
+{
+public:
+ ColouredTileBuffer(const TilesTexture *tex = NULL);
+
+ void add(int idx, int x, int y, int z,
+ int ox, int oy, int ymin, int ymax,
+ int alpha_top, int alpha_bottom);
+};
+
+// Helper class for tiles submerged in water.
+class SubmergedTileBuffer
+{
+public:
+ // mask_idx is the tile index in tex of the mask texture
+ // It should be opaque white for water and fully transparent above.
+ //
+ // above_max is the maximum height (from the top of the tile) where
+ // there are still pixels above water.
+ //
+ // below_min is the minimum height (from the top of the tile) where
+ // there are still pixels below water.
+ //
+ // All heights are from 0 (top of the tile) to TILE_Y-1 (bottom of the tile)
+ SubmergedTileBuffer(const TilesTexture *tex,
+ int mask_idx, int above_max, int below_min);
+
+ void add(int idx, int x, int y, int z = 0, bool submerged = false,
+ bool ghost = false, int ox = 0, int oy = 0, int ymax = -1);
+
+ void draw() const;
+ void clear();
+
+protected:
+ int m_mask_idx;
+ int m_above_max;
+ int m_below_min;
+
+ int m_max_z;
+
+ ColouredTileBuffer m_below_water;
+ ColouredTileBuffer m_mask;
+ ColouredTileBuffer m_above_water;
+};
+
class ShapeBuffer : public VertBuffer<PCVert>
{
public:
@@ -121,6 +209,7 @@ template<class V>
inline VertBuffer<V>::VertBuffer(const GenericTexture *tex, int prim) :
m_tex(tex), m_prim(prim)
{
+ init_state();
}
template<class V>
diff --git a/crawl-ref/source/tilemcache.cc b/crawl-ref/source/tilemcache.cc
index 12b4859fcc..8cf4058a91 100644
--- a/crawl-ref/source/tilemcache.cc
+++ b/crawl-ref/source/tilemcache.cc
@@ -104,6 +104,8 @@ public:
virtual void construct(writer &th);
+ virtual bool transparent() const;
+
protected:
dolls_data m_doll;
};
@@ -818,6 +820,11 @@ void mcache_ghost::construct(writer &th)
marshallDoll(th, m_doll);
}
+bool mcache_ghost::transparent() const
+{
+ return (true);
+}
+
/////////////////////////////////////////////////////////////////////////////
// mcache_demon
diff --git a/crawl-ref/source/tilemcache.h b/crawl-ref/source/tilemcache.h
index fef7bd6d77..67ff52f9c1 100644
--- a/crawl-ref/source/tilemcache.h
+++ b/crawl-ref/source/tilemcache.h
@@ -47,6 +47,8 @@ public:
virtual void construct(writer &th);
+ virtual bool transparent() const { return false; }
+
protected:
mcache_entry(reader &th);
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index b1d2024e1d..94d4cb9641 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -5087,6 +5087,10 @@ void tile_finish_dngn(unsigned int *tileb, int cx, int cy)
}
}
+ dungeon_feature_type feat = grd(gc);
+ if (feat_is_water(feat) || feat == DNGN_LAVA)
+ tileb[count+1] |= TILE_FLAG_WATER;
+
if (print_blood && is_bloodcovered(gc))
tileb[count+1] |= TILE_FLAG_BLOOD;
diff --git a/crawl-ref/source/tilereg.cc b/crawl-ref/source/tilereg.cc
index 8886b5d737..682a4b717e 100644
--- a/crawl-ref/source/tilereg.cc
+++ b/crawl-ref/source/tilereg.cc
@@ -249,7 +249,8 @@ DungeonRegion::DungeonRegion(ImageManager* im, FTFont *tag_font,
m_cx_to_gx(0),
m_cy_to_gy(0),
m_buf_dngn(&im->m_textures[TEX_DUNGEON]),
- m_buf_doll(&im->m_textures[TEX_PLAYER]),
+ m_buf_doll(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16),
+ m_buf_main_trans(&im->m_textures[TEX_DEFAULT], TILE_MASK_SUBMERGED, 18, 16),
m_buf_main(&im->m_textures[TEX_DEFAULT])
{
for (int i = 0; i < CURSOR_MAX; i++)
@@ -805,14 +806,14 @@ void save_doll_file(FILE *dollf)
fprintf(dollf, "net\n");
}
-void DungeonRegion::pack_player(int x, int y)
+void DungeonRegion::pack_player(int x, int y, bool submerged)
{
dolls_data result = player_doll;
_fill_doll_equipment(result);
- pack_doll(result, x, y);
+ pack_doll(result, x, y, submerged, false);
}
-void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
+void pack_doll_buf(SubmergedTileBuffer& buf, const dolls_data &doll, int x, int y, bool submerged, bool ghost)
{
int p_order[TILEP_PART_MAX] =
{
@@ -865,13 +866,22 @@ void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
flags[TILEP_PART_BOOTS] = is_cent ? TILEP_FLAG_NORMAL : TILEP_FLAG_HIDE;
}
- for (int i = 0; i < TILEP_PART_MAX; i++)
+ // A higher index here means that the part should be drawn on top.
+ // This is drawn in reverse order because this could be a ghost
+ // or being drawn in water, in which case we want the top-most part
+ // to blend with the background underneath and not with the parts
+ // underneath. Parts drawn afterwards will not obscure parts drawn
+ // previously, because "i" is passed as the depth below.
+ for (int i = TILEP_PART_MAX - 1; i >= 0; --i)
{
int p = p_order[i];
if (!doll.parts[p] || flags[p] == TILEP_FLAG_HIDE)
continue;
+ if (p == TILEP_PART_SHADOW && (submerged || ghost))
+ continue;
+
int ymax = TILE_Y;
if (flags[p] == TILEP_FLAG_CUT_CENTAUR
@@ -880,68 +890,51 @@ void pack_doll_buf(TileBuffer& buf, const dolls_data &doll, int x, int y)
ymax = 18;
}
- buf.add(doll.parts[p], x, y, 0, 0, true, ymax);
+ buf.add(doll.parts[p], x, y, i, submerged, ghost, 0, 0, ymax);
}
}
-void DungeonRegion::pack_doll(const dolls_data &doll, int x, int y)
+void DungeonRegion::pack_doll(const dolls_data &doll, int x, int y, bool submerged, bool ghost)
{
- pack_doll_buf(m_buf_doll, doll, x, y);
+ pack_doll_buf(m_buf_doll, doll, x, y, submerged, ghost);
}
-void DungeonRegion::pack_mcache(mcache_entry *entry, int x, int y)
+void DungeonRegion::pack_mcache(mcache_entry *entry, int x, int y, bool submerged)
{
ASSERT(entry);
+ bool trans = entry->transparent();
+
const dolls_data *doll = entry->doll();
if (doll)
- pack_doll(*doll, x, y);
+ pack_doll(*doll, x, y, submerged, trans);
tile_draw_info dinfo[3];
unsigned int draw_info_count = entry->info(&dinfo[0]);
ASSERT(draw_info_count <= sizeof(dinfo) / (sizeof(dinfo[0])));
for (unsigned int i = 0; i < draw_info_count; i++)
- m_buf_doll.add(dinfo[i].idx, x, y, dinfo[i].ofs_x, dinfo[i].ofs_y);
+ {
+ m_buf_doll.add(dinfo[i].idx, x, y, 0, submerged, trans,
+ dinfo[i].ofs_x, dinfo[i].ofs_y);
+ }
}
void DungeonRegion::pack_foreground(unsigned int bg, unsigned int fg, int x, int y)
{
unsigned int fg_idx = fg & TILE_FLAG_MASK;
- unsigned int bg_idx = bg & TILE_FLAG_MASK;
if (fg_idx && fg_idx <= TILE_MAIN_MAX)
- m_buf_main.add(fg_idx, x, y);
-
- if (fg_idx && !(fg & TILE_FLAG_FLYING))
{
- if (tile_dngn_equal(TILE_DNGN_LAVA, bg_idx))
- m_buf_main.add(TILE_MASK_LAVA, x, y);
- else if (tile_dngn_equal(TILE_DNGN_SHALLOW_WATER, bg_idx)
- || tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_DISTURBANCE,
- bg_idx))
- {
- m_buf_main.add(TILE_MASK_SHALLOW_WATER, x, y);
- }
- else if (tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_MURKY, bg_idx)
- || tile_dngn_equal(TILE_DNGN_SHALLOW_WATER_MURKY_DISTURBANCE,
- bg_idx))
- {
- m_buf_main.add(TILE_MASK_SHALLOW_WATER_MURKY, x, y);
- }
- else if (tile_dngn_equal(TILE_DNGN_DEEP_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER, x, y);
- else if (tile_dngn_equal(TILE_DNGN_DEEP_WATER_MURKY, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER_MURKY, x, y);
- else if (tile_dngn_equal(TILE_SHOALS_DEEP_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_DEEP_WATER_SHOALS, x, y);
- else if (tile_dngn_equal(TILE_SHOALS_SHALLOW_WATER, bg_idx))
- m_buf_main.add(TILE_MASK_SHALLOW_WATER_SHOALS, x, y);
+ if (bg & TILE_FLAG_WATER && !(fg & TILE_FLAG_FLYING))
+ m_buf_main_trans.add(fg_idx, x, y, 0, true, false);
+ else
+ m_buf_main.add(fg_idx, x, y);
}
if (fg & TILE_FLAG_NET)
- m_buf_doll.add(TILEP_TRAP_NET, x, y);
+ m_buf_doll.add(TILEP_TRAP_NET, x, y, 0, bg & TILE_FLAG_WATER, false);
if (fg & TILE_FLAG_S_UNDER)
m_buf_main.add(TILE_SOMETHING_UNDER, x, y);
@@ -1058,6 +1051,7 @@ void DungeonRegion::pack_buffers()
{
m_buf_dngn.clear();
m_buf_doll.clear();
+ m_buf_main_trans.clear();
m_buf_main.clear();
if (m_tileb.empty())
@@ -1077,17 +1071,20 @@ void DungeonRegion::pack_buffers()
{
mcache_entry *entry = mcache.get(fg_idx);
if (entry)
- pack_mcache(entry, x, y);
+ pack_mcache(entry, x, y, bg & TILE_FLAG_WATER);
else
- m_buf_doll.add(TILEP_MONS_UNKNOWN, x, y);
+ {
+ m_buf_doll.add(TILEP_MONS_UNKNOWN, x, y, 0,
+ bg & TILE_FLAG_WATER, false);
+ }
}
else if (fg_idx == TILEP_PLAYER)
{
- pack_player(x, y);
+ pack_player(x, y, bg & TILE_FLAG_WATER);
}
else if (fg_idx >= TILE_MAIN_MAX)
{
- m_buf_doll.add(fg_idx, x, y);
+ m_buf_doll.add(fg_idx, x, y, 0, bg & TILE_FLAG_WATER, false);
}
pack_foreground(bg, fg, x, y);
@@ -1146,6 +1143,7 @@ void DungeonRegion::render()
set_transform();
m_buf_dngn.draw();
m_buf_doll.draw();
+ m_buf_main_trans.draw();
m_buf_main.draw();
if (you.berserk())
@@ -4029,7 +4027,9 @@ void TitleRegion::run()
}
DollEditRegion::DollEditRegion(ImageManager *im, FTFont *font) :
- m_font_buf(font)
+ m_font_buf(font),
+ m_tile_buf(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16),
+ m_cur_buf(&im->m_textures[TEX_PLAYER], TILEP_MASK_SUBMERGED, 18, 16)
{
sx = sy = 0;
dx = dy = 32;
@@ -4040,9 +4040,6 @@ DollEditRegion::DollEditRegion(ImageManager *im, FTFont *font) :
m_doll_idx = 0;
m_cat_idx = TILEP_PART_BASE;
m_copy_valid = false;
-
- m_tile_buf.set_tex(&im->m_textures[TEX_PLAYER]);
- m_cur_buf.set_tex(&im->m_textures[TEX_PLAYER]);
}
void DollEditRegion::clear()
@@ -4188,7 +4185,7 @@ void DollEditRegion::render()
{
dolls_data temp = m_dolls[m_doll_idx];
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 0, 0);
+ pack_doll_buf(m_cur_buf, temp, 0, 0, false, false);
}
// Draw set of dolls.
@@ -4202,7 +4199,7 @@ void DollEditRegion::render()
dolls_data temp = m_dolls[i];
_fill_doll_equipment(temp);
- pack_doll_buf(m_tile_buf, temp, x, y);
+ pack_doll_buf(m_tile_buf, temp, x, y, false, false);
m_shape_buf.add(x, y, x + 1, y + 1, grey);
}
@@ -4261,12 +4258,12 @@ void DollEditRegion::render()
dolls_data temp;
temp = m_job_default;
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 2, 0);
+ pack_doll_buf(m_cur_buf, temp, 2, 0, false, false);
for (unsigned int i = 0; i < TILEP_PART_MAX; ++i)
temp.parts[i] = TILEP_SHOW_EQUIP;
_fill_doll_equipment(temp);
- pack_doll_buf(m_cur_buf, temp, 4, 0);
+ pack_doll_buf(m_cur_buf, temp, 4, 0, false, false);
if (m_mode == TILEP_MODE_LOADING)
m_cur_buf.add(TILEP_CURSOR, 0, 0);
diff --git a/crawl-ref/source/tilereg.h b/crawl-ref/source/tilereg.h
index 74fbb18f60..a3584cac8a 100644
--- a/crawl-ref/source/tilereg.h
+++ b/crawl-ref/source/tilereg.h
@@ -276,10 +276,10 @@ public:
protected:
void pack_background(unsigned int bg, int x, int y);
- void pack_mcache(mcache_entry *entry, int x, int y);
- void pack_player(int x, int y);
+ void pack_mcache(mcache_entry *entry, int x, int y, bool submerged);
+ void pack_player(int x, int y, bool submerged);
void pack_foreground(unsigned int bg, unsigned int fg, int x, int y);
- void pack_doll(const dolls_data &doll, int x, int y);
+ void pack_doll(const dolls_data &doll, int x, int y, bool submerged, bool ghost);
void pack_cursor(cursor_type type, unsigned int tile);
void pack_buffers();
@@ -293,7 +293,8 @@ protected:
std::vector<TextTag> m_tags[TAG_MAX];
TileBuffer m_buf_dngn;
- TileBuffer m_buf_doll;
+ SubmergedTileBuffer m_buf_doll;
+ SubmergedTileBuffer m_buf_main_trans;
TileBuffer m_buf_main;
struct tile_overlay
@@ -489,8 +490,8 @@ protected:
ShapeBuffer m_shape_buf;
FontBuffer m_font_buf;
- TileBuffer m_tile_buf;
- TileBuffer m_cur_buf;
+ SubmergedTileBuffer m_tile_buf;
+ SubmergedTileBuffer m_cur_buf;
};
#endif
diff --git a/crawl-ref/source/tiles.h b/crawl-ref/source/tiles.h
index d50482a673..be49c3f12e 100644
--- a/crawl-ref/source/tiles.h
+++ b/crawl-ref/source/tiles.h
@@ -170,6 +170,7 @@ enum tile_flags
TILE_FLAG_TUT_CURSOR = 0x00800000,
TILE_FLAG_RAY_OOR = 0x01000000,
TILE_FLAG_OOR = 0x02000000,
+ TILE_FLAG_WATER = 0x04000000,
// General
TILE_FLAG_MASK = 0x000007FF
diff --git a/crawl-ref/source/tilesdl.cc b/crawl-ref/source/tilesdl.cc
index ff6af904ab..5210eedf81 100644
--- a/crawl-ref/source/tilesdl.cc
+++ b/crawl-ref/source/tilesdl.cc
@@ -49,59 +49,6 @@ static int _screen_sizes[4][8] =
{800, 480, 3, 13, 12, 10, 13, 11}
};
-// Note: these defaults should match the OpenGL defaults
-GLState::GLState() :
- array_vertex(false),
- array_texcoord(false),
- array_colour(false),
- blend(false),
- texture(false)
-{
-}
-
-void GLStateManager::init()
-{
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glClearColor(0.0, 0.0, 0.0, 1.0f);
-}
-
-void GLStateManager::set(const GLState& state)
-{
- if (state.array_vertex)
- glEnableClientState(GL_VERTEX_ARRAY);
- else
- glDisableClientState(GL_VERTEX_ARRAY);
-
- if (state.array_texcoord)
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- else
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- if (state.array_colour)
- {
- glEnableClientState(GL_COLOR_ARRAY);
- }
- else
- {
- glDisableClientState(GL_COLOR_ARRAY);
-
- // [enne] This should *not* be necessary, but the Linux OpenGL
- // driver that I'm using sets this to the last colour of the
- // colour array. So, we need to unset it here.
- glColor3f(1.0f, 1.0f, 1.0f);
- }
-
- if (state.texture)
- glEnable(GL_TEXTURE_2D);
- else
- glDisable(GL_TEXTURE_2D);
-
- if (state.blend)
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
-}
-
TilesFramework tiles;
TilesFramework::TilesFramework() :
@@ -486,7 +433,7 @@ void TilesFramework::resize()
glLoadIdentity();
// For ease, vertex positions are pixel positions.
- glOrtho(0, m_windowsz.x, m_windowsz.y, 0, 0, 100);
+ glOrtho(0, m_windowsz.x, m_windowsz.y, 0, -1000, 1000);
}
static unsigned char _get_modifiers(SDL_keysym &keysym)
diff --git a/crawl-ref/source/tilesdl.h b/crawl-ref/source/tilesdl.h
index 993de5c302..8e0812e35a 100644
--- a/crawl-ref/source/tilesdl.h
+++ b/crawl-ref/source/tilesdl.h
@@ -11,24 +11,6 @@
#include "externs.h"
#include "tilereg.h"
-// This struct defines all of the state that any particular rendering needs.
-// If other rendering states are needed, they should be added here so that
-// they do not introduce unneeded side effects for other parts of the code
-// that have not thought about turning that new state off.
-struct GLState
-{
- GLState();
-
- // vertex arrays
- bool array_vertex;
- bool array_texcoord;
- bool array_colour;
-
- // render state
- bool blend;
- bool texture;
-};
-
enum key_mod
{
MOD_SHIFT = 0x1,
@@ -68,13 +50,6 @@ struct MouseEvent
unsigned int py;
};
-class GLStateManager
-{
-public:
- static void init();
- static void set(const GLState& state);
-};
-
class SDL_Surface;
class FTFont;
diff --git a/crawl-ref/source/tiletex.h b/crawl-ref/source/tiletex.h
index a50b85dc26..c95067a3fe 100644
--- a/crawl-ref/source/tiletex.h
+++ b/crawl-ref/source/tiletex.h
@@ -76,12 +76,13 @@ public:
void set_info(int max, tile_info_func *info);
inline const tile_info &get_info(int idx) const;
- inline void get_coords(int idx, int ofs_x, int ofs_y,
+ inline bool get_coords(int idx, int ofs_x, int ofs_y,
float &pos_sx, float &pos_sy,
float &pos_ex, float &pos_ey,
float &tex_sx, float &tex_sy,
float &tex_ex, float &tex_ey,
- bool centre = true, int ymax = -1) const;
+ bool centre = true, int ymin = -1, int ymax = -1,
+ float tile_x = TILE_X, float tile_y = TILE_Y) const;
protected:
int m_tile_max;
@@ -94,12 +95,13 @@ inline const tile_info &TilesTexture::get_info(int idx) const
return m_info_func(idx);
}
-inline void TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
+inline bool TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
float &pos_sx, float &pos_sy,
float &pos_ex, float &pos_ey,
float &tex_sx, float &tex_sy,
float &tex_ex, float &tex_ey,
- bool centre, int ymax) const
+ bool centre, int ymin, int ymax,
+ float tile_x, float tile_y) const
{
const tile_info &inf = get_info(idx);
@@ -110,19 +112,32 @@ inline void TilesTexture::get_coords(int idx, int ofs_x, int ofs_y,
int size_ox = centre ? TILE_X / 2 - inf.width / 2 : 0;
int size_oy = centre ? TILE_Y - inf.height : 0;
- int ey = inf.ey;
- if (ymax > 0)
- ey = std::min(inf.sy + ymax - inf.offset_y, ey);
+ int pos_sy_adjust = ofs_y + inf.offset_y + size_oy;
+ int pos_ey_adjust = pos_sy_adjust + inf.ey - inf.sy;
- pos_sx += (ofs_x + inf.offset_x + size_ox) / (float) TILE_X;
- pos_sy += (ofs_y + inf.offset_y + size_oy) / (float) TILE_Y;
- pos_ex = pos_sx + (inf.ex - inf.sx) / (float)TILE_X;
- pos_ey = pos_sy + (ey - inf.sy) / (float)TILE_Y;
+ int sy = pos_sy_adjust;
+ if (ymin >= 0)
+ sy = std::max(ymin, sy);
+
+ int ey = pos_ey_adjust;
+ if (ymax >= 0)
+ ey = std::min(ymax, ey);
+
+ // Nothing to draw.
+ if (sy >= ey)
+ return (false);
+
+ pos_sx += (ofs_x + inf.offset_x + size_ox) / tile_x;
+ pos_sy += sy / tile_y;
+ pos_ex = pos_sx + (inf.ex - inf.sx) / tile_x;
+ pos_ey = pos_sy + (ey - sy) / tile_y;
tex_sx = inf.sx / fwidth;
- tex_sy = inf.sy / fheight;
+ tex_sy = (inf.sy + sy - pos_sy_adjust) / fheight;
tex_ex = inf.ex / fwidth;
- tex_ey = ey / fheight;
+ tex_ey = (inf.ey + ey - pos_ey_adjust) / fheight;
+
+ return (true);
}
#endif