slang-shaders/misc/shaders/cmyk-halftone-dot.slang

80 lines
2.4 KiB
Plaintext

#version 450
layout(push_constant) uniform Push
{
vec4 SourceSize;
vec4 OriginalSize;
vec4 OutputSize;
uint FrameCount;
float frequency;
} params;
#pragma parameter frequency "CMYK HalfTone Dot Density" 275.0 50.0 500.0 25.0
#define frequency params.frequency
#define mul(a,b) (b*a)
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;
void main()
{
// Distance to nearest point in a grid of
// (frequency x frequency) points over the unit square
mat2 rotation_matrix = mat2(0.707, 0.707, -0.707, 0.707);
vec2 st2 = mul(rotation_matrix , vTexCoord);
vec2 nearest = 2.0 * fract(frequency * st2) - 1.0;
float dist = length(nearest);
vec3 texcolor = texture(Source, vTexCoord).rgb; // Unrotated coords
vec3 black = texcolor; // kinda cheating, but it makes the colors look much better
// Perform a rough RGB-to-CMYK conversion
vec4 cmyk;
cmyk.xyz = 1.0 - texcolor;
cmyk.w = min(cmyk.x, min(cmyk.y, cmyk.z)); // Create K
mat2 k_matrix = mat2(0.707, 0.707, -0.707, 0.707);
vec2 Kst = frequency * mul(k_matrix , vTexCoord);
vec2 Kuv = 2.0 * fract(Kst) - 1.0;
float k = step(0.0, sqrt(cmyk.w) - length(Kuv));
mat2 c_matrix = mat2(0.966, 0.259, -0.259, 0.966);
vec2 Cst = frequency * mul(c_matrix , vTexCoord);
vec2 Cuv = 2.0 * fract(Cst) - 1.0;
float c = step(0.0, sqrt(cmyk.x) - length(Cuv));
mat2 m_matrix = mat2(0.966, -0.259, 0.259, 0.966);
vec2 Mst = frequency * mul(m_matrix , vTexCoord);
vec2 Muv = 2.0 * fract(Mst) - 1.0;
float m = step(0.0, sqrt(cmyk.y) - length(Muv));
vec2 Yst = frequency * vTexCoord; // 0 deg
vec2 Yuv = 2.0 * fract(Yst) - 1.0;
float y = step(0.0, sqrt(cmyk.z) - length(Yuv));
vec3 rgbscreen = 1.0 - vec3(c,m,y);
rgbscreen = mix(rgbscreen, black, k);
float afwidth = 2.0 * frequency * length(params.OutputSize.zw);
float blend = smoothstep(0.0, 1.0, afwidth);
vec4 color = vec4(mix(rgbscreen , texcolor, blend), 1.0);
color = (max(texcolor.r, max(texcolor.g, texcolor.b)) < 0.01) ? vec4(0.,0.,0.,0.) : color; // make blacks actually black
FragColor = color;
}