diff --git a/Enhancement/SuperMarioMaker_CRT/d2a97b2fb99411a5_0000000000000079_ps.txt b/Enhancement/SuperMarioMaker_CRT/d2a97b2fb99411a5_0000000000000079_ps.txt new file mode 100644 index 00000000..2bf8b0d4 --- /dev/null +++ b/Enhancement/SuperMarioMaker_CRT/d2a97b2fb99411a5_0000000000000079_ps.txt @@ -0,0 +1,282 @@ +#version 420 +#extension GL_ARB_texture_gather : enable +#extension GL_ARB_separate_shader_objects : enable +// shader d2a97b2fb99411a5 +// CRT filter - Just for fun, probably won't be fixing any issues.. + + +layout(binding = 0) uniform sampler2D textureUnitPS0;// Tex0 addr 0xf4481800 res 768x384x1 dim 1 tm: 4 format 001a compSel: 0 1 2 3 mipView: 0x0 (num 0x1) sliceView: 0x0 (num 0x1) Sampler0 ClampX/Y/Z: 2 2 2 border: 1 +layout(location = 0) in vec4 passParameterSem0; +layout(location = 0) out vec4 passPixelColor0; +uniform vec2 uf_fragCoordScale; +// +// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER +// +// by Timothy Lottes +// +// This is more along the style of a really good CGA arcade monitor. +// With RGB inputs instead of NTSC. +// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration. +// +// Left it unoptimized to show the theory behind the algorithm. +// +// It is an example what I personally would want as a display option for pixel art games. +// Please take and use, change, or whatever. +// +//old contrasty, or just copy paste clarity +const float gamma = 0.95; // 1.0 is neutral +const float exposure = 1.2; // 1.0 is neutral, first lessen to avoid truncation prob around .25 for radeon. +const float vibrance = 0.175; // 0.0 is neutral +const float crushContrast = 0.01; // 0.0 is neutral. loss of shadow detail +//const float postExposure = 1.16; // 1.0 is neutral, then slightly raise exposure back up. + +vec3 contrasty(vec3 colour) { + vec3 fColour = (colour.xyz); + + fColour = clamp(exposure * fColour, 0.0, 1.0); + fColour = pow(fColour, vec3(1.0 / gamma)); + float luminance = fColour.r*0.299 + fColour.g*0.587 + fColour.b*0.114; + float mn = min(min(fColour.r, fColour.g), fColour.b); + float mx = max(max(fColour.r, fColour.g), fColour.b); + float sat = (1.0 - (mx - mn)) * (1.0 - mx) * luminance * 5.0; + vec3 lightness = vec3((mn + mx) / 2.0); + // vibrance + fColour = mix(fColour, mix(fColour, lightness, -vibrance), sat); + fColour = max(vec3(0.0), fColour - vec3(crushContrast)); + return fColour; +} +#define RGBA(r, g, b, a) vec4(float(r)/255.0, float(g)/255.0, float(b)/255.0, float(a)/255.0) + +const vec3 kBackgroundColor = RGBA(0x00, 0x60, 0xb8, 0xff).rgb; // medium-blue sky +//const vec3 kBackgroundColor = RGBA(0xff, 0x00, 0xff, 0xff).rgb; // test magenta +//const vec3 kBackgroundColor = RGBA(0x50, 0x50, 0x50, 0xff).rgb; + // Emulated input resolution. +#if 1 + // Fix resolution to set amount. + //768x384x1 // Note: 256x224 is the most common resolution of the SNES, and that of Super Mario World. +vec2 res = vec2( + textureSize(textureUnitPS0, 0).x / 1.0, + textureSize(textureUnitPS0, 0).y / 2.0 +); +#else + // Optimize for resize. +vec2 res = textureSize(textureUnitPS0, 0) / 6.0; +#endif + +// Hardness of scanline. +// -8.0 = soft +// -16.0 = medium +float sHardScan = -8.0; + +// Hardness of pixels in scanline. +// -2.0 = soft +// -4.0 = hard +const float kHardPix = -2.0; + +// Display warp. +// 0.0 = none +// 1.0 / 8.0 = extreme +const vec2 kWarp = vec2(1.0 / 64.0, 1.0 / 48.0); +//const vec2 kWarp = vec2(0); + +// Amount of shadow mask. +float kMaskDark = 2.0; +float kMaskLight = 0.5; + +//------------------------------------------------------------------------ +/* +// sRGB to Linear. +// Assuing using sRGB typed textures this should not be needed. +float toLinear1(float c) { + return (c <= 0.04045) ? + (c / 12.92) : + pow((c + 0.055) / 1.055, 2.4); +} +vec3 toLinear(vec3 c) { + return vec3(toLinear1(c.r), toLinear1(c.g), toLinear1(c.b)); +} + +// Linear to sRGB. +// Assuing using sRGB typed textures this should not be needed. +float toSrgb1(float c) { + return(c < 0.0031308 ? + (c * 12.92) : + (1.055 * pow(c, 0.41666) - 0.055)); +} +vec3 toSrgb(vec3 c) { + return vec3(toSrgb1(c.r), toSrgb1(c.g), toSrgb1(c.b)); +} +*/ +// Nearest emulated sample given floating point position and texel offset. +// Also zero's off screen. +vec4 fetch(vec2 pos, vec2 off) +{ + pos = floor(pos * res + off) / res; + if (max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5) + return vec4(vec3(0.0), 0.0); + + //vec4 sampledColor = texture(textureUnitPS0, pos.xy, -16.0); + vec4 sampledColor = texture(textureUnitPS0, pos.xy,0); + sampledColor = vec4( + (sampledColor.rgb * sampledColor.a) + + (kBackgroundColor * (1.0 - sampledColor.a)), + 1.0 + ); + + return vec4( + //toLinear(sampledColor.rgb), + //sampledColor.a + sampledColor.rgba + ); +} + +// Distance in emulated pixels to nearest texel. +vec2 dist(vec2 pos) { + pos = pos * res; + return -((pos - floor(pos)) - vec2(0.5)); +} + +// 1D Gaussian. +float gaus(float pos, float scale) { + return exp2(scale * pos * pos); +} + +// 3-tap Gaussian filter along horz line. +vec3 horz3(vec2 pos, float off) +{ + vec3 b = fetch(pos, vec2(-1.0, off)).rgb; + vec3 c = fetch(pos, vec2(0.0, off)).rgb; + vec3 d = fetch(pos, vec2(+1.0, off)).rgb; + float dst = dist(pos).x; + // Convert distance to weight. + float scale = kHardPix; + float wb = gaus(dst - 1.0, scale); + float wc = gaus(dst + 0.0, scale); + float wd = gaus(dst + 1.0, scale); + // Return filtered sample. + return (b * wb + c * wc + d * wd) / (wb + wc + wd); +} + +// 5-tap Gaussian filter along horz line. +vec3 horz5(vec2 pos, float off) +{ + vec3 a = fetch(pos, vec2(-2.0, off)).rgb; + vec3 b = fetch(pos, vec2(-1.0, off)).rgb; + vec3 c = fetch(pos, vec2(0.0, off)).rgb; + vec3 d = fetch(pos, vec2(+1.0, off)).rgb; + vec3 e = fetch(pos, vec2(+2.0, off)).rgb; + float dst = dist(pos).x; + // Convert distance to weight. + float scale = kHardPix; + float wa = gaus(dst - 2.0, scale); + float wb = gaus(dst - 1.0, scale); + float wc = gaus(dst + 0.0, scale); + float wd = gaus(dst + 1.0, scale); + float we = gaus(dst + 2.0, scale); + // Return filtered sample. + return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we); +} + +// Return scanline weight. +float scan(vec2 pos, float off) { + float dst = dist(pos).y; + return gaus(dst + off, sHardScan); +} + +// Allow nearest three lines to effect pixel. +vec3 tri(vec2 pos) +{ + vec3 a = horz3(pos, -1.0); + vec3 b = horz5(pos, 0.0); + vec3 c = horz3(pos, +1.0); + float wa = scan(pos, -1.0); + float wb = scan(pos, 0.0); + float wc = scan(pos, +1.0); + return a * wa + b * wb + c * wc; +} + +// Distortion of scanlines, and end of screen alpha. +vec2 warp(vec2 pos) +{ + pos = pos * 2.0 - 1.0; + pos *= vec2( + 1.0 + (pos.y * pos.y) * kWarp.x, + 1.0 + (pos.x * pos.x) * kWarp.y + ); + return pos * 0.5 + 0.5; +} + +// Shadow mask. +vec3 mask(vec2 pos) +{ + pos.x += pos.y * 3.0; + vec3 mask = vec3(kMaskDark, kMaskDark, kMaskDark); + pos.x = fract(pos.x / 6.0); + if (pos.x < 0.333) + mask.r = kMaskLight; + else if (pos.x < 0.666) + mask.g = kMaskLight; + else + mask.b = kMaskLight; + return mask; +} + +// Draw dividing bars. +float bar(float pos, float bar) { + pos -= bar; + return (pos * pos < 4.0) ? 0.0 : 1.0; +} + +float rand(vec2 co) { + return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453); +} +int clampFI32(int v) +{ +if( v == 0x7FFFFFFF ) + return floatBitsToInt(1.0); +else if( v == 0xFFFFFFFF ) + return floatBitsToInt(0.0); +return floatBitsToInt(clamp(intBitsToFloat(v), 0.0, 1.0)); +} +float mul_nonIEEE(float a, float b){ if( a == 0.0 || b == 0.0 ) return 0.0; return a*b; } +void main() +{ +vec4 R0f = vec4(0.0); +float backupReg0f, backupReg1f, backupReg2f, backupReg3f, backupReg4f; +vec4 PV0f = vec4(0.0), PV1f = vec4(0.0); +float PS0f = 0.0, PS1f = 0.0; +vec4 tempf = vec4(0.0); +float tempResultf; +int tempResulti; +ivec4 ARi = ivec4(0); +bool predResult = true; +vec3 cubeMapSTM; +int cubeMapFaceId; +R0f = passParameterSem0; +//R0f.xyzw = (texture(textureUnitPS0, R0f.xy).xyzw); +// export +//passPixelColor0 = vec4(R0f.x, R0f.y, R0f.z, R0f.w); + +vec2 pos = warp(gl_FragCoord.xy / textureSize(textureUnitPS0, 0));//iResolution.xy); +vec4 unmodifiedColor = fetch(pos, vec2(0)); + +// Unmodified. +if (passPixelColor0.x > textureSize(textureUnitPS0, 0).x * 0.333) +{ + passPixelColor0.rgb = contrasty(unmodifiedColor.rgb); +} +else +{ + if (passPixelColor0.x > textureSize(textureUnitPS0, 0).x * 0.666) { + sHardScan = -12.0; + kMaskDark = kMaskLight = 1.0; + } + passPixelColor0.rgb = tri(pos) * mask(gl_FragCoord.xy); +} +//passPixelColor0.rgb *= bar(gl_FragCoord.x, textureSize(textureUnitPS0, 0).x * 0.333) * bar(gl_FragCoord.x, textureSize(textureUnitPS0, 0).x * 0.666); +//passPixelColor0 = vec4( + //toSrgb(passPixelColor0.rgb), + //1.0 +//); +passPixelColor0 = vec4(passPixelColor0.rgb, 1.0); +} diff --git a/Enhancement/SuperMarioMaker_CRT/rules.txt b/Enhancement/SuperMarioMaker_CRT/rules.txt new file mode 100644 index 00000000..6d742423 --- /dev/null +++ b/Enhancement/SuperMarioMaker_CRT/rules.txt @@ -0,0 +1,5 @@ + +[Definition] +titleIds = 000500001018DB00,000500001018DC00,000500001018DD00 +name = "Super Mario Maker - CRT filter" +version = 2 \ No newline at end of file