Fix #14: Don't recolour 32bpp sprites to 8bpp when not tinted

This commit is contained in:
dP
2024-02-17 22:29:34 +05:30
parent f844546ed7
commit 782c80b589
14 changed files with 117 additions and 178 deletions

View File

@@ -15,6 +15,8 @@
#include "../table/sprites.h"
#include "../citymania/cm_colour.hpp"
#include "../safeguards.h"
/** Instantiation of the 32bpp with animation blitter factory. */
@@ -103,6 +105,43 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
draw:;
switch (mode) {
case CM_BM_TINT_REMAP:
if (src_px->a == 255) {
do {
uint m = *src_n;
/* In case the m-channel is zero, do not remap this pixel in any way */
if (m == 0) {
*dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap);
*anim = 0;
} else {
uint r = remap[GB(m, 0, 8)];
*anim = r | (m & 0xFF00);
if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8));
}
anim++;
dst++;
src_px++;
src_n++;
} while (--n != 0);
} else {
do {
uint m = *src_n;
if (m == 0) {
*dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst, remap);
*anim = 0;
} else {
uint r = remap[GB(m, 0, 8)];
*anim = 0;
if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst);
}
anim++;
dst++;
src_px++;
src_n++;
} while (--n != 0);
}
break;
case BM_COLOUR_REMAP:
if (src_px->a == 255) {
do {
@@ -278,6 +317,7 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
default: NOT_REACHED();
case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
case CM_BM_TINT_REMAP: Draw<CM_BM_TINT_REMAP>(bp, zoom); return;
case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
case BM_TRANSPARENT_REMAP: Draw<BM_TRANSPARENT_REMAP>(bp, zoom); return;
case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP> (bp, zoom); return;

View File

@@ -40,7 +40,7 @@ public:
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator) override {
return Blitter_32bppSSE2::Encode(sprite, allocator); // CM FIXME 14.0-beta1 why SSE -> SSE2
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
}
const char *GetName() override { return "32bpp-sse4-anim"; }
using Blitter_32bppSSE2_Anim::LookupColourInPalette;

View File

@@ -175,33 +175,6 @@ public:
return rgb_max;
}
/* CM */
uint8 cm_mdict[64*64*64] = {0};
uint8 CM_GetMForRGB(uint8 r, uint8 g, uint8 b) {
if (r==0 && g==0 && b==0) return 0;
r &= 252; g &= 252; b &= 252;
auto key = (r << 10) | (g << 4) | (b >> 2);
auto m = this->cm_mdict[key];
if (m != 0) return m;
uint md = UINT_MAX;
for (uint8 i = 1; i < 0xc0; i++) {
auto c = this->LookupColourInPalette(i);
auto rmean = (int)c.r + (int)r;
auto dr = (int)c.r - (int)r;
auto dg = (int)c.g - (int)g;
auto db = (int)c.b - (int)b;
auto dist = (1020 + rmean) * dr * dr + 2040 * dg * dg + (1530 - rmean) * db * db;
// auto dist = r * r + g * g + b * b;
if (dist < md) {
md = dist;
m = i;
}
}
this->cm_mdict[key] = m;
return m;
}
};
#endif /* BLITTER_32BPP_BASE_HPP */

View File

@@ -13,6 +13,8 @@
#include "../palette_func.h"
#include "32bpp_optimized.hpp"
#include "../citymania/cm_colour.hpp"
#include "../safeguards.h"
/** Instantiation of the optimized 32bpp blitter factory. */
@@ -111,6 +113,37 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
draw:;
switch (mode) {
case CM_BM_TINT_REMAP:
if (src_px->a == 255) {
do {
uint m = *src_n;
/* In case the m-channel is zero, do not remap this pixel in any way */
if (m == 0) {
*dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap);
} else {
uint r = remap[GB(m, 0, 8)];
if (r != 0) *dst = this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8));
}
dst++;
src_px++;
src_n++;
} while (--n != 0);
} else {
do {
uint m = *src_n;
if (m == 0) {
*dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst, remap);
} else {
uint r = remap[GB(m, 0, 8)];
if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), GB(m, 8, 8)), src_px->a, *dst);
}
dst++;
src_px++;
src_n++;
} while (--n != 0);
}
break;
case BM_COLOUR_REMAP:
if (src_px->a == 255) {
do {
@@ -263,6 +296,7 @@ void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode,
default: NOT_REACHED();
case BM_NORMAL: Draw<BM_NORMAL, Tpal_to_rgb>(bp, zoom); return;
case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP, Tpal_to_rgb>(bp, zoom); return;
case CM_BM_TINT_REMAP: Draw<CM_BM_TINT_REMAP, Tpal_to_rgb>(bp, zoom); return;
case BM_TRANSPARENT: Draw<BM_TRANSPARENT, Tpal_to_rgb>(bp, zoom); return;
case BM_TRANSPARENT_REMAP: Draw<BM_TRANSPARENT_REMAP, Tpal_to_rgb>(bp, zoom); return;
case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP, Tpal_to_rgb>(bp, zoom); return;
@@ -379,7 +413,6 @@ template <bool Tpal_to_rgb> Sprite *Blitter_32bppOptimized::EncodeInternal(const
dst_px->r = src->r;
dst_px->g = src->g;
dst_px->b = src->b;
if (Tpal_to_rgb) *dst_n = this->CM_GetMForRGB(src->r, src->g, src->b) | (DEFAULT_BRIGHTNESS << 8);
}
dst_px++;
dst_n++;

View File

@@ -14,6 +14,8 @@
#include "../table/sprites.h"
#include "../citymania/cm_colour.hpp"
#include "../safeguards.h"
/** Instantiation of the simple 32bpp blitter factory. */
@@ -37,6 +39,15 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo
for (int x = 0; x < bp->width; x++) {
switch (mode) {
case CM_BM_TINT_REMAP:
/* In case the m-channel is zero, do not remap this pixel in any way */
if (src->m == 0) {
if (src->a != 0) *dst = citymania::Remap32RGBA(src->r, src->g, src->b, src->a, *dst, bp->remap);
} else {
if (bp->remap[src->m] != 0) *dst = ComposeColourPA(this->AdjustBrightness(this->LookupColourInPalette(bp->remap[src->m]), src->v), src->a, *dst);
}
break;
case BM_COLOUR_REMAP:
/* In case the m-channel is zero, do not remap this pixel in any way */
if (src->m == 0) {
@@ -90,6 +101,7 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo
void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height, PaletteID pal)
{
Colour *udst = (Colour *)dst;
if (pal == PALETTE_TO_TRANSPARENT) {
do {
for (int i = 0; i != width; i++) {
@@ -133,8 +145,8 @@ Sprite *Blitter_32bppSimple::Encode(const SpriteLoader::SpriteCollection &sprite
dst[i].g = src->g;
dst[i].b = src->b;
dst[i].a = src->a;
dst[i].m = this->CM_GetMForRGB(src->r, src->g, src->b);
dst[i].v = DEFAULT_BRIGHTNESS;
dst[i].m = 0;
dst[i].v = 0;
} else {
/* Get brightest value */
uint8_t rgb_max = std::max({src->r, src->g, src->b});

View File

@@ -20,7 +20,7 @@
/** Instantiation of the SSE2 32bpp blitter factory. */
static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator, Blitter_32bppSimple *base_blitter)
Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator)
{
/* First uint32_t of a line = the number of transparent pixels from the left.
* Second uint32_t of a line = the number of transparent pixels from the right.
@@ -89,11 +89,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::SpriteCollection &spri
dst_rgba->g = colour.g;
dst_rgba->b = colour.b;
} else {
has_remap = true;
dst_rgba->r = src->r;
dst_rgba->g = src->g;
dst_rgba->b = src->b;
dst_mv->m = base_blitter->CM_GetMForRGB(src->r, src->g, src->b);
dst_mv->v = Blitter_32bppBase::DEFAULT_BRIGHTNESS;
}
} else {

View File

@@ -76,7 +76,7 @@ public:
byte data[]; ///< Data, all zoomlevels.
};
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator, Blitter_32bppSimple *base_blitter);
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator);
};
DECLARE_ENUM_AS_BIT_SET(Blitter_32bppSSE_Base::SpriteFlags);
@@ -89,7 +89,7 @@ public:
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
Sprite *Encode(const SpriteLoader::SpriteCollection &sprite, AllocatorProc *allocator) override {
return Blitter_32bppSSE_Base::Encode(sprite, allocator, this);
return Blitter_32bppSSE_Base::Encode(sprite, allocator);
}
const char *GetName() override { return "32bpp-sse2"; }

View File

@@ -17,6 +17,8 @@
#include "../table/sprites.h"
#include "../citymania/cm_colour.hpp"
#include "../safeguards.h"
@@ -182,14 +184,20 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
switch (mode) {
case BM_COLOUR_REMAP:
case CM_BM_TINT_REMAP:
case BM_CRASH_REMAP:
if (src_px->a == 255) {
do {
uint8_t m = GB(*src_n, 0, 8);
/* In case the m-channel is zero, only apply the crash remap by darkening the RGB colour. */
if (m == 0) {
*dst = mode == BM_CRASH_REMAP ? this->MakeDark(*src_px) : *src_px;
*anim = mode == BM_CRASH_REMAP ? 0 : remap[this->CM_GetMForRGB(src_px->r, src_px->g, src_px->b)];
switch (mode) {
case BM_COLOUR_REMAP: *dst = *src_px; break;
case CM_BM_TINT_REMAP: *dst = citymania::Remap32RGB(src_px->r, src_px->g, src_px->b, remap); break;
case BM_CRASH_REMAP: *dst = this->MakeDark(*src_px); break;
default: NOT_REACHED();
}
*anim = 0;
} else {
uint r = remap[m];
if (r != 0) {
@@ -207,8 +215,12 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
uint8_t m = GB(*src_n, 0, 8);
Colour b = this->RealizeBlendedColour(*anim, *dst);
if (m == 0) {
Colour c = mode == BM_CRASH_REMAP ? this->MakeDark(*src_px) : *src_px;
*dst = this->ComposeColourRGBANoCheck(c.r, c.g, c.b, src_px->a, b);
switch (mode) {
case BM_COLOUR_REMAP: *dst = this->ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, b); break;
case CM_BM_TINT_REMAP: *dst = citymania::Remap32RGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, b, remap); break;
case BM_CRASH_REMAP: *dst = this->ComposeColourPANoCheck(this->MakeDark(*src_px), src_px->a, b); break;
default: NOT_REACHED();
}
*anim = 0;
} else {
uint r = remap[m];
@@ -341,6 +353,7 @@ void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
default: NOT_REACHED();
case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
case CM_BM_TINT_REMAP: Draw<CM_BM_TINT_REMAP>(bp, zoom); return;
case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
case BM_TRANSPARENT_REMAP: Draw<BM_TRANSPARENT_REMAP>(bp, zoom); return;
case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP> (bp, zoom); return;

View File

@@ -84,6 +84,7 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z
width -= pixels;
switch (mode) {
case CM_BM_TINT_REMAP:
case BM_COLOUR_REMAP:
case BM_CRASH_REMAP: {
const uint8_t *remap = bp->remap;

View File

@@ -36,6 +36,7 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom
uint colour = 0;
switch (mode) {
case CM_BM_TINT_REMAP:
case BM_COLOUR_REMAP:
case BM_CRASH_REMAP:
colour = bp->remap[*src];

View File

@@ -1,138 +0,0 @@
/* $Id: base.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
/*
* This file is part of OpenTTD.
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file base.cpp Implementation of the base for all blitters. */
#include "../stdafx.h"
#include "base.hpp"
#include "../core/math_func.hpp"
#include "../safeguards.h"
void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash)
{
int dy;
int dx;
int stepx;
int stepy;
dy = (y2 - y) * 2;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
dx = (x2 - x) * 2;
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
if (dx == 0 && dy == 0) {
/* The algorithm below cannot handle this special case; make it work at least for line width 1 */
if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour);
return;
}
int frac_diff = width * max(dx, dy);
if (width > 1) {
/* compute frac_diff = width * sqrt(dx*dx + dy*dy)
* Start interval:
* max(dx, dy) <= sqrt(dx*dx + dy*dy) <= sqrt(2) * max(dx, dy) <= 3/2 * max(dx, dy) */
int frac_sq = width * width * (dx * dx + dy * dy);
int frac_max = 3 * frac_diff / 2;
while (frac_diff < frac_max) {
int frac_test = (frac_diff + frac_max) / 2;
if (frac_test * frac_test < frac_sq) {
frac_diff = frac_test + 1;
} else {
frac_max = frac_test - 1;
}
}
}
int gap = dash;
if (dash == 0) dash = 1;
int dash_count = 0;
if (dx > dy) {
int y_low = y;
int y_high = y;
int frac_low = dy - frac_diff / 2;
int frac_high = dy + frac_diff / 2;
while (frac_low + dx / 2 < 0) {
frac_low += dx;
y_low -= stepy;
}
while (frac_high - dx / 2 >= 0) {
frac_high -= dx;
y_high += stepy;
}
x2 += stepx;
while (x != x2) {
if (dash_count < dash && x >= 0 && x < screen_width) {
for (int y = y_low; y != y_high; y += stepy) {
if (y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour);
}
}
if (frac_low >= 0) {
y_low += stepy;
frac_low -= dx;
}
if (frac_high >= 0) {
y_high += stepy;
frac_high -= dx;
}
x += stepx;
frac_low += dy;
frac_high += dy;
if (++dash_count >= dash + gap) dash_count = 0;
}
} else {
int x_low = x;
int x_high = x;
int frac_low = dx - frac_diff / 2;
int frac_high = dx + frac_diff / 2;
while (frac_low + dy / 2 < 0) {
frac_low += dy;
x_low -= stepx;
}
while (frac_high - dy / 2 >= 0) {
frac_high -= dy;
x_high += stepx;
}
y2 += stepy;
while (y != y2) {
if (dash_count < dash && y >= 0 && y < screen_height) {
for (int x = x_low; x != x_high; x += stepx) {
if (x >= 0 && x < screen_width) this->SetPixel(video, x, y, colour);
}
}
if (frac_low >= 0) {
x_low += stepx;
frac_low -= dy;
}
if (frac_high >= 0) {
x_high += stepx;
frac_high -= dy;
}
y += stepy;
frac_low += dx;
frac_high += dx;
if (++dash_count >= dash + gap) dash_count = 0;
}
}
}

View File

@@ -21,6 +21,7 @@ enum BlitterMode {
BM_TRANSPARENT_REMAP, ///< Perform transparency colour remapping.
BM_CRASH_REMAP, ///< Perform a crash remapping.
BM_BLACK_REMAP, ///< Perform remapping to a completely blackened sprite
CM_BM_TINT_REMAP, ///< Perform tinting.
};
/**

View File

@@ -27,6 +27,8 @@ add_files(
cm_cargo_table_gui.cpp
cm_client_list_gui.hpp
cm_client_list_gui.cpp
cm_colour.hpp
cm_colour.cpp
cm_commands.hpp
cm_commands.cpp
cm_commands_gui.hpp

View File

@@ -7,6 +7,7 @@
/** @file gfx.cpp Handling of drawing text and other gfx related stuff. */
#include "blitter/base.hpp"
#include "stdafx.h"
#include "gfx_layout.h"
#include "progress.h"
@@ -978,6 +979,8 @@ static BlitterMode GetBlitterMode(PaletteID pal)
case PAL_NONE: return BM_NORMAL;
case PALETTE_CRASH: return BM_CRASH_REMAP;
case PALETTE_ALL_BLACK: return BM_BLACK_REMAP;
case CM_PALETTE_TINT_BASE ... (CM_PALETTE_TINT_BASE + CM_PALETTE_TINT_COUNT - 1):
return CM_BM_TINT_REMAP;
default: return BM_COLOUR_REMAP;
}
}