mirror of
https://github.com/italicsjenga/slang-shaders.git
synced 2024-11-26 17:31:31 +11:00
Merge pull request #211 from MajorPainTheCactus/master
v1.0 of Sony PVM 4K HDR shader that tries to emulate a Sony PVM 20L4
This commit is contained in:
commit
b243ceb426
|
@ -1,11 +1,13 @@
|
|||
/*
|
||||
A group of shaders that tries to emulate a sony PVM type aperture grille screen but with full brightness.
|
||||
A group of shaders that tries to emulate a Sony PVM type aperture grille screen but with full brightness.
|
||||
|
||||
The novel thing about this group of shaders is that it transforms the image output by the 'console/arcade/computer' into HDR space first i.e brightens it first and then applies
|
||||
an aperture grille afterwards which is kind of what a CRT would actually do - its kind of a kin to the electron beam (but nothing like it lol).
|
||||
|
||||
My HDR 700 monitors does seem to get reasonably close to the brightness of my PVM's - its not quite there but its close.
|
||||
|
||||
Currently geared towards a Sony PVM 20L4.
|
||||
|
||||
To use:
|
||||
Please Enable HDR in RetroArch,
|
||||
|
||||
|
@ -75,4 +77,7 @@ mipmap_input3 = "false"
|
|||
alias3 = ""
|
||||
float_framebuffer3 = "false"
|
||||
srgb_framebuffer3 = "false"
|
||||
ScanlineWidth = "1.000000"
|
||||
|
||||
ScanlineWidth = "0.600000"
|
||||
Contrast = "4.500000"
|
||||
PaperWhiteNits = "500.000000"
|
|
@ -27,15 +27,16 @@ layout(push_constant) uniform Push
|
|||
vec4 OriginalSize;
|
||||
vec4 OutputSize;
|
||||
uint FrameCount;
|
||||
float ScanlineWidth;
|
||||
float ScreenWidth;
|
||||
float ScreenHeight;
|
||||
float ScanlineWidth;
|
||||
float ScreenWidth;
|
||||
float ScreenHeight;
|
||||
float ResolutionPattern;
|
||||
} params;
|
||||
|
||||
/* #pragma parameter ScanlineWidth "Scanline Width" 4.0 0.0 20.0 1.0 */
|
||||
#pragma parameter ScanlineWidth "Scanline Width" 0.5 0.0 1.0 0.01
|
||||
#pragma parameter ScreenWidth "Screen Width" 3840.0 0.0 7680.0 1.0
|
||||
#pragma parameter ScreenHeight "Screen Height" 2160.0 0.0 4320.0 1.0
|
||||
#pragma parameter ScanlineWidth "Scanline Width" 0.5 0.0 1.0 0.01
|
||||
#pragma parameter ScreenWidth "Screen Width" 3840.0 0.0 7680.0 1.0
|
||||
#pragma parameter ScreenHeight "Screen Height" 2160.0 0.0 4320.0 1.0
|
||||
#pragma parameter ResolutionPattern "Resolution Pattern" 1.0 0.0 8.0 1.0
|
||||
|
||||
layout(std140, set = 0, binding = 0) uniform UBO
|
||||
{
|
||||
|
@ -46,35 +47,15 @@ layout(std140, set = 0, binding = 0) uniform UBO
|
|||
layout(location = 0) in vec4 Position;
|
||||
layout(location = 1) in vec2 TexCoord;
|
||||
layout(location = 0) out vec2 vTexCoord;
|
||||
layout(location = 1) out float Scale;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = global.MVP * Position;
|
||||
vTexCoord = TexCoord;
|
||||
|
||||
vec2 ScreenSize = max(params.OutputSize.xy, vec2(params.ScreenWidth, params.ScreenHeight));
|
||||
|
||||
if((params.SourceSize.x > ScreenSize.x) || (params.SourceSize.y > ScreenSize.y))
|
||||
{
|
||||
Scale = 1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
float ScaleFactor = 2.0;
|
||||
|
||||
while(((params.SourceSize.x * ScaleFactor) <= ScreenSize.x) && ((params.SourceSize.y * ScaleFactor) <= ScreenSize.y))
|
||||
{
|
||||
ScaleFactor += 1.0;
|
||||
}
|
||||
|
||||
Scale = ScaleFactor - 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma stage fragment
|
||||
layout(location = 0) in vec2 vTexCoord;
|
||||
layout(location = 1) in float Scale;
|
||||
layout(location = 0) out vec4 FragColor;
|
||||
layout(set = 0, binding = 2) uniform sampler2D Source;
|
||||
layout(set = 0, binding = 3) uniform sampler2D StockPass;
|
||||
|
@ -89,165 +70,171 @@ float ModInteger(float a, float b)
|
|||
#define kEuler 2.718281828459
|
||||
#define kMax 1.0
|
||||
|
||||
#define kGuassianMin 1.1
|
||||
#define kGuassianMax 3.0
|
||||
#define kGuassianMin vec3(1.1)
|
||||
#define kGuassianMax vec3(3.0)
|
||||
#define Sharpness 2.5
|
||||
|
||||
#define kRed vec3(1.0, 0.0, 0.0)
|
||||
#define kGreen vec3(0.0, 1.0, 0.0)
|
||||
#define kBlue vec3(0.0, 0.0, 1.0)
|
||||
#define kMagenta vec3(1.0, 0.0, 1.0)
|
||||
#define kYellow vec3(1.0, 1.0, 0.0)
|
||||
#define kCyan vec3(0.0, 1.0, 1.0)
|
||||
#define kBlack vec3(0.0, 0.0, 0.0)
|
||||
#define kWhite vec3(1.0, 1.0, 1.0)
|
||||
|
||||
float Ramp(const float gaussian, float colour)
|
||||
{
|
||||
return clamp(gaussian * colour, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 Ramp3(const vec3 gaussian, vec3 colour)
|
||||
{
|
||||
return clamp(gaussian * colour, vec3(0.0), vec3(1.0));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
float ScanlineSize = params.OutputSize.y / params.SourceSize.y;
|
||||
|
||||
/* vec2 InPixels = (vTexCoord * params.SourceSize.xy) * vec2(Scale); */
|
||||
const vec2 InPixels = (vTexCoord * params.OutputSize.xy);
|
||||
|
||||
const float ScanlinePosition = (floor(vTexCoord.y * params.SourceSize.y) * ScanlineSize) + (ScanlineSize * 0.5);
|
||||
|
||||
float ScanlineDistance = ScanlinePosition - (floor(InPixels.y) + 0.5);
|
||||
|
||||
/*
|
||||
if(ModInteger(floor(InPixels.y), Scale) < params.ScanlineWidth)
|
||||
{
|
||||
FragColor = vec4(texture(Source, vTexCoord).xyz, 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
FragColor = vec4(0.0,0.0,0.0,1.0);
|
||||
}
|
||||
*/
|
||||
|
||||
ScanlineDistance /= ScanlineSize * params.ScanlineWidth;
|
||||
ScanlineDistance = clamp(abs(ScanlineDistance * 2.0), 0.0, 1.0);
|
||||
|
||||
/* Gaussian distribution */
|
||||
const float gaussian = pow(kEuler, -0.5 * pow(ScanlineDistance/0.3, 2.0));
|
||||
|
||||
//const float guassianf = gaussian * clamp(ScanlineSize / 2, 1.2, 5.0);
|
||||
//const float guassian_clamp = clamp(guassianf, 0.0, 1.0);
|
||||
const float Gaussian = pow(kEuler, -0.5 * pow(ScanlineDistance/0.3, 2.0)); /* Gaussian distribution */
|
||||
|
||||
float Ratio = (vTexCoord.x * params.SourceSize.x) - (floor(vTexCoord.x * params.SourceSize.x));
|
||||
Ratio = clamp(((Ratio - 0.5) * Sharpness) + 0.5, 0.0f, 1.0);
|
||||
|
||||
const vec2 SourceTexCoord0 = vec2(vTexCoord.x, ScanlinePosition / params.OutputSize.y);
|
||||
|
||||
vec3 hdr_colour0 = texture(Source, SourceTexCoord0).xyz;
|
||||
vec3 sdr_colour0 = texture(StockPass, SourceTexCoord0).xyz;
|
||||
vec3 HDRColour0 = texture(Source, SourceTexCoord0).xyz;
|
||||
vec3 SDRColour0 = texture(StockPass, SourceTexCoord0).xyz;
|
||||
|
||||
const vec2 SourceTexCoord1 = vec2(vTexCoord.x + (1.0 / params.SourceSize.x), ScanlinePosition / params.OutputSize.y);
|
||||
|
||||
vec3 hdr_colour1 = texture(Source, SourceTexCoord1).xyz;
|
||||
vec3 sdr_colour1 = texture(StockPass, SourceTexCoord1).xyz;
|
||||
const vec3 HDRColour1 = texture(Source, SourceTexCoord1).xyz;
|
||||
const vec3 SDRColour1 = texture(StockPass, SourceTexCoord1).xyz;
|
||||
|
||||
vec3 hdr_colour = mix(hdr_colour0, hdr_colour1, vec3(Ratio));
|
||||
vec3 sdr_colour = mix(sdr_colour0, sdr_colour1, vec3(Ratio));
|
||||
const vec3 HDRColour = mix(HDRColour0, HDRColour1, vec3(Ratio));
|
||||
const vec3 SDRColour = mix(SDRColour0, SDRColour1, vec3(Ratio));
|
||||
|
||||
/* TODO: Below needs optimising - just needs a mask array rather than doing if's! Ran out of time */
|
||||
vec3 Luminance = Ramp3(vec3(Gaussian), (SDRColour * kGuassianMax) + kGuassianMin);
|
||||
|
||||
#if 0 /* 12 pattern - 8K screens */
|
||||
float x = ModInteger(floor(InPixels.x), 12.0);
|
||||
vec3 OutputColour;
|
||||
|
||||
if(x < 3.0)
|
||||
{
|
||||
float red = Ramp(gaussian, (sdr_colour.x * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(red * hdr_colour.x, 0.0, 0.0, 1.0);
|
||||
}
|
||||
else if(x < 4.0)
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
else if(x < 7.0)
|
||||
{
|
||||
float green = Ramp(gaussian, (sdr_colour.y * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, green * hdr_colour.y, 0.0, 1.0);
|
||||
}
|
||||
else if(x < 8.0)
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
else if(x < 11.0)
|
||||
{
|
||||
float blue = Ramp(gaussian, (sdr_colour.z * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, 0.0, blue * hdr_colour.z, 1.0);
|
||||
}
|
||||
else /* if(x < 12.0) */
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
#endif /* 0 */
|
||||
/* Various resolution patterns - remember your LCD 4K screen will likely be 16:9 whereas
|
||||
the CRT TV will likely be 4:3 and so higher TVL values will be required on your 16:9 screen
|
||||
to get an equivalent TVL seen on a 4:3 CRT TV.
|
||||
Pattern 1's 960TVL at 16:9 is about right for a 800TVL at 4:3.
|
||||
*/
|
||||
|
||||
#if 0 /* 9 pattern - 8K screens */
|
||||
float x = ModInteger(floor(InPixels.x), 9.0);
|
||||
uint ResolutionPattern = uint(params.ResolutionPattern);
|
||||
|
||||
if(x < 2.0)
|
||||
switch(ResolutionPattern)
|
||||
{
|
||||
float red = Ramp(gaussian, (sdr_colour.x * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(red * hdr_colour.x, 0.0, 0.0, 1.0);
|
||||
}
|
||||
else if(x < 3.0)
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
else if(x < 5.0)
|
||||
{
|
||||
float green = Ramp(gaussian, (sdr_colour.y * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, green * hdr_colour.y, 0.0, 1.0);
|
||||
}
|
||||
else if(x < 6.0)
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
else if(x < 8.0)
|
||||
{
|
||||
float blue = Ramp(gaussian, (sdr_colour.z * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, 0.0, blue * hdr_colour.z, 1.0);
|
||||
}
|
||||
else /* if(x < 9.0) */
|
||||
{
|
||||
FragColor = vec4(0.0, 0.0, 0.0, 1.0); /* black */
|
||||
}
|
||||
#endif /* 0 */
|
||||
case 0: /* 2 pattern - 1440TVL (16:9) horiz resolution (too high?) on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 2;
|
||||
const vec3 Mask[2] = vec3[]( kYellow, kCyan );
|
||||
|
||||
#if 1 /* 6 pattern - 4K screens */
|
||||
float x = ModInteger(floor(InPixels.x), 6.0);
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
if(x < 2.0)
|
||||
{
|
||||
float red = Ramp(gaussian, (sdr_colour.x * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(red * hdr_colour.x, 0.0, 0.0, 1.0);
|
||||
}
|
||||
else if(x < 4.0)
|
||||
{
|
||||
float green = Ramp(gaussian, (sdr_colour.y * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, green * hdr_colour.y, 0.0, 1.0);
|
||||
}
|
||||
else /* if(x < 6.0) */
|
||||
{
|
||||
float blue = Ramp(gaussian, (sdr_colour.z * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, 0.0, blue * hdr_colour.z, 1.0);
|
||||
}
|
||||
#endif /* 1 */
|
||||
break;
|
||||
}
|
||||
case 1: /* 3 pattern - 960TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 3;
|
||||
const vec3 Mask[3] = vec3[]( kRed, kGreen, kBlue );
|
||||
|
||||
#if 0 /* 3 pattern - 1080-1440p screens */
|
||||
float x = ModInteger(floor(InPixels.x), 3.0);
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
if(x < 1.0)
|
||||
{
|
||||
float red = Ramp(gaussian, (sdr_colour.x * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(red * hdr_colour.x, 0.0, 0.0, 1.0);
|
||||
break;
|
||||
}
|
||||
case 2: /* 4 pattern - 720TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 4;
|
||||
const vec3 Mask[4] = vec3[]( kRed, kYellow, kCyan, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: /* 5 BRG pattern - 576TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 5;
|
||||
const vec3 Mask[5] = vec3[]( kRed, kMagenta, kBlue, kGreen, kGreen );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 4: /* 5 pattern - 576TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 5;
|
||||
const vec3 Mask[5] = vec3[]( kRed, kYellow, kGreen, kCyan, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 5: /* 6 pattern - 480TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 6;
|
||||
const vec3 Mask[6] = vec3[]( kRed, kRed, kGreen, kGreen, kBlue, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 6: /* 7 pattern - 410TVL (16:9) horiz resolution on a 4K screen */
|
||||
{
|
||||
const uint PatternSize = 7;
|
||||
const vec3 Mask[7] = vec3[]( kRed, kRed, kYellow, kGreen, kCyan, kBlue, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 7: /* 9 pattern - 640TVL (16:9) horiz resolution on a *8K* screen */
|
||||
{
|
||||
const uint PatternSize = 9;
|
||||
const vec3 Mask[9] = vec3[]( kBlack, kRed, kRed, kBlack, kGreen, kGreen, kBlack, kBlue, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
case 8: /* 12 pattern - 480TVL (16:9) horiz resolution on a *8K* screen */
|
||||
{
|
||||
const uint PatternSize = 12;
|
||||
const vec3 Mask[12] = vec3[]( kBlack, kRed, kRed, kRed, kBlack, kGreen, kGreen, kGreen, kBlack, kBlue, kBlue, kBlue );
|
||||
|
||||
uint PatternX = uint(ModInteger(floor(InPixels.x), PatternSize));
|
||||
OutputColour = Luminance * HDRColour * Mask[PatternX];
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
OutputColour = vec3(0.0);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if(x < 2.0)
|
||||
{
|
||||
float green = Ramp(gaussian, (sdr_colour.y * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, green * hdr_colour.y, 0.0, 1.0);
|
||||
}
|
||||
else /* if(x < 3.0) */
|
||||
{
|
||||
float blue = Ramp(gaussian, (sdr_colour.z * kGuassianMax) + kGuassianMin);
|
||||
FragColor = vec4(0.0, 0.0, blue * hdr_colour.z, 1.0);
|
||||
}
|
||||
#endif /* 0 */
|
||||
|
||||
FragColor = vec4(OutputColour, 1.0);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue