mirror of
https://github.com/libretro/gambatte-libretro.git
synced 2025-02-20 00:20:33 +00:00
Merge pull request #123 from jdgleaver/gbc-cc-update
Update GBC colour correction
This commit is contained in:
commit
e91f844cb6
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(); }
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user