diff options
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 |
commit | 75466ad87d2af99d05b0c5b84e661523734d710b (patch) | |
tree | 0a11390cf8d214d52155666910e1910fb192bfac /src/osd | |
parent | f3fb60fee6fb83c80e776fcfd1bd271dc83d126f (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')
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)); |