summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
author cgwg <cgwg@users.noreply.github.com>2022-07-07 10:15:55 +0100
committer GitHub <noreply@github.com>2022-07-07 19:15:55 +1000
commit75466ad87d2af99d05b0c5b84e661523734d710b (patch)
tree0a11390cf8d214d52155666910e1910fb192bfac /src/osd
parentf3fb60fee6fb83c80e776fcfd1bd271dc83d126f (diff)
bgfx: crt-geom and crt-geom-deluxe improvements: (#8653)
* crt-geom-deluxe: Increased number of taps for halation and increased maximum width. * crt-geom*: Moved repeated crt-geom/crt-geom-deluxe functions into their own file. * crt-geom and crt-geom-deluxe: added support for sRGB output gamma ramp and made it the default.
Diffstat (limited to 'src/osd')
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc203
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc185
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc184
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc13
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc13
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/varying.def.sc5
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc3
-rw-r--r--src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc3
8 files changed, 238 insertions, 371 deletions
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc
new file mode 100644
index 00000000000..6863a180ef6
--- /dev/null
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/crt-geom_common.sc
@@ -0,0 +1,203 @@
+// Comment the next line to disable interpolation in linear gamma (and gain speed).
+//#define LINEAR_PROCESSING
+
+// Enable 3x oversampling of the beam profile
+#define OVERSAMPLE
+
+// Use the older, purely gaussian beam profile
+#define USEGAUSSIAN
+
+// Macros.
+#define FIX(c) max(abs(c), 1e-5)
+#define PI 3.141592653589
+
+vec4 TEX2D(vec2 c)
+{
+ vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c);
+ vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y);
+#ifdef LINEAR_PROCESSING
+ col = pow(col, vec4_splat(CRTgamma.x));
+#endif
+ return col;
+}
+
+// Enable screen curvature.
+uniform vec4 curvature;
+
+uniform vec4 spot_size;
+uniform vec4 spot_growth;
+uniform vec4 spot_growth_power;
+
+uniform vec4 u_interp;
+
+uniform vec4 aperture_strength;
+uniform vec4 aperture_brightboost;
+
+uniform vec4 CRTgamma;
+uniform vec4 monitorsRGB;
+uniform vec4 monitorgamma;
+
+uniform vec4 overscan;
+uniform vec4 aspect;
+
+uniform vec4 d;
+uniform vec4 R;
+
+uniform vec4 cornersize;
+uniform vec4 cornersmooth;
+
+float intersect(vec2 xy , vec2 sinangle, vec2 cosangle)
+{
+ float A = dot(xy,xy)+d.x*d.x;
+ float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
+ float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
+ return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
+}
+
+vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle)
+{
+ float c = intersect(xy, sinangle, cosangle);
+ vec2 pt = vec2_splat(c)*xy;
+ pt -= vec2_splat(-R.x)*sinangle;
+ pt /= vec2_splat(R.x);
+ vec2 tang = sinangle/cosangle;
+ vec2 poc = pt/cosangle;
+ float A = dot(tang,tang)+1.0;
+ float B = -2.0*dot(poc,tang);
+ float C = dot(poc,poc)-1.0;
+ float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
+ vec2 uv = (pt-a*sinangle)/cosangle;
+ float r = FIX(R.x*acos(a));
+ return uv*r/sin(r/R.x);
+}
+
+vec2 transform(vec2 coord, vec3 stretch, vec2 sinangle, vec2 cosangle)
+{
+ coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy;
+ return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5));
+}
+
+float corner(vec2 coord)
+{
+ coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5);
+ coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy;
+ vec2 cdist = vec2_splat(cornersize.x);
+ coord = (cdist - min(coord,cdist));
+ float dist = sqrt(dot(coord,coord));
+ return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0);
+}
+
+// Calculate the influence of a scanline on the current pixel.
+//
+// 'distance' is the distance in texture coordinates from the current
+// pixel to the scanline in question.
+// 'color' is the colour of the scanline at the horizontal location of
+// the current pixel.
+vec4 scanlineWeights(float distance, vec4 color)
+{
+ // "wid" controls the width of the scanline beam, for each RGB channel
+ // The "weights" lines basically specify the formula that gives
+ // you the profile of the beam, i.e. the intensity as
+ // a function of distance from the vertical center of the
+ // scanline. In this case, it is gaussian if width=2, and
+ // becomes nongaussian for larger widths. Ideally this should
+ // be normalized so that the integral across the beam is
+ // independent of its width. That is, for a narrower beam
+ // "weights" should have a higher peak at the center of the
+ // scanline than for a wider beam.
+#ifdef USEGAUSSIAN
+ vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x));
+ vec4 weights = vec4(distance / wid);
+ float maxwid = spot_size.x + spot_growth.x;
+ float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) );
+ return norm * exp(-weights * weights) / wid;
+#else
+ vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0));
+ vec4 weights = vec4_splat(distance / 0.3);
+ return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
+#endif
+}
+
+vec4 cubic(vec4 x, float B, float C)
+{
+ // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters
+ vec2 a = x.yz; // components in [0,1]
+ vec2 b = x.xw; // components in [1,2]
+ vec2 a2 = a*a;
+ vec2 b2 = b*b;
+ a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B);
+ b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C);
+ return vec4(b.x,a.x,a.y,b.y);
+}
+
+vec4 x_coeffs(vec4 x, float pos_x)
+{
+ if (u_interp.x < 0.5) { // box
+ float wid = length(vec2(dFdx(pos_x),dFdy(pos_x)));
+ float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0);
+ return vec4(0.0,dx,1.0-dx,0.0);
+ } else if (u_interp.x < 1.5) { // linear
+ return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0);
+ } else if (u_interp.x < 2.5) { // Lanczos
+ // Prevent division by zero.
+ vec4 coeffs = FIX(PI * x);
+ // Lanczos2 kernel.
+ coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
+ // Normalize.
+ coeffs /= dot(coeffs, vec4_splat(1.0));
+ return coeffs;
+ } else if (u_interp.x < 3.5) { // Catmull-Rom
+ return cubic(x,0.0,0.5);
+ } else if (u_interp.x < 4.5) { // Mitchell-Netravali
+ return cubic(x,1.0/3.0,1.0/3.0);
+ } else /*if (u_interp.x < 5.5)*/ { // B-spline
+ return cubic(x,1.0,0.0);
+ }
+}
+
+vec4 sample_scanline(vec2 xy, vec4 coeffs, float onex)
+{
+ // Calculate the effective colour of the given
+ // scanline at the horizontal location of the current pixel,
+ // using the Lanczos coefficients.
+ vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x +
+ TEX2D(xy)*coeffs.y +
+ TEX2D(xy +vec2(onex, 0.0))*coeffs.z +
+ TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0);
+ return col;
+}
+
+vec3 apply_shadow_mask(vec2 coord, vec3 col)
+{
+ vec2 xy = coord * u_quad_dims.xy / u_tex_size1.xy;
+ vec4 mask = texture2D(mask_texture, xy);
+ // count of total bright pixels is encoded in the mask's alpha channel
+ float nbright = 255.0 - 255.0*mask.a;
+ // fraction of bright pixels in the mask
+ float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y );
+ // average darkening factor of the mask
+ float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright);
+ // colour of dark mask pixels
+ vec3 clow = vec3_splat(1.0-aperture_strength.x) * col + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * col * col;
+ float ifbright = 1.0 / fbright;
+ // colour of bright mask pixels
+ vec3 chi = vec3_splat(ifbright*aperture_average) * col - vec3_splat(ifbright - 1.0) * clow;
+ return mix(clow,chi,mask.rgb); // mask texture selects dark vs bright
+}
+
+vec3 linear_to_sRGB(vec3 col)
+{
+ // only applies the gamma ramp; does not adjust the primaries
+ vec3 linear_ramp = vec3(lessThan(col, vec3_splat(0.0031308)));
+ vec3 clin = col * vec3_splat(12.92);
+ vec3 cpow = pow(col, vec3_splat(1.0/2.4)) * vec3_splat(1.055) - vec3_splat(0.055);
+ return mix(cpow, clin, linear_ramp);
+}
+
+vec3 linear_to_output(vec3 col)
+{
+ if (monitorsRGB.x > 0.5)
+ return linear_to_sRGB(col);
+ else
+ return pow(col, vec3_splat(1.0 / monitorgamma.x));
+}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
index 53d67e2b37a..72705bdcb83 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom-deluxe.sc
@@ -12,61 +12,16 @@ $input v_sinangle, v_cosangle, v_stretch, v_one, v_texCoord
#include "common.sh"
-// Comment the next line to disable interpolation in linear gamma (and gain speed).
-//#define LINEAR_PROCESSING
-
-// Enable 3x oversampling of the beam profile
-#define OVERSAMPLE
-
-// Use the older, purely gaussian beam profile
-#define USEGAUSSIAN
-
-// Macros.
-#define FIX(c) max(abs(c), 1e-5)
-#define PI 3.141592653589
-
SAMPLER2D(mpass_texture, 0);
SAMPLER2D(mask_texture, 1);
SAMPLER2D(blur_texture, 2);
SAMPLER2D(mipmap_texture, 3);
-vec4 TEX2D(vec2 c)
-{
- vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c);
- vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y);
-#ifdef LINEAR_PROCESSING
- col = pow(col, vec4_splat(CRTgamma.x));
-#endif
- return col;
-}
-
-// Enable screen curvature.
-uniform vec4 curvature;
-
uniform vec4 u_tex_size0;
uniform vec4 u_tex_size1;
uniform vec4 u_quad_dims;
-uniform vec4 spot_size;
-uniform vec4 spot_growth;
-uniform vec4 spot_growth_power;
-
-uniform vec4 u_interp;
-
-uniform vec4 aperture_strength;
-uniform vec4 aperture_brightboost;
-
-uniform vec4 CRTgamma;
-uniform vec4 monitorgamma;
-
-uniform vec4 overscan;
-uniform vec4 aspect;
-
-uniform vec4 d;
-uniform vec4 R;
-
-uniform vec4 cornersize;
-uniform vec4 cornersmooth;
+#include "crt-geom_common.sc"
uniform vec4 halation;
uniform vec4 rasterbloom;
@@ -86,127 +41,6 @@ vec3 texblur(vec2 c)
return col * vec3_splat( c.x * c.y );
}
-float intersect(vec2 xy , vec2 sinangle, vec2 cosangle)
-{
- float A = dot(xy,xy)+d.x*d.x;
- float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
- float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
- return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
-}
-
-vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle)
-{
- float c = intersect(xy, sinangle, cosangle);
- vec2 pt = vec2_splat(c)*xy;
- pt -= vec2_splat(-R.x)*sinangle;
- pt /= vec2_splat(R.x);
- vec2 tang = sinangle/cosangle;
- vec2 poc = pt/cosangle;
- float A = dot(tang,tang)+1.0;
- float B = -2.0*dot(poc,tang);
- float C = dot(poc,poc)-1.0;
- float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
- vec2 uv = (pt-a*sinangle)/cosangle;
- float r = FIX(R.x*acos(a));
- return uv*r/sin(r/R.x);
-}
-
-vec2 transform(vec2 coord, vec3 stretch, vec2 sinangle, vec2 cosangle)
-{
- coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy;
- return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5));
-}
-
-float corner(vec2 coord)
-{
- coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5);
- coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy;
- vec2 cdist = vec2_splat(cornersize.x);
- coord = (cdist - min(coord,cdist));
- float dist = sqrt(dot(coord,coord));
- return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0);
-}
-
-// Calculate the influence of a scanline on the current pixel.
-//
-// 'distance' is the distance in texture coordinates from the current
-// pixel to the scanline in question.
-// 'color' is the colour of the scanline at the horizontal location of
-// the current pixel.
-vec4 scanlineWeights(float distance, vec4 color)
-{
- // "wid" controls the width of the scanline beam, for each RGB channel
- // The "weights" lines basically specify the formula that gives
- // you the profile of the beam, i.e. the intensity as
- // a function of distance from the vertical center of the
- // scanline. In this case, it is gaussian if width=2, and
- // becomes nongaussian for larger widths. Ideally this should
- // be normalized so that the integral across the beam is
- // independent of its width. That is, for a narrower beam
- // "weights" should have a higher peak at the center of the
- // scanline than for a wider beam.
-#ifdef USEGAUSSIAN
- vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x));
- vec4 weights = vec4(distance / wid);
- float maxwid = spot_size.x + spot_growth.x;
- float norm = maxwid / ( 1.0 + 2.0 * exp(-1.0/(maxwid*maxwid)) );
- return norm * exp(-weights * weights) / wid;
-#else
- vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0));
- vec4 weights = vec4_splat(abs(distance) / 0.3);
- return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
-#endif
-}
-
-vec4 cubic(vec4 x, float B, float C)
-{
- // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters
- vec2 a = x.yz; // components in [0,1]
- vec2 b = x.xw; // components in [1,2]
- vec2 a2 = a*a;
- vec2 b2 = b*b;
- a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B);
- b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C);
- return vec4(b.x,a.x,a.y,b.y);
-}
-
-vec4 x_coeffs(vec4 x, float pos_x)
-{
- if (u_interp.x < 0.5) { // box
- float wid = length(vec2(dFdx(pos_x),dFdy(pos_x)));
- float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0);
- return vec4(0.0,dx,1.0-dx,0.0);
- } else if (u_interp.x < 1.5) { // linear
- return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0);
- } else if (u_interp.x < 2.5) { // Lanczos
- // Prevent division by zero.
- vec4 coeffs = FIX(PI * x);
- // Lanczos2 kernel.
- coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
- // Normalize.
- coeffs /= dot(coeffs, vec4_splat(1.0));
- return coeffs;
- } else if (u_interp.x < 3.5) { // Catmull-Rom
- return cubic(x,0.0,0.5);
- } else if (u_interp.x < 4.5) { // Mitchell-Netravali
- return cubic(x,1.0/3.0,1.0/3.0);
- } else /*if (u_interp.x < 5.5)*/ { // B-spline
- return cubic(x,1.0,0.0);
- }
-}
-
-vec4 sample_scanline(vec2 xy, vec4 coeffs, float onex)
-{
- // Calculate the effective colour of the given
- // scanline at the horizontal location of the current pixel,
- // using the Lanczos coefficients.
- vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x +
- TEX2D(xy)*coeffs.y +
- TEX2D(xy +vec2(onex, 0.0))*coeffs.z +
- TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0);
- return col;
-}
-
void main()
{
// Here's a helpful diagram to keep in mind while trying to
@@ -300,23 +134,10 @@ void main()
mul_res = mix(mul_res, blur, halation.x) * vec3_splat(cval*rbloom);
// Shadow mask
- xy = v_texCoord.xy * u_quad_dims.xy / u_tex_size1.xy;
- vec4 mask = texture2D(mask_texture, xy);
- // count of total bright pixels is encoded in the mask's alpha channel
- float nbright = 255.0 - 255.0*mask.a;
- // fraction of bright pixels in the mask
- float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y );
- // average darkening factor of the mask
- float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright);
- // colour of dark mask pixels
- vec3 clow = vec3_splat(1.0-aperture_strength.x) * mul_res + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * mul_res * mul_res;
- float ifbright = 1.0 / fbright;
- // colour of bright mask pixels
- vec3 chi = vec3_splat(ifbright*aperture_average) * mul_res - vec3_splat(ifbright - 1.0) * clow;
- vec3 cout = mix(clow,chi,mask.rgb); // mask texture selects dark vs bright
+ vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res);
// Convert the image gamma for display on our output device.
- cout = pow(cout, vec3_splat(1.0 / monitorgamma.x));
+ cout = linear_to_output(cout);
gl_FragColor = vec4(cout,1.0);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
index b7ff6362018..c096ebca7e0 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_crt-geom.sc
@@ -12,180 +12,15 @@ $input v_sinangle, v_cosangle, v_stretch, v_one, v_texCoord
#include "common.sh"
-// Comment the next line to disable interpolation in linear gamma (and gain speed).
-//#define LINEAR_PROCESSING
-
-// Enable 3x oversampling of the beam profile
-#define OVERSAMPLE
-
-// Use the older, purely gaussian beam profile
-#define USEGAUSSIAN
-
-// Macros.
-#define FIX(c) max(abs(c), 1e-5)
-#define PI 3.141592653589
-
SAMPLER2D(mpass_texture, 0);
SAMPLER2D(mask_texture, 1);
-vec4 TEX2D(vec2 c)
-{
- vec2 underscan = step(0.0,c) * step(0.0,vec2_splat(1.0)-c);
- vec4 col = texture2D(mpass_texture, c) * vec4_splat(underscan.x*underscan.y);
-#ifdef LINEAR_PROCESSING
- col = pow(col, vec4_splat(CRTgamma.x));
-#endif
- return col;
-}
-
-// Enable screen curvature.
-uniform vec4 curvature;
-
uniform vec4 u_tex_size0;
uniform vec4 u_tex_size1;
uniform vec4 u_quad_dims;
-uniform vec4 spot_size;
-uniform vec4 spot_growth;
-uniform vec4 spot_growth_power;
-
-uniform vec4 u_interp;
+#include "crt-geom_common.sc"
-uniform vec4 aperture_strength;
-uniform vec4 aperture_brightboost;
-
-uniform vec4 CRTgamma;
-uniform vec4 monitorgamma;
-
-uniform vec4 overscan;
-uniform vec4 aspect;
-
-uniform vec4 d;
-uniform vec4 R;
-
-uniform vec4 cornersize;
-uniform vec4 cornersmooth;
-
-float intersect(vec2 xy , vec2 sinangle, vec2 cosangle)
-{
- float A = dot(xy,xy)+d.x*d.x;
- float B = 2.0*(R.x*(dot(xy,sinangle)-d.x*cosangle.x*cosangle.y)-d.x*d.x);
- float C = d.x*d.x + 2.0*R.x*d.x*cosangle.x*cosangle.y;
- return (-B-sqrt(B*B-4.0*A*C))/(2.0*A);
-}
-
-vec2 bkwtrans(vec2 xy, vec2 sinangle, vec2 cosangle)
-{
- float c = intersect(xy, sinangle, cosangle);
- vec2 pt = vec2_splat(c)*xy;
- pt -= vec2_splat(-R.x)*sinangle;
- pt /= vec2_splat(R.x);
- vec2 tang = sinangle/cosangle;
- vec2 poc = pt/cosangle;
- float A = dot(tang,tang)+1.0;
- float B = -2.0*dot(poc,tang);
- float C = dot(poc,poc)-1.0;
- float a = (-B+sqrt(B*B-4.0*A*C))/(2.0*A);
- vec2 uv = (pt-a*sinangle)/cosangle;
- float r = FIX(R.x*acos(a));
- return uv*r/sin(r/R.x);
-}
-
-vec2 transform(vec2 coord, vec3 stretch, vec2 sinangle, vec2 cosangle)
-{
- coord = (coord-vec2_splat(0.5))*aspect.xy*stretch.z+stretch.xy;
- return (bkwtrans(coord, sinangle, cosangle)/overscan.xy/aspect.xy+vec2_splat(0.5));
-}
-
-float corner(vec2 coord)
-{
- coord = (coord - vec2_splat(0.5)) * overscan.xy + vec2_splat(0.5);
- coord = min(coord, vec2_splat(1.0)-coord) * aspect.xy;
- vec2 cdist = vec2_splat(cornersize.x);
- coord = (cdist - min(coord,cdist));
- float dist = sqrt(dot(coord,coord));
- return clamp((max(cdist.x,1e-3)-dist)*cornersmooth.x,0.0, 1.0);
-}
-
-// Calculate the influence of a scanline on the current pixel.
-//
-// 'distance' is the distance in texture coordinates from the current
-// pixel to the scanline in question.
-// 'color' is the colour of the scanline at the horizontal location of
-// the current pixel.
-vec4 scanlineWeights(float distance, vec4 color)
-{
- // "wid" controls the width of the scanline beam, for each RGB channel
- // The "weights" lines basically specify the formula that gives
- // you the profile of the beam, i.e. the intensity as
- // a function of distance from the vertical center of the
- // scanline. In this case, it is gaussian if width=2, and
- // becomes nongaussian for larger widths. Ideally this should
- // be normalized so that the integral across the beam is
- // independent of its width. That is, for a narrower beam
- // "weights" should have a higher peak at the center of the
- // scanline than for a wider beam.
-#ifdef USEGAUSSIAN
- vec4 wid = spot_size.x + spot_growth.x * pow(color, vec4_splat(spot_growth_power.x));
- vec4 weights = vec4(distance / wid);
- float maxwid = spot_size.x + spot_growth.x;
- float norm = maxwid / ( 1.0 + exp(-1.0/(maxwid*maxwid)) );
- return norm * exp(-weights * weights) / wid;
-#else
- vec4 wid = 2.0 + 2.0 * pow(color, vec4_splat(4.0));
- vec4 weights = vec4_splat(distance / 0.3);
- return 1.4 * exp(-pow(weights * inversesqrt(0.5 * wid), wid)) / (0.6 + 0.2 * wid);
-#endif
-}
-
-vec4 cubic(vec4 x, float B, float C)
-{
- // https://en.wikipedia.org/wiki/Mitchell%E2%80%93Netravali_filters
- vec2 a = x.yz; // components in [0,1]
- vec2 b = x.xw; // components in [1,2]
- vec2 a2 = a*a;
- vec2 b2 = b*b;
- a = (2.0-1.5*B-1.0*C)*a*a2 + (-3.0+2.0*B+C)*a2 + (1.0-(1.0/3.0)*B);
- b = ((-1.0/6.0)*B-C)*b*b2 + (B+5.0*C)*b2 + (-2.0*B-8.0*C)*b + ((4.0/3.0)*B+4.0*C);
- return vec4(b.x,a.x,a.y,b.y);
-}
-
-vec4 x_coeffs(vec4 x, float pos_x)
-{
- if (u_interp.x < 0.5) { // box
- float wid = length(vec2(dFdx(pos_x),dFdy(pos_x)));
- float dx = clamp((0.5 + 0.5*wid - x.y)/wid, 0.0, 1.0);
- return vec4(0.0,dx,1.0-dx,0.0);
- } else if (u_interp.x < 1.5) { // linear
- return vec4(0.0, 1.0-x.y, 1.0-x.z, 0.0);
- } else if (u_interp.x < 2.5) { // Lanczos
- // Prevent division by zero.
- vec4 coeffs = FIX(PI * x);
- // Lanczos2 kernel.
- coeffs = 2.0 * sin(coeffs) * sin(coeffs / 2.0) / (coeffs * coeffs);
- // Normalize.
- coeffs /= dot(coeffs, vec4_splat(1.0));
- return coeffs;
- } else if (u_interp.x < 3.5) { // Catmull-Rom
- return cubic(x,0.0,0.5);
- } else if (u_interp.x < 4.5) { // Mitchell-Netravali
- return cubic(x,1.0/3.0,1.0/3.0);
- } else /*if (u_interp.x < 5.5)*/ { // B-spline
- return cubic(x,1.0,0.0);
- }
-}
-
-vec4 sample_scanline(vec2 xy, vec4 coeffs, float onex)
-{
- // Calculate the effective colour of the given
- // scanline at the horizontal location of the current pixel,
- // using the Lanczos coefficients.
- vec4 col = clamp(TEX2D(xy + vec2(-onex, 0.0))*coeffs.x +
- TEX2D(xy)*coeffs.y +
- TEX2D(xy +vec2(onex, 0.0))*coeffs.z +
- TEX2D(xy + vec2(2.0 * onex, 0.0))*coeffs.w , 0.0, 1.0);
- return col;
-}
void main()
{
@@ -258,23 +93,10 @@ void main()
vec3 mul_res = (col * weights + col2 * weights2).rgb * vec3_splat(cval);
// Shadow mask
- xy = v_texCoord.xy * u_quad_dims.xy / u_tex_size1.xy;
- vec4 mask = texture2D(mask_texture, xy);
- // count of total bright pixels is encoded in the mask's alpha channel
- float nbright = 255.0 - 255.0*mask.a;
- // fraction of bright pixels in the mask
- float fbright = nbright / ( u_tex_size1.x * u_tex_size1.y );
- // average darkening factor of the mask
- float aperture_average = mix(1.0-aperture_strength.x*(1.0-aperture_brightboost.x), 1.0, fbright);
- // colour of dark mask pixels
- vec3 clow = vec3_splat(1.0-aperture_strength.x) * mul_res + vec3_splat(aperture_strength.x*(aperture_brightboost.x)) * mul_res * mul_res;
- float ifbright = 1.0 / fbright;
- // colour of bright mask pixels
- vec3 chi = vec3_splat(ifbright*aperture_average) * mul_res - vec3_splat(ifbright - 1.0) * clow;
- vec3 cout = mix(clow,chi,mask.rgb); // mask texture selects dark vs bright
+ vec3 cout = apply_shadow_mask(v_texCoord.xy, mul_res);
// Convert the image gamma for display on our output device.
- cout = pow(cout, vec3_splat(1.0 / monitorgamma.x));
+ cout = linear_to_output(cout);
gl_FragColor = vec4(cout,1.0);
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
index 6c7c2c8560c..74faf15a740 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussx.sc
@@ -1,4 +1,4 @@
-$input v_texCoord, v_coeffs
+$input v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
@@ -13,6 +13,10 @@ void main()
vec3 sum = vec3_splat(0.0);
float onex = 1.0/u_tex_size0.x;
+ sum += TEX2D(v_texCoord + vec2(-8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(-7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(-6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(-5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x);
sum += TEX2D(v_texCoord + vec2(-4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w);
sum += TEX2D(v_texCoord + vec2(-3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z);
sum += TEX2D(v_texCoord + vec2(-2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y);
@@ -22,8 +26,13 @@ void main()
sum += TEX2D(v_texCoord + vec2(+2.0 * onex, 0.0)) * vec3_splat(v_coeffs.y);
sum += TEX2D(v_texCoord + vec2(+3.0 * onex, 0.0)) * vec3_splat(v_coeffs.z);
sum += TEX2D(v_texCoord + vec2(+4.0 * onex, 0.0)) * vec3_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(+5.0 * onex, 0.0)) * vec3_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(+6.0 * onex, 0.0)) * vec3_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(+7.0 * onex, 0.0)) * vec3_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(+8.0 * onex, 0.0)) * vec3_splat(v_coeffs2.w);
- float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w));
+ float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w
+ +v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w));
gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 );
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
index f6044f4d8f9..c4fa73cdcce 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/fs_gaussy.sc
@@ -1,4 +1,4 @@
-$input v_texCoord, v_coeffs
+$input v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
@@ -13,6 +13,10 @@ void main()
vec3 sum = vec3_splat(0.0);
float oney = 1.0/u_tex_size0.y;
+ sum += TEX2D(v_texCoord + vec2(0.0, -8.0 * oney)) * vec3_splat(v_coeffs2.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, -7.0 * oney)) * vec3_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, -6.0 * oney)) * vec3_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, -5.0 * oney)) * vec3_splat(v_coeffs2.x);
sum += TEX2D(v_texCoord + vec2(0.0, -4.0 * oney)) * vec3_splat(v_coeffs.w);
sum += TEX2D(v_texCoord + vec2(0.0, -3.0 * oney)) * vec3_splat(v_coeffs.z);
sum += TEX2D(v_texCoord + vec2(0.0, -2.0 * oney)) * vec3_splat(v_coeffs.y);
@@ -22,8 +26,13 @@ void main()
sum += TEX2D(v_texCoord + vec2(0.0, +2.0 * oney)) * vec3_splat(v_coeffs.y);
sum += TEX2D(v_texCoord + vec2(0.0, +3.0 * oney)) * vec3_splat(v_coeffs.z);
sum += TEX2D(v_texCoord + vec2(0.0, +4.0 * oney)) * vec3_splat(v_coeffs.w);
+ sum += TEX2D(v_texCoord + vec2(0.0, +5.0 * oney)) * vec3_splat(v_coeffs2.x);
+ sum += TEX2D(v_texCoord + vec2(0.0, +6.0 * oney)) * vec3_splat(v_coeffs2.y);
+ sum += TEX2D(v_texCoord + vec2(0.0, +7.0 * oney)) * vec3_splat(v_coeffs2.z);
+ sum += TEX2D(v_texCoord + vec2(0.0, +8.0 * oney)) * vec3_splat(v_coeffs2.w);
- float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w));
+ float norm = 1.0 / (1.0 + 2.0*(v_coeffs.x+v_coeffs.y+v_coeffs.z+v_coeffs.w
+ +v_coeffs2.x+v_coeffs2.y+v_coeffs2.z+v_coeffs2.w));
gl_FragColor = vec4( pow(sum*vec3_splat(norm), vec3_splat(1.0/u_gamma.x)), 1.0 );
}
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/varying.def.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/varying.def.sc
index 6b1e8e2bf66..0de371e22c8 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/varying.def.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/varying.def.sc
@@ -4,8 +4,9 @@ vec2 v_sinangle : TEXCOORD2 = vec2(0.0,0.0);
vec2 v_cosangle : TEXCOORD3 = vec2(0.0,0.0);
vec2 v_one : TEXCOORD4 = vec2(0.0,0.0);
vec4 v_coeffs : TEXCOORD5 = vec4(0.0,0.0,0.0,0.0);
-vec4 v_lpcoeffs1: TEXCOORD6 = vec4(0.0,0.0,0.0,0.0);
-vec4 v_lpcoeffs2: TEXCOORD7 = vec4(0.0,0.0,0.0,0.0);
+vec4 v_coeffs2 : TEXCOORD6 = vec4(0.0,0.0,0.0,0.0);
+vec4 v_lpcoeffs1: TEXCOORD7 = vec4(0.0,0.0,0.0,0.0);
+vec4 v_lpcoeffs2: TEXCOORD8 = vec4(0.0,0.0,0.0,0.0);
vec3 a_position : POSITION;
vec4 a_color0 : COLOR0;
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
index c91a8948bf1..e9969187c94 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussx.sc
@@ -1,5 +1,5 @@
$input a_position, a_texcoord0, a_color0
-$output v_texCoord, v_coeffs
+$output v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
@@ -11,6 +11,7 @@ void main()
{
float wid = u_width.x*u_tex_size0.x/(320.*u_aspect.x);
v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
+ v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
// Do the standard vertex processing.
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));
diff --git a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
index 3ff1e07f236..0b7ff9b411f 100644
--- a/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
+++ b/src/osd/modules/render/bgfx/shaders/chains/crt-geom/vs_gaussy.sc
@@ -1,5 +1,5 @@
$input a_position, a_texcoord0, a_color0
-$output v_texCoord, v_coeffs
+$output v_texCoord, v_coeffs, v_coeffs2
#include "common.sh"
@@ -11,6 +11,7 @@ void main()
{
float wid = u_width.x*u_tex_size0.y/(320.*u_aspect.y);
v_coeffs = exp(vec4(1.,4.,9.,16.)*vec4_splat(-1.0/wid/wid));
+ v_coeffs2 = exp(vec4(25.,36.,49.,64.)*vec4_splat(-1.0/wid/wid));
// Do the standard vertex processing.
gl_Position = mul(u_viewProj, vec4(a_position.xy, 0.0, 1.0));