mirror of https://github.com/Enne2/win9xman
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
6.4 KiB
199 lines
6.4 KiB
/* |
|
zfast_crt_standard - A simple, fast CRT shader. |
|
|
|
Copyright (C) 2017 Greg Hogan (SoltanGris42) |
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
under the terms of the GNU General Public License as published by the Free |
|
Software Foundation; either version 2 of the License, or (at your option) |
|
any later version. |
|
|
|
|
|
Notes: This shader does scaling with a weighted linear filter for adjustable |
|
sharpness on the x and y axes based on the algorithm by Inigo Quilez here: |
|
http://http://www.iquilezles.org/www/articles/texture/texture.htm |
|
but modified to be somewhat sharper. Then a scanline effect that varies |
|
based on pixel brighness is applied along with a monochrome aperture mask. |
|
This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s |
|
resolutions (1920x1080 or 1600x1200). |
|
*/ |
|
|
|
//For testing compilation |
|
//#define FRAGMENT |
|
//#define VERTEX |
|
|
|
//This can't be an option without slowing the shader down |
|
//Comment this out for a coarser 3 pixel mask...which is currently broken |
|
//on SNES Classic Edition due to Mali 400 gpu precision |
|
#define FINEMASK |
|
//Some drivers don't return black with texture coordinates out of bounds |
|
//SNES Classic is too slow to black these areas out when using fullscreen |
|
//overlays. But you can uncomment the below to black them out if necessary |
|
//#define BLACK_OUT_BORDER |
|
|
|
// Parameter lines go here: |
|
#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05 |
|
#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5 |
|
#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0 |
|
#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05 |
|
#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05 |
|
#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05 |
|
|
|
#if defined(VERTEX) |
|
|
|
#if __VERSION__ >= 130 |
|
#define COMPAT_VARYING out |
|
#define COMPAT_ATTRIBUTE in |
|
#define COMPAT_TEXTURE texture |
|
#else |
|
#define COMPAT_VARYING varying |
|
#define COMPAT_ATTRIBUTE attribute |
|
#define COMPAT_TEXTURE texture2D |
|
#endif |
|
|
|
#ifdef GL_ES |
|
#define COMPAT_PRECISION mediump |
|
#else |
|
#define COMPAT_PRECISION |
|
#endif |
|
|
|
COMPAT_ATTRIBUTE vec4 VertexCoord; |
|
COMPAT_ATTRIBUTE vec4 COLOR; |
|
COMPAT_ATTRIBUTE vec4 TexCoord; |
|
COMPAT_VARYING vec4 COL0; |
|
COMPAT_VARYING vec4 TEX0; |
|
COMPAT_VARYING float maskFade; |
|
COMPAT_VARYING vec2 invDims; |
|
|
|
vec4 _oPosition1; |
|
uniform mat4 MVPMatrix; |
|
uniform COMPAT_PRECISION int FrameDirection; |
|
uniform COMPAT_PRECISION int FrameCount; |
|
uniform COMPAT_PRECISION vec2 OutputSize; |
|
uniform COMPAT_PRECISION vec2 TextureSize; |
|
uniform COMPAT_PRECISION vec2 InputSize; |
|
|
|
// compatibility #defines |
|
#define vTexCoord TEX0.xy |
|
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize |
|
#define OutSize vec4(OutputSize, 1.0 / OutputSize) |
|
|
|
#ifdef PARAMETER_UNIFORM |
|
// All parameter floats need to have COMPAT_PRECISION in front of them |
|
uniform COMPAT_PRECISION float BLURSCALEX; |
|
//uniform COMPAT_PRECISION float BLURSCALEY; |
|
uniform COMPAT_PRECISION float LOWLUMSCAN; |
|
uniform COMPAT_PRECISION float HILUMSCAN; |
|
uniform COMPAT_PRECISION float BRIGHTBOOST; |
|
uniform COMPAT_PRECISION float MASK_DARK; |
|
uniform COMPAT_PRECISION float MASK_FADE; |
|
#else |
|
#define BLURSCALEX 0.45 |
|
//#define BLURSCALEY 0.20 |
|
#define LOWLUMSCAN 5.0 |
|
#define HILUMSCAN 10.0 |
|
#define BRIGHTBOOST 1.25 |
|
#define MASK_DARK 0.25 |
|
#define MASK_FADE 0.8 |
|
#endif |
|
|
|
void main() |
|
{ |
|
gl_Position = MVPMatrix * VertexCoord; |
|
|
|
TEX0.xy = TexCoord.xy*1.0001; |
|
maskFade = 0.3333*MASK_FADE; |
|
invDims = 1.0/TextureSize.xy; |
|
} |
|
|
|
#elif defined(FRAGMENT) |
|
|
|
#ifdef GL_ES |
|
#ifdef GL_FRAGMENT_PRECISION_HIGH |
|
precision highp float; |
|
#else |
|
precision mediump float; |
|
#endif |
|
#define COMPAT_PRECISION mediump |
|
#else |
|
#define COMPAT_PRECISION |
|
#endif |
|
|
|
#if __VERSION__ >= 130 |
|
#define COMPAT_VARYING in |
|
#define COMPAT_TEXTURE texture |
|
out COMPAT_PRECISION vec4 FragColor; |
|
#else |
|
#define COMPAT_VARYING varying |
|
#define FragColor gl_FragColor |
|
#define COMPAT_TEXTURE texture2D |
|
#endif |
|
|
|
uniform COMPAT_PRECISION int FrameDirection; |
|
uniform COMPAT_PRECISION int FrameCount; |
|
uniform COMPAT_PRECISION vec2 OutputSize; |
|
uniform COMPAT_PRECISION vec2 TextureSize; |
|
uniform COMPAT_PRECISION vec2 InputSize; |
|
uniform sampler2D Texture; |
|
COMPAT_VARYING vec4 TEX0; |
|
COMPAT_VARYING float maskFade; |
|
COMPAT_VARYING vec2 invDims; |
|
|
|
// compatibility #defines |
|
#define Source Texture |
|
#define vTexCoord TEX0.xy |
|
#define texture(c, d) COMPAT_TEXTURE(c, d) |
|
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize |
|
#define OutSize vec4(OutputSize, 1.0 / OutputSize) |
|
|
|
#ifdef PARAMETER_UNIFORM |
|
// All parameter floats need to have COMPAT_PRECISION in front of them |
|
uniform COMPAT_PRECISION float BLURSCALEX; |
|
//uniform COMPAT_PRECISION float BLURSCALEY; |
|
uniform COMPAT_PRECISION float LOWLUMSCAN; |
|
uniform COMPAT_PRECISION float HILUMSCAN; |
|
uniform COMPAT_PRECISION float BRIGHTBOOST; |
|
uniform COMPAT_PRECISION float MASK_DARK; |
|
uniform COMPAT_PRECISION float MASK_FADE; |
|
#else |
|
#define BLURSCALEX 0.45 |
|
//#define BLURSCALEY 0.20 |
|
#define LOWLUMSCAN 5.0 |
|
#define HILUMSCAN 10.0 |
|
#define BRIGHTBOOST 1.25 |
|
#define MASK_DARK 0.25 |
|
#define MASK_FADE 0.8 |
|
#endif |
|
|
|
void main() |
|
{ |
|
|
|
//This is just like "Quilez Scaling" but sharper |
|
COMPAT_PRECISION vec2 p = vTexCoord * TextureSize; |
|
COMPAT_PRECISION vec2 i = floor(p) + 0.50; |
|
COMPAT_PRECISION vec2 f = p - i; |
|
p = (i + 4.0*f*f*f)*invDims; |
|
p.x = mix( p.x , vTexCoord.x, BLURSCALEX); |
|
COMPAT_PRECISION float Y = f.y*f.y; |
|
COMPAT_PRECISION float YY = Y*Y; |
|
#define ratio SourceSize.x/InputSize.x |
|
#if defined(FINEMASK) |
|
COMPAT_PRECISION float whichmask = floor(vTexCoord.x*OutputSize.x*ratio)*-0.5; |
|
COMPAT_PRECISION float mask = 1.0 + float(fract(whichmask) < 0.5) * -MASK_DARK; |
|
#else |
|
COMPAT_PRECISION float whichmask = floor(vTexCoord.x*OutputSize.x*ratio)*-0.3333; |
|
COMPAT_PRECISION float mask = 1.0 + float(fract(whichmask) < 0.3333) * -MASK_DARK; |
|
#endif |
|
COMPAT_PRECISION vec3 colour = COMPAT_TEXTURE(Source, p).rgb; |
|
|
|
COMPAT_PRECISION float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY)); |
|
COMPAT_PRECISION float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y); |
|
|
|
#if defined(BLACK_OUT_BORDER) |
|
colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing? |
|
#endif |
|
|
|
FragColor.rgba = vec4(colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,vec3(maskFade))),1.0); |
|
|
|
} |
|
#endif
|
|
|