Video: Precalculate brightness/etc for the palette instead of manually applying it to each pixel

This commit is contained in:
Sour 2019-02-07 19:45:17 -05:00
parent 3a752d6755
commit c5e4de9542
2 changed files with 37 additions and 34 deletions

View file

@ -50,22 +50,48 @@ void DefaultVideoFilter::OnBeforeApplyFilter()
}
_pictureSettings = currentSettings;
_needToProcess = _pictureSettings.Hue != 0 || _pictureSettings.Saturation != 0 || _pictureSettings.Brightness || _pictureSettings.Contrast;
if(_needToProcess) {
double y, i, q;
uint32_t* originalPalette = _console->GetSettings()->GetRgbPalette();
for(int pal = 0; pal < 512; pal++) {
uint32_t pixelOutput = originalPalette[pal];
double redChannel = ((pixelOutput & 0xFF0000) >> 16) / 255.0;
double greenChannel = ((pixelOutput & 0xFF00) >> 8) / 255.0;
double blueChannel = (pixelOutput & 0xFF) / 255.0;
//Apply brightness, contrast, hue & saturation
RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
y *= _pictureSettings.Contrast * 0.5f + 1;
y += _pictureSettings.Brightness * 0.5f;
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
int r = std::min(255, (int)(redChannel * 255));
int g = std::min(255, (int)(greenChannel * 255));
int b = std::min(255, (int)(blueChannel * 255));
_calculatedPalette[pal] = 0xFF000000 | (r << 16) | (g << 8) | b;
}
} else {
memcpy(_calculatedPalette, _console->GetSettings()->GetRgbPalette(), sizeof(_calculatedPalette));
}
}
void DefaultVideoFilter::DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines)
{
uint32_t* out = outputBuffer;
OverscanDimensions overscan = GetOverscan();
double scanlineIntensity = 1.0 - _console->GetSettings()->GetPictureSettings().ScanlineIntensity;
uint8_t scanlineIntensity = (uint8_t)((1.0 - _console->GetSettings()->GetPictureSettings().ScanlineIntensity) * 255);
for(uint32_t i = overscan.Top, iMax = 240 - overscan.Bottom; i < iMax; i++) {
if(displayScanlines && (i + overscan.Top) % 2 == 0) {
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
*out = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j], scanlineIntensity);
*out = ApplyScanlineEffect(ppuOutputBuffer[i * 256 + j], scanlineIntensity);
out++;
}
} else {
for(uint32_t j = overscan.Left, jMax = 256 - overscan.Right; j < jMax; j++) {
*out = ProcessIntensifyBits(ppuOutputBuffer[i * 256 + j]);
*out = _calculatedPalette[ppuOutputBuffer[i * 256 + j]];
out++;
}
}
@ -91,37 +117,13 @@ void DefaultVideoFilter::YiqToRgb(double y, double i, double q, double &r, doubl
b = std::max(0.0, std::min(1.0, (y + _yiqToRgbMatrix[4] * i + _yiqToRgbMatrix[5] * q)));
}
uint32_t DefaultVideoFilter::ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity)
uint32_t DefaultVideoFilter::ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity)
{
uint32_t pixelOutput = _console->GetSettings()->GetRgbPalette()[ppuPixel & 0x1FF];
uint32_t pixelOutput = _calculatedPalette[ppuPixel];
if(_needToProcess || scanlineIntensity < 1.0) {
//Incorrect emphasis bit implementation, but will do for now.
double redChannel = ((pixelOutput & 0xFF0000) >> 16) / 255.0;
double greenChannel = ((pixelOutput & 0xFF00) >> 8) / 255.0;
double blueChannel = (pixelOutput & 0xFF) / 255.0;
uint8_t r = ((pixelOutput & 0xFF0000) >> 16) * scanlineIntensity / 255;
uint8_t g = ((pixelOutput & 0xFF00) >> 8) * scanlineIntensity / 255;
uint8_t b = (pixelOutput & 0xFF) * scanlineIntensity / 255;
//Apply brightness, contrast, hue & saturation
if(_needToProcess) {
double y, i, q;
RgbToYiq(redChannel, greenChannel, blueChannel, y, i, q);
y *= _pictureSettings.Contrast * 0.5f + 1;
y += _pictureSettings.Brightness * 0.5f;
YiqToRgb(y, i, q, redChannel, greenChannel, blueChannel);
}
if(scanlineIntensity < 1.0) {
redChannel *= scanlineIntensity;
greenChannel *= scanlineIntensity;
blueChannel *= scanlineIntensity;
}
int r = std::min(255, (int)(redChannel * 255));
int g = std::min(255, (int)(greenChannel * 255));
int b = std::min(255, (int)(blueChannel * 255));
return 0xFF000000 | (r << 16) | (g << 8) | b;
} else {
return pixelOutput;
}
return 0xFF000000 | (r << 16) | (g << 8) | b;
}

View file

@ -7,6 +7,7 @@ class DefaultVideoFilter : public BaseVideoFilter
{
private:
double _yiqToRgbMatrix[6];
uint32_t _calculatedPalette[512];
PictureSettings _pictureSettings;
bool _needToProcess = false;
@ -17,7 +18,7 @@ private:
protected:
void DecodePpuBuffer(uint16_t *ppuOutputBuffer, uint32_t* outputBuffer, bool displayScanlines);
uint32_t ProcessIntensifyBits(uint16_t ppuPixel, double scanlineIntensity = 1.0);
uint32_t ApplyScanlineEffect(uint16_t ppuPixel, uint8_t scanlineIntensity);
void OnBeforeApplyFilter();
public: