Merge pull request #123 from jdgleaver/gbc-cc-update

Update GBC colour correction
This commit is contained in:
hizzlekizzle 2019-03-28 15:25:33 -05:00 committed by GitHub
commit e91f844cb6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 13 deletions

View File

@ -114,6 +114,7 @@ public:
void setColorCorrection(bool enable);
void setColorCorrectionMode(unsigned colorCorrectionMode);
void setColorCorrectionBrightness(float colorCorrectionBrightness);
void setDarkFilterLevel(unsigned darkFilterLevel);
video_pixel_t gbcToRgb32(const unsigned bgr15);

View File

@ -366,6 +366,7 @@ Special 3"
}, // So many... place on seperate lines for readability...
{ "gambatte_gbc_color_correction", "Color correction; GBC only|always|disabled" },
{ "gambatte_gbc_color_correction_mode", "Color correction mode; accurate|fast" },
{ "gambatte_gbc_frontlight_position", "Color correction - frontlight position; central|above screen|below screen" },
{ "gambatte_dark_filter_level", "Dark Filter Level (percent); 0|5|10|15|20|25|30|35|40|45|50" },
{ "gambatte_gb_hwmode", "Emulated hardware (restart); Auto|GB|GBC|GBA" },
{ "gambatte_gb_bootloader", "Use official bootloader (restart); enabled|disabled" },
@ -626,6 +627,18 @@ static void check_variables(void)
}
gb.setColorCorrectionMode(colorCorrectionMode);
float colorCorrectionBrightness = 0.5f; /* central */
var.key = "gambatte_gbc_frontlight_position";
var.value = NULL;
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
{
if (!strcmp(var.value, "above screen"))
colorCorrectionBrightness = 1.2f;
else if (!strcmp(var.value, "below screen"))
colorCorrectionBrightness = 0.0f;
}
gb.setColorCorrectionBrightness(colorCorrectionBrightness);
unsigned darkFilterLevel = 0;
var.key = "gambatte_dark_filter_level";
var.value = NULL;

View File

@ -49,6 +49,7 @@ public:
unsigned rtcdata_size() { return cart_.rtcdata_size(); }
void display_setColorCorrection(bool enable) { lcd_.setColorCorrection(enable); }
void display_setColorCorrectionMode(unsigned colorCorrectionMode) { lcd_.setColorCorrectionMode(colorCorrectionMode); }
void display_setColorCorrectionBrightness(float colorCorrectionBrightness) { lcd_.setColorCorrectionBrightness(colorCorrectionBrightness); }
void display_setDarkFilterLevel(unsigned darkFilterLevel) { lcd_.setDarkFilterLevel(darkFilterLevel); }
video_pixel_t display_gbcToRgb32(const unsigned bgr15) { return lcd_.gbcToRgb32(bgr15); }
void clearCheats() { cart_.clearCheats(); }

View File

@ -158,6 +158,10 @@ void GB::setColorCorrectionMode(unsigned colorCorrectionMode) {
p_->cpu.mem_.display_setColorCorrectionMode(colorCorrectionMode);
}
void GB::setColorCorrectionBrightness(float colorCorrectionBrightness) {
p_->cpu.mem_.display_setColorCorrectionBrightness(colorCorrectionBrightness);
}
void GB::setDarkFilterLevel(unsigned darkFilterLevel) {
p_->cpu.mem_.display_setDarkFilterLevel(darkFilterLevel);
}

View File

@ -155,6 +155,7 @@ class LCD
void setColorCorrection(bool colorCorrection);
void setColorCorrectionMode(unsigned colorCorrectionMode);
void setColorCorrectionBrightness(float colorCorrectionBrightness);
void setDarkFilterLevel(unsigned darkFilterLevel);
video_pixel_t gbcToRgb32(const unsigned bgr15);
private:
@ -228,6 +229,7 @@ class LCD
bool colorCorrection;
unsigned colorCorrectionMode;
float colorCorrectionBrightness;
unsigned darkFilterLevel;
void doCgbColorChange(unsigned char *const pdata,
video_pixel_t *const palette, unsigned index, const unsigned data);

View File

@ -22,6 +22,17 @@
#include <algorithm>
#include <cmath>
/* GBC colour correction factors */
#define GBC_CC_R 0.87
#define GBC_CC_G 0.66
#define GBC_CC_B 0.79
#define GBC_CC_RG 0.115
#define GBC_CC_RB 0.14
#define GBC_CC_GR 0.18
#define GBC_CC_GB 0.07
#define GBC_CC_BR -0.05
#define GBC_CC_BG 0.225
namespace gambatte
{
void LCD::setDmgPaletteColor(const unsigned index, const video_pixel_t rgb32)
@ -53,6 +64,12 @@ namespace gambatte
refreshPalettes();
}
void LCD::setColorCorrectionBrightness(float colorCorrectionBrightness_)
{
colorCorrectionBrightness = colorCorrectionBrightness_;
refreshPalettes();
}
void LCD::setDarkFilterLevel(unsigned darkFilterLevel_)
{
darkFilterLevel = darkFilterLevel_;
@ -146,16 +163,16 @@ namespace gambatte
//
// Constants
// > Luminosity factors: photometric/digital ITU BT.709
static const float lumaR = 0.2126;
static const float lumaG = 0.7152;
static const float lumaB = 0.0722;
static const float lumaR = 0.2126f;
static const float lumaG = 0.7152f;
static const float lumaB = 0.0722f;
// Calculate luminosity
float luma = (lumaR * r) + (lumaG * g) + (lumaB * b);
// Get 'darkness' scaling factor
// > User set 'dark filter' level scaled by current luminosity
// (i.e. lighter colours affected more than darker colours)
float darkFactor = 1.0 - ((static_cast<float>(darkFilterLevel) * 0.01) * luma);
darkFactor = darkFactor < 0.0 ? 0.0 : darkFactor;
float darkFactor = 1.0f - ((static_cast<float>(darkFilterLevel) * 0.01f) * luma);
darkFactor = darkFactor < 0.0f ? 0.0f : darkFactor;
// Perform scaling...
r = r * darkFactor;
g = g * darkFactor;
@ -193,7 +210,7 @@ namespace gambatte
else
{
// Use Pokefan531's "gold standard" GBC colour correction
// (https://forums.libretro.com/t/real-gba-and-ds-phat-colors/1540/159)
// (https://forums.libretro.com/t/real-gba-and-ds-phat-colors/1540/174)
// NB: The results produced by this implementation are ever so slightly
// different from the output of the gbc-colour shader. This is due to the
// fact that we have to tolerate rounding errors here that are simply not
@ -206,17 +223,26 @@ namespace gambatte
static const float targetGamma = 2.2;
static const float displayGammaInv = 1.0 / targetGamma;
// Perform gamma expansion
float rCorrect = std::pow(static_cast<float>(r) * rgbMaxInv, targetGamma);
float gCorrect = std::pow(static_cast<float>(g) * rgbMaxInv, targetGamma);
float bCorrect = std::pow(static_cast<float>(b) * rgbMaxInv, targetGamma);
// Perform colour mangling (lots of magic numbers...)
rCorrect = (0.86629 * rCorrect) + (0.13361 * gCorrect);
gCorrect = (0.02429 * rCorrect) + (0.70857 * gCorrect) + (0.26714 * bCorrect);
bCorrect = (0.11337 * rCorrect) + (0.11448 * gCorrect) + (0.77215 * bCorrect);
float adjustedGamma = targetGamma - colorCorrectionBrightness;
float rFloat = std::pow(static_cast<float>(r) * rgbMaxInv, adjustedGamma);
float gFloat = std::pow(static_cast<float>(g) * rgbMaxInv, adjustedGamma);
float bFloat = std::pow(static_cast<float>(b) * rgbMaxInv, adjustedGamma);
// Perform colour mangling
float rCorrect = (GBC_CC_R * rFloat) + (GBC_CC_GR * gFloat) + (GBC_CC_BR * bFloat);
float gCorrect = (GBC_CC_RG * rFloat) + (GBC_CC_G * gFloat) + (GBC_CC_BG * bFloat);
float bCorrect = (GBC_CC_RB * rFloat) + (GBC_CC_GB * gFloat) + (GBC_CC_B * bFloat);
// Range check...
rCorrect = rCorrect > 0.0f ? rCorrect : 0.0f;
gCorrect = gCorrect > 0.0f ? gCorrect : 0.0f;
bCorrect = bCorrect > 0.0f ? bCorrect : 0.0f;
// Perform gamma compression
rCorrect = std::pow(rCorrect, displayGammaInv);
gCorrect = std::pow(gCorrect, displayGammaInv);
bCorrect = std::pow(bCorrect, displayGammaInv);
// Range check...
rCorrect = rCorrect > 1.0f ? 1.0f : rCorrect;
gCorrect = gCorrect > 1.0f ? 1.0f : gCorrect;
bCorrect = bCorrect > 1.0f ? 1.0f : bCorrect;
// Perform image darkening, if required
if (darkFilterLevel > 0)
{