Try this one (the first one was hardcoded to 30% mask strength, which is probably why you’re getting the faint mask in your second shot):
#version 130
#pragma parameter phosphor_layout "Phosphor Layout" 1.0 1.0 3.0 1.0
#pragma parameter mask_strength "Mask Strength" 0.3 0.0 1.0 0.01
#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 TexCoord;
COMPAT_VARYING vec4 TEX0;
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;
// vertex compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define outsize vec4(OutputSize, 1.0 / OutputSize)
void main()
{
gl_Position = MVPMatrix * VertexCoord;
TEX0.xy = TexCoord.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;
// fragment compatibility #defines
#define Source Texture
#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
uniform COMPAT_PRECISION float phosphor_layout, mask_strength;
#else
#define phosphor_layout 1.0
#define mask_strength 0.3
#endif
vec3 mask_weights(vec2 coord, float mask_strength){
vec3 weights = vec3(0.,0.,0.);
vec3 green = vec3(1.-mask_strength, 1.0, 1.-mask_strength);
vec3 magenta = vec3(1.0,1.-mask_strength,1.0);
vec3 black = vec3(1.-mask_strength,1.-mask_strength,1.-mask_strength);
// classic aperture
vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0)));
// 2x2 shadow mask
vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0)));
vec3 shadow_weights = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0)));
// slot mask
// Can't do 2D arrays until version 430, so do this stupid thing instead
// first lay out the horizontal pixels in arrays
vec3 slotmask_x1[6] = vec3[](magenta,green,black,magenta,green,black);
vec3 slotmask_x2[6] = vec3[](magenta,green,black,black,black,black);
vec3 slotmask_x3[6] = vec3[](magenta,green,black,magenta,green,black);
vec3 slotmask_x4[6] = vec3[](black,black,black,magenta,green,black);
// find the horizontal index
int slot_index_x = int(floor(mod(coord.x, 6.0)));
int j = slot_index_x; // use a single letter for variable to make comparison easier to read later
// find the vertical index
int slot_index_y = int(floor(mod(coord.y, 4.0)));
// do a big, dumb comparison in place of a 2D array
vec3 slot_weights = (slot_index_y == 1) ? slotmask_x1[j] : (slot_index_y == 2) ? slotmask_x2[j] : (slot_index_y == 3) ? slotmask_x3[j] : slotmask_x4[j];
if(phosphor_layout == 1.) weights = aperture_weights;
else if(phosphor_layout == 2.) weights = shadow_weights;
else weights = slot_weights;
return weights;
}
void main()
{
vec3 mask_weights = mask_weights(gl_FragCoord.xy, mask_strength);
vec4 screen = vec4(COMPAT_TEXTURE(Texture, vTexCoord * 1.0001).rgb, 1.0);
FragColor = vec4(screen.rgb * mask_weights, 1.0);
}
#endif
I also made a slang version here:
#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float phosphor_selector, mask_strength;
} params;
#pragma parameter phosphor_selector "Phosphor Layout" 1.0 1.0 3.0 1.0
#pragma parameter mask_strength "Mask Strength" 0.3 0.0 1.0 0.01
int phosphor_layout = int(params.phosphor_selector);
#define mask_strength params.mask_strength
layout(std140, set = 0, binding = 0) uniform UBO
{
mat4 MVP;
} global;
#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;
void main()
{
gl_Position = global.MVP * Position;
vTexCoord = TexCoord;
}
#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
vec3 mask_weights(vec2 coord, float mask_intensity){
vec3 weights = vec3(0.,0.,0.);
vec3 green = vec3(1.-mask_intensity, 1.0, 1.-mask_intensity);
vec3 magenta = vec3(1.0,1.-mask_intensity,1.0);
vec3 black = vec3(1.-mask_intensity,1.-mask_intensity,1.-mask_intensity);
vec3 aperture_weights = mix(magenta, green, floor(mod(coord.x, 2.0)));
if(phosphor_layout == 1){
// classic aperture
weights = aperture_weights;
}
if(phosphor_layout == 2){
// 2x2 shadow mask
vec3 inverse_aperture = mix(green, magenta, floor(mod(coord.x, 2.0)));
weights = mix(aperture_weights, inverse_aperture, floor(mod(coord.y, 2.0)));
}
if(phosphor_layout == 3){
// slot mask
vec3 slotmask[4][6] = {
{magenta, green, black, magenta, green, black},
{magenta, green, black, black, black, black},
{magenta, green, black, magenta, green, black},
{black, black, black, magenta, green, black}
};
// find the vertical index
int j = int(floor(mod(coord.y, 4.0)));
// find the horizontal index
int k = int(floor(mod(coord.x, 6.0)));
// use the indexes to find which color to apply to the current pixel
weights = slotmask[j][k];
}
return weights;
}
void main()
{
vec3 mask_weights = mask_weights(vTexCoord.xy * params.OutputSize.xy, mask_strength);
vec4 screen = vec4(texture(Source, vTexCoord * 1.0001).rgb, 1.0);
FragColor = vec4(screen.rgb * mask_weights, 1.0);
}
It’s much cleaner (and about 50% faster in my testing), thanks to being able to use a 2D array.
Both of these are set up with the mask bits in an easy-to-copy/paste function that you can add to other shaders without too much trouble, to avoid having it as a follow-on pass.
EDITEDIT: you might need to rename the ‘mask_strength’ variable if you add it to something else. I think that’s a pretty generic name that probably has collisions with other shader variable names.