diff --git a/orx-fx/src/commonMain/kotlin/dither/CMYKHalftone.kt b/orx-fx/src/commonMain/kotlin/dither/CMYKHalftone.kt index 719de37b..f2278869 100644 --- a/orx-fx/src/commonMain/kotlin/dither/CMYKHalftone.kt +++ b/orx-fx/src/commonMain/kotlin/dither/CMYKHalftone.kt @@ -2,14 +2,31 @@ package org.openrndr.extra.fx.dither +import org.openrndr.color.ColorRGBa import org.openrndr.draw.Filter1to1 +import org.openrndr.draw.filterShaderFromCode import org.openrndr.extra.fx.fx_cmyk_halftone -import org.openrndr.extra.fx.mppFilterShader +import org.openrndr.extra.parameters.ColorParameter import org.openrndr.extra.parameters.Description import org.openrndr.extra.parameters.DoubleParameter +import org.openrndr.extra.shaderphrases.sdf.sdCirclePhrase @Description("CMYK Halftone") -class CMYKHalftone: Filter1to1(mppFilterShader(fx_cmyk_halftone, "cmyk-halftone")) { +class CMYKHalftone( + domainWarpFunction: String = "vec2 domainWarp(vec2 p) { return p; }", + elementFunction: String = """ + $sdCirclePhrase + float element(in vec2 p, float v) { + return sdCircle(p, v * dotSize); + }""".trimIndent() +) : Filter1to1( + filterShaderFromCode( + fx_cmyk_halftone.split("#pragma INSERT_PHRASES").let { + listOf(it[0], elementFunction, domainWarpFunction, it[1]) + }.joinToString("\n"), + "cmyk-halftone" + ) +) { @DoubleParameter("scale", 1.0, 30.0, precision = 4) var scale: Double by parameters @@ -19,9 +36,45 @@ class CMYKHalftone: Filter1to1(mppFilterShader(fx_cmyk_halftone, "cmyk-halftone" @DoubleParameter("rotation", -180.0, 180.0) var rotation: Double by parameters + @DoubleParameter("cyan rotation", -180.0, 180.0, precision = 4) + var cyanRotation: Double by parameters + + @DoubleParameter("magenta rotation", -180.0, 180.0, precision = 4) + var magentaRotation: Double by parameters + + @DoubleParameter("yellow rotation", -180.0, 180.0, precision = 4) + var yellowRotation: Double by parameters + + @DoubleParameter("black rotation", -180.0, 180.0, precision = 4) + var blackRotation: Double by parameters + + @ColorParameter("cyan color") + var cyanColor: ColorRGBa by parameters + + @ColorParameter("magenta color") + var magentaColor: ColorRGBa by parameters + + @ColorParameter("yellow color") + var yellowColor: ColorRGBa by parameters + + @ColorParameter("black color") + var blackColor: ColorRGBa by parameters + + var phase: Double by parameters + init { + blackRotation = 45.0 + magentaRotation = 75.0 + cyanRotation = 15.0 + yellowRotation = 0.0 + cyanColor = ColorRGBa.CYAN + magentaColor = ColorRGBa.MAGENTA + yellowColor = ColorRGBa.YELLOW + blackColor = ColorRGBa.BLACK + scale = 3.0 rotation = 0.0 - dotSize = 1.0 + dotSize = 0.9 + phase = 0.0 } } \ No newline at end of file diff --git a/orx-fx/src/shaders/glsl/dither/cmyk-halftone.frag b/orx-fx/src/shaders/glsl/dither/cmyk-halftone.frag index a5c31ea7..bd99ff28 100644 --- a/orx-fx/src/shaders/glsl/dither/cmyk-halftone.frag +++ b/orx-fx/src/shaders/glsl/dither/cmyk-halftone.frag @@ -1,17 +1,27 @@ /* Based on CMYK Halftone by tsone https://www.shadertoy.com/view/Mdf3Dn */ uniform float dotSize; -#define SST 0.888 -#define SSQ 0.288 - uniform float scale; uniform float rotation; +uniform float phase; + +uniform float blackRotation; +uniform float yellowRotation; +uniform float magentaRotation; +uniform float cyanRotation; + +uniform vec4 blackColor; +uniform vec4 yellowColor; +uniform vec4 magentaColor; +uniform vec4 cyanColor; in vec2 v_texCoord0; uniform sampler2D tex0; out vec4 o_color; +#pragma INSERT_PHRASES + vec4 rgb2cmyki(in vec3 c) { float k = max(max(c.r, c.g), c.b); @@ -26,20 +36,20 @@ vec3 u(vec4 c) { if (c.a == 0.0) { return vec3(0.0); } else { - return c.rgb/c.a; + return c.rgb / c.a; } } -vec4 cmyki2rgba(in vec4 cmyk){ - vec4 c = vec4(0.0, 1.0, 1.0, 1.0)*(1.0-cmyk.r); - vec4 m = vec4(1.0, 0.0, 1.0, 1.0)*(1.0-cmyk.g); - vec4 y = vec4(1.0, 1.0, 0.0, 1.0)*(1.0-cmyk.b); - vec4 k = vec4(0.0, 0.0, 0.0, 1.0)*(1.0-cmyk.a); +vec4 cmyki2rgba(in vec4 cmyk) { + vec4 c = cyanColor * (1.0 - cmyk.r); + vec4 m = magentaColor * (1.0 - cmyk.g); + vec4 y = yellowColor * (1.0 - cmyk.b); + vec4 k = blackColor * (1.0 - cmyk.a); vec4 f = c; - f = (1.0-f.a) * m + f.a * vec4(u(f)*u(m),1.0) * m.a + (1.0-m.a) * f; - f = (1.0-f.a) * y + f.a * vec4(u(f)*u(y),1.0) * y.a + (1.0-y.a) * f; - f = (1.0-f.a) * k + f.a * vec4(u(f)*u(k),1.0) * k.a + (1.0-k.a) * f; + f = (1.0 - f.a) * m + f.a * vec4(u(f) * u(m), 1.0) * m.a + (1.0 - m.a) * f; + f = (1.0 - f.a) * y + f.a * vec4(u(f) * u(y), 1.0) * y.a + (1.0 - y.a) * f; + f = (1.0 - f.a) * k + f.a * vec4(u(f) * u(k), 1.0) * k.a + (1.0 - k.a) * f; return f; } @@ -56,43 +66,46 @@ vec2 grid(in vec2 px) vec4 ss(in vec4 v) { - return smoothstep(vec4(SST-SSQ), vec4(SST+SSQ), v); + vec4 vw = fwidth(v); + return smoothstep(vec4(-vw), vec4(vw), v); } -vec4 halftone(in vec2 fc,in mat2 m) + +float halftone(in vec2 fc, in mat2 m, int channel) { - vec2 smp = (grid(m*fc) + 0.5*scale) * m; - float s = min(length(fc-smp) / (dotSize*0.5*scale), 1.0); - vec3 texc = texture(tex0, px2uv(smp+vec2(textureSize(tex0, 0))/2.0)).rgb; - vec4 c = rgb2cmyki(texc); - return c+s; + vec2 smp = (grid(m * fc) + 0.5 * scale) * m; + + float s = length(fc - smp) / (dotSize * 2.0 * scale); + vec2 d2 = m * ((fc) - smp) / (dotSize * 0.5 * scale); + vec3 texc = texture(tex0, px2uv(smp + vec2(textureSize(tex0, 0)) / 2.0)).rgb; + float c = 1.0 - rgb2cmyki(texc)[channel]; + return element(d2, c); } -mat2 rotm(in float r) -{ +mat2 rotm(in float r) { float cr = cos(r); float sr = sin(r); - return mat2( - cr,-sr, - sr,cr - ); + return mat2(cr, -sr, sr, cr); } void main() { - vec2 fc = v_texCoord0 * vec2(textureSize(tex0, 0)) - vec2(textureSize(tex0, 0))/2.0; + vec2 fc = (v_texCoord0 - vec2(0.5)) * vec2(textureSize(tex0, 0)); + fc = domainWarp(fc); - mat2 mc = rotm(rotation + radians(15.0)); - mat2 mm = rotm(rotation + radians(75.0)); - mat2 my = rotm(rotation); - mat2 mk = rotm(rotation + radians(45.0)); + mat2 mc = rotm(rotation + radians(cyanRotation)); + mat2 mm = rotm(rotation + radians(magentaRotation)); + mat2 my = rotm(rotation + radians(yellowRotation)); + mat2 mk = rotm(rotation + radians(blackRotation)); - float k = halftone(fc, mk).a; - vec4 c = cmyki2rgba(ss(vec4( - halftone(fc, mc).r, - halftone(fc, mm).g, - halftone(fc, my).b, - halftone(fc, mk).a - ))); + vec4 c = cmyki2rgba( + ss(vec4( + halftone(fc, mc, 0), + halftone(fc, mm, 1), + halftone(fc, my, 2), + halftone(fc, mk, 3) + ) + ) + ); o_color = c; } \ No newline at end of file