Godot Version
4.2
Question
I’m trying to port this shader from glsl to godot shader, but when I place it on a ColorRect as an overlay, it does nothing. I think it has to do with the way it’s getting the texture but I’m pretty new to shaders and can’t figure it out. The code is very long but I’ll post it here.
shader_type canvas_item;
uniform float BEAM_PROFILE : hint_range(0.0, 6.0);
uniform float BEAM_MIN_WIDTH : hint_range(0.0, 1.0) = 0.86;
uniform float BEAM_MAX_WIDTH : hint_range(0.0, 1.0) = 1.0;
uniform float SCANLINES_STRENGTH : hint_range(0.0, 1.0) = 0.58;
uniform float COLOR_BOOST : hint_range(1.0, 2.0) = 1.25;
uniform float HFILTER_SHARPNESS : hint_range(0.0, 1.0) = 1.0;
uniform float PHOSPHOR_LAYOUT : hint_range(0.0, 19.0) = 4.0;
uniform float MASK_INTENSITY : hint_range(0.0, 1.0) = 0.5;
uniform float CRT_ANTI_RINGING : hint_range(0.0, 1.0) = 1.0;
uniform float InputGamma : hint_range(0.0, 5.0) = 2.4;
uniform float OutputGamma : hint_range(0.0, 5.0) = 2.2;
uniform float VSCANLINES : hint_range(0.0, 1.0) = 0.0;
uniform float CRT_CURVATURE : hint_range(0.0, 1.0) = 1.0;
uniform float CRT_warpX : hint_range(0.0, 0.125) = 0.031;
uniform float CRT_warpY : hint_range(0.0, 0.125) = 0.041;
uniform float CRT_cornersize : hint_range(0.001, 1.0) = 0.01;
uniform float CRT_cornersmooth : hint_range(80.0, 2000.0) = 1000.0;
#define GAMMA_IN(color) pow(color, vec4(InputGamma, InputGamma, InputGamma, InputGamma))
#define GAMMA_OUT(color) pow(color, vec4(1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma, 1.0 / OutputGamma))
#define texCoord TEX0
#define IN varying
#define FragColor COLOR
#define tex2D texture
#define PRECISION
uniform PRECISION int FrameDirection;
uniform PRECISION int FrameCount;
uniform PRECISION vec2 OutputSize;
uniform PRECISION vec2 TextureSize;
uniform PRECISION vec2 InputSize;
uniform sampler2D s_p;
IN vec2 texCoord;
vec3 mask_weights(vec2 coord, float mask_intensity, int phosphor_layout) {
vec3 weights = vec3(1.0, 1.0, 1.0);
float on = 1.0;
float off = 1.0 - mask_intensity;
vec3 red = vec3(on, off, off);
vec3 green = vec3(off, on, off);
vec3 blue = vec3(off, off, on );
vec3 magenta = vec3(on, off, on );
vec3 yellow = vec3(on, on, off);
vec3 cyan = vec3(off, on, on );
vec3 black = vec3(off, off, off);
vec3 white = vec3(on, on, on );
int w, z = 0;
vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0)));
if(phosphor_layout == 0) {
weights = vec3(1.0, 1.0, 1.0);
}
else if(phosphor_layout == 1) {
weights = aperture_weights;
}
else if(phosphor_layout == 2) {
vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0)));
weights = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0)));
}
else if(phosphor_layout == 3) {
vec3 slotmask_x1[4] = vec3[](magenta, green, black, black);
vec3 slotmask_x2[4] = vec3[](magenta, green, magenta, green);
vec3 slotmask_x3[4] = vec3[](black, black, magenta, green);
w = int(floor(mod(coord.y, 3.0)));
z = int(floor(mod(coord.x, 4.0)));
if (w == 1) {
weights = slotmask_x1[z];
} else if (w == 2) {
weights = slotmask_x2[z];
} else {
weights = slotmask_x3[z];
}
}
else if(phosphor_layout == 4) {
weights = mix(yellow, blue, floor(mod(coord.x, 2.0)));
}
else if(phosphor_layout == 5) {
vec3 inverse_aperture = mix(blue, yellow, floor(mod(coord.x, 2.0)));
weights = mix(mix(yellow, blue, floor(mod(coord.x, 2.0))), inverse_aperture, floor(mod(coord.y, 2.0)));
}
else if(phosphor_layout == 6) {
vec3 ap4[4] = vec3[](red, green, blue, black);
weights = ap4[int(floor(mod(coord.x, 4.0)))];
}
else if(phosphor_layout == 7) {
vec3 ap3[5] = vec3[](red, magenta, blue, green, green);
weights = ap3[int(floor(mod(coord.x, 5.0)))];
}
else if(phosphor_layout == 8) {
vec3 big_ap[7] = vec3[](red, red, yellow, green, cyan, blue, blue);
weights = big_ap[int(floor(mod(coord.x, 7.0)))];
}
else if(phosphor_layout == 9) {
vec3 big_ap_rgb[4] = vec3[](red, yellow, cyan, blue);
weights = big_ap_rgb[int(floor(mod(coord.x, 4.0)))];
}
else if(phosphor_layout == 10) {
vec3 big_ap_rbg[4] = vec3[](red, magenta, cyan, green);
weights = big_ap_rbg[int(floor(mod(coord.x, 4.0)))];
}
else if(phosphor_layout == 11) {
vec3 delta_1_1[4] = vec3[](red, green, blue, black);
vec3 delta_1_2[4] = vec3[](blue, black, red, green);
w = int(floor(mod(coord.y, 2.0)));
z = int(floor(mod(coord.x, 4.0)));
if (w == 1) {
weights = delta_1_1[z];
} else {
weights = delta_1_2[z];
}
}
else if(phosphor_layout == 12) {
vec3 delta_2_1[4] = vec3[](red, yellow, cyan, blue);
vec3 delta_2_2[4] = vec3[](cyan, blue, red, yellow);
w = int(floor(mod(coord.y, 2.0)));
if (w == 1) {
weights = delta_2_1[int(floor(mod(coord.x, 4.0)))];
} else {
weights = delta_2_2[int(floor(mod(coord.x, 4.0)))];
}
}
else if(phosphor_layout == 13) {
vec3 delta_1[4] = vec3[](red, yellow, cyan, blue);
vec3 delta_2[4] = vec3[](red, yellow, cyan, blue);
vec3 delta_3[4] = vec3[](cyan, blue, red, yellow);
vec3 delta_4[4] = vec3[](cyan, blue, red, yellow);
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 4.0)));
if (w == 1) {
weights = delta_1[z];
} else if (w == 2) {
weights = delta_2[z];
} else if (w == 3) {
weights = delta_3[z];
} else {
weights = delta_4[z];
}
}
else if(phosphor_layout == 14) {
vec3 slot2_1[6] = vec3[](magenta, green, black, black, black, black);
vec3 slot2_2[6] = vec3[](magenta, green, black, magenta, green, black);
vec3 slot2_3[6] = vec3[](black, black, black, magenta, green, black);
w = int(floor(mod(coord.y, 3.0)));
z = int(floor(mod(coord.x, 6.0)));
if (w == 1) {
weights = slot2_1[z];
} else if (w == 2) {
weights = slot2_2[z];
} else {
weights = slot2_3[z];
}
}
else if(phosphor_layout == 15) {
vec3 slotmask_RBG_x1[8] = vec3[](red, yellow, cyan, blue, black, black, black, black);
vec3 slotmask_RBG_x2[8] = vec3[](black, black, black, black, red, yellow, cyan, blue);
vec3 slotmask_RBG_x3[8] = vec3[](red, yellow, cyan, blue, red, yellow, cyan, blue);
vec3 slotmask_RBG_x4[8] = vec3[](red, yellow, cyan, blue, red, yellow, cyan, blue);
vec3 slotmask_RBG_x5[8] = vec3[](red, yellow, cyan, blue, red, yellow, cyan, blue);
vec3 slotmask_RBG_x6[8] = vec3[](red, yellow, cyan, blue, black, black, black, black);
vec3 slotmask_RBG_x7[8] = vec3[](black, black, black, black, red, yellow, cyan, blue);
w = int(floor(mod(coord.y, 7.0)));
z = int(floor(mod(coord.x, 8.0)));
if (w == 1) {
weights = slotmask_RBG_x1[z];
} else if (w == 2) {
weights = slotmask_RBG_x2[z];
} else if (w == 3) {
weights = slotmask_RBG_x3[z];
} else if (w == 4) {
weights = slotmask_RBG_x4[z];
} else if (w == 5) {
weights = slotmask_RBG_x5[z];
} else if (w == 6) {
weights = slotmask_RBG_x6[z];
} else {
weights = slotmask_RBG_x7[z];
}
}
else if(phosphor_layout == 16) {
vec3 triad_rgb_x1[6] = vec3[](red, green, blue, red, green, blue);
vec3 triad_rgb_x2[6] = vec3[](red, green, blue, black, black, black);
vec3 triad_rgb_x3[6] = vec3[](black, black, black, red, green, blue);
w = int(floor(mod(coord.y, 3.0)));
z = int(floor(mod(coord.x, 6.0)));
if (w == 1) {
weights = triad_rgb_x1[z];
} else if (w == 2) {
weights = triad_rgb_x2[z];
} else {
weights = triad_rgb_x3[z];
}
}
else if(phosphor_layout == 17) {
vec3 delta_3_1[4] = vec3[](red, yellow, cyan, blue);
vec3 delta_3_2[4] = vec3[](yellow, cyan, blue, red);
vec3 delta_3_3[4] = vec3[](cyan, blue, red, yellow);
vec3 delta_3_4[4] = vec3[](blue, red, yellow, cyan);
w = int(floor(mod(coord.y, 4.0)));
z = int(floor(mod(coord.x, 4.0)));
if (w == 1) {
weights = delta_3_1[z];
} else if (w == 2) {
weights = delta_3_2[z];
} else if (w == 3) {
weights = delta_3_3[z];
} else {
weights = delta_3_4[z];
}
}
else if(phosphor_layout == 18) {
vec3 trinitron[3] = vec3[](red, green, blue);
vec3 trinitron_2[3] = vec3[](yellow, cyan, magenta);
vec3 trinitron_3[3] = vec3[](magenta, cyan, yellow);
w = int(floor(mod(coord.y, 3.0)));
z = int(floor(mod(coord.x, 3.0)));
if (w == 1) {
weights = trinitron[z];
} else if (w == 2) {
weights = trinitron_2[z];
} else {
weights = trinitron_3[z];
}
}
else if(phosphor_layout == 19) {
vec3 arcade_x1[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x2[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x3[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x4[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x5[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x6[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x7[8] = vec3[](red, red, red, green, green, green, blue, blue);
vec3 arcade_x8[8] = vec3[](red, red, red, green, green, green, blue, blue);
w = int(floor(mod(coord.y, 8.0)));
z = int(floor(mod(coord.x, 8.0)));
if (w == 1) {
weights = arcade_x1[z];
} else if (w == 2) {
weights = arcade_x2[z];
} else if (w == 3) {
weights = arcade_x3[z];
} else if (w == 4) {
weights = arcade_x4[z];
} else if (w == 5) {
weights = arcade_x5[z];
} else if (w == 6) {
weights = arcade_x6[z];
} else if (w == 7) {
weights = arcade_x7[z];
} else {
weights = arcade_x8[z];
}
}
return weights;
}
float corner(vec2 coord)
{
vec2 corner_aspect = vec2(1.0, 0.75);
coord = (coord - vec2(0.5)) + vec2(0.5, 0.5);
coord = min(coord, vec2(1.0) - coord) * corner_aspect;
vec2 cdist = vec2(CRT_cornersize);
coord = (cdist - min(coord, cdist));
float dist = sqrt(dot(coord, coord));
return clamp((cdist.x - dist)*CRT_cornersmooth, 0.0, 1.0);
}
vec2 Warp(vec2 texcoord){
vec2 curvedCoords = texcoord * 2.0 - 1.0;
float curvedCoordsDistance = sqrt(curvedCoords.x*curvedCoords.x+curvedCoords.y*curvedCoords.y);
vec2 CRT_Distortion = vec2(CRT_warpX, CRT_warpY) * 15.;
curvedCoords = curvedCoords / curvedCoordsDistance;
curvedCoords = curvedCoords * (1.0-pow(vec2(1.0-(curvedCoordsDistance/1.4142135623730950488016887242097)),(1.0/(1.0+CRT_Distortion*0.2))));
curvedCoords = curvedCoords / (1.0-pow(vec2(0.29289321881345247559915563789515),(1.0/(vec2(1.0)+CRT_Distortion*0.2))));
curvedCoords = curvedCoords * 0.5 + 0.5;
return curvedCoords;
}
// Horizontal cubic filter.
// Some known filters use these values:
// B = 0.0, C = 0.0 => Hermite cubic filter.
// B = 1.0, C = 0.0 => Cubic B-Spline filter.
// B = 0.0, C = 0.5 => Catmull-Rom Spline filter. This is the default used in this shader.
// B = C = 1.0/3.0 => Mitchell-Netravali cubic filter.
// B = 0.3782, C = 0.3109 => Robidoux filter.
// B = 0.2620, C = 0.3690 => Robidoux Sharp filter.
#define scanlines_strength (4.0*profile.x)
#define beam_min_width profile.y
#define beam_max_width profile.z
#define color_boost profile.w
vec4 get_beam_profile()
{
vec4 bp = vec4(SCANLINES_STRENGTH, BEAM_MIN_WIDTH, BEAM_MAX_WIDTH, COLOR_BOOST);
if (BEAM_PROFILE == 1.0) bp = vec4(0.40, 1.00, 1.00, 1.00); // Catmull-rom
if (BEAM_PROFILE == 2.0) bp = vec4(0.72, 1.00, 1.00, 1.25); // Catmull-rom
if (BEAM_PROFILE == 3.0) bp = vec4(0.60, 0.50, 1.00, 1.25); // Hermite
if (BEAM_PROFILE == 4.0) bp = vec4(0.60, 0.72, 1.00, 1.25); // Hermite
if (BEAM_PROFILE == 5.0) bp = vec4(0.68, 0.68, 1.00, 1.25); // Hermite
if (BEAM_PROFILE == 6.0) bp = vec4(0.70, 0.50, 1.00, 1.80); // Catmull-rom
return bp;
}
void fragment()
{
float B = 1.0 - HFILTER_SHARPNESS;
float C = HFILTER_SHARPNESS*0.5; // B+2C=1 Mitchel-Netravali recommendation line.
mat4 invX = mat4( vec4((-B - 6.0*C)/6.0, (12.0 - 9.0*B - 6.0*C)/6.0, -(12.0 - 9.0*B - 6.0*C)/6.0, (B + 6.0*C)/6.0),
vec4((3.0*B + 12.0*C)/6.0, (-18.0 + 12.0*B + 6.0*C)/6.0, (18.0 - 15.0*B - 12.0*C)/6.0, -C),
vec4((-3.0*B - 6.0*C)/6.0, 0.0, (3.0*B + 6.0*C)/6.0, 0.0),
vec4(B/6.0, (6.0 - 2.0*B)/6.0, B/6.0, 0.0));
vec4 profile = get_beam_profile();
vec2 dx = mix(vec2(1.0/TextureSize.x, 0.0), vec2(0.0, 1.0/TextureSize.y), VSCANLINES);
vec2 dy = mix(vec2(0.0, 1.0/TextureSize.y), vec2(1.0/TextureSize.x, 0.0), VSCANLINES);
// vec2 pix_coord = texCoord.xy*TextureSize + vec2(-0.5, 0.5);
vec2 pp = texCoord.xy;
pp = (CRT_CURVATURE > 0.5) ? (Warp(pp*TextureSize.xy/InputSize.xy)*InputSize.xy/TextureSize.xy) : pp;
vec2 pix_coord = pp.xy*TextureSize + vec2(-0.5, 0.5);
vec2 tc = mix((floor(pix_coord) + vec2(0.5, 0.5))/TextureSize, (floor(pix_coord) + vec2(1.0, -0.5))/TextureSize, VSCANLINES);
vec2 fp = mix(fract(pix_coord), fract(pix_coord.yx), VSCANLINES);
vec4 c00 = GAMMA_IN(tex2D(s_p, tc - dx - dy).xyzw);
vec4 c01 = GAMMA_IN(tex2D(s_p, tc - dy).xyzw);
vec4 c02 = GAMMA_IN(tex2D(s_p, tc + dx - dy).xyzw);
vec4 c03 = GAMMA_IN(tex2D(s_p, tc + 2.0*dx - dy).xyzw);
vec4 c10 = GAMMA_IN(tex2D(s_p, tc - dx).xyzw);
vec4 c11 = GAMMA_IN(tex2D(s_p, tc ).xyzw);
vec4 c12 = GAMMA_IN(tex2D(s_p, tc + dx).xyzw);
vec4 c13 = GAMMA_IN(tex2D(s_p, tc + 2.0*dx).xyzw);
mat4 color_matrix0 = mat4(c00, c01, c02, c03);
mat4 color_matrix1 = mat4(c10, c11, c12, c13);
vec4 lobes = vec4(fp.x*fp.x*fp.x, fp.x*fp.x, fp.x, 1.0);
vec4 invX_Px = invX * lobes;
vec4 color0 = color_matrix0 * invX_Px;
vec4 color1 = color_matrix1 * invX_Px;
// Get min/max samples
vec4 min_sample0 = min(c01,c02);
vec4 max_sample0 = max(c01,c02);
vec4 min_sample1 = min(c11,c12);
vec4 max_sample1 = max(c11,c12);
// Anti-ringing
vec4 aux = color0;
color0 = clamp(color0, min_sample0, max_sample0);
color0 = mix(aux, color0, CRT_ANTI_RINGING);
aux = color1;
color1 = clamp(color1, min_sample1, max_sample1);
color1 = mix(aux, color1, CRT_ANTI_RINGING);
float pos0 = fp.y;
float pos1 = 1.0 - fp.y;
vec4 lum0 = mix(vec4(beam_min_width), vec4(beam_max_width), color0);
vec4 lum1 = mix(vec4(beam_min_width), vec4(beam_max_width), color1);
vec4 d0 = scanlines_strength*pos0/(lum0+0.0000001);
vec4 d1 = scanlines_strength*pos1/(lum1+0.0000001);
d0 = exp(-d0*d0);
d1 = exp(-d1*d1);
vec4 color = color_boost*(color0*d0+color1*d1);
// vec2 mask_coords = gl_FragCoord.xy; //texCoord.xy * OutputSize.xy;
vec2 mask_coords = (texCoord.xy * OutputSize.xy) * TextureSize.xy / InputSize.xy;
mask_coords = mix(mask_coords.xy, mask_coords.yx, VSCANLINES);
color.rgb*=mask_weights(mask_coords, MASK_INTENSITY, int(PHOSPHOR_LAYOUT));
color = GAMMA_OUT(color);
FragColor = vec4(color);
FragColor *= (CRT_CURVATURE > 0.5) ? corner(pp*TextureSize.xy/InputSize.xy) : 1.0;
COLOR = FragColor;
}