Created
October 26, 2025 00:33
-
-
Save mariodivece/3fac33939f3342706ea69f12beee0e1c to your computer and use it in GitHub Desktop.
zfast_crt_standard Ported for Dolphin emulator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| 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. | |
| Ported for Dolphin Emulator by Mario Di Vece, 2025 | |
| */ | |
| /* | |
| [configuration] | |
| # zfast_crt (Dolphin) — scanlines locked to OUTPUT pixel rows | |
| # Version 6 — 2025-10-25 | |
| [OptionRangeFloat] | |
| GUIName = Blur Amount (X) | |
| OptionName = BLURSCALEX | |
| MinValue = 0.0 | |
| MaxValue = 5.0 | |
| StepAmount = 0.05 | |
| DefaultValue = 0.10 | |
| [OptionRangeFloat] | |
| GUIName = Scanline Strength (Low Luma) | |
| OptionName = LOWLUMSCAN | |
| MinValue = 0.0 | |
| MaxValue = 1.5 | |
| StepAmount = 0.05 | |
| DefaultValue = 0.60 | |
| [OptionRangeFloat] | |
| GUIName = Scanline Strength (High Luma) | |
| OptionName = HILUMSCAN | |
| MinValue = 0.0 | |
| MaxValue = 1.5 | |
| StepAmount = 0.05 | |
| DefaultValue = 0.60 | |
| [OptionRangeFloat] | |
| GUIName = Dark Pixel Brightness Boost | |
| OptionName = BRIGHTBOOST | |
| MinValue = 0.5 | |
| MaxValue = 5.0 | |
| StepAmount = 0.10 | |
| DefaultValue = 1.80 | |
| [OptionRangeFloat] | |
| GUIName = Mask Effect Amount | |
| OptionName = MASK_DARK | |
| MinValue = 0.0 | |
| MaxValue = 4.0 | |
| StepAmount = 0.05 | |
| DefaultValue = 0.50 | |
| [OptionRangeFloat] | |
| GUIName = Mask/Scanline Fade by Brightness | |
| OptionName = MASK_FADE | |
| MinValue = 0.0 | |
| MaxValue = 1.0 | |
| StepAmount = 0.05 | |
| DefaultValue = 0.80 | |
| [OptionRangeFloat] | |
| GUIName = Scanline Thickness (relative) | |
| OptionName = SL_THICK | |
| MinValue = 0.05 | |
| MaxValue = 4.0 | |
| StepAmount = 0.05 | |
| DefaultValue = 1.50 | |
| [OptionRangeFloat] | |
| GUIName = Pixels per Scanline | |
| OptionName = PX_PER_SL | |
| MinValue = 2.25 | |
| MaxValue = 25.0 | |
| StepAmount = 0.25 | |
| DefaultValue = 6.0 | |
| [/configuration] | |
| */ | |
| #define saturate(x) clamp((x), 0.0, 1.0) | |
| void main() | |
| { | |
| float blurX = GetOption(BLURSCALEX); | |
| float loScan = GetOption(LOWLUMSCAN); | |
| float hiScan = GetOption(HILUMSCAN); | |
| float boost = GetOption(BRIGHTBOOST); | |
| float maskDark = GetOption(MASK_DARK); | |
| float maskFade = GetOption(MASK_FADE); | |
| // Compute pixels-per-scanline as integer multiple of 4 | |
| float pxPerSL = GetOption(PX_PER_SL); | |
| float slThick = saturate(GetOption(SL_THICK)); | |
| float2 uv = GetCoordinates(); | |
| float2 winRes = GetWindowResolution(); | |
| float2 invRes = GetInvResolution(); | |
| float4 src = Sample(); | |
| if (blurX > 0.0) | |
| { | |
| float2 dx = float2(invRes.x, 0.0); | |
| float3 L = SampleLocation(uv - dx).rgb; | |
| float3 R = SampleLocation(uv + dx).rgb; | |
| float3 avg = 0.5 * (L + R); | |
| src.rgb = mix(src.rgb, avg, saturate(blurX)); | |
| } | |
| float3 col = src.rgb; | |
| float luma = dot(col, float3(0.299, 0.587, 0.114)); | |
| // --- Scanlines tied to OUTPUT pixel grid with 4-multiple spacing --- | |
| float vPix = uv.y * winRes.y; | |
| float cell = (vPix / pxPerSL); | |
| float phase = fract(cell); | |
| float dist = abs(phase - 0.5); | |
| float halfWidth = clamp(slThick * 0.5, 0.01, 0.50); | |
| float core = 1.0 - smoothstep(0.0, halfWidth, dist); | |
| float strength = mix(loScan, hiScan, saturate(luma * maskFade)); | |
| float scanMul = 1.0 - (strength * core); | |
| // --- Aperture mask aligned to OUTPUT columns --- | |
| float xPix = uv.x * winRes.x; | |
| float mstep = mod(floor(xPix), 2.0); | |
| float mask = 1.0 - maskDark * (1.0 - mstep); | |
| float3 outRGB = col * boost * scanMul * mask; | |
| outRGB = clamp(outRGB, 0.0, 1.125); | |
| SetOutput(float4(outRGB, 1.0)); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment