#version 450 layout(std140, set = 0, binding = 0) uniform UBO { mat4 MVP; vec4 OutputSize; vec4 OriginalSize; vec4 SourceSize; uint FrameCount; } global; //////////////////////////////////////////////////////// // GTU-famicom version 0.50 // Author: aliaspider - aliaspider@gmail.com // License: GPLv3 //////////////////////////////////////////////////////// #define TO_INT2(X) int(floor(((X) * 3.0) + 0.5)) #define TO_INT3(X) int(floor(((X) * 7.0) + 0.5)) #define TO_INT4(X) int(floor(((X) * 15.0) + 0.5)) bool InColorp (int p, int color) { return ((color + p) % 12 < 6); } float NTSCsignal(int emphasis, int level, int color, int p) { float black=.518; float white=1.962; float attenuation=0.746; const float levels[8] = float[] (0.350 , 0.518, 0.962, 1.550, 1.094f, 1.506, 1.962, 1.962); if(color > 13) level = 1; float low = levels[0 + level]; float high = levels[4 + level]; if(color == 0) low = high; if(color > 12) high = low; float signal = InColorp(p, color) ? high : low; if( (bool(emphasis & 1) && InColorp(p, 0)) || (bool(emphasis & 2) && InColorp(p, 4)) || (bool(emphasis & 4) && InColorp(p, 8)) ) signal = signal * attenuation; signal = (signal-black) / (white-black); return signal; } #pragma stage vertex layout(location = 0) in vec4 Position; layout(location = 1) in vec2 TexCoord; layout(location = 0) out vec2 vTexCoord; layout(location = 1) out float colorPhase; void main() { gl_Position = global.MVP * Position; vTexCoord = TexCoord; vec2 pos = (vTexCoord.xy*global.OutputSize.xy)-0.5; colorPhase = 8.0001 + pos.x + pos.y * 4.0001 + global.FrameCount * 4.0001; } #pragma stage fragment layout(location = 0) in vec2 vTexCoord; layout(location = 1) in float colorPhase; layout(location = 0) out vec4 FragColor; layout(set = 0, binding = 2) uniform sampler2D Source; void main() { vec4 c=texture(Source, vTexCoord.xy); int color = TO_INT4(c.x); int level = TO_INT2(c.y); int emphasis = TO_INT3(c.z); float signal = NTSCsignal(emphasis,level,color,int(colorPhase + 0.5)); FragColor = vec4(signal); }