diff options
-rw-r--r-- | crawl-ref/source/rltiles/dc-misc.txt | 3 | ||||
-rw-r--r-- | crawl-ref/source/rltiles/dc-misc/mask_submerged.png | bin | 0 -> 593 bytes | |||
-rw-r--r-- | crawl-ref/source/rltiles/dc-player.txt | 5 | ||||
-rw-r--r-- | crawl-ref/source/tilebuf.cc | 378 | ||||
-rw-r--r-- | crawl-ref/source/tilebuf.h | 89 | ||||
-rw-r--r-- | crawl-ref/source/tilemcache.cc | 7 | ||||
-rw-r--r-- | crawl-ref/source/tilemcache.h | 2 | ||||
-rw-r--r-- | crawl-ref/source/tilepick.cc | 4 | ||||
-rw-r--r-- | crawl-ref/source/tilereg.cc | 97 | ||||
-rw-r--r-- | crawl-ref/source/tilereg.h | 13 | ||||
-rw-r--r-- | crawl-ref/source/tiles.h | 1 | ||||
-rw-r--r-- | crawl-ref/source/tilesdl.cc | 55 | ||||
-rw-r--r-- | crawl-ref/source/tilesdl.h | 25 | ||||
-rw-r--r-- | crawl-ref/source/tiletex.h | 41 |
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 Binary files differnew file mode 100644 index 0000000000..4ccb0aa8ae --- /dev/null +++ b/crawl-ref/source/rltiles/dc-misc/mask_submerged.png 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 |