archive mame_hlsl and update to version based on bgfx code

This commit is contained in:
hunterk 2020-06-26 16:18:00 -05:00
parent 603be636dc
commit 5db5e6572d
30 changed files with 2824 additions and 519 deletions

View file

@ -1,85 +1,75 @@
# info on how the passes come together can be found in mame/src/osd/modules/render/d3d/d3dhlsl.cpp
shaders = 12
# info on how the passes come together can be found in mame/bgfx/chains/hlsl.json
shaders = 11
shader0 = shaders/mame_hlsl/shaders/mame_ntsc.slang
shader0 = shaders/mame_hlsl/shaders/mame_ntsc_encode.slang
filter_linear0 = true
alias0 = NTSCPass
scale_type0 = source
scale0 = 1.0
filter_linear0 = true
shader1 = shaders/mame_hlsl/shaders/mame_color.slang
alias1 = ColorPass
shader1 = shaders/mame_hlsl/shaders/mame_ntsc_decode.slang
filter_linear1 = true
alias1 = NTSCPass
scale_type1 = source
scale1 = 1.0
filter_linear1 = true
shader2 = ../interpolation/shaders/sharp-bilinear.slang
alias2 = PrescalePass
shader2 = shaders/mame_hlsl/shaders/mame_color.slang
alias2 = ColorPass
scale_type2 = source
scale2 = 1.0
filter_linear2 = true
scale2 = 4.0
shader3 = shaders/mame_hlsl/shaders/mame_deconverge.slang
alias3 = DeconvergePass
shader3 = shaders/mame_hlsl/shaders/mame_prescale.slang
alias3 = PrescalePass
scale_type3 = viewport
filter_linear3 = true
scale_type3 = source
scale3 = 0.5
scale3 = 1.0
shader4 = shaders/mame_hlsl/shaders/mame_scanline.slang
alias4 = ScanlinePass
shader4 = shaders/mame_hlsl/shaders/mame_deconverge.slang
alias4 = DeconvergePass
filter_linear4 = true
scale_type4 = source
scale4 = 2.0
scale_type4 = viewport
scale4 = 1.0
shader5 = shaders/mame_hlsl/shaders/mame_focus.slang
alias5 = FocusPass
shader5 = shaders/mame_hlsl/shaders/mame_scanline.slang
alias5 = ScanlinePass
filter_linear5 = true
scale_type5 = viewport
scale5 = 1.0
shader6 = shaders/mame_hlsl/shaders/mame_phosphor.slang
alias6 = PhosphorPass
shader6 = shaders/mame_hlsl/shaders/mame_defocus.slang
alias6 = FocusPass
filter_linear6 = true
scale_type6 = viewport
scale6 = 1.0
shader7 = shaders/mame_hlsl/shaders/mame_post.slang
alias7 = PostPass
filter_linear7 = true
scale_type7 = viewport
scale7 = 1.0
shader8 = shaders/mame_hlsl/shaders/mame_chroma.slang
alias8 = ChromaPass
shader8 = shaders/mame_hlsl/shaders/mame_phosphor.slang
alias8 = PhosphorPass
filter_linear8 = true
scale_type8 = viewport
scale8 = 1.0
shader9 = shaders/mame_hlsl/shaders/mame_downsample.slang
alias9 = DownsamplePass
shader9 = shaders/mame_hlsl/shaders/mame_chroma.slang
alias9 = ChromaPass
filter_linear9 = true
scale_type9 = viewport
scale9 = 1.0
shader10 = shaders/mame_hlsl/shaders/mame_bloom.slang
alias10 = BloomPass
shader10 = shaders/mame_hlsl/shaders/mame_distortion.slang
alias10 = DistortionPass
filter_linear10 = true
mipmap_input10 = true
scale_type10 = source
scale_type10 = viewport
scale10 = 1.0
shader11 = shaders/mame_hlsl/shaders/mame_distortion.slang
alias11 = DistortionPass
shader11 = shaders/mame_hlsl/shaders/lut.slang
filter_linear11 = true
# doesn't work, so commenting
# shader12 = shaders/mame_hlsl/shaders/mame_vector.slang
# alias12 = VectorPass
# filter_linear12 = true
# mame's textures are available here: https://github.com/mamedev/mame/tree/master/artwork
textures = "MaskTexture"
MaskTexture = shaders/mame_hlsl/resources/aperture-grille.png
parameters = "AUTO_PRESCALE;chromaa_x;chromaa_y;chromab_x;chromab_y;chromac_x;chromac_y;ygain_r;ygain_g;ygain_b"
chromaa_x = "0.630"
chromaa_y = "0.340"
chromab_x = "0.310"
chromab_y = "0.595"
chromac_x = "0.155"
chromac_y = "0.070"
ygain_r = "0.1875"
ygain_g = "0.6940"
ygain_b = "0.1185"
AUTO_PRESCALE = "0.0"

View file

@ -10,6 +10,8 @@ layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OutputSize;
vec4 OriginalSize;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"

View file

@ -12,6 +12,7 @@ layout(push_constant) uniform Push
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"

View file

@ -12,6 +12,7 @@ layout(push_constant) uniform Push
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
@ -19,47 +20,47 @@ layout(push_constant) uniform Push
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
#define s_tex Source
vec3 RedRatios = vec3(global.col_red, 0.0, 0.0);
vec3 GrnRatios = vec3(0.0, global.col_grn, 0.0);
vec3 BluRatios = vec3(0.0, 0.0, global.col_blu);
vec3 Offset = vec3(global.col_offset_x, global.col_offset_y, global.col_offset_z);
vec3 Scale = vec3(global.col_scale_x, global.col_scale_y, global.col_scale_z);
float Saturation = global.col_saturation;
vec4 u_red_ratios = vec4(global.col_rr, global.col_rg, global.col_rb, 0.0);
vec4 u_grn_ratios = vec4(global.col_gr, global.col_gg, global.col_gb, 0.0);
vec4 u_blu_ratios = vec4(global.col_br, global.col_bg, global.col_bb, 0.0);
vec4 u_offset = vec4(global.col_offset_x, global.col_offset_y, global.col_offset_z, 0.);
vec4 u_scale = vec4(global.col_scale_x, global.col_scale_y, global.col_scale_z, 0.);
vec4 u_saturation = vec4(global.col_saturation);
void main()
{
vec4 BaseTexel = texture(DiffuseSampler, vTexCoord);
vec4 BaseTexel = texture(s_tex, v_texcoord0);
vec3 OutRGB = BaseTexel.rgb;
// RGB Tint & Shift
float ShiftedRed = dot(OutRGB, RedRatios);
float ShiftedGrn = dot(OutRGB, GrnRatios);
float ShiftedBlu = dot(OutRGB, BluRatios);
float ShiftedRed = dot(OutRGB, u_red_ratios.xyz);
float ShiftedGrn = dot(OutRGB, u_grn_ratios.xyz);
float ShiftedBlu = dot(OutRGB, u_blu_ratios.xyz);
// RGB Scale & Offset
vec3 OutTexel = vec3(ShiftedRed, ShiftedGrn, ShiftedBlu) * Scale + Offset;
vec3 OutTexel = vec3(ShiftedRed, ShiftedGrn, ShiftedBlu) * u_scale.xyz + u_offset.xyz;
// Saturation
vec3 Grayscale = vec3(0.299f, 0.587f, 0.114f);
vec3 Grayscale = vec3(0.299, 0.587, 0.114);
float OutLuma = dot(OutTexel, Grayscale);
vec3 OutChroma = OutTexel - OutLuma;
vec3 Saturated = OutLuma + OutChroma * Saturation;
vec3 Saturated = OutLuma + OutChroma * u_saturation.x;
FragColor = vec4(Saturated, BaseTexel.a);
}

View file

@ -12,65 +12,59 @@ layout(push_constant) uniform Push
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
vec3 ConvergeX = vec3(global.converge_x_r, global.converge_x_g, global.converge_x_b);
vec3 ConvergeY = vec3(global.converge_y_r, global.converge_y_g, global.converge_y_b);
vec3 RadialConvergeX = vec3(global.radial_conv_x_r, global.radial_conv_x_g, global.radial_conv_x_b);
vec3 RadialConvergeY = vec3(global.radial_conv_y_r, global.radial_conv_y_g, global.radial_conv_y_b);
#define u_source_size params.OutputSize
vec4 u_converge_red = vec4(global.converge_x_r, global.converge_y_r, 0.,0.);
vec4 u_converge_green = vec4(global.converge_x_g, global.converge_y_g, 0.,0.);
vec4 u_converge_blue = vec4(global.converge_x_b, global.converge_y_b, 0.,0.);
vec4 u_radial_converge_red = vec4(global.radial_conv_x_r, global.radial_conv_y_r, 0.,0.);
vec4 u_radial_converge_green = vec4(global.radial_conv_x_g, global.radial_conv_y_g, 0.,0.);
vec4 u_radial_converge_blue = vec4(global.radial_conv_x_b, global.radial_conv_y_b, 0.,0.);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec3 TexCoordX;
layout(location = 1) out vec3 TexCoordY;
layout(location = 0) out vec2 v_texcoord0;
layout(location = 1) out vec2 v_texcoord1;
layout(location = 2) out vec2 v_texcoord2;
layout(location = 3) out vec2 v_texcoord3;
#define a_texcoord0 TexCoord.xy
void main()
{
gl_Position = global.MVP * Position;
// imaginary texel dimensions independed from screen dimension, but ratio
vec2 TexelDims = vec2(1.0 / 1024.);
vec2 half_value = vec2(0.5, 0.5);
TexCoordX = TexCoord.xxx;
TexCoordY = TexCoord.yyy;
// center coordinates
TexCoordX -= 0.5;
TexCoordY -= 0.5;
// radial converge offset to "translate" the most outer pixel as thay would be translated by the linar converge with the same amount
vec2 radialConvergeOffset = vec2(2.0);
// radial converge
TexCoordX *= 1.0 + RadialConvergeX * TexelDims.xxx * radialConvergeOffset.xxx;
TexCoordY *= 1.0 + RadialConvergeY * TexelDims.yyy * radialConvergeOffset.yyy;
// un-center coordinates
TexCoordX += 0.5;
TexCoordY += 0.5;
// linear converge
TexCoordX += ConvergeX * TexelDims.xxx;
TexCoordY += ConvergeY * TexelDims.yyy;
v_texcoord0 = a_texcoord0;
v_texcoord1 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_red.xy ) + half_value + u_converge_red.xy * (vec2(1.0, 1.0) / u_source_size.xy);
v_texcoord2 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_green.xy) + half_value + u_converge_green.xy * (vec2(1.0, 1.0) / u_source_size.xy);
v_texcoord3 = (a_texcoord0 - half_value) * (1.0 + u_radial_converge_blue.xy ) + half_value + u_converge_blue.xy * (vec2(1.0, 1.0) / u_source_size.xy);
}
#pragma stage fragment
layout(location = 0) in vec3 TexCoordX;
layout(location = 1) in vec3 TexCoordY;
layout(location = 0) in vec2 v_texcoord0;
layout(location = 1) in vec2 v_texcoord1;
layout(location = 2) in vec2 v_texcoord2;
layout(location = 3) in vec2 v_texcoord3;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
#define s_tex Source
#define v_color0 vec4(1.,1.,1.,1.)
void main()
{
float r = texture(DiffuseSampler, vec2(TexCoordX.x, TexCoordY.x)).r;
float g = texture(DiffuseSampler, vec2(TexCoordX.y, TexCoordY.y)).g;
float b = texture(DiffuseSampler, vec2(TexCoordX.z, TexCoordY.z)).b;
float a = texture(s_tex, v_texcoord0).a;
float r = texture(s_tex, v_texcoord1).r;
float g = texture(s_tex, v_texcoord2).g;
float b = texture(s_tex, v_texcoord3).b;
FragColor = vec4(r, g, b, 1.0);
FragColor = vec4(r, g, b, a) * v_color0;
}

View file

@ -0,0 +1,75 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Defocus Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define s_tex Source
#define v_color0 vec4(1.,1.,1.,1.)
vec4 u_defocus = vec4(global.defocus_x, global.defocus_y, 0., 0.);
void main()
{
// previously this pass was applied two times with offsets of 0.25, 0.5, 0.75, 1.0
// now this pass is applied only once with offsets of 0.25, 0.55, 1.0, 1.6 to achieve the same appearance as before till a maximum defocus of 2.0
// 0.075x² + 0.225x + 0.25
const vec2 Coord1Offset = vec2(-1.60, 0.25);
const vec2 Coord2Offset = vec2(-1.00, -0.55);
const vec2 Coord3Offset = vec2(-0.55, 1.00);
const vec2 Coord4Offset = vec2(-0.25, -1.60);
const vec2 Coord5Offset = vec2( 0.25, 1.60);
const vec2 Coord6Offset = vec2( 0.55, -1.00);
const vec2 Coord7Offset = vec2( 1.00, 0.55);
const vec2 Coord8Offset = vec2( 1.60, -0.25);
// imaginary texel dimensions independed from source and target dimension
vec2 TexelDims = vec2(1.0 / 1024.0);
vec2 DefocusTexelDims = u_defocus.xy * TexelDims.xy;
vec4 d0 = texture(s_tex, v_texcoord0);
vec4 d1 = texture(s_tex, v_texcoord0 + Coord1Offset * DefocusTexelDims);
vec4 d2 = texture(s_tex, v_texcoord0 + Coord2Offset * DefocusTexelDims);
vec4 d3 = texture(s_tex, v_texcoord0 + Coord3Offset * DefocusTexelDims);
vec4 d4 = texture(s_tex, v_texcoord0 + Coord4Offset * DefocusTexelDims);
vec4 d5 = texture(s_tex, v_texcoord0 + Coord5Offset * DefocusTexelDims);
vec4 d6 = texture(s_tex, v_texcoord0 + Coord6Offset * DefocusTexelDims);
vec4 d7 = texture(s_tex, v_texcoord0 + Coord7Offset * DefocusTexelDims);
vec4 d8 = texture(s_tex, v_texcoord0 + Coord8Offset * DefocusTexelDims);
vec4 blurred = (d0 + d1 + d2 + d3 + d4 + d5 + d6 + d7 + d8) / 9.0;
blurred.a = blurred.a + d0.a;
FragColor = blurred * v_color0;
}

View file

@ -17,29 +17,40 @@ layout(push_constant) uniform Push
#include "mame_parameters.inc"
#define saturate(c) clamp(c, 0.0, 1.0)
#define mul(a,b) (b*a)
const int ScreenCount = 1;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 v_texcoord0;
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
void main()
{
gl_Position = global.MVP * Position;
v_texcoord0 = TexCoord;
}
const float Epsilon = 1.0e-7;
const float PI = 3.1415927;
const float E = 2.7182817;
const float Gelfond = 23.140692; // e^pi (Gelfond constant)
const float GelfondSchneider = 2.6651442; // 2^sqrt(2) (Gelfond-Schneider constant)
#pragma stage fragment
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
vec4 u_distortion = vec4(global.distortion_amount);
vec4 u_cubic_distortion = vec4(global.cubic_distortion_amount);
vec4 u_distort_corner = vec4(global.distort_corner_amount);
vec4 u_round_corner = vec4(global.round_corner_amount);
vec4 u_smooth_border = vec4(global.smooth_border_amount);
vec4 u_vignetting = vec4(global.vignette_amount);
vec4 u_reflection = vec4(global.reflection_amount);
#define s_tex Source
#define saturate(c) clamp(c, 0., 1.)
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/
float random(vec2 seed)
float rand(vec2 seed)
{
// irrationals for pseudo randomness
vec2 i = vec2(Gelfond, GelfondSchneider);
vec2 i = vec2(23.140692, 2.6651442); // e^pi (Gelfond constant), 2^sqrt(2) (Gelfond-Schneider constant)
return fract(cos(dot(seed, i)) * 123456.0);
}
@ -48,7 +59,7 @@ float random(vec2 seed)
float normalizedSigmoid(float n, float k)
{
// valid for n and k in range of -1.0 and 1.0
return (n - n * k) / (k - abs(n) * 2.0 * k + 1);
return (n - n * k) / (k - abs(n) * 2.0 * k + 1.0);
}
// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
@ -57,41 +68,10 @@ float roundBox(vec2 p, vec2 b, float r)
return length(max(abs(p) - b + r, 0.0)) - r;
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
float DistortionAmount = global.distortion_amount; // k - quartic distortion coefficient
float CubicDistortionAmount = global.cubic_distortion_amount; // kcube - cubic distortion modifier
float DistortCornerAmount = global.distort_corner_amount;
float RoundCornerAmount = global.round_corner_amount;
float SmoothBorderAmount = global.smooth_border_amount;
float VignettingAmount = global.vignette_amount;
float ReflectionAmount = global.reflection_amount;
vec3 LightReflectionColor = vec3(global.reflection_col_r, global.reflection_col_g, global.reflection_col_b); // color temperature 5.000 Kelvin
vec2 QuadDims = params.OutputSize.xy;
vec2 TargetDims = params.FinalViewportSize.xy;
float TargetScale = 1.0;
float GetNoiseFactor(vec3 n, float random)
float GetNoiseFactor(float n, float random)
{
// smaller n become more noisy
return 1.0f + random * max(0.0f, 0.25f * pow(E, -8 * n.x));
return 1.0 + random * max(0.0, 0.25 * pow(2.7182817, -8.0 * n));
}
float GetVignetteFactor(vec2 coord, float amount)
@ -99,10 +79,10 @@ float GetVignetteFactor(vec2 coord, float amount)
vec2 VignetteCoord = coord;
float VignetteLength = length(VignetteCoord);
float VignetteBlur = (amount * 0.75f) + 0.25;
float VignetteBlur = (amount * 0.75) + 0.25;
// 0.5 full screen fitting circle
float VignetteRadius = 1.0f - (amount * 0.25f);
float VignetteRadius = 1.0 - (amount * 0.25);
float Vignette = smoothstep(VignetteRadius, VignetteRadius - VignetteBlur, VignetteLength);
return saturate(Vignette);
@ -113,12 +93,10 @@ float GetSpotAddend(vec2 coord, float amount)
vec2 SpotCoord = coord;
// upper right quadrant
vec2 spotOffset = vec2(-0.25f, 0.25f);
vec2 spotOffset = vec2(-0.25, 0.25);
// normalized screen canvas ratio
vec2 CanvasRatio = SwapXY
? vec2(1.0f, QuadDims.x / QuadDims.y)
: vec2(1.0f, QuadDims.y / QuadDims.x);
vec2 CanvasRatio = ((u_swap_xy.x > 0.0) ? vec2(1.0, u_quad_dims.x / u_quad_dims.y) : vec2(1.0, u_quad_dims.y / u_quad_dims.x));
SpotCoord += spotOffset;
SpotCoord *= CanvasRatio;
@ -126,13 +104,13 @@ float GetSpotAddend(vec2 coord, float amount)
float SpotBlur = amount;
// 0.5 full screen fitting circle
float SpotRadius = amount * 0.75f;
float SpotRadius = amount * 0.75;
float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord));
float SigmoidSpot = amount * normalizedSigmoid(Spot, 0.75);
// increase strength by 100%
SigmoidSpot = SigmoidSpot * 2.0f;
SigmoidSpot = SigmoidSpot * 2.0;
return saturate(SigmoidSpot);
}
@ -143,18 +121,18 @@ float GetBoundsFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothA
smoothAmount = min(smoothAmount, radiusAmount);
float range = min(bounds.x, bounds.y);
float amountMinimum = 1.0f / range;
float amountMinimum = range > 0.0f ? 1.0f / range : 0.0f;
float radius = range * max(radiusAmount, amountMinimum);
float smooth_ = 1.0f / (range * max(smoothAmount, amountMinimum * 2.0f));
float smooth_val = 1.0f / (range * max(smoothAmount, amountMinimum * 2.0f));
// compute box
float box = roundBox(bounds * (coord * 2.0f), bounds, radius);
// apply smooth
box *= smooth_;
box += 1.0f - pow(smooth_ * 0.5f, 0.5f);
box *= smooth_val;
box += 1.0 - pow(smooth_val * 0.5, 0.5);
float border = smoothstep(1.0f, 0.0f, box);
float border = smoothstep(1.0, 0.0, box);
return saturate(border);
}
@ -170,12 +148,10 @@ vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube)
// compute cubic distortion factor
float r2 = centerCoord.x * centerCoord.x + centerCoord.y * centerCoord.y;
float f = kcube == 0.0f
? 1.0f + r2 * k
: 1.0f + r2 * (k + kcube * sqrt(r2));
float f = kcube == 0.0 ? 1.0 + r2 * k : 1.0 + r2 * (k + kcube * sqrt(r2));
// fit screen bounds
f /= 1.0f + amount * 0.25f + amountCube * 0.125f;
f /= 1.0 + amount * 0.25 + amountCube * 0.125;
// apply cubic distortion factor
centerCoord *= f;
@ -186,13 +162,13 @@ vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube)
vec2 GetTextureCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
coord -= 0.5;
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount, cubicDistortionAmount);
// un-center coordinates
coord += 0.5f;
coord += 0.5;
return coord;
}
@ -200,7 +176,7 @@ vec2 GetTextureCoords(vec2 coord, float distortionAmount, float cubicDistortionA
vec2 GetQuadCoords(vec2 coord, vec2 scale, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
coord -= 0.5;
// apply scale
coord *= scale;
@ -211,83 +187,101 @@ vec2 GetQuadCoords(vec2 coord, vec2 scale, float distortionAmount, float cubicDi
return coord;
}
float noise(vec2 p){
vec2 ip = floor(p);
vec2 u = fract(p);
u = u*u*(3.0-2.0*u);
float res = mix(
mix(rand(ip),rand(ip+vec2(1.0,0.0)),u.x),
mix(rand(ip+vec2(0.0,1.0)),rand(ip+vec2(1.0,1.0)),u.x),u.y);
return res*res;
}
vec2 noisecoord(vec2 coord){
float offset_x = noise(sin(gl_FragCoord.xy) * float(mod(params.FrameCount + 873, 3061.)));
float offset_y = noise(cos(gl_FragCoord.yx) * float(mod(params.FrameCount + 2157, 8703.)));
return coord + vec2(offset_x, offset_y) * 0.001 * global.noise_amt;
}
void main()
{
if(!Distortion)
if (!Distortion)
{
FragColor = texture(Source, vTexCoord);
return;
FragColor = texture(s_tex, v_texcoord0);
}
else
{
// image distortion
float distortionAmount = DistortionAmount;
float cubicDistortionAmount = CubicDistortionAmount > 0.0f
? CubicDistortionAmount * 1.1f // cubic distortion need to be a little higher to compensate the quartic distortion
: CubicDistortionAmount * 1.2f; // negativ values even more
float distortionAmount = u_distortion.x;
float cubicDistortionAmount = u_cubic_distortion.x > 0.0
? u_cubic_distortion.x * 1.1 // cubic distortion need to be a little higher to compensate the quartic distortion
: u_cubic_distortion.x * 1.2; // negativ values even more
// corner distortion at least by the amount of the image distorition
float distortCornerAmount = max(DistortCornerAmount, DistortionAmount + CubicDistortionAmount);
float distortCornerAmount = max(u_distort_corner.x, u_distortion.x + u_cubic_distortion.x);
float roundCornerAmount = RoundCornerAmount * 0.5f;
float smoothBorderAmount = SmoothBorderAmount * 0.5f;
float roundCornerAmount = u_round_corner.x * 0.5;
float smoothBorderAmount = u_smooth_border.x * 0.5;
vec2 TexelDims = 1.0f / TargetDims;
vec2 TexelDims = vec2(1.0 / u_target_dims.x, 1.0 / u_target_dims.y);
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = TargetDims / TargetScale;
BaseTargetDims = SwapXY
vec2 BaseTargetDims = u_target_dims.xy / u_target_scale.xy;
BaseTargetDims = (u_swap_xy.x > 0.0)
? BaseTargetDims.yx
: BaseTargetDims.xy;
// base-target/quad difference scale
vec2 BaseTargetQuadScale = (ScreenCount == 1)
? BaseTargetDims / QuadDims // keeps the coords inside of the quad bounds of a single screen
: vec2(1.0);
vec2 BaseTargetQuadScale = (u_screen_count.x > 0.0 && u_screen_count.x < 2.0)
? BaseTargetDims / u_quad_dims.xy // keeps the coords inside of the quad bounds of a single screen
: vec2(1.0, 1.0);
// Screen Texture Curvature
vec2 BaseCoord = GetTextureCoords(vTexCoord, distortionAmount, cubicDistortionAmount);
vec2 BaseCoord = GetTextureCoords(v_texcoord0, distortionAmount, cubicDistortionAmount);
BaseCoord = noisecoord(BaseCoord);
// Screen Quad Curvature
vec2 QuadCoord = GetQuadCoords(vTexCoord, BaseTargetQuadScale, distortCornerAmount, 0.0f);
/*
// clip border
if (BaseCoord.x < 0.0f - TexelDims.x || BaseCoord.y < 0.0f - TexelDims.y ||
BaseCoord.x > 1.0f + TexelDims.x || BaseCoord.y > 1.0f + TexelDims.y)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
*/
vec2 QuadCoord = GetQuadCoords(v_texcoord0, BaseTargetQuadScale, distortCornerAmount, 0.0);
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
vec4 BaseColor = texture(s_tex, BaseCoord);
// Vignetting Simulation
vec2 VignetteCoord = QuadCoord;
// Clamp
if (BaseCoord.x > 1.0 + TexelDims.x || BaseCoord.y > 1.0 + TexelDims.y || BaseCoord.x < 0.0 - TexelDims.x || BaseCoord.y < 0.0 - TexelDims.y)
{
FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
else
{
// Vignetting Simulation
vec2 VignetteCoord = QuadCoord;
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
BaseColor.rgb *= VignetteFactor;
float VignetteFactor = GetVignetteFactor(VignetteCoord, u_vignetting.x);
BaseColor.rgb *= VignetteFactor;
// Light Reflection Simulation
vec2 SpotCoord = QuadCoord;
// Light Reflection Simulation
vec4 LightColor = vec4(1.0, 0.90, 0.80, 1.0); // color temperature 5.000 Kelvin
vec3 SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount) * LightReflectionColor;
BaseColor.rgb += SpotAddend * GetNoiseFactor(SpotAddend, random(SpotCoord));
vec2 SpotCoord = QuadCoord;
vec2 NoiseCoord = QuadCoord;
// Round Corners Simulation
vec2 RoundCornerCoord = QuadCoord;
vec2 RoundCornerBounds = (ScreenCount == 1)
? QuadDims // align corners to quad bounds of a single screen
: BaseTargetDims; // align corners to target bounds of multiple screens
RoundCornerBounds = SwapXY
? RoundCornerBounds.yx
: RoundCornerBounds.xy;
float SpotAddend = GetSpotAddend(SpotCoord, u_reflection.x);
float NoiseFactor = GetNoiseFactor(SpotAddend, rand(NoiseCoord));
BaseColor += SpotAddend * NoiseFactor * LightColor;
float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount);
BaseColor.rgb *= roundCornerFactor;
// Round Corners Simulation
vec2 RoundCornerCoord = QuadCoord;
vec2 RoundCornerBounds = (u_screen_count.x > 0.0 && u_screen_count.x < 2.0)
? u_quad_dims.xy // align corners to screen quad bounds
: BaseTargetDims; // align corners to target texture bounds
RoundCornerBounds = (u_swap_xy.x > 0.0)
? RoundCornerBounds.yx
: RoundCornerBounds.xy;
FragColor = BaseColor;
float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount);
BaseColor.rgb *= roundCornerFactor;
FragColor = BaseColor;
}
}
}
}

View file

@ -0,0 +1,331 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// NTSC Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
vec4 u_a_value = vec4(global.avalue);
vec4 u_b_value = vec4(global.bvalue);
vec4 u_cc_value = vec4(global.ccvalue);
vec4 u_o_value = vec4(global.ovalue);
vec4 u_scan_time = vec4(global.scantime);
vec4 u_notch_width = vec4(global.notch_width);
vec4 u_y_freq_response = vec4(global.yfreqresponse);
vec4 u_i_freq_response = vec4(global.ifreqresponse);
vec4 u_q_freq_response = vec4(global.qfreqresponse);
vec4 u_jitter_offset = vec4(global.jitter_offset);
vec4 u_jitter_amount = vec4(global.jitter);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D Original;
#define s_tex Source
#define s_screen Source
#define v_color0 vec4(1.,1.,1.,1.)
////// Sticking with old NTSC decode because it actually works ///////
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float PI = 3.1415927f;
const float PI2 = PI * 2.0f;
const vec4 YDot = vec4(0.299f, 0.587f, 0.114f, 0.0f);
const vec4 IDot = vec4(0.595716f, -0.274453f, -0.321263f, 0.0f);
const vec4 QDot = vec4(0.211456f, -0.522591f, 0.311135f, 0.0f);
const vec3 RDot = vec3(1.0f, 0.956f, 0.621f);
const vec3 GDot = vec3(1.0f, -0.272f, -0.647f);
const vec3 BDot = vec3(1.0f, -1.106f, 1.703f);
const vec4 OffsetX = vec4(0.0f, 0.25f, 0.50f, 0.75f);
const vec4 NotchOffset = vec4(0.0f, 1.0f, 2.0f, 3.0f);
const int SampleCount = 64;
const int HalfSampleCount = SampleCount / 2;
float AValue = global.avalue;
float BValue = global.bvalue;
float CCValue = global.ccvalue;
float OValue = global.ovalue;
float PValue = global.pvalue;
float ScanTime = global.scantime;
float NotchHalfWidth = global.notch_width / 2.0;
float YFreqResponse = global.yfreqresponse;
float IFreqResponse = global.ifreqresponse;
float QFreqResponse = global.qfreqresponse;
float SignalOffset = 0.0;//global.jitter_offset;
void main()
{
if(!NTSCSignal)
{
FragColor = texture(s_tex, v_texcoord0);
return;
}
else
{
vec4 BaseTexel = texture(s_tex, v_texcoord0);
float TimePerSample = ScanTime / (u_source_dims.x * 4.0f);
float Fc_y1 = (CCValue - NotchHalfWidth) * TimePerSample;
float Fc_y2 = (CCValue + NotchHalfWidth) * TimePerSample;
float Fc_y3 = YFreqResponse * TimePerSample;
float Fc_i = IFreqResponse * TimePerSample;
float Fc_q = QFreqResponse * TimePerSample;
float Fc_i_2 = Fc_i * 2.0f;
float Fc_q_2 = Fc_q * 2.0f;
float Fc_y1_2 = Fc_y1 * 2.0f;
float Fc_y2_2 = Fc_y2 * 2.0f;
float Fc_y3_2 = Fc_y3 * 2.0f;
float Fc_i_pi2 = Fc_i * PI2;
float Fc_q_pi2 = Fc_q * PI2;
float Fc_y1_pi2 = Fc_y1 * PI2;
float Fc_y2_pi2 = Fc_y2 * PI2;
float Fc_y3_pi2 = Fc_y3 * PI2;
float PI2Length = PI2 / SampleCount;
float W = PI2 * CCValue * ScanTime;
float WoPI = W / PI;
float HOffset = (BValue + SignalOffset) / WoPI;
float VScale = (AValue * u_source_dims.y) / WoPI;
vec4 YAccum = vec4(0.0);
vec4 IAccum = vec4(0.0);
vec4 QAccum = vec4(0.0);
vec4 Cy = v_texcoord0.yyyy;
vec4 VPosition = Cy;
for (float i = 0; i < SampleCount; i += 4.0f)
{
float n = i - HalfSampleCount;
vec4 n4 = n + NotchOffset;
vec4 Cx = v_texcoord0.x + (n4 * 0.25f) / u_source_dims.x;
vec4 HPosition = Cx;
vec4 C = texture(Source, vec2(Cx.r, Cy.r));
vec4 T = HPosition + HOffset + VPosition * VScale;
vec4 WT = W * T + OValue;
vec4 SincKernel = 0.54f + 0.46f * cos(PI2Length * n4);
vec4 SincYIn1 = Fc_y1_pi2 * n4;
vec4 SincYIn2 = Fc_y2_pi2 * n4;
vec4 SincYIn3 = Fc_y3_pi2 * n4;
vec4 SincIIn = Fc_i_pi2 * n4;
vec4 SincQIn = Fc_q_pi2 * n4;
vec4 SincY1, SincY2, SincY3;
SincY1.x = (SincYIn1.x != 0.0f) ? sin(SincYIn1.x) / SincYIn1.x : 1.0f;
SincY1.y = (SincYIn1.y != 0.0f) ? sin(SincYIn1.y) / SincYIn1.y : 1.0f;
SincY1.z = (SincYIn1.z != 0.0f) ? sin(SincYIn1.z) / SincYIn1.z : 1.0f;
SincY1.w = (SincYIn1.w != 0.0f) ? sin(SincYIn1.w) / SincYIn1.w : 1.0f;
SincY2.x = (SincYIn2.x != 0.0f) ? sin(SincYIn2.x) / SincYIn2.x : 1.0f;
SincY2.y = (SincYIn2.y != 0.0f) ? sin(SincYIn2.y) / SincYIn2.y : 1.0f;
SincY2.z = (SincYIn2.z != 0.0f) ? sin(SincYIn2.z) / SincYIn2.z : 1.0f;
SincY2.w = (SincYIn2.w != 0.0f) ? sin(SincYIn2.w) / SincYIn2.w : 1.0f;
SincY3.x = (SincYIn3.x != 0.0f) ? sin(SincYIn3.x) / SincYIn3.x : 1.0f;
SincY3.y = (SincYIn3.y != 0.0f) ? sin(SincYIn3.y) / SincYIn3.y : 1.0f;
SincY3.z = (SincYIn3.z != 0.0f) ? sin(SincYIn3.z) / SincYIn3.z : 1.0f;
SincY3.w = (SincYIn3.w != 0.0f) ? sin(SincYIn3.w) / SincYIn3.w : 1.0f;
vec4 IdealY, IdealI, IdealQ;
IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3;
IdealI.x = Fc_i_2 * (SincIIn.x != 0.0f ? sin(SincIIn.x) / SincIIn.x : 1.0f);
IdealI.y = Fc_i_2 * (SincIIn.y != 0.0f ? sin(SincIIn.y) / SincIIn.y : 1.0f);
IdealI.z = Fc_i_2 * (SincIIn.z != 0.0f ? sin(SincIIn.z) / SincIIn.z : 1.0f);
IdealI.w = Fc_i_2 * (SincIIn.w != 0.0f ? sin(SincIIn.w) / SincIIn.w : 1.0f);
IdealQ.x = Fc_q_2 * (SincQIn.x != 0.0f ? sin(SincQIn.x) / SincQIn.x : 1.0f);
IdealQ.y = Fc_q_2 * (SincQIn.y != 0.0f ? sin(SincQIn.y) / SincQIn.y : 1.0f);
IdealQ.z = Fc_q_2 * (SincQIn.z != 0.0f ? sin(SincQIn.z) / SincQIn.z : 1.0f);
IdealQ.w = Fc_q_2 * (SincQIn.w != 0.0f ? sin(SincQIn.w) / SincQIn.w : 1.0f);
vec4 FilterY = SincKernel * IdealY;
vec4 FilterI = SincKernel * IdealI;
vec4 FilterQ = SincKernel * IdealQ;
YAccum = YAccum + C * FilterY;
IAccum = IAccum + C * cos(WT) * FilterI;
QAccum = QAccum + C * sin(WT) * FilterQ;
}
vec3 YIQ = vec3(
(YAccum.r + YAccum.g + YAccum.b + YAccum.a),
(IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0f,
(QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0f);
vec3 RGB = vec3(
dot(YIQ, RDot),
dot(YIQ, GDot),
dot(YIQ, BDot));
FragColor = vec4(RGB, BaseTexel.a);
}
}
////// new version included for future debugging purposes ///////////
/*
void main()
{
vec4 BaseTexel = texture(s_screen, v_texcoord0.xy);
vec4 zero = vec4(0.0, 0.0, 0.0, 0.0);
vec4 quarter = vec4(0.25, 0.25, 0.25, 0.25);
vec4 onehalf = vec4(0.5, 0.5, 0.5, 0.5);
vec4 one = vec4(1.0, 1.0, 1.0, 1.0);
vec4 two = vec4(2.0, 2.0, 2.0, 2.0);
vec4 four = vec4(4.0, 4.0, 4.0, 4.0);
int iSampleCount = 64;
vec4 SampleCount = vec4(64.0, 64.0, 64.0, 64.0);
vec4 HalfSampleCount = SampleCount / two;
vec4 TimePerSample = u_scan_time.xxxx / (u_source_dims.xxxx * four);
vec4 PI = vec4(3.1415927, 3.1415927, 3.1415927, 3.1415927);
vec4 PI2 = vec4(6.2831854, 6.2831854, 6.2831854, 6.2831854);
vec4 Fc_y1 = (u_cc_value.xxxx - u_notch_width.xxxx * onehalf) * TimePerSample;
vec4 Fc_y2 = (u_cc_value.xxxx + u_notch_width.xxxx * onehalf) * TimePerSample;
vec4 Fc_y3 = u_y_freq_response.xxxx * TimePerSample;
vec4 Fc_i = u_i_freq_response.xxxx * TimePerSample;
vec4 Fc_q = u_q_freq_response.xxxx * TimePerSample;
vec4 Fc_i_2 = Fc_i * two;
vec4 Fc_q_2 = Fc_q * two;
vec4 Fc_y1_2 = Fc_y1 * two;
vec4 Fc_y2_2 = Fc_y2 * two;
vec4 Fc_y3_2 = Fc_y3 * two;
vec4 Fc_i_pi2 = Fc_i * PI2;
vec4 Fc_q_pi2 = Fc_q * PI2;
vec4 Fc_y1_pi2 = Fc_y1 * PI2;
vec4 Fc_y2_pi2 = Fc_y2 * PI2;
vec4 Fc_y3_pi2 = Fc_y3 * PI2;
vec4 PI2Length = PI2 / SampleCount;
vec4 W = PI2 * u_cc_value.xxxx * u_scan_time.xxxx;
vec4 WoPI = W / PI;
vec4 HOffset = (u_b_value.xxxx + u_jitter_amount.xxxx * u_jitter_offset.xxxx) / WoPI;
vec4 VScale = (u_a_value.xxxx * u_source_dims.yyyy) / WoPI;
vec4 YAccum = vec4(0.0);
vec4 IAccum = vec4(0.0);
vec4 QAccum = vec4(0.0);
vec4 Cy = v_texcoord0.yyyy;
vec4 VPosition = Cy;
vec4 n = vec4(0.0);
vec4 n4 = vec4(0.0);
vec4 Cx = vec4(0.0);
vec4 HPosition = vec4(0.0);
vec4 C = vec4(0.0);
vec4 T = vec4(0.0);
vec4 WT = vec4(0.0);
vec4 SincKernel = vec4(0.0);
vec4 SincYIn1 = vec4(0.0);
vec4 SincYIn2 = vec4(0.0);
vec4 SincYIn3 = vec4(0.0);
vec4 SincIIn = vec4(0.0);
vec4 SincQIn = vec4(0.0);
vec4 SincY1 = vec4(0.0);
vec4 SincY2 = vec4(0.0);
vec4 SincY3 = vec4(0.0);
vec4 IdealY = vec4(0.0);
vec4 IdealI = vec4(0.0);
vec4 IdealQ = vec4(0.0);
vec4 FilterY = vec4(0.0);
vec4 FilterI = vec4(0.0);
vec4 FilterQ = vec4(0.0);
for (int i = 0; i < 64; i++)
{
i += 4;
n = vec4(i, i, i, i) - vec4(32.0, 32.0, 32.0, 32.0);
n4 = n + vec4(0.0, 1.0, 2.0, 3.0);
Cx = v_texcoord0.xxxx + (n4 * quarter) / u_source_dims.xxxx;
HPosition = Cx;
C = texture(s_tex, vec2(Cx.x, Cy.x));
T = HPosition + HOffset + VPosition * VScale;
WT = W * T + u_o_value.xxxx;
SincKernel.rgb = vec4(0.54, 0.54, 0.54, 0.54).rgb + vec4(0.46, 0.46, 0.46, 0.46).rgb * cos(PI2Length * n4).rgb;
// SincKernel.a = anything nonzero, we get NaN
SincYIn1 = Fc_y1_pi2 * n4;
SincYIn2 = Fc_y2_pi2 * n4;
SincYIn3 = Fc_y3_pi2 * n4;
SincIIn = Fc_i_pi2 * n4;
SincQIn = Fc_q_pi2 * n4;
SincY1 = (SincYIn1 != zero) ? sin(SincYIn1) / SincYIn1 : one;
SincY2 = (SincYIn2 != zero) ? sin(SincYIn2) / SincYIn2 : one;
SincY3 = (SincYIn3 != zero) ? sin(SincYIn3) / SincYIn3 : one;
IdealY = (Fc_y1_2 * SincY1 - Fc_y2_2 * SincY2) + Fc_y3_2 * SincY3;
IdealI = Fc_i_2 * (SincIIn != zero ? sin(SincIIn) / SincIIn : one);
IdealQ = Fc_q_2 * (SincQIn != zero ? sin(SincQIn) / SincQIn : one);
FilterY = SincKernel * IdealY;
FilterI = SincKernel * IdealI;
FilterQ = SincKernel * IdealQ;
YAccum = YAccum + C * FilterY;
IAccum = IAccum + C * cos(WT) * FilterI;
QAccum = QAccum + C * sin(WT) * FilterQ;
}
vec3 YIQ = vec3(
(YAccum.r + YAccum.g + YAccum.b + YAccum.a),
(IAccum.r + IAccum.g + IAccum.b + IAccum.a) * 2.0,
(QAccum.r + QAccum.g + QAccum.b + QAccum.a) * 2.0);
vec3 RGB = vec3(
dot(YIQ, vec3(1.0, 0.956, 0.621)),
dot(YIQ, vec3(1.0, -0.272, -0.647)),
dot(YIQ, vec3(1.0, -1.106, 1.703)));
// RGB obviously contains a NaN somewhere along the line! Returns black if vec4 etc. are included, white if just vec4(1.0)
FragColor = vec4(RGB, BaseTexel.a) * v_color0;
}
*/

View file

@ -0,0 +1,114 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// NTSC Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
vec4 u_a_value = vec4(global.avalue);
vec4 u_b_value = vec4(global.bvalue);
vec4 u_cc_value = vec4(global.ccvalue);
vec4 u_p_value = vec4(global.pvalue);
vec4 u_scan_time = vec4(global.scantime);
vec4 u_jitter_offset = vec4(global.jitter_offset);
vec4 u_jitter_amount = vec4(global.jitter);
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float PI = 3.1415927f;
const float PI2 = PI * 2.0f;
const vec4 YDot = vec4(0.299f, 0.587f, 0.114f, 0.0f);
const vec4 IDot = vec4(0.595716f, -0.274453f, -0.321263f, 0.0f);
const vec4 QDot = vec4(0.211456f, -0.522591f, 0.311135f, 0.0f);
const vec3 RDot = vec3(1.0f, 0.956f, 0.621f);
const vec3 GDot = vec3(1.0f, -0.272f, -0.647f);
const vec3 BDot = vec3(1.0f, -1.106f, 1.703f);
const vec4 OffsetX = vec4(0.0f, 0.25f, 0.50f, 0.75f);
const vec4 NotchOffset = vec4(0.0f, 1.0f, 2.0f, 3.0f);
const int SampleCount = 64;
const int HalfSampleCount = SampleCount / 2;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define s_tex Source
void main()
{
if(!NTSCSignal)
{
FragColor = texture(s_tex, v_texcoord0);
return;
}
else
{
vec2 PValueSourceTexel = vec2(u_p_value.x, 0.0) / u_source_dims.xy;
vec2 C0 = v_texcoord0 + PValueSourceTexel * vec2(0.0, 0.0);
vec2 C1 = v_texcoord0 + PValueSourceTexel * vec2(0.25, 0.0);
vec2 C2 = v_texcoord0 + PValueSourceTexel * vec2(0.5, 0.0);
vec2 C3 = v_texcoord0 + PValueSourceTexel * vec2(0.75, 0.0);
vec4 Cx = vec4(C0.x, C1.x, C2.x, C3.x);
vec4 Cy = vec4(C0.y, C1.y, C2.y, C3.y);
vec4 Texel0 = texture(s_tex, C0);
vec4 Texel1 = texture(s_tex, C1);
vec4 Texel2 = texture(s_tex, C2);
vec4 Texel3 = texture(s_tex, C3);
vec4 HPosition = Cx;
vec4 VPosition = Cy;
const vec4 YDot = vec4(0.299, 0.587, 0.114, 0.0);
const vec4 IDot = vec4(0.595716, -0.274453, -0.321263, 0.0);
const vec4 QDot = vec4(0.211456, -0.522591, 0.311135, 0.0);
vec4 Y = vec4(dot(Texel0, YDot), dot(Texel1, YDot), dot(Texel2, YDot), dot(Texel3, YDot));
vec4 I = vec4(dot(Texel0, IDot), dot(Texel1, IDot), dot(Texel2, IDot), dot(Texel3, IDot));
vec4 Q = vec4(dot(Texel0, QDot), dot(Texel1, QDot), dot(Texel2, QDot), dot(Texel3, QDot));
const float PI = 3.1415927;
const float PI2 = 6.2831854;
float W = PI2 * u_cc_value.x * u_scan_time.x;
float WoPI = W / PI;
float HOffset = (u_a_value.x + u_jitter_amount.x * u_jitter_offset.x) / WoPI;
float VScale = (u_b_value.x * u_source_dims.y) / WoPI;
vec4 T = HPosition + vec4(HOffset, HOffset, HOffset, HOffset) + VPosition * vec4(VScale, VScale, VScale, VScale);
vec4 TW = T * W;
FragColor = Y + I * cos(TW) + Q * sin(TW);
}
}

View file

@ -2,7 +2,7 @@ layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
// effect toggles and multi
float bloomtoggle;
// float bloomtoggle;
float ntscsignal;
float scanlinetoggle;
float chromatoggle;
@ -15,19 +15,19 @@ layout(std140, set = 0, binding = 0) uniform UBO
// bloom params
float bloomblendmode;
// float vectorscreen;
float bloomscale;
float bloomoverdrive_r;
float bloomoverdrive_g;
float bloomoverdrive_b;
float level0weight;
float level1weight;
float level2weight;
float level3weight;
float level4weight;
float level5weight;
float level6weight;
float level7weight;
float level8weight;
// float bloomscale;
// float bloomoverdrive_r;
// float bloomoverdrive_g;
// float bloomoverdrive_b;
// float level0weight;
// float level1weight;
// float level2weight;
// float level3weight;
// float level4weight;
// float level5weight;
// float level6weight;
// float level7weight;
// float level8weight;
// post params
float mask_width;
float mask_height;
@ -61,15 +61,21 @@ layout(std140, set = 0, binding = 0) uniform UBO
float ovalue;
float pvalue;
float scantime;
float notchhalfwidth;
float notch_width;
float yfreqresponse;
float ifreqresponse;
float qfreqresponse;
float signaloffset;
float jitter_offset;
// color params
float col_red;
float col_grn;
float col_blu;
float col_rr;
float col_rg;
float col_rb;
float col_gr;
float col_gg;
float col_gb;
float col_br;
float col_bg;
float col_bb;
float col_offset_x;
float col_offset_y;
float col_offset_z;
@ -98,11 +104,12 @@ layout(std140, set = 0, binding = 0) uniform UBO
float scanlineoffset;
float scanlinebrightscale;
float scanlinebrightoffset;
float scanline_jitter_amount;
// defocus params
float defocus_x;
float defocus_y;
// phosphor params
float deltatime;
float time;
float phosphor_r;
float phosphor_g;
float phosphor_b;
@ -125,9 +132,14 @@ layout(std140, set = 0, binding = 0) uniform UBO
float smooth_border_amount;
float vignette_amount;
float reflection_amount;
float reflection_col_r;
float reflection_col_g;
float reflection_col_b;
// float reflection_col_r;
// float reflection_col_g;
// float reflection_col_b;
float jitter;
float humbar_hertz_rate;
float prescale;
float scanline_crawl;
float noise_amt;
// vector params
// float timeratio;
// float timescale;
@ -141,58 +153,61 @@ layout(std140, set = 0, binding = 0) uniform UBO
bool NTSCSignal = bool(global.ntscsignal);
#pragma parameter scanlinetoggle "Scanline Toggle" 1.0 0.0 1.0 1.0
bool ScanlineToggle = bool(global.scanlinetoggle);
#pragma parameter bloomtoggle "Bloom Enable" 0.0 0.0 1.0 1.0
bool BloomToggle = bool(global.bloomtoggle);
//#pragma parameter bloomtoggle "Bloom Enable" 0.0 0.0 1.0 1.0
//bool BloomToggle = bool(global.bloomtoggle);
#pragma parameter chromatoggle "Chromaticity Toggle" 0.0 0.0 1.0 1.0
bool Chromaticity = bool(global.chromatoggle);
#pragma parameter distortiontoggle "Distortion Toggle" 0.0 0.0 1.0 1.0
bool Distortion = bool(global.distortiontoggle);
#pragma parameter phosphortoggle "Phosphor Toggle" 0.0 0.0 1.0 1.0
bool Passthrough = !bool(global.phosphortoggle);
#pragma parameter screenscale_x "Screen Scale X" 1.0 0.5 3.0 0.01
#pragma parameter screenscale_y "Screen Scale Y" 1.0 0.5 3.0 0.01
#pragma parameter screenscale_x "Screen Scale X" 0.0 -3.0 3.0 0.005
#pragma parameter screenscale_y "Screen Scale Y" 0.0 -3.0 3.0 0.005
vec2 ScreenScale = vec2(global.screenscale_x, global.screenscale_y);
//#pragma parameter vectorscreen "Vector Screen Mode" 0.0 0.0 1.0 1.0 // TODO/FIXME
const float vectorscreen = 0.0;
bool VectorScreen = bool(vectorscreen);
#pragma parameter jitter "Scanline Jitter (OFF/ON/AUTO)" 0.0 0.0 2.0 1.0
#pragma parameter scanline_crawl "Scanline Crawl" 0.0 0.0 1.0 1.0
#pragma parameter screenoffset_x "Screen Offset X" 0.0 -1.0 1.0 0.005
#pragma parameter screenoffset_y "Screen Offset Y" 0.0 -1.0 1.0 0.005
#pragma parameter screenoffset_x "Screen Offset X" 0.0 -1.0 1.0 0.001
#pragma parameter screenoffset_y "Screen Offset Y" 0.0 -1.0 1.0 0.001
vec2 ScreenOffset = vec2(global.screenoffset_x, global.screenoffset_y);
#pragma parameter swapxy "Swap X and Y" 0.0 0.0 1.0 1.0
bool SwapXY = bool(global.swapxy);
// Bloom Pass
#pragma parameter bloomblendmode "Bloom Blend Mode" 0.0 0.0 1.0 1.0
#pragma parameter bloomscale "Bloom Scale" 0.33 0.0 1.0 0.01
#pragma parameter bloomoverdrive_r "Bloom Overdrive R" 1.0 0.0 2.0 0.01
#pragma parameter bloomoverdrive_g "Bloom Overdrive G" 1.0 0.0 2.0 0.01
#pragma parameter bloomoverdrive_b "Bloom Overdrive B" 1.0 0.0 2.0 0.01
#pragma parameter level0weight "Bloom Level 0 Weight" 0.64 0.0 1.0 0.01
#pragma parameter level1weight "Bloom Level 1 Weight" 0.64 0.0 1.0 0.01
#pragma parameter level2weight "Bloom Level 2 Weight" 0.32 0.0 1.0 0.01
#pragma parameter level3weight "Bloom Level 3 Weight" 0.16 0.0 1.0 0.01
#pragma parameter level4weight "Bloom Level 4 Weight" 0.08 0.0 1.0 0.01
#pragma parameter level5weight "Bloom Level 5 Weight" 0.06 0.0 1.0 0.01
#pragma parameter level6weight "Bloom Level 6 Weight" 0.04 0.0 1.0 0.01
#pragma parameter level7weight "Bloom Level 7 Weight" 0.02 0.0 1.0 0.01
#pragma parameter level8weight "Bloom Level 8 Weight" 0.01 0.0 1.0 0.01
//#pragma parameter bloomblendmode "Bloom Blend Mode" 0.0 0.0 1.0 1.0
//#pragma parameter bloomscale "Bloom Scale" 0.33 0.0 1.0 0.01
//#pragma parameter bloomoverdrive_r "Bloom Overdrive R" 1.0 0.0 2.0 0.01
//#pragma parameter bloomoverdrive_g "Bloom Overdrive G" 1.0 0.0 2.0 0.01
//#pragma parameter bloomoverdrive_b "Bloom Overdrive B" 1.0 0.0 2.0 0.01
//#pragma parameter level0weight "Bloom Level 0 Weight" 0.64 0.0 1.0 0.01
//#pragma parameter level1weight "Bloom Level 1 Weight" 0.64 0.0 1.0 0.01
//#pragma parameter level2weight "Bloom Level 2 Weight" 0.32 0.0 1.0 0.01
//#pragma parameter level3weight "Bloom Level 3 Weight" 0.16 0.0 1.0 0.01
//#pragma parameter level4weight "Bloom Level 4 Weight" 0.08 0.0 1.0 0.01
//#pragma parameter level5weight "Bloom Level 5 Weight" 0.06 0.0 1.0 0.01
//#pragma parameter level6weight "Bloom Level 6 Weight" 0.04 0.0 1.0 0.01
//#pragma parameter level7weight "Bloom Level 7 Weight" 0.02 0.0 1.0 0.01
//#pragma parameter level8weight "Bloom Level 8 Weight" 0.01 0.0 1.0 0.01
// Post Pass
#pragma parameter humbaralpha "Hum Bar Alpha" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_r "Back Color R" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_g "Back Color G" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_b "Back Color B" 0.0 0.0 1.0 0.01
#pragma parameter shadowtilemode "Mask Tiling Mode" 0.0 0.0 1.0 1.0
#pragma parameter shadowalpha "Mask Alpha" 0.3 0.0 1.0 0.01
#pragma parameter shadowcount_x "Mask Tile Size X" 6.0 1.0 32.0 1.0
#pragma parameter shadowcount_y "Mask Tile Size Y" 6.0 1.0 32.0 1.0
#pragma parameter shadowuv_x "Mask UV X" 0.25 0.0 1.0 0.01
#pragma parameter shadowuv_y "Mask UV Y" 0.25 0.0 1.0 0.01
#pragma parameter mask_width "Mask Texture Width" 32.0 0.0 256.0 16.0
#pragma parameter mask_height "Mask Texture Height" 32.0 0.0 256.0 16.0
#pragma parameter mask_offset_x "Mask Offset X" 0.0 -10.0 10.0 0.1
#pragma parameter mask_offset_y "Mask Offset Y" 0.0 -10.0 10.0 0.1
#pragma parameter humbaralpha "Hum Bar Amount" 0.0 0.0 1.0 0.01
#pragma parameter humbar_hertz_rate "Hum Bar Frequency" 0.001 0.0 1.0 0.001
//#pragma parameter backcolor_r "Back Color R" 0.0 0.0 1.0 0.01
//#pragma parameter backcolor_g "Back Color G" 0.0 0.0 1.0 0.01
//#pragma parameter backcolor_b "Back Color B" 0.0 0.0 1.0 0.01
#pragma parameter shadowtilemode "Shadow Mask Tile Mode" 0.0 0.0 1.0 1.0
#pragma parameter shadowalpha "Shadow Mask Amount" 0.5 0.0 1.0 0.01
#pragma parameter shadowcount_x "Shadow Mask Pixel Count X" 12.0 1.0 128.0 1.0
#pragma parameter shadowcount_y "Shadow Mask Pixel Count Y" 12.0 1.0 128.0 1.0
#pragma parameter shadowuv_x "Shadow Mask UV Size X" 0.5 0.0 1.0 0.001
#pragma parameter shadowuv_y "Shadow Mask UV Size Y" 0.5 0.0 1.0 0.001
//#pragma parameter mask_width "Mask Texture Width" 32.0 0.0 256.0 16.0
//#pragma parameter mask_height "Mask Texture Height" 32.0 0.0 256.0 16.0
#pragma parameter mask_offset_x "Mask Offset X" 0.0 0.0 10.0 0.001
#pragma parameter mask_offset_y "Mask Offset Y" 0.0 0.0 10.0 0.001
#pragma parameter chromamode "Chroma Mode" 3.0 1.0 3.0 1.0
#pragma parameter conversiongain_x "Conversion Gain X" 0.0 -5.0 5.0 0.5
#pragma parameter conversiongain_y "Conversion Gain Y" 0.0 -5.0 5.0 0.5
@ -203,32 +218,38 @@ bool SwapXY = bool(global.swapxy);
#pragma parameter floor_r "Color Floor R" 0.0 0.0 1.0 0.01
#pragma parameter floor_g "Color Floor G" 0.0 0.0 1.0 0.01
#pragma parameter floor_b "Color Floor B" 0.0 0.0 1.0 0.01
#pragma parameter preparebloom "Prepare Bloom" 0.0 0.0 1.0 1.0
//#pragma parameter preparebloom "Prepare Bloom" 0.0 0.0 1.0 1.0
// NTSC Pass
#pragma parameter avalue "A Value" 0.5 -1.0 1.0 0.01
#pragma parameter bvalue "B Value" 0.5 -1.0 1.0 0.01
#pragma parameter ccvalue "CC Value" 3.5795454 0.0 6.0 0.0005
#pragma parameter ovalue "O Value" 0.0 -3.0 3.0 0.1
#pragma parameter pvalue "P Value" 1.0 -3.0 3.0 0.1
#pragma parameter scantime "Scan Time" 52.6 0.0 100.0 0.1
#pragma parameter notchhalfwidth "Notch Half Width" 1.0 0.0 6.0 0.05
#pragma parameter yfreqresponse "Y Freq Response" 6.0 0.0 6.0 0.05
#pragma parameter ifreqresponse "I Freq Response" 1.2 0.0 6.0 0.05
#pragma parameter qfreqresponse "Q Freq Response" 0.6 0.0 6.0 0.05
#pragma parameter signaloffset "Signal Offset" 1.0 0.0 1.0 0.01
#pragma parameter avalue "NTSC A Value" 0.5 0.0 1.0 0.01
#pragma parameter bvalue "NTSC B Value" 0.5 0.0 1.0 0.01
#pragma parameter ccvalue "NTSC Color Carrier (Hz)" 3.5795454 3.47954 3.67954 0.00001
#pragma parameter ovalue "NTSC Outgoing Phase Offset" 0.0 0.0 1.0 0.01
#pragma parameter pvalue "NTSC Incoming Phase Pixel Clock Scale" 1.0 0.0 2.0 0.01
#pragma parameter scantime "NTSC Scanline Duration (uSec)" 52.6 1.0 150.0 0.1
#pragma parameter notch_width "NTSC Color Notch Filter Width" 2.0 1.0 4.0 0.01
#pragma parameter yfreqresponse "NTSC Y Signal Bandwidth (Hz)" 6.0 0.0 21.0 0.05
#pragma parameter ifreqresponse "NTSC I Signal Bandwidth (Hz)" 1.2 0.0 21.0 0.05
#pragma parameter qfreqresponse "NTSC Q Signal Bandwidth (Hz)" 0.6 0.0 21.0 0.05
#pragma parameter jitter_offset "NTSC Frame Jitter Offset" 0.0 0.0 2.0 0.01
// Color Pass
#pragma parameter col_red "Red Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_grn "Green Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_blu "Blue Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_offset_x "Offset X" 0.0 -1.0 1.0 0.01
#pragma parameter col_offset_y "Offset Y" 0.0 -1.0 1.0 0.01
#pragma parameter col_offset_z "Offset Z" 0.0 -1.0 1.0 0.01
#pragma parameter col_scale_x "Scale X" 1.0 0.0 2.0 0.01
#pragma parameter col_scale_y "Scale Y" 1.0 0.0 2.0 0.01
#pragma parameter col_scale_z "Scale Z" 1.0 0.0 2.0 0.01
#pragma parameter col_saturation "Saturation" 1.0 0.0 5.0 0.01
#pragma parameter col_rr "Red Shift Red" 1.0 0.0 2.0 0.01
#pragma parameter col_rg "Red Shift Green" 0.0 0.0 2.0 0.01
#pragma parameter col_rb "Red Shift Blue" 0.0 0.0 2.0 0.01
#pragma parameter col_gr "Green Shift Red" 0.0 0.0 2.0 0.01
#pragma parameter col_gg "Green Shift Green" 1.0 0.0 2.0 0.01
#pragma parameter col_gb "Green Shift Blue" 0.0 0.0 2.0 0.01
#pragma parameter col_br "Blue Shift Red" 0.0 0.0 2.0 0.01
#pragma parameter col_bg "Blue Shift Green" 0.0 0.0 2.0 0.01
#pragma parameter col_bb "Blue Shift Blue" 1.0 0.0 2.0 0.01
#pragma parameter col_offset_x "Offset X" 0.0 0.0 2.0 0.01
#pragma parameter col_offset_y "Offset Y" 0.0 0.0 2.0 0.01
#pragma parameter col_offset_z "Offset Z" 0.0 0.0 2.0 0.01
#pragma parameter col_scale_x "Scale X" 0.95 0.0 2.0 0.01
#pragma parameter col_scale_y "Scale Y" 0.95 0.0 2.0 0.01
#pragma parameter col_scale_z "Scale Z" 0.95 0.0 2.0 0.01
#pragma parameter col_saturation "Color Saturation" 1.2 0.0 4.0 0.01
// Deconverge Pass
#pragma parameter converge_x_r "Convergence X Red" 0.0 -10.0 10.0 0.05
@ -237,31 +258,31 @@ bool SwapXY = bool(global.swapxy);
#pragma parameter converge_y_r "Convergence Y Red" 0.0 -10.0 10.0 0.05
#pragma parameter converge_y_g "Convergence Y Green" 0.0 -10.0 10.0 0.05
#pragma parameter converge_y_b "Convergence Y Blue" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_r "Radial Conv X Red" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_g "Radial Conv X Green" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_b "Radial Conv X Blue" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_r "Radial Conv Y Red" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_g "Radial Conv Y Green" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_b "Radial Conv Y Blue" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_r "Radial Conv X Red" 0.0 -10.0 10.0 0.01
#pragma parameter radial_conv_x_g "Radial Conv X Green" 0.0 -10.0 10.0 0.01
#pragma parameter radial_conv_x_b "Radial Conv X Blue" 0.0 -10.0 10.0 0.01
#pragma parameter radial_conv_y_r "Radial Conv Y Red" 0.0 -10.0 10.0 0.01
#pragma parameter radial_conv_y_g "Radial Conv Y Green" 0.0 -10.0 10.0 0.01
#pragma parameter radial_conv_y_b "Radial Conv Y Blue" 0.0 -10.0 10.0 0.01
// Scanline Pass
#pragma parameter scanlinealpha "Scanline Alpha" 0.5 0.0 1.0 0.01
#pragma parameter scanlinescale "Scanline Scale" 5.0 1.0 5.0 1.0
#pragma parameter scanlineheight "Scanline Height" 1.0 0.0 2.0 0.1
#pragma parameter scanlinevariation "Scanline Variation" 1.0 0.0 5.0 0.5
#pragma parameter scanlineoffset "Scanline Offset" 1.0 -1.5 3.0 0.1
#pragma parameter scanlinebrightscale "Scanline Bright Scale" 1.0 0.0 2.0 0.1
#pragma parameter scanlinebrightoffset "Scanline Bright Offset" 1.0 -1.5 3.0 0.1
#pragma parameter scanlinealpha "Scanline Amount" 0.35 0.0 1.0 0.01
#pragma parameter scanlinescale "Overall Scanline Scale" 1.0 0.0 4.0 0.01
#pragma parameter scanlineheight "Individual Scanline Scale" 1.0 0.0 4.0 0.01
#pragma parameter scanlinevariation "Scanline Variation" 1.0 0.0 4.0 0.01
//#pragma parameter scanlineoffset "Scanline Offset" 1.0 -1.5 3.0 0.01
#pragma parameter scanlinebrightscale "Scanline Brightness Scale" 2.0 0.0 4.0 0.01
#pragma parameter scanlinebrightoffset "Scanline Brightness Offset" 1.5 0.0 4.0 0.01
#pragma parameter scanline_jitter_amount "Scanline Jitter Amount" 0.25 0.0 2.0 0.01
// Defocus Pass
#pragma parameter defocus_x "Defocus X Axis" 0.0 0.0 10.0 0.1
#pragma parameter defocus_y "Defocus Y Axis" 0.0 0.0 10.0 0.1
// Phosphor Pass
#pragma parameter deltatime "Delta Time" 1.0 0.0 2.0 0.1
#pragma parameter phosphor_r "Phosphor Red" 0.8 0.0 0.99 0.1
#pragma parameter phosphor_g "Phosphor Green" 0.0 0.0 0.99 0.1
#pragma parameter phosphor_b "Phosphor Blue" 0.0 0.0 0.99 0.1
#pragma parameter phosphor_r "Phosphor Red" 0.45 0.0 0.99 0.01
#pragma parameter phosphor_g "Phosphor Green" 0.45 0.0 0.99 0.01
#pragma parameter phosphor_b "Phosphor Blue" 0.45 0.0 0.99 0.01
// Chroma Pass
#pragma parameter ygain_r "Y Gain R Channel" 0.2126 0.0 1.0 0.01
@ -275,16 +296,17 @@ bool SwapXY = bool(global.swapxy);
#pragma parameter chromac_y "Chroma C Y" 0.070 0.0 1.0 0.01
// Distortion Pass
#pragma parameter distortion_amount "Distortion Amount" 0.0 0.0 1.0 0.01
#pragma parameter cubic_distortion_amount "Cubic Dist. Amt" 0.0 0.0 1.0 0.01
#pragma parameter distort_corner_amount "Corner Dist. Amt" 0.0 0.0 1.0 0.01
#pragma parameter round_corner_amount "Corner Rounding" 0.0 0.0 1.0 0.01
#pragma parameter smooth_border_amount "Border Smoothing" 0.0 0.0 1.0 0.01
#pragma parameter vignette_amount "Vignetting Amount" 0.0 0.0 1.0 0.01
#pragma parameter reflection_amount "Reflection Amount" 0.0 0.0 1.0 0.01
#pragma parameter reflection_col_r "Reflection Color R" 1.0 0.0 1.0 0.01
#pragma parameter reflection_col_g "Reflection Color G" 0.9 0.0 1.0 0.01
#pragma parameter reflection_col_b "Reflection Color B" 0.8 0.0 1.0 0.01
#pragma parameter distortion_amount "Quadric Dist. Amt" 0.05 -2.0 2.0 0.01
#pragma parameter cubic_distortion_amount "Cubic Dist. Amt" 0.0 -2.0 2.0 0.01
#pragma parameter distort_corner_amount "Dist. Corner Amt" 0.05 0.0 2.0 0.01
#pragma parameter round_corner_amount "Rounded Corner Amt" 0.05 0.0 2.0 0.01
#pragma parameter smooth_border_amount "Smooth Border Amt" 0.03 0.0 2.0 0.01
#pragma parameter vignette_amount "Vignetting Amount" 0.08 0.0 2.0 0.01
#pragma parameter reflection_amount "Reflection Amount" 0.05 0.0 2.0 0.01
#pragma parameter noise_amt "Noise/Grain (reduces moire)" 1.0 0.0 5.0 0.25
//#pragma parameter reflection_col_r "Reflection Color R" 1.0 0.0 1.0 0.01
//#pragma parameter reflection_col_g "Reflection Color G" 1.0 0.0 1.0 0.01
//#pragma parameter reflection_col_b "Reflection Color B" 1.0 0.0 1.0 0.01
// Vector Pass
//#pragma parameter timeratio "Time Ratio" 1.0 0.0 2.0 0.01
@ -292,3 +314,17 @@ bool SwapXY = bool(global.swapxy);
//#pragma parameter lengthratio "Length Ratio" 1.0 1.0 10.0 1.0
//#pragma parameter lengthscale "Length Scale" 1.0 1.0 10.0 1.0
//#pragma parameter beamsmooth "Beam Smooth Amt" 0.5 0.1 1.0 0.1
// Prescale Pass
#pragma parameter prescale "PreScale Factor" 2.0 1.0 4.0 1.0
vec4 u_swap_xy = vec4(global.swapxy);
vec4 u_source_dims = params.OriginalSize;
vec4 u_target_dims = params.OutputSize;
vec4 u_target_scale = params.OutputSize / params.SourceSize;
vec4 u_screen_scale = vec4(1.-global.screenscale_x, 1.-global.screenscale_y, 1., 1.);
vec4 u_screen_offset = vec4(global.screenoffset_x, global.screenoffset_y, 0.,0.);
vec4 u_screen_count = vec4(1.);
vec4 u_screen_dims = vec4(params.OutputSize);
vec4 u_quad_dims = params.FinalViewportSize;
vec4 u_time = vec4(params.FrameCount);//vec4(mod(params.FrameCount, global.time / 16.));

View file

@ -12,45 +12,40 @@ layout(push_constant) uniform Push
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
float DeltaTime = global.deltatime;
vec3 Phosphor = vec3(global.phosphor_r, global.phosphor_g, global.phosphor_b);
const float F = 1.0;
vec4 u_passthrough = vec4(1.0 - global.phosphortoggle);
vec4 u_phosphor = vec4(global.phosphor_r, global.phosphor_g, global.phosphor_b, 0.0);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D PassFeedback6;
layout(set = 0, binding = 3) uniform sampler2D PassFeedback8;
#define DiffuseSampler Source
#define PreviousSampler PassFeedback6
#define s_tex Source
#define s_prev PassFeedback8
void main()
{
vec4 CurrY = texture(DiffuseSampler, vTexCoord);
vec3 PrevY = texture(PreviousSampler, vTexCoord).rgb;
vec4 curr = texture(s_tex, v_texcoord0);
vec3 prev = texture(s_prev, v_texcoord0).rgb * u_phosphor.rgb;
PrevY[0] *= (Phosphor[0] == 0.0) ? 0.0 : pow(Phosphor[0], F * DeltaTime);
PrevY[1] *= (Phosphor[1] == 0.0) ? 0.0 : pow(Phosphor[1], F * DeltaTime);
PrevY[2] *= (Phosphor[2] == 0.0) ? 0.0 : pow(Phosphor[2], F * DeltaTime);
float a = max(PrevY[0], CurrY[0]);
float b = max(PrevY[1], CurrY[1]);
float c = max(PrevY[2], CurrY[2]);
FragColor = Passthrough ? CurrY : vec4(a, b, c, CurrY.a);
vec3 maxed = max(curr.rgb, prev);
FragColor = u_passthrough.x > 0.0 ? curr : vec4(maxed, curr.a);
}

View file

@ -2,9 +2,6 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Shadowmask Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
@ -12,85 +9,68 @@ layout(push_constant) uniform Push
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
#define TargetDims params.OutputSize.xy
#define SourceDims params.OriginalSize.xy
float TargetScale = 1.0;//max(TargetDims.x / SourceDims.x, TargetDims.y / SourceDims.y);
float HumBarAlpha = global.humbaralpha;
float TimeMilliseconds = float(mod(params.FrameCount, 1000));
vec3 BackColor = vec3(global.backcolor_r, global.backcolor_g, global.backcolor_b);
int ShadowTileMode = int(global.shadowtilemode); // 0 based on screen (quad) dimension, 1 based on source dimension
float ShadowAlpha = global.shadowalpha;
vec2 ShadowCount = vec2(global.shadowcount_x, global.shadowcount_y);
vec2 ShadowUV = vec2(global.shadowuv_x, global.shadowuv_y);
vec2 ShadowDims = vec2(global.mask_width, global.mask_height);
vec2 ShadowUVOffset = vec2(global.mask_offset_x, global.mask_offset_y);
int ChromaMode = int(global.chromamode);
vec3 ConversionGain = vec3(global.conversiongain_x, global.conversiongain_y, global.conversiongain_z);
vec3 Power = vec3(global.power_r, global.power_g, global.power_b);
vec3 Floor = vec3(global.floor_r, global.floor_g, global.floor_b);
bool PrepareBloom = bool(global.preparebloom);
#define MONOCHROME 1
#define DICHROME 2
#define TRICHROME 3
vec4 u_shadow_tile_mode = vec4(global.shadowtilemode);
vec4 u_shadow_alpha = vec4(global.shadowalpha);
vec4 u_shadow_count = vec4(global.shadowcount_x, global.shadowcount_y, 0., 0.);
vec4 u_shadow_uv = vec4(global.shadowuv_x, global.shadowuv_y, 0., 0.);
vec4 u_shadow_uv_offset = vec4(global.mask_offset_x, global.mask_offset_y, 0., 0.);
vec4 u_humbar_hertz_rate = vec4(global.humbar_hertz_rate);
// ^^difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC)
vec4 u_humbar_alpha = vec4(global.humbaralpha);
vec4 u_power = vec4(global.power_r, global.power_g, global.power_b, 0.);
vec4 u_floor = vec4(global.floor_r, global.floor_g, global.floor_b, 0.);
//-----------------------------------------------------------------------------
// Constants
// Shadowmask Pixel Shader
//-----------------------------------------------------------------------------
const float PI = 3.1415927;
const float HalfPI = PI * 0.5;
float HumBarDesync = 60.0 / 59.94 - 1.0; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC)
vec2 GetAdjustedCoords(vec2 coord)
{
// center coordinates
coord -= 0.5;
// apply screen scale
coord *= ScreenScale;
coord *= u_screen_scale.xy;
// un-center coordinates
coord += 0.5;
// apply screen offset
coord += ScreenOffset;
coord += u_screen_offset.xy;
return coord;
}
vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
{
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = TargetDims / TargetScale;
BaseTargetDims = SwapXY
// base-target dimensions (remove oversampling)
vec2 BaseTargetDims = u_target_dims.xy / u_target_scale.xy;
BaseTargetDims = u_swap_xy.x > 0.0
? BaseTargetDims.yx
: BaseTargetDims.xy;
vec2 canvasCoord = ShadowTileMode == 0
? TargetCoord + ShadowUVOffset / BaseTargetDims
: SourceCoord + ShadowUVOffset / SourceDims;
vec2 canvasTexelDims = ShadowTileMode == 0
? 1.0 / BaseTargetDims
: 1.0 / SourceDims;
vec2 canvasCoord = u_shadow_tile_mode.x == 0.0
? TargetCoord + u_shadow_uv_offset.xy / BaseTargetDims
: SourceCoord + u_shadow_uv_offset.xy / u_source_dims.xy;
vec2 canvasTexelDims = u_shadow_tile_mode.x == 0.0
? vec2(1.0, 1.0) / BaseTargetDims
: vec2(1.0, 1.0) / u_source_dims.xy;
vec2 shadowDims = ShadowDims;
vec2 shadowUV = ShadowUV;
vec2 shadowCount = ShadowCount;
vec2 shadowUV = u_shadow_uv.xy;
vec2 shadowCount = u_shadow_count.xy;
// swap x/y in screen mode (not source mode)
canvasCoord = ShadowTileMode == 0 && SwapXY
canvasCoord = u_shadow_tile_mode.x == 0.0 && u_swap_xy.x > 0.0
? canvasCoord.yx
: canvasCoord.xy;
// swap x/y in screen mode (not source mode)
shadowCount = ShadowTileMode == 0 && SwapXY
shadowCount = u_shadow_tile_mode.x == 0.0 && u_swap_xy.x > 0.0
? shadowCount.yx
: shadowCount.xy;
@ -99,14 +79,11 @@ vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
vec2 shadowFrac = fract(canvasCoord / shadowTile);
// swap x/y in screen mode (not source mode)
shadowFrac = ShadowTileMode == 0 && SwapXY
shadowFrac = u_shadow_tile_mode.x == 0.0 && u_swap_xy.x > 0.0
? shadowFrac.yx
: shadowFrac.xy;
vec2 shadowCoord = (shadowFrac * shadowUV);
shadowCoord += ShadowTileMode == 0
? vec2(0.5) * (vec2(1.0) / shadowDims) // fix half texel offset (DX9)
: vec2(0.0);
return shadowCoord;
}
@ -114,84 +91,74 @@ vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D MaskTexture;
#define DiffuseSampler Source
#define ShadowSampler MaskTexture
#define s_tex Source
#define s_shadow MaskTexture
//#define ScreenCoord vTexCoord
#define v_color0 vec4(1.,1.,1.,1.)
void main()
{
vec2 ScreenCoord = vTexCoord;
vec2 BaseCoord = GetAdjustedCoords(ScreenCoord);
vec2 BaseCoord = GetAdjustedCoords(v_texcoord0);
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0;
/*
// clip border
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 ||
BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
vec4 BaseColor = texture(s_tex, BaseCoord);
// Clamp
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 || BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0, 0.0, 0.0, 1.0);
FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
*/
// Color Compression (may not affect bloom)
if (!PrepareBloom)
else
{
// Mask Simulation
if (u_shadow_alpha.x > 0.0)
{
vec2 ShadowCoord = GetShadowCoord(v_texcoord0.xy, BaseCoord.xy);
vec4 ShadowColor = texture(s_shadow, ShadowCoord);
vec3 ShadowMaskColor = mix(vec3(1.0, 1.0, 1.0), ShadowColor.rgb, u_shadow_alpha.xxx);
// apply shadow mask color
BaseColor.rgb *= ShadowMaskColor;
// // TODO
// vec3 ShadowMaskClear = (1.0f - ShadowColor.a) * u_shadow_alpha.xxx;
// // clear shadow mask by background color
// BaseColor.rgb = mix(BaseColor.rgb, u_back_color.rgb, ShadowMaskClear);
}
// Color Compression
// increasing the floor of the signal without affecting the ceiling
BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb;
BaseColor.rgb = u_floor.rgb + (vec3(1.0, 1.0, 1.0) - u_floor.rgb) * BaseColor.rgb;
// Color Power
BaseColor.r = pow(BaseColor.r, u_power.r);
BaseColor.g = pow(BaseColor.g, u_power.g);
BaseColor.b = pow(BaseColor.b, u_power.b);
// Hum Bar Simulation
if (u_humbar_alpha.x > 0.0f)
{
float HumTimeStep = fract(u_time.x * u_humbar_hertz_rate.x);
float HumBrightness = 1.0 - fract(BaseCoord.y + HumTimeStep) * u_humbar_alpha.x;
BaseColor.rgb *= HumBrightness;
}
FragColor = vec4(BaseColor.rgb * v_color0.rgb, BaseColor.a);
}
// Color Power (may affect bloom)
BaseColor.r = pow(BaseColor.r, Power.r);
BaseColor.g = pow(BaseColor.g, Power.g);
BaseColor.b = pow(BaseColor.b, Power.b);
// Hum Bar Simulation (may not affect vector screen)
if (!PrepareBloom && !VectorScreen && HumBarAlpha > 0.0)
{
float HumBarStep = fract(TimeMilliseconds * HumBarDesync);
float HumBarBrightness = 1.0 - fract(BaseCoord.y + HumBarStep) * HumBarAlpha;
BaseColor.rgb *= HumBarBrightness;
}
// Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0)
{
vec2 ShadowCoord = GetShadowCoord(ScreenCoord, BaseCoord);
vec4 ShadowColor = texture(ShadowSampler, ShadowCoord);
vec3 ShadowMaskColor = mix(vec3(1.0), ShadowColor.rgb, ShadowAlpha);
float ShadowMaskClear = (1.0 - ShadowColor.a) * ShadowAlpha;
// apply shadow mask color
BaseColor.rgb *= ShadowMaskColor;
// clear shadow mask by background color
BaseColor.rgb = mix(BaseColor.rgb, BackColor, ShadowMaskClear);
}
// Preparation for phosphor color conversion
if (ChromaMode == MONOCHROME) {
BaseColor.r = dot(ConversionGain, BaseColor.rgb);
BaseColor.gb = vec2(BaseColor.r, BaseColor.r);
} else if (ChromaMode == DICHROME) {
BaseColor.r = dot(ConversionGain.rg, BaseColor.rg);
BaseColor.g = BaseColor.r;
}
FragColor = BaseColor;
}

View file

@ -0,0 +1,51 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
vec4 u_tex_size0 = params.SourceSize;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define s_tex Source
#define v_color0 vec4(1.,1.,1.,1.)
void main()
{
vec2 Scale = (global.prescale * u_tex_size0.xy) / u_source_dims.xy;
vec2 TexelDims = v_texcoord0.xy * u_source_dims.xy;
vec2 i = floor(TexelDims);
vec2 s = fract(TexelDims);
// Figure out where in the texel to sample to get the correct pre-scaled bilinear.
vec2 CenterDistance = s - 0.5;
vec2 RegionRange = 0.5 - 0.5 / Scale;
vec2 f = (CenterDistance - clamp(CenterDistance, -RegionRange, RegionRange)) * Scale + 0.5;
vec2 TexCoord = (i + f) / u_source_dims.xy;
FragColor = texture(s_tex, TexCoord.xy) * v_color0;
}

View file

@ -17,41 +17,33 @@ layout(push_constant) uniform Push
#include "mame_parameters.inc"
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
vec4 u_scanline_alpha = vec4(global.scanlinealpha);
vec4 u_scanline_scale = vec4(global.scanlinescale);
vec4 u_scanline_bright_scale = vec4(global.scanlinebrightscale);
vec4 u_scanline_bright_offset = vec4(global.scanlinebrightoffset);
vec4 u_scanline_jitter = vec4((global.jitter != 0.0) ? (params.OriginalSize.y > 400.0 || global.jitter == 1.0) ? (mod(params.FrameCount, 2.0)) : 0.0 : 0.0);
vec4 u_scanline_height = vec4(global.scanlineheight);
vec4 u_scanline_variation = vec4(global.scanlinevariation);
const float PI = 3.1415927;
const float HalfPI = PI * 0.5;
vec4 u_jitter_amount = vec4(global.scanline_jitter_amount);
//-----------------------------------------------------------------------------
// Scanline Pixel Shader
//-----------------------------------------------------------------------------
float ScanlineAlpha = global.scanlinealpha;
float ScanlineScale = global.scanlinescale;
float ScanlineHeight = global.scanlineheight;
float ScanlineVariation = global.scanlinevariation;
float ScanlineOffset = global.scanlineoffset;
float ScanlineBrightScale = global.scanlinebrightscale;
float ScanlineBrightOffset = global.scanlinebrightoffset;
vec2 QuadDims = params.FinalViewportSize.xy;
vec2 SourceDims = params.OriginalSize.xy;
vec2 GetAdjustedCoords(vec2 coord)
{
// center coordinates
coord -= 0.5;
// apply screen scale
coord *= ScreenScale;
coord *= u_screen_scale.xy;
// un-center coordinates
coord += 0.5;
// apply screen offset
coord += ScreenOffset;
coord += u_screen_offset.xy;
return coord;
}
@ -59,67 +51,67 @@ vec2 GetAdjustedCoords(vec2 coord)
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 0) out vec2 v_texcoord0;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
v_texcoord0 = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) in vec2 v_texcoord0;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D MaskTexture;
#define DiffuseSampler Source
#define s_tex Source
#define s_shadow MaskTexture
#define v_color0 vec4(1.,1.,1.,1.)
void main()
{
if(!ScanlineToggle)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
vec2 BaseCoord = GetAdjustedCoords(vTexCoord);
vec2 BaseCoord = GetAdjustedCoords(v_texcoord0);
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0;
/*
// clip border
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 ||
BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0, 0.0, 0.0, 1.0);
}
*/
float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha);
float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0 - ScanlineAlpha);
// Color
vec4 BaseColor = texture(s_tex, BaseCoord);
float ColorBrightness = 0.299 * BaseColor.r + 0.587 * BaseColor.g + 0.114 * BaseColor.b;
// Clamp
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 || BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
{
FragColor = vec4(0.0, 0.0, 0.0, 0.0);
}
else
{
// Scanline Simulation
if (ScanlineToggle)
{
float BrightnessOffset = (u_scanline_bright_offset.x * u_scanline_alpha.x);
float BrightnessScale = (u_scanline_bright_scale.x * u_scanline_alpha.x) + (1.0 - u_scanline_alpha.x);
float ScanlineCoord = BaseCoord.y;
ScanlineCoord += (SwapXY)
? QuadDims.x <= SourceDims.x * 2.0
? 0.5 / QuadDims.x // uncenter scanlines if the quad is less than twice the size of the source
: 0.0
: QuadDims.y <= SourceDims.y * 2.0
? 0.5 / QuadDims.y // uncenter scanlines if the quad is less than twice the size of the source
: 0.0;
ScanlineCoord *= SourceDims.y * ScanlineScale * PI;
float ColorBrightness = 0.299 * BaseColor.r + 0.587 * BaseColor.g + 0.114 * BaseColor.b;
float ScanlineCoordJitter = ScanlineOffset * HalfPI;
float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter);
float ScanlineWide = ScanlineHeight + ScanlineVariation * max(1.0f, ScanlineHeight) * (1.0 - ColorBrightness);
float ScanlineAmount = pow(ScanlineSine * ScanlineSine, ScanlineWide);
float ScanlineBrightness = ScanlineAmount * BrightnessScale + BrightnessOffset * BrightnessScale;
float ScanCoord = BaseCoord.y;
ScanCoord += (global.scanline_crawl > 0.0) ? -1.* u_time.x * params.OutputSize.w * u_jitter_amount.x : 0.0;
ScanCoord += u_swap_xy.x > 0.0
? u_quad_dims.x <= u_source_dims.x * 2.0
? 0.5 / u_quad_dims.x // uncenter scanlines if the quad is less than twice the size of the source
: 0.0
: u_quad_dims.y <= u_source_dims.y * 2.0
? 0.5 / u_quad_dims.y // uncenter scanlines if the quad is less than twice the size of the source
: 0.0;
BaseColor.rgb *= mix(1.0, ScanlineBrightness, ScanlineAlpha);
ScanCoord *= u_source_dims.y * u_scanline_scale.x * 3.1415927; // PI
FragColor = BaseColor;
}
float ScanCoordJitter = u_scanline_jitter.x * 1.5707963; // half PI
float ScanSine = sin(ScanCoord + ScanCoordJitter);
float ScanlineWide = u_scanline_height.x + u_scanline_variation.x * max(1.0, u_scanline_height.x) * (1.0 - ColorBrightness);
float ScanSineScaled = pow(ScanSine * ScanSine, ScanlineWide);
float ScanBrightness = ScanSineScaled * BrightnessScale + BrightnessOffset * BrightnessScale;
BaseColor.rgb *= mix(vec3(1.0, 1.0, 1.0), vec3(ScanBrightness, ScanBrightness, ScanBrightness), u_scanline_alpha.xxx);
}
FragColor = vec4(BaseColor.rgb * v_color0.rgb, BaseColor.a);
}
}

View file

@ -0,0 +1,85 @@
# info on how the passes come together can be found in mame/src/osd/modules/render/d3d/d3dhlsl.cpp
shaders = 12
shader0 = shaders/mame_hlsl/shaders/mame_ntsc.slang
filter_linear0 = true
alias0 = NTSCPass
scale_type0 = source
scale0 = 1.0
shader1 = shaders/mame_hlsl/shaders/mame_color.slang
alias1 = ColorPass
scale_type1 = source
scale1 = 1.0
filter_linear1 = true
shader2 = ../interpolation/shaders/sharp-bilinear.slang
alias2 = PrescalePass
scale_type2 = source
filter_linear2 = true
scale2 = 4.0
shader3 = shaders/mame_hlsl/shaders/mame_deconverge.slang
alias3 = DeconvergePass
filter_linear3 = true
scale_type3 = source
scale3 = 0.5
shader4 = shaders/mame_hlsl/shaders/mame_scanline.slang
alias4 = ScanlinePass
filter_linear4 = true
scale_type4 = source
scale4 = 2.0
shader5 = shaders/mame_hlsl/shaders/mame_focus.slang
alias5 = FocusPass
filter_linear5 = true
shader6 = shaders/mame_hlsl/shaders/mame_phosphor.slang
alias6 = PhosphorPass
filter_linear6 = true
shader7 = shaders/mame_hlsl/shaders/mame_post.slang
alias7 = PostPass
filter_linear7 = true
scale_type7 = viewport
shader8 = shaders/mame_hlsl/shaders/mame_chroma.slang
alias8 = ChromaPass
filter_linear8 = true
scale_type8 = viewport
shader9 = shaders/mame_hlsl/shaders/mame_downsample.slang
alias9 = DownsamplePass
filter_linear9 = true
shader10 = shaders/mame_hlsl/shaders/mame_bloom.slang
alias10 = BloomPass
filter_linear10 = true
mipmap_input10 = true
scale_type10 = source
shader11 = shaders/mame_hlsl/shaders/mame_distortion.slang
alias11 = DistortionPass
filter_linear11 = true
# doesn't work, so commenting
# shader12 = shaders/mame_hlsl/shaders/mame_vector.slang
# alias12 = VectorPass
# filter_linear12 = true
# mame's textures are available here: https://github.com/mamedev/mame/tree/master/artwork
textures = "MaskTexture"
MaskTexture = shaders/mame_hlsl/resources/aperture-grille.png
parameters = "AUTO_PRESCALE;chromaa_x;chromaa_y;chromab_x;chromab_y;chromac_x;chromac_y;ygain_r;ygain_g;ygain_b"
chromaa_x = "0.630"
chromaa_y = "0.340"
chromab_x = "0.310"
chromab_y = "0.595"
chromac_x = "0.155"
chromac_y = "0.070"
ygain_r = "0.1875"
ygain_g = "0.6940"
ygain_b = "0.1185"
AUTO_PRESCALE = "0.0"

View file

@ -0,0 +1,231 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Bloom Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OutputSize;
} params;
#include "mame_parameters.inc"
float Level0Weight = global.level0weight;
float Level1Weight = global.level1weight;
float Level2Weight = global.level2weight;
float Level3Weight = global.level3weight;
float Level4Weight = global.level4weight;
float Level5Weight = global.level5weight;
float Level6Weight = global.level6weight;
float Level7Weight = global.level7weight;
float Level8Weight = global.level8weight;
int BloomBlendMode = int(global.bloomblendmode); // 0 brighten, 1 darken
float BloomScale = global.bloomscale;
vec3 BloomOverdrive = vec3(global.bloomoverdrive_r, global.bloomoverdrive_g, global.bloomoverdrive_b);
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float E = 2.7182817f;
const float Gelfond = 23.140692f; // e^pi (Gelfond constant)
const float GelfondSchneider = 2.6651442f; // 2^sqrt(2) (Gelfond-Schneider constant)
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/
float random(vec2 seed)
{
// irrationals for pseudo randomness
vec2 i = vec2(Gelfond, GelfondSchneider);
return fract(cos(dot(seed, i)) * 123456.0f);
}
//-----------------------------------------------------------------------------
// Bloom Vertex Shader
//-----------------------------------------------------------------------------
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
layout(location = 1) out vec2 BloomCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
BloomCoord = vTexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 1) in vec2 BloomCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
#define BloomSamplerA Source
#define BloomSamplerB Source
#define BloomSamplerC Source
#define BloomSamplerD Source
#define BloomSamplerE Source
#define BloomSamplerF Source
#define BloomSamplerG Source
#define BloomSamplerH Source
// vector screen uses twice -1 as many bloom levels
#define BloomSamplerI Source
#define BloomSamplerJ Source
#define BloomSamplerK Source
#define BloomSamplerL Source
#define BloomSamplerM Source
#define BloomSamplerN Source
#define BloomSamplerO Source
vec3 GetNoiseFactor(vec3 n, float random)
{
// smaller n become more noisy
vec3 NoiseFactor;
NoiseFactor.x = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.x));
NoiseFactor.y = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.y));
NoiseFactor.z = 1.0 + random * max(0.0, 0.25 * pow(E, -8. * n.z));
return NoiseFactor;
}
void main()
{
if(!BloomToggle)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
vec3 texel = texture(DiffuseSampler, vTexCoord).rgb;
vec3 texelA = texture(BloomSamplerA, BloomCoord.xy).rgb;
vec3 texelB = texture(BloomSamplerB, BloomCoord.xy).rgb;
vec3 texelC = texture(BloomSamplerC, BloomCoord.xy).rgb;
vec3 texelD = texture(BloomSamplerD, BloomCoord.xy).rgb;
vec3 texelE = texture(BloomSamplerE, BloomCoord.xy).rgb;
vec3 texelF = texture(BloomSamplerF, BloomCoord.xy).rgb;
vec3 texelG = texture(BloomSamplerG, BloomCoord.xy).rgb;
vec3 texelH = texture(BloomSamplerH, BloomCoord.xy).rgb;
vec3 texelI = vec3(0.0, 0.0, 0.0);
vec3 texelJ = vec3(0.0, 0.0, 0.0);
vec3 texelK = vec3(0.0, 0.0, 0.0);
vec3 texelL = vec3(0.0, 0.0, 0.0);
vec3 texelM = vec3(0.0, 0.0, 0.0);
vec3 texelN = vec3(0.0, 0.0, 0.0);
vec3 texelO = vec3(0.0, 0.0, 0.0);
// vector screen uses twice -1 as many bloom levels
if (VectorScreen)
{
texelI = texture(BloomSamplerI, BloomCoord.xy).rgb;
texelJ = texture(BloomSamplerJ, BloomCoord.xy).rgb;
texelK = texture(BloomSamplerK, BloomCoord.xy).rgb;
texelL = texture(BloomSamplerL, BloomCoord.xy).rgb;
texelM = texture(BloomSamplerM, BloomCoord.xy).rgb;
texelN = texture(BloomSamplerN, BloomCoord.xy).rgb;
texelO = texture(BloomSamplerO, BloomCoord.xy).rgb;
}
vec3 blend;
// brighten
if (BloomBlendMode < 0.5)
{
vec3 bloom = vec3(0.0, 0.0, 0.0);
texel *= Level0Weight;
if (VectorScreen)
{
bloom += texelA * Level1Weight;
bloom += texelB * Level2Weight;
bloom += texelC * Level3Weight;
bloom += texelD * Level4Weight;
bloom += texelE * Level5Weight;
bloom += texelF * Level6Weight;
bloom += texelG * Level7Weight;
bloom += texelH * Level8Weight;
}
// vector screen uses twice -1 as many bloom levels
else
{
bloom += texelA * (Level1Weight);
bloom += texelB * (Level1Weight + Level2Weight) * 0.5;
bloom += texelC * (Level2Weight);
bloom += texelD * (Level2Weight + Level3Weight) * 0.5;
bloom += texelE * (Level3Weight);
bloom += texelF * (Level3Weight + Level4Weight) * 0.5;
bloom += texelG * (Level4Weight);
bloom += texelH * (Level4Weight + Level5Weight) * 0.5;
bloom += texelI * (Level5Weight);
bloom += texelJ * (Level5Weight + Level6Weight) * 0.5;
bloom += texelK * (Level6Weight);
bloom += texelL * (Level6Weight + Level7Weight) * 0.5;
bloom += texelM * (Level7Weight);
bloom += texelN * (Level7Weight + Level8Weight) * 0.5;
bloom += texelO * (Level8Weight);
}
bloom *= BloomScale;
vec3 bloomOverdrive;
bloomOverdrive.r = max(0.0, texel.r + bloom.r - 1.0) * BloomOverdrive.r;
bloomOverdrive.g = max(0.0, texel.g + bloom.g - 1.0) * BloomOverdrive.g;
bloomOverdrive.b = max(0.0, texel.b + bloom.b - 1.0) * BloomOverdrive.b;
bloom.r += bloomOverdrive.g * 0.5;
bloom.r += bloomOverdrive.b * 0.5;
bloom.g += bloomOverdrive.r * 0.5;
bloom.g += bloomOverdrive.b * 0.5;
bloom.b += bloomOverdrive.r * 0.5;
bloom.b += bloomOverdrive.g * 0.5;
vec2 NoiseCoord = vTexCoord;
vec3 NoiseFactor = GetNoiseFactor(bloom, random(NoiseCoord));
blend = texel + bloom * NoiseFactor;
}
// darken
else
{
texelA = min(texel, texelA);
texelB = min(texel, texelB);
texelC = min(texel, texelC);
texelD = min(texel, texelD);
texelE = min(texel, texelE);
texelF = min(texel, texelF);
texelG = min(texel, texelG);
texelH = min(texel, texelH);
blend = texel * Level0Weight;
blend = mix(blend, texelA, Level1Weight * BloomScale);
blend = mix(blend, texelB, Level2Weight * BloomScale);
blend = mix(blend, texelC, Level3Weight * BloomScale);
blend = mix(blend, texelD, Level4Weight * BloomScale);
blend = mix(blend, texelE, Level5Weight * BloomScale);
blend = mix(blend, texelF, Level6Weight * BloomScale);
blend = mix(blend, texelG, Level7Weight * BloomScale);
blend = mix(blend, texelH, Level8Weight * BloomScale);
}
FragColor = vec4(blend, 1.0);
}
}

View file

@ -0,0 +1,69 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:W. M. Martinez
//-----------------------------------------------------------------------------
// Phosphor Chromaticity to sRGB Transform Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
#define mul(a,b) (b*a)
vec3 YGain = vec3(global.ygain_r, global.ygain_g, global.ygain_b);
vec2 ChromaA = vec2(global.chromaa_x, global.chromaa_y);
vec2 ChromaB = vec2(global.chromab_x, global.chromab_y);
vec2 ChromaC = vec2(global.chromac_x, global.chromac_y);
const mat3 XYZ_TO_sRGB = mat3(
3.2406, -1.5372, -0.4986,
-0.9689, 1.8758, 0.0415,
0.0557, -0.2040, 1.0570);
void main()
{
if(!Chromaticity)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
vec4 cin = texture(DiffuseSampler, vTexCoord);
vec4 cout = vec4(0.0, 0.0, 0.0, cin.a);
mat3x2 xy = { ChromaA, ChromaB, ChromaC };
for (int i = 0; i < 3; ++i) {
float Y = YGain[i] * cin[i];
float X = xy[i].x * (Y / xy[i].y);
float Z = (1.0 - xy[i].x - xy[i].y) * (Y / xy[i].y);
cout.rgb += mul(XYZ_TO_sRGB, vec3(X, Y, Z));
}
FragColor = cout;
}
}

View file

@ -0,0 +1,65 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
//-----------------------------------------------------------------------------
// Color-Convolution Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
vec3 RedRatios = vec3(global.col_red, 0.0, 0.0);
vec3 GrnRatios = vec3(0.0, global.col_grn, 0.0);
vec3 BluRatios = vec3(0.0, 0.0, global.col_blu);
vec3 Offset = vec3(global.col_offset_x, global.col_offset_y, global.col_offset_z);
vec3 Scale = vec3(global.col_scale_x, global.col_scale_y, global.col_scale_z);
float Saturation = global.col_saturation;
void main()
{
vec4 BaseTexel = texture(DiffuseSampler, vTexCoord);
vec3 OutRGB = BaseTexel.rgb;
// RGB Tint & Shift
float ShiftedRed = dot(OutRGB, RedRatios);
float ShiftedGrn = dot(OutRGB, GrnRatios);
float ShiftedBlu = dot(OutRGB, BluRatios);
// RGB Scale & Offset
vec3 OutTexel = vec3(ShiftedRed, ShiftedGrn, ShiftedBlu) * Scale + Offset;
// Saturation
vec3 Grayscale = vec3(0.299f, 0.587f, 0.114f);
float OutLuma = dot(OutTexel, Grayscale);
vec3 OutChroma = OutTexel - OutLuma;
vec3 Saturated = OutLuma + OutChroma * Saturation;
FragColor = vec4(Saturated, BaseTexel.a);
}

View file

@ -0,0 +1,76 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Deconvergence Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
vec3 ConvergeX = vec3(global.converge_x_r, global.converge_x_g, global.converge_x_b);
vec3 ConvergeY = vec3(global.converge_y_r, global.converge_y_g, global.converge_y_b);
vec3 RadialConvergeX = vec3(global.radial_conv_x_r, global.radial_conv_x_g, global.radial_conv_x_b);
vec3 RadialConvergeY = vec3(global.radial_conv_y_r, global.radial_conv_y_g, global.radial_conv_y_b);
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec3 TexCoordX;
layout(location = 1) out vec3 TexCoordY;
void main()
{
gl_Position = global.MVP * Position;
// imaginary texel dimensions independed from screen dimension, but ratio
vec2 TexelDims = vec2(1.0 / 1024.);
TexCoordX = TexCoord.xxx;
TexCoordY = TexCoord.yyy;
// center coordinates
TexCoordX -= 0.5;
TexCoordY -= 0.5;
// radial converge offset to "translate" the most outer pixel as thay would be translated by the linar converge with the same amount
vec2 radialConvergeOffset = vec2(2.0);
// radial converge
TexCoordX *= 1.0 + RadialConvergeX * TexelDims.xxx * radialConvergeOffset.xxx;
TexCoordY *= 1.0 + RadialConvergeY * TexelDims.yyy * radialConvergeOffset.yyy;
// un-center coordinates
TexCoordX += 0.5;
TexCoordY += 0.5;
// linear converge
TexCoordX += ConvergeX * TexelDims.xxx;
TexCoordY += ConvergeY * TexelDims.yyy;
}
#pragma stage fragment
layout(location = 0) in vec3 TexCoordX;
layout(location = 1) in vec3 TexCoordY;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
void main()
{
float r = texture(DiffuseSampler, vec2(TexCoordX.x, TexCoordY.x)).r;
float g = texture(DiffuseSampler, vec2(TexCoordX.y, TexCoordY.y)).g;
float b = texture(DiffuseSampler, vec2(TexCoordX.z, TexCoordY.z)).b;
FragColor = vec4(r, g, b, 1.0);
}

View file

@ -0,0 +1,293 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:ImJezze
//-----------------------------------------------------------------------------
// Distortion Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
#define saturate(c) clamp(c, 0.0, 1.0)
#define mul(a,b) (b*a)
const int ScreenCount = 1;
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float Epsilon = 1.0e-7;
const float PI = 3.1415927;
const float E = 2.7182817;
const float Gelfond = 23.140692; // e^pi (Gelfond constant)
const float GelfondSchneider = 2.6651442; // 2^sqrt(2) (Gelfond-Schneider constant)
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
// www.stackoverflow.com/questions/5149544/can-i-generate-a-random-number-inside-a-pixel-shader/
float random(vec2 seed)
{
// irrationals for pseudo randomness
vec2 i = vec2(Gelfond, GelfondSchneider);
return fract(cos(dot(seed, i)) * 123456.0);
}
// www.dinodini.wordpress.com/2010/04/05/normalized-tunable-sigmoid-functions/
float normalizedSigmoid(float n, float k)
{
// valid for n and k in range of -1.0 and 1.0
return (n - n * k) / (k - abs(n) * 2.0 * k + 1);
}
// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float roundBox(vec2 p, vec2 b, float r)
{
return length(max(abs(p) - b + r, 0.0)) - r;
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
float DistortionAmount = global.distortion_amount; // k - quartic distortion coefficient
float CubicDistortionAmount = global.cubic_distortion_amount; // kcube - cubic distortion modifier
float DistortCornerAmount = global.distort_corner_amount;
float RoundCornerAmount = global.round_corner_amount;
float SmoothBorderAmount = global.smooth_border_amount;
float VignettingAmount = global.vignette_amount;
float ReflectionAmount = global.reflection_amount;
vec3 LightReflectionColor = vec3(global.reflection_col_r, global.reflection_col_g, global.reflection_col_b); // color temperature 5.000 Kelvin
vec2 QuadDims = params.OutputSize.xy;
vec2 TargetDims = params.FinalViewportSize.xy;
float TargetScale = 1.0;
float GetNoiseFactor(vec3 n, float random)
{
// smaller n become more noisy
return 1.0f + random * max(0.0f, 0.25f * pow(E, -8 * n.x));
}
float GetVignetteFactor(vec2 coord, float amount)
{
vec2 VignetteCoord = coord;
float VignetteLength = length(VignetteCoord);
float VignetteBlur = (amount * 0.75f) + 0.25;
// 0.5 full screen fitting circle
float VignetteRadius = 1.0f - (amount * 0.25f);
float Vignette = smoothstep(VignetteRadius, VignetteRadius - VignetteBlur, VignetteLength);
return saturate(Vignette);
}
float GetSpotAddend(vec2 coord, float amount)
{
vec2 SpotCoord = coord;
// upper right quadrant
vec2 spotOffset = vec2(-0.25f, 0.25f);
// normalized screen canvas ratio
vec2 CanvasRatio = SwapXY
? vec2(1.0f, QuadDims.x / QuadDims.y)
: vec2(1.0f, QuadDims.y / QuadDims.x);
SpotCoord += spotOffset;
SpotCoord *= CanvasRatio;
float SpotBlur = amount;
// 0.5 full screen fitting circle
float SpotRadius = amount * 0.75f;
float Spot = smoothstep(SpotRadius, SpotRadius - SpotBlur, length(SpotCoord));
float SigmoidSpot = amount * normalizedSigmoid(Spot, 0.75);
// increase strength by 100%
SigmoidSpot = SigmoidSpot * 2.0f;
return saturate(SigmoidSpot);
}
float GetBoundsFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
float range = min(bounds.x, bounds.y);
float amountMinimum = 1.0f / range;
float radius = range * max(radiusAmount, amountMinimum);
float smooth_ = 1.0f / (range * max(smoothAmount, amountMinimum * 2.0f));
// compute box
float box = roundBox(bounds * (coord * 2.0f), bounds, radius);
// apply smooth
box *= smooth_;
box += 1.0f - pow(smooth_ * 0.5f, 0.5f);
float border = smoothstep(1.0f, 0.0f, box);
return saturate(border);
}
// www.francois-tarlier.com/blog/cubic-lens-distortion-shader/
vec2 GetDistortedCoords(vec2 centerCoord, float amount, float amountCube)
{
// lens distortion coefficient
float k = amount;
// cubic distortion value
float kcube = amountCube;
// compute cubic distortion factor
float r2 = centerCoord.x * centerCoord.x + centerCoord.y * centerCoord.y;
float f = kcube == 0.0f
? 1.0f + r2 * k
: 1.0f + r2 * (k + kcube * sqrt(r2));
// fit screen bounds
f /= 1.0f + amount * 0.25f + amountCube * 0.125f;
// apply cubic distortion factor
centerCoord *= f;
return centerCoord;
}
vec2 GetTextureCoords(vec2 coord, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount, cubicDistortionAmount);
// un-center coordinates
coord += 0.5f;
return coord;
}
vec2 GetQuadCoords(vec2 coord, vec2 scale, float distortionAmount, float cubicDistortionAmount)
{
// center coordinates
coord -= 0.5f;
// apply scale
coord *= scale;
// distort coordinates
coord = GetDistortedCoords(coord, distortionAmount, cubicDistortionAmount);
return coord;
}
void main()
{
if(!Distortion)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
// image distortion
float distortionAmount = DistortionAmount;
float cubicDistortionAmount = CubicDistortionAmount > 0.0f
? CubicDistortionAmount * 1.1f // cubic distortion need to be a little higher to compensate the quartic distortion
: CubicDistortionAmount * 1.2f; // negativ values even more
// corner distortion at least by the amount of the image distorition
float distortCornerAmount = max(DistortCornerAmount, DistortionAmount + CubicDistortionAmount);
float roundCornerAmount = RoundCornerAmount * 0.5f;
float smoothBorderAmount = SmoothBorderAmount * 0.5f;
vec2 TexelDims = 1.0f / TargetDims;
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = TargetDims / TargetScale;
BaseTargetDims = SwapXY
? BaseTargetDims.yx
: BaseTargetDims.xy;
// base-target/quad difference scale
vec2 BaseTargetQuadScale = (ScreenCount == 1)
? BaseTargetDims / QuadDims // keeps the coords inside of the quad bounds of a single screen
: vec2(1.0);
// Screen Texture Curvature
vec2 BaseCoord = GetTextureCoords(vTexCoord, distortionAmount, cubicDistortionAmount);
// Screen Quad Curvature
vec2 QuadCoord = GetQuadCoords(vTexCoord, BaseTargetQuadScale, distortCornerAmount, 0.0f);
/*
// clip border
if (BaseCoord.x < 0.0f - TexelDims.x || BaseCoord.y < 0.0f - TexelDims.y ||
BaseCoord.x > 1.0f + TexelDims.x || BaseCoord.y > 1.0f + TexelDims.y)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0f, 0.0f, 0.0f, 1.0f);
}
*/
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0f;
// Vignetting Simulation
vec2 VignetteCoord = QuadCoord;
float VignetteFactor = GetVignetteFactor(VignetteCoord, VignettingAmount);
BaseColor.rgb *= VignetteFactor;
// Light Reflection Simulation
vec2 SpotCoord = QuadCoord;
vec3 SpotAddend = GetSpotAddend(SpotCoord, ReflectionAmount) * LightReflectionColor;
BaseColor.rgb += SpotAddend * GetNoiseFactor(SpotAddend, random(SpotCoord));
// Round Corners Simulation
vec2 RoundCornerCoord = QuadCoord;
vec2 RoundCornerBounds = (ScreenCount == 1)
? QuadDims // align corners to quad bounds of a single screen
: BaseTargetDims; // align corners to target bounds of multiple screens
RoundCornerBounds = SwapXY
? RoundCornerBounds.yx
: RoundCornerBounds.xy;
float roundCornerFactor = GetBoundsFactor(RoundCornerCoord, RoundCornerBounds, roundCornerAmount, smoothBorderAmount);
BaseColor.rgb *= roundCornerFactor;
FragColor = BaseColor;
}
}

View file

@ -0,0 +1,63 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Downsample Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec4 TexCoord01;
layout(location = 1) out vec4 TexCoord23;
const vec2 Coord0Offset = vec2(-0.5, -0.5);
const vec2 Coord1Offset = vec2( 0.5, -0.5);
const vec2 Coord2Offset = vec2(-0.5, 0.5);
const vec2 Coord3Offset = vec2( 0.5, 0.5);
void main()
{
gl_Position = global.MVP * Position;
vec2 HalfTargetTexelDims = 0.5 * params.SourceSize.zw;
TexCoord01.xy = TexCoord + Coord0Offset * HalfTargetTexelDims;
TexCoord01.zw = TexCoord + Coord1Offset * HalfTargetTexelDims;
TexCoord23.xy = TexCoord + Coord2Offset * HalfTargetTexelDims;
TexCoord23.zw = TexCoord + Coord3Offset * HalfTargetTexelDims;
}
#pragma stage fragment
layout(location = 0) in vec4 TexCoord01;
layout(location = 1) in vec4 TexCoord23;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
void main()
{
vec3 texel0 = texture(DiffuseSampler, TexCoord01.xy).rgb;
vec3 texel1 = texture(DiffuseSampler, TexCoord01.zw).rgb;
vec3 texel2 = texture(DiffuseSampler, TexCoord23.xy).rgb;
vec3 texel3 = texture(DiffuseSampler, TexCoord23.zw).rgb;
vec3 outTexel = (texel0 + texel1 + texel2 + texel3) / 4.0;
FragColor = vec4(outTexel, 1.0);
}

View file

@ -0,0 +1,294 @@
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
// effect toggles and multi
float bloomtoggle;
float ntscsignal;
float scanlinetoggle;
float chromatoggle;
float distortiontoggle;
float screenscale_x;
float screenscale_y;
float screenoffset_x;
float screenoffset_y;
float swapxy;
// bloom params
float bloomblendmode;
// float vectorscreen;
float bloomscale;
float bloomoverdrive_r;
float bloomoverdrive_g;
float bloomoverdrive_b;
float level0weight;
float level1weight;
float level2weight;
float level3weight;
float level4weight;
float level5weight;
float level6weight;
float level7weight;
float level8weight;
// post params
float mask_width;
float mask_height;
float mask_offset_x;
float mask_offset_y;
float preparebloom;
float shadowtilemode;
float power_r;
float power_g;
float power_b;
float floor_r;
float floor_g;
float floor_b;
float chromamode;
float conversiongain_x;
float conversiongain_y;
float conversiongain_z;
float humbaralpha;
float backcolor_r;
float backcolor_g;
float backcolor_b;
float shadowalpha;
float shadowcount_x;
float shadowcount_y;
float shadowuv_x;
float shadowuv_y;
// ntsc params
float avalue;
float bvalue;
float ccvalue;
float ovalue;
float pvalue;
float scantime;
float notchhalfwidth;
float yfreqresponse;
float ifreqresponse;
float qfreqresponse;
float signaloffset;
// color params
float col_red;
float col_grn;
float col_blu;
float col_offset_x;
float col_offset_y;
float col_offset_z;
float col_scale_x;
float col_scale_y;
float col_scale_z;
float col_saturation;
// deconverge params
float converge_x_r;
float converge_x_g;
float converge_x_b;
float converge_y_r;
float converge_y_g;
float converge_y_b;
float radial_conv_x_r;
float radial_conv_x_g;
float radial_conv_x_b;
float radial_conv_y_r;
float radial_conv_y_g;
float radial_conv_y_b;
// scanline params
float scanlinealpha;
float scanlinescale;
float scanlineheight;
float scanlinevariation;
float scanlineoffset;
float scanlinebrightscale;
float scanlinebrightoffset;
// defocus params
float defocus_x;
float defocus_y;
// phosphor params
float deltatime;
float phosphor_r;
float phosphor_g;
float phosphor_b;
float phosphortoggle;
// chroma params
float ygain_r;
float ygain_g;
float ygain_b;
float chromaa_x;
float chromaa_y;
float chromab_x;
float chromab_y;
float chromac_x;
float chromac_y;
// distortion params
float distortion_amount;
float cubic_distortion_amount;
float distort_corner_amount;
float round_corner_amount;
float smooth_border_amount;
float vignette_amount;
float reflection_amount;
float reflection_col_r;
float reflection_col_g;
float reflection_col_b;
// vector params
// float timeratio;
// float timescale;
// float lengthratio;
// float lengthscale;
// float beamsmooth;
} global;
// Effect Toggles and Settings Used In Multiple Passes
#pragma parameter ntscsignal "NTSC Signal Mode" 0.0 0.0 1.0 1.01.0
bool NTSCSignal = bool(global.ntscsignal);
#pragma parameter scanlinetoggle "Scanline Toggle" 1.0 0.0 1.0 1.0
bool ScanlineToggle = bool(global.scanlinetoggle);
#pragma parameter bloomtoggle "Bloom Enable" 0.0 0.0 1.0 1.0
bool BloomToggle = bool(global.bloomtoggle);
#pragma parameter chromatoggle "Chromaticity Toggle" 0.0 0.0 1.0 1.0
bool Chromaticity = bool(global.chromatoggle);
#pragma parameter distortiontoggle "Distortion Toggle" 0.0 0.0 1.0 1.0
bool Distortion = bool(global.distortiontoggle);
#pragma parameter phosphortoggle "Phosphor Toggle" 0.0 0.0 1.0 1.0
bool Passthrough = !bool(global.phosphortoggle);
#pragma parameter screenscale_x "Screen Scale X" 1.0 0.5 3.0 0.01
#pragma parameter screenscale_y "Screen Scale Y" 1.0 0.5 3.0 0.01
vec2 ScreenScale = vec2(global.screenscale_x, global.screenscale_y);
//#pragma parameter vectorscreen "Vector Screen Mode" 0.0 0.0 1.0 1.0 // TODO/FIXME
const float vectorscreen = 0.0;
bool VectorScreen = bool(vectorscreen);
#pragma parameter screenoffset_x "Screen Offset X" 0.0 -1.0 1.0 0.005
#pragma parameter screenoffset_y "Screen Offset Y" 0.0 -1.0 1.0 0.005
vec2 ScreenOffset = vec2(global.screenoffset_x, global.screenoffset_y);
#pragma parameter swapxy "Swap X and Y" 0.0 0.0 1.0 1.0
bool SwapXY = bool(global.swapxy);
// Bloom Pass
#pragma parameter bloomblendmode "Bloom Blend Mode" 0.0 0.0 1.0 1.0
#pragma parameter bloomscale "Bloom Scale" 0.33 0.0 1.0 0.01
#pragma parameter bloomoverdrive_r "Bloom Overdrive R" 1.0 0.0 2.0 0.01
#pragma parameter bloomoverdrive_g "Bloom Overdrive G" 1.0 0.0 2.0 0.01
#pragma parameter bloomoverdrive_b "Bloom Overdrive B" 1.0 0.0 2.0 0.01
#pragma parameter level0weight "Bloom Level 0 Weight" 0.64 0.0 1.0 0.01
#pragma parameter level1weight "Bloom Level 1 Weight" 0.64 0.0 1.0 0.01
#pragma parameter level2weight "Bloom Level 2 Weight" 0.32 0.0 1.0 0.01
#pragma parameter level3weight "Bloom Level 3 Weight" 0.16 0.0 1.0 0.01
#pragma parameter level4weight "Bloom Level 4 Weight" 0.08 0.0 1.0 0.01
#pragma parameter level5weight "Bloom Level 5 Weight" 0.06 0.0 1.0 0.01
#pragma parameter level6weight "Bloom Level 6 Weight" 0.04 0.0 1.0 0.01
#pragma parameter level7weight "Bloom Level 7 Weight" 0.02 0.0 1.0 0.01
#pragma parameter level8weight "Bloom Level 8 Weight" 0.01 0.0 1.0 0.01
// Post Pass
#pragma parameter humbaralpha "Hum Bar Alpha" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_r "Back Color R" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_g "Back Color G" 0.0 0.0 1.0 0.01
#pragma parameter backcolor_b "Back Color B" 0.0 0.0 1.0 0.01
#pragma parameter shadowtilemode "Mask Tiling Mode" 0.0 0.0 1.0 1.0
#pragma parameter shadowalpha "Mask Alpha" 0.3 0.0 1.0 0.01
#pragma parameter shadowcount_x "Mask Tile Size X" 6.0 1.0 32.0 1.0
#pragma parameter shadowcount_y "Mask Tile Size Y" 6.0 1.0 32.0 1.0
#pragma parameter shadowuv_x "Mask UV X" 0.25 0.0 1.0 0.01
#pragma parameter shadowuv_y "Mask UV Y" 0.25 0.0 1.0 0.01
#pragma parameter mask_width "Mask Texture Width" 32.0 0.0 256.0 16.0
#pragma parameter mask_height "Mask Texture Height" 32.0 0.0 256.0 16.0
#pragma parameter mask_offset_x "Mask Offset X" 0.0 -10.0 10.0 0.1
#pragma parameter mask_offset_y "Mask Offset Y" 0.0 -10.0 10.0 0.1
#pragma parameter chromamode "Chroma Mode" 3.0 1.0 3.0 1.0
#pragma parameter conversiongain_x "Conversion Gain X" 0.0 -5.0 5.0 0.5
#pragma parameter conversiongain_y "Conversion Gain Y" 0.0 -5.0 5.0 0.5
#pragma parameter conversiongain_z "Conversion Gain Z" 0.0 -5.0 5.0 0.5
#pragma parameter power_r "Color Power R" 1.0 1.0 10.0 1.0
#pragma parameter power_g "Color Power G" 1.0 1.0 10.0 1.0
#pragma parameter power_b "Color Power B" 1.0 1.0 10.0 1.0
#pragma parameter floor_r "Color Floor R" 0.0 0.0 1.0 0.01
#pragma parameter floor_g "Color Floor G" 0.0 0.0 1.0 0.01
#pragma parameter floor_b "Color Floor B" 0.0 0.0 1.0 0.01
#pragma parameter preparebloom "Prepare Bloom" 0.0 0.0 1.0 1.0
// NTSC Pass
#pragma parameter avalue "A Value" 0.5 -1.0 1.0 0.01
#pragma parameter bvalue "B Value" 0.5 -1.0 1.0 0.01
#pragma parameter ccvalue "CC Value" 3.5795454 0.0 6.0 0.0005
#pragma parameter ovalue "O Value" 0.0 -3.0 3.0 0.1
#pragma parameter pvalue "P Value" 1.0 -3.0 3.0 0.1
#pragma parameter scantime "Scan Time" 52.6 0.0 100.0 0.1
#pragma parameter notchhalfwidth "Notch Half Width" 1.0 0.0 6.0 0.05
#pragma parameter yfreqresponse "Y Freq Response" 6.0 0.0 6.0 0.05
#pragma parameter ifreqresponse "I Freq Response" 1.2 0.0 6.0 0.05
#pragma parameter qfreqresponse "Q Freq Response" 0.6 0.0 6.0 0.05
#pragma parameter signaloffset "Signal Offset" 1.0 0.0 1.0 0.01
// Color Pass
#pragma parameter col_red "Red Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_grn "Green Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_blu "Blue Shift" 1.0 0.0 2.0 0.01
#pragma parameter col_offset_x "Offset X" 0.0 -1.0 1.0 0.01
#pragma parameter col_offset_y "Offset Y" 0.0 -1.0 1.0 0.01
#pragma parameter col_offset_z "Offset Z" 0.0 -1.0 1.0 0.01
#pragma parameter col_scale_x "Scale X" 1.0 0.0 2.0 0.01
#pragma parameter col_scale_y "Scale Y" 1.0 0.0 2.0 0.01
#pragma parameter col_scale_z "Scale Z" 1.0 0.0 2.0 0.01
#pragma parameter col_saturation "Saturation" 1.0 0.0 5.0 0.01
// Deconverge Pass
#pragma parameter converge_x_r "Convergence X Red" 0.0 -10.0 10.0 0.05
#pragma parameter converge_x_g "Convergence X Green" 0.0 -10.0 10.0 0.05
#pragma parameter converge_x_b "Convergence X Blue" 0.0 -10.0 10.0 0.05
#pragma parameter converge_y_r "Convergence Y Red" 0.0 -10.0 10.0 0.05
#pragma parameter converge_y_g "Convergence Y Green" 0.0 -10.0 10.0 0.05
#pragma parameter converge_y_b "Convergence Y Blue" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_r "Radial Conv X Red" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_g "Radial Conv X Green" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_x_b "Radial Conv X Blue" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_r "Radial Conv Y Red" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_g "Radial Conv Y Green" 0.0 -10.0 10.0 0.05
#pragma parameter radial_conv_y_b "Radial Conv Y Blue" 0.0 -10.0 10.0 0.05
// Scanline Pass
#pragma parameter scanlinealpha "Scanline Alpha" 0.5 0.0 1.0 0.01
#pragma parameter scanlinescale "Scanline Scale" 5.0 1.0 5.0 1.0
#pragma parameter scanlineheight "Scanline Height" 1.0 0.0 2.0 0.1
#pragma parameter scanlinevariation "Scanline Variation" 1.0 0.0 5.0 0.5
#pragma parameter scanlineoffset "Scanline Offset" 1.0 -1.5 3.0 0.1
#pragma parameter scanlinebrightscale "Scanline Bright Scale" 1.0 0.0 2.0 0.1
#pragma parameter scanlinebrightoffset "Scanline Bright Offset" 1.0 -1.5 3.0 0.1
// Defocus Pass
#pragma parameter defocus_x "Defocus X Axis" 0.0 0.0 10.0 0.1
#pragma parameter defocus_y "Defocus Y Axis" 0.0 0.0 10.0 0.1
// Phosphor Pass
#pragma parameter deltatime "Delta Time" 1.0 0.0 2.0 0.1
#pragma parameter phosphor_r "Phosphor Red" 0.8 0.0 0.99 0.1
#pragma parameter phosphor_g "Phosphor Green" 0.0 0.0 0.99 0.1
#pragma parameter phosphor_b "Phosphor Blue" 0.0 0.0 0.99 0.1
// Chroma Pass
#pragma parameter ygain_r "Y Gain R Channel" 0.2126 0.0 1.0 0.01
#pragma parameter ygain_g "Y Gain G Channel" 0.7152 0.0 1.0 0.01
#pragma parameter ygain_b "Y Gain B Channel" 0.0722 0.0 1.0 0.01
#pragma parameter chromaa_x "Chroma A X" 0.630 0.0 1.0 0.01
#pragma parameter chromaa_y "Chroma A Y" 0.340 0.0 1.0 0.01
#pragma parameter chromab_x "Chroma B X" 0.310 0.0 1.0 0.01
#pragma parameter chromab_y "Chroma B Y" 0.595 0.0 1.0 0.01
#pragma parameter chromac_x "Chroma C X" 0.155 0.0 1.0 0.01
#pragma parameter chromac_y "Chroma C Y" 0.070 0.0 1.0 0.01
// Distortion Pass
#pragma parameter distortion_amount "Distortion Amount" 0.0 0.0 1.0 0.01
#pragma parameter cubic_distortion_amount "Cubic Dist. Amt" 0.0 0.0 1.0 0.01
#pragma parameter distort_corner_amount "Corner Dist. Amt" 0.0 0.0 1.0 0.01
#pragma parameter round_corner_amount "Corner Rounding" 0.0 0.0 1.0 0.01
#pragma parameter smooth_border_amount "Border Smoothing" 0.0 0.0 1.0 0.01
#pragma parameter vignette_amount "Vignetting Amount" 0.0 0.0 1.0 0.01
#pragma parameter reflection_amount "Reflection Amount" 0.0 0.0 1.0 0.01
#pragma parameter reflection_col_r "Reflection Color R" 1.0 0.0 1.0 0.01
#pragma parameter reflection_col_g "Reflection Color G" 0.9 0.0 1.0 0.01
#pragma parameter reflection_col_b "Reflection Color B" 0.8 0.0 1.0 0.01
// Vector Pass
//#pragma parameter timeratio "Time Ratio" 1.0 0.0 2.0 0.01
//#pragma parameter timescale "Time Scale" 1.0 1.0 10.0 1.0
//#pragma parameter lengthratio "Length Ratio" 1.0 1.0 10.0 1.0
//#pragma parameter lengthscale "Length Scale" 1.0 1.0 10.0 1.0
//#pragma parameter beamsmooth "Beam Smooth Amt" 0.5 0.1 1.0 0.1

View file

@ -0,0 +1,56 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
//-----------------------------------------------------------------------------
// Phosphor Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
float DeltaTime = global.deltatime;
vec3 Phosphor = vec3(global.phosphor_r, global.phosphor_g, global.phosphor_b);
const float F = 1.0;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D PassFeedback6;
#define DiffuseSampler Source
#define PreviousSampler PassFeedback6
void main()
{
vec4 CurrY = texture(DiffuseSampler, vTexCoord);
vec3 PrevY = texture(PreviousSampler, vTexCoord).rgb;
PrevY[0] *= (Phosphor[0] == 0.0) ? 0.0 : pow(Phosphor[0], F * DeltaTime);
PrevY[1] *= (Phosphor[1] == 0.0) ? 0.0 : pow(Phosphor[1], F * DeltaTime);
PrevY[2] *= (Phosphor[2] == 0.0) ? 0.0 : pow(Phosphor[2], F * DeltaTime);
float a = max(PrevY[0], CurrY[0]);
float b = max(PrevY[1], CurrY[1]);
float c = max(PrevY[2], CurrY[2]);
FragColor = Passthrough ? CurrY : vec4(a, b, c, CurrY.a);
}

View file

@ -0,0 +1,197 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Shadowmask Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
#define TargetDims params.OutputSize.xy
#define SourceDims params.OriginalSize.xy
float TargetScale = 1.0;//max(TargetDims.x / SourceDims.x, TargetDims.y / SourceDims.y);
float HumBarAlpha = global.humbaralpha;
float TimeMilliseconds = float(mod(params.FrameCount, 1000));
vec3 BackColor = vec3(global.backcolor_r, global.backcolor_g, global.backcolor_b);
int ShadowTileMode = int(global.shadowtilemode); // 0 based on screen (quad) dimension, 1 based on source dimension
float ShadowAlpha = global.shadowalpha;
vec2 ShadowCount = vec2(global.shadowcount_x, global.shadowcount_y);
vec2 ShadowUV = vec2(global.shadowuv_x, global.shadowuv_y);
vec2 ShadowDims = vec2(global.mask_width, global.mask_height);
vec2 ShadowUVOffset = vec2(global.mask_offset_x, global.mask_offset_y);
int ChromaMode = int(global.chromamode);
vec3 ConversionGain = vec3(global.conversiongain_x, global.conversiongain_y, global.conversiongain_z);
vec3 Power = vec3(global.power_r, global.power_g, global.power_b);
vec3 Floor = vec3(global.floor_r, global.floor_g, global.floor_b);
bool PrepareBloom = bool(global.preparebloom);
#define MONOCHROME 1
#define DICHROME 2
#define TRICHROME 3
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float PI = 3.1415927;
const float HalfPI = PI * 0.5;
float HumBarDesync = 60.0 / 59.94 - 1.0; // difference between the 59.94 Hz field rate and 60 Hz line frequency (NTSC)
vec2 GetAdjustedCoords(vec2 coord)
{
// center coordinates
coord -= 0.5;
// apply screen scale
coord *= ScreenScale;
// un-center coordinates
coord += 0.5;
// apply screen offset
coord += ScreenOffset;
return coord;
}
vec2 GetShadowCoord(vec2 TargetCoord, vec2 SourceCoord)
{
// base-target dimensions (without oversampling)
vec2 BaseTargetDims = TargetDims / TargetScale;
BaseTargetDims = SwapXY
? BaseTargetDims.yx
: BaseTargetDims.xy;
vec2 canvasCoord = ShadowTileMode == 0
? TargetCoord + ShadowUVOffset / BaseTargetDims
: SourceCoord + ShadowUVOffset / SourceDims;
vec2 canvasTexelDims = ShadowTileMode == 0
? 1.0 / BaseTargetDims
: 1.0 / SourceDims;
vec2 shadowDims = ShadowDims;
vec2 shadowUV = ShadowUV;
vec2 shadowCount = ShadowCount;
// swap x/y in screen mode (not source mode)
canvasCoord = ShadowTileMode == 0 && SwapXY
? canvasCoord.yx
: canvasCoord.xy;
// swap x/y in screen mode (not source mode)
shadowCount = ShadowTileMode == 0 && SwapXY
? shadowCount.yx
: shadowCount.xy;
vec2 shadowTile = canvasTexelDims * shadowCount;
vec2 shadowFrac = fract(canvasCoord / shadowTile);
// swap x/y in screen mode (not source mode)
shadowFrac = ShadowTileMode == 0 && SwapXY
? shadowFrac.yx
: shadowFrac.xy;
vec2 shadowCoord = (shadowFrac * shadowUV);
shadowCoord += ShadowTileMode == 0
? vec2(0.5) * (vec2(1.0) / shadowDims) // fix half texel offset (DX9)
: vec2(0.0);
return shadowCoord;
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D MaskTexture;
#define DiffuseSampler Source
#define ShadowSampler MaskTexture
//#define ScreenCoord vTexCoord
void main()
{
vec2 ScreenCoord = vTexCoord;
vec2 BaseCoord = GetAdjustedCoords(ScreenCoord);
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0;
/*
// clip border
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 ||
BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0, 0.0, 0.0, 1.0);
}
*/
// Color Compression (may not affect bloom)
if (!PrepareBloom)
{
// increasing the floor of the signal without affecting the ceiling
BaseColor.rgb = Floor + (1.0f - Floor) * BaseColor.rgb;
}
// Color Power (may affect bloom)
BaseColor.r = pow(BaseColor.r, Power.r);
BaseColor.g = pow(BaseColor.g, Power.g);
BaseColor.b = pow(BaseColor.b, Power.b);
// Hum Bar Simulation (may not affect vector screen)
if (!PrepareBloom && !VectorScreen && HumBarAlpha > 0.0)
{
float HumBarStep = fract(TimeMilliseconds * HumBarDesync);
float HumBarBrightness = 1.0 - fract(BaseCoord.y + HumBarStep) * HumBarAlpha;
BaseColor.rgb *= HumBarBrightness;
}
// Mask Simulation (may not affect bloom)
if (!PrepareBloom && ShadowAlpha > 0.0)
{
vec2 ShadowCoord = GetShadowCoord(ScreenCoord, BaseCoord);
vec4 ShadowColor = texture(ShadowSampler, ShadowCoord);
vec3 ShadowMaskColor = mix(vec3(1.0), ShadowColor.rgb, ShadowAlpha);
float ShadowMaskClear = (1.0 - ShadowColor.a) * ShadowAlpha;
// apply shadow mask color
BaseColor.rgb *= ShadowMaskColor;
// clear shadow mask by background color
BaseColor.rgb = mix(BaseColor.rgb, BackColor, ShadowMaskClear);
}
// Preparation for phosphor color conversion
if (ChromaMode == MONOCHROME) {
BaseColor.r = dot(ConversionGain, BaseColor.rgb);
BaseColor.gb = vec2(BaseColor.r, BaseColor.r);
} else if (ChromaMode == DICHROME) {
BaseColor.r = dot(ConversionGain.rg, BaseColor.rg);
BaseColor.g = BaseColor.r;
}
FragColor = BaseColor;
}

View file

@ -0,0 +1,125 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz,ImJezze
//-----------------------------------------------------------------------------
// Scanline Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
vec4 FinalViewportSize;
} params;
#include "mame_parameters.inc"
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
const float PI = 3.1415927;
const float HalfPI = PI * 0.5;
//-----------------------------------------------------------------------------
// Scanline Pixel Shader
//-----------------------------------------------------------------------------
float ScanlineAlpha = global.scanlinealpha;
float ScanlineScale = global.scanlinescale;
float ScanlineHeight = global.scanlineheight;
float ScanlineVariation = global.scanlinevariation;
float ScanlineOffset = global.scanlineoffset;
float ScanlineBrightScale = global.scanlinebrightscale;
float ScanlineBrightOffset = global.scanlinebrightoffset;
vec2 QuadDims = params.FinalViewportSize.xy;
vec2 SourceDims = params.OriginalSize.xy;
vec2 GetAdjustedCoords(vec2 coord)
{
// center coordinates
coord -= 0.5;
// apply screen scale
coord *= ScreenScale;
// un-center coordinates
coord += 0.5;
// apply screen offset
coord += ScreenOffset;
return coord;
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
#define DiffuseSampler Source
void main()
{
if(!ScanlineToggle)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
vec2 BaseCoord = GetAdjustedCoords(vTexCoord);
// Color
vec4 BaseColor = texture(DiffuseSampler, BaseCoord);
BaseColor.a = 1.0;
/*
// clip border
if (BaseCoord.x < 0.0 || BaseCoord.y < 0.0 ||
BaseCoord.x > 1.0 || BaseCoord.y > 1.0)
{
// we don't use the clip function, because we don't clear the render target before
return vec4(0.0, 0.0, 0.0, 1.0);
}
*/
float BrightnessOffset = (ScanlineBrightOffset * ScanlineAlpha);
float BrightnessScale = (ScanlineBrightScale * ScanlineAlpha) + (1.0 - ScanlineAlpha);
float ColorBrightness = 0.299 * BaseColor.r + 0.587 * BaseColor.g + 0.114 * BaseColor.b;
float ScanlineCoord = BaseCoord.y;
ScanlineCoord += (SwapXY)
? QuadDims.x <= SourceDims.x * 2.0
? 0.5 / QuadDims.x // uncenter scanlines if the quad is less than twice the size of the source
: 0.0
: QuadDims.y <= SourceDims.y * 2.0
? 0.5 / QuadDims.y // uncenter scanlines if the quad is less than twice the size of the source
: 0.0;
ScanlineCoord *= SourceDims.y * ScanlineScale * PI;
float ScanlineCoordJitter = ScanlineOffset * HalfPI;
float ScanlineSine = sin(ScanlineCoord + ScanlineCoordJitter);
float ScanlineWide = ScanlineHeight + ScanlineVariation * max(1.0f, ScanlineHeight) * (1.0 - ColorBrightness);
float ScanlineAmount = pow(ScanlineSine * ScanlineSine, ScanlineWide);
float ScanlineBrightness = ScanlineAmount * BrightnessScale + BrightnessOffset * BrightnessScale;
BaseColor.rgb *= mix(1.0, ScanlineBrightness, ScanlineAlpha);
FragColor = BaseColor;
}
}

View file

@ -0,0 +1,102 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
#include "mame_parameters.inc"
#define saturate(c) clamp(c, 0.0, 1.0)
#define TargetDims params.OutputSize.xy
#define DiffuseSampler Source
float TimeRatio = global.timeratio; // Frame time of the vector (not set)
float TimeScale = global.timescale; // How much frame time affects the vector's fade (not set)
float LengthRatio = global.lengthratio; // Size at which fade is maximum
float LengthScale = global.lengthscale; // How much length affects the vector's fade
float BeamSmooth = global.beamsmooth;
// vec2 SizeInfo;
// vec4 Color;
const vec2 SizeInfo = vec2(1.0);
const vec4 Color = vec4(1.0);
//-----------------------------------------------------------------------------
// Functions
//-----------------------------------------------------------------------------
// www.iquilezles.org/www/articles/distfunctions/distfunctions.htm
float roundBox(vec2 p, vec2 b, float r)
{
return length(max(abs(p) - b + r, 0.0f)) - r;
}
float GetBoundsFactor(vec2 coord, vec2 bounds, float radiusAmount, float smoothAmount)
{
// reduce smooth amount down to radius amount
smoothAmount = min(smoothAmount, radiusAmount);
float range = min(bounds.x, bounds.y);
float amountMinimum = 1.0f / range;
float radius = range * max(radiusAmount, amountMinimum);
float smooth_ = 1.0f / (range * max(smoothAmount, amountMinimum * 2.0f));
// compute box
float box = roundBox(bounds * (coord * 2.0f), bounds, radius);
// apply smooth_
box *= smooth_;
box += 1.0f - pow(smooth_ * 0.5f, 0.5f);
float border = smoothstep(1.0f, 0.0f, box);
return saturate(border);
}
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
if(!VectorScreen)
{
FragColor = texture(Source, vTexCoord);
return;
}
else
{
vec2 lineSize = SizeInfo / max(TargetDims.x, TargetDims.y); // normalize
float lineLength = lineSize.x;
float lineLengthRatio = params.LengthRatio;
float lineLengthScale = params.LengthScale;
float timeModulate = mix(1.0f, params.TimeRatio, params.TimeScale);
float lengthModulate = 1.0f - clamp(lineLength / lineLengthRatio, 0.0f, 1.0f);
float timeLengthModulate = mix(1.0f, timeModulate * lengthModulate, params.LengthScale);
vec4 outColor = vec4(timeLengthModulate, timeLengthModulate, timeLengthModulate, 1.0f);
outColor *= Color;
float RoundCornerFactor = GetBoundsFactor(vTexCoord - 0.5f, SizeInfo, 1.0f, params.BeamSmooth);
outColor.rgb *= RoundCornerFactor;
FragColor = outColor;
}
}

View file

@ -0,0 +1,71 @@
#version 450
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz, W. M. Martinez
//-----------------------------------------------------------------------------
// Primary Effect
//-----------------------------------------------------------------------------
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define LUT_TEXTURE_WIDTH 4096.0f
#define LUT_SIZE 64.0f
#define LUT_SCALE vec2(1.0f / LUT_TEXTURE_WIDTH, 1.0f / LUT_SIZE)
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D MaskTexture;
#define DiffuseSampler Source
#define LutSampler MaskTexture
//-----------------------------------------------------------------------------
// Utilities
//-----------------------------------------------------------------------------
vec3 apply_lut(vec3 color)
{
// NOTE: Do not change the order of parameters here.
vec3 lutcoord = vec3((color.rg * (LUT_SIZE - 1.0f) + 0.5f) *
LUT_SCALE, color.b * (LUT_SIZE - 1.0f));
float shift = floor(lutcoord.z);
lutcoord.x += shift * LUT_SCALE.y;
color.rgb = mix(texture(LutSampler, lutcoord.xy).rgb, texture(LutSampler,
float2(lutcoord.x + LUT_SCALE.y, lutcoord.y)).rgb,
lutcoord.z - shift);
return color;
}
void main()
{
FragColor = vec4(texture(Source, vTexCoord).rgb, 1.0);
}

View file

@ -0,0 +1,35 @@
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
} params;
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
void main()
{
FragColor = vec4(texture(Source, vTexCoord).rgb, 1.0);
}