Video: Precalculate brightness/etc for the palette instead of manually applying it to each pixel
This commit is contained in:
parent
3a752d6755
commit
c5e4de9542
2 changed files with 37 additions and 34 deletions
|
@ -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;
|
||||
}
|
|
@ -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:
|
||||
|
|
Loading…
Add table
Reference in a new issue