[orx-fx] Refactor CMYKHalftone to support customizable elements/colors

This commit is contained in:
Edwin Jakobs
2025-03-10 10:59:52 +01:00
parent b74ad477c7
commit 977be4ee6f
2 changed files with 106 additions and 40 deletions

View File

@@ -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
}
}

View File

@@ -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);
@@ -31,10 +41,10 @@ vec3 u(vec4 c) {
}
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 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;
@@ -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);
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;
vec4 c = rgb2cmyki(texc);
return c+s;
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;
}