diff --git a/misc/cmyk-halftone-dot.slang b/misc/cmyk-halftone-dot.slang new file mode 100644 index 0000000..e9be9a3 --- /dev/null +++ b/misc/cmyk-halftone-dot.slang @@ -0,0 +1,80 @@ +#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; +} \ No newline at end of file diff --git a/reshade/halftone-print.slangp b/reshade/halftone-print.slangp new file mode 100644 index 0000000..34ac06c --- /dev/null +++ b/reshade/halftone-print.slangp @@ -0,0 +1,10 @@ +shaders = 2 + +shader0 = shaders/LUT/LUT.slang +shader1 = ../misc/cmyk-halftone-dot.slang +filter_linear1 = true + +textures = SamplerLUT + +SamplerLUT = shaders/LUT/cmyk-16.png +SamplerLUT_linear = true diff --git a/reshade/shaders/LUT/cmyk-16.png b/reshade/shaders/LUT/cmyk-16.png new file mode 100644 index 0000000..0f046a8 Binary files /dev/null and b/reshade/shaders/LUT/cmyk-16.png differ