@paper-design/shaders 0.0.69 → 0.0.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -132,15 +132,15 @@ vec2 gridToImageUV(vec2 cellCenter, float cosA, float sinA, float shift, vec2 pa
|
|
|
132
132
|
return uvGrid * pad + 0.5;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
void colorMask(vec2 pos, vec2 cellCenter, float rad, float
|
|
135
|
+
void colorMask(vec2 pos, vec2 cellCenter, float rad, float transparency, float grain, float channelAddon, float channelgain, float generalComp, bool isJoined, inout float outMask) {
|
|
136
136
|
float dist = length(pos - cellCenter);
|
|
137
137
|
|
|
138
138
|
float radius = rad;
|
|
139
139
|
radius *= (1. + generalComp);
|
|
140
|
-
radius +=
|
|
141
|
-
radius += .15;
|
|
140
|
+
radius += (.15 + channelgain * radius);
|
|
142
141
|
radius = max(0., radius);
|
|
143
|
-
radius = mix(0., radius,
|
|
142
|
+
radius = mix(0., radius, transparency);
|
|
143
|
+
radius += channelAddon;
|
|
144
144
|
radius *= (1. - grain);
|
|
145
145
|
|
|
146
146
|
float mask = 1. - sst(0., radius, dist);
|
|
@@ -168,7 +168,7 @@ void main() {
|
|
|
168
168
|
float cellSizeY = 1.0 / cellsPerSide;
|
|
169
169
|
vec2 pad = cellSizeY * vec2(1.0 / u_imageAspectRatio, 1.0);
|
|
170
170
|
vec2 uvGrid = (uv - .5) / pad;
|
|
171
|
-
float
|
|
171
|
+
float insideImageBox = getUvFrame(uv, pad);
|
|
172
172
|
|
|
173
173
|
float generalComp = .1 * u_softness + .1 * u_gridNoise + .1 * (1. - step(0.5, u_type)) * (1.5 - u_softness);
|
|
174
174
|
|
|
@@ -194,34 +194,35 @@ void main() {
|
|
|
194
194
|
|
|
195
195
|
vec2 cellCenterC = cellCenterPos(uvC, cellOffset, 0.);
|
|
196
196
|
vec4 texC = texture(u_image, gridToImageUV(cellCenterC, cosC, sinC, shiftC, pad));
|
|
197
|
-
colorMask(uvC, cellCenterC, getCyan(texC),
|
|
197
|
+
colorMask(uvC, cellCenterC, getCyan(texC), insideImageBox * texC.a, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);
|
|
198
198
|
|
|
199
199
|
vec2 cellCenterM = cellCenterPos(uvM, cellOffset, 1.);
|
|
200
200
|
vec4 texM = texture(u_image, gridToImageUV(cellCenterM, cosM, sinM, shiftM, pad));
|
|
201
|
-
colorMask(uvM, cellCenterM, getMagenta(texM),
|
|
201
|
+
colorMask(uvM, cellCenterM, getMagenta(texM), insideImageBox * texM.a, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);
|
|
202
202
|
|
|
203
203
|
vec2 cellCenterY = cellCenterPos(uvY, cellOffset, 2.);
|
|
204
204
|
vec4 texY = texture(u_image, gridToImageUV(cellCenterY, cosY, sinY, shiftY, pad));
|
|
205
|
-
colorMask(uvY, cellCenterY, getYellow(texY),
|
|
205
|
+
colorMask(uvY, cellCenterY, getYellow(texY), insideImageBox * texY.a, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);
|
|
206
206
|
|
|
207
207
|
vec2 cellCenterK = cellCenterPos(uvK, cellOffset, 3.);
|
|
208
208
|
vec4 texK = texture(u_image, gridToImageUV(cellCenterK, cosK, sinK, shiftK, pad));
|
|
209
|
-
colorMask(uvK, cellCenterK, getBlack(texK),
|
|
209
|
+
colorMask(uvK, cellCenterK, getBlack(texK), insideImageBox * texK.a, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
} else {
|
|
213
213
|
// sharp: direct px color sampling
|
|
214
214
|
vec4 tex = texture(u_image, uv);
|
|
215
215
|
tex.rgb = applyContrast(tex.rgb);
|
|
216
|
+
insideImageBox *= tex.a;
|
|
216
217
|
vec4 cmykOriginal = RGBAtoCMYK(tex);
|
|
217
218
|
for (int dy = -1; dy <= 1; dy++) {
|
|
218
219
|
for (int dx = -1; dx <= 1; dx++) {
|
|
219
220
|
vec2 cellOffset = vec2(float(dx), float(dy));
|
|
220
221
|
|
|
221
|
-
colorMask(uvC, cellCenterPos(uvC, cellOffset, 0.), cmykOriginal.x,
|
|
222
|
-
colorMask(uvM, cellCenterPos(uvM, cellOffset, 1.), cmykOriginal.y,
|
|
223
|
-
colorMask(uvY, cellCenterPos(uvY, cellOffset, 2.), cmykOriginal.z,
|
|
224
|
-
colorMask(uvK, cellCenterPos(uvK, cellOffset, 3.), cmykOriginal.w,
|
|
222
|
+
colorMask(uvC, cellCenterPos(uvC, cellOffset, 0.), cmykOriginal.x, insideImageBox, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);
|
|
223
|
+
colorMask(uvM, cellCenterPos(uvM, cellOffset, 1.), cmykOriginal.y, insideImageBox, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);
|
|
224
|
+
colorMask(uvY, cellCenterPos(uvY, cellOffset, 2.), cmykOriginal.z, insideImageBox, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);
|
|
225
|
+
colorMask(uvK, cellCenterPos(uvK, cellOffset, 3.), cmykOriginal.w, insideImageBox, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
}
|
|
@@ -258,6 +259,7 @@ void main() {
|
|
|
258
259
|
shape = clamp(max(max(C, M), max(Y, K)), 0., 1.);
|
|
259
260
|
|
|
260
261
|
vec3 color = u_colorBack.rgb * u_colorBack.a;
|
|
262
|
+
|
|
261
263
|
float opacity = u_colorBack.a;
|
|
262
264
|
color = mix(color, ink, shape);
|
|
263
265
|
opacity += shape;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/halftone-cmyk.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI } from '../shader-utils.js';\n\n/**\n * CMYK halftone printing effect applied to images with customizable dot patterns\n * and ink colors for each channel (Cyan, Magenta, Yellow, Black).\n *\n * Fragment shader uniforms:\n * - u_image (sampler2D): Source image texture\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n * - u_colorBack (vec4): Background (paper) color in RGBA\n * - u_colorC (vec4): Cyan ink color in RGBA\n * - u_colorM (vec4): Magenta ink color in RGBA\n * - u_colorY (vec4): Yellow ink color in RGBA\n * - u_colorK (vec4): Black ink color in RGBA\n * - u_size (float): Halftone cell size (0 to 1)\n * - u_minDot (float): Minimum dot thickness (0 to 1)\n * - u_contrast (float): Image contrast adjustment (0 to 2)\n * - u_softness (float): Edge softness of dots (0 to 1)\n * - u_grainSize (float): Size of grain overlay texture (0 to 1)\n * - u_grainMixer (float): Strength of grain affecting dot size (0 to 1)\n * - u_grainOverlay (float): Strength of grain overlay on final output (0 to 1)\n * - u_gridNoise (float): Strength of smooth noise applied to both dot positions and color sampling (0 to 1)\n * - u_floodC (float): Flat cyan dot size adjustment applied uniformly (-1 to 1)\n * - u_floodM (float): Flat magenta dot size adjustment applied uniformly (-1 to 1)\n * - u_floodY (float): Flat yellow dot size adjustment applied uniformly (-1 to 1)\n * - u_floodK (float): Flat black dot size adjustment applied uniformly (-1 to 1)\n * - u_gainC (float): Proportional cyan dot size gain (enhances existing dots, -1 to 1)\n * - u_gainM (float): Proportional magenta dot size gain (enhances existing dots, -1 to 1)\n * - u_gainY (float): Proportional yellow dot size gain (enhances existing dots, -1 to 1)\n * - u_gainK (float): Proportional black dot size gain (enhances existing dots, -1 to 1)\n * - u_type (float): Dot shape style (0 = dots, 1 = ink, 2 = sharp)\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_imageUV (vec2): UV coordinates for sampling the source image, with fit, scale, rotation, and offset applied\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n *\n */\n\n// language=GLSL\nexport const halftoneCmykFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorC;\nuniform vec4 u_colorM;\nuniform vec4 u_colorY;\nuniform vec4 u_colorK;\nuniform float u_size;\nuniform float u_minDot;\nuniform float u_contrast;\nuniform float u_grainSize;\nuniform float u_grainMixer;\nuniform float u_grainOverlay;\nuniform float u_gridNoise;\nuniform float u_softness;\nuniform float u_floodC;\nuniform float u_floodM;\nuniform float u_floodY;\nuniform float u_floodK;\nuniform float u_gainC;\nuniform float u_gainM;\nuniform float u_gainY;\nuniform float u_gainK;\nuniform float u_type;\nuniform sampler2D u_noiseTexture;\n\nin vec2 v_imageUV;\nout vec4 fragColor;\n\nconst float shiftC = -.5;\nconst float shiftM = -.25;\nconst float shiftY = .2;\nconst float shiftK = 0.;\n\n// Precomputed sin/cos for rotation angles (15\u00B0, 75\u00B0, 0\u00B0, 45\u00B0)\nconst float cosC = 0.9659258; const float sinC = 0.2588190; // 15\u00B0\nconst float cosM = 0.2588190; const float sinM = 0.9659258; // 75\u00B0\nconst float cosY = 1.0; const float sinY = 0.0; // 0\u00B0\nconst float cosK = 0.7071068; const float sinK = 0.7071068; // 45\u00B0\n\n${ declarePI }\n\nvec2 randomRG(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).rg;\n}\nvec3 hash23(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * vec3(0.3183099, 0.3678794, 0.3141592)) + 0.1;\n p3 += dot(p3, p3.yzx + 19.19);\n return fract(vec3(p3.x * p3.y, p3.y * p3.z, p3.z * p3.x));\n}\n\nfloat sst(float edge0, float edge1, float x) {\n return smoothstep(edge0, edge1, x);\n}\n\nvec3 valueNoise3(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n vec3 a = hash23(i);\n vec3 b = hash23(i + vec2(1.0, 0.0));\n vec3 c = hash23(i + vec2(0.0, 1.0));\n vec3 d = hash23(i + vec2(1.0, 1.0));\n vec2 u = f * f * (3.0 - 2.0 * f);\n vec3 x1 = mix(a, b, u.x);\n vec3 x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\n\nfloat getUvFrame(vec2 uv, vec2 pad) {\n float left = smoothstep(-pad.x, 0., uv.x);\n float right = smoothstep(1. + pad.x, 1., uv.x);\n float bottom = smoothstep(-pad.y, 0., uv.y);\n float top = smoothstep(1. + pad.y, 1., uv.y);\n\n return left * right * bottom * top;\n}\n\nvec4 RGBAtoCMYK(vec4 rgba) {\n float k = 1. - max(max(rgba.r, rgba.g), rgba.b);\n float denom = 1. - k;\n vec3 cmy = vec3(0.);\n if (denom > 1e-5) {\n cmy = (1. - rgba.rgb - vec3(k)) / denom;\n }\n return vec4(cmy, k) * rgba.a;\n}\n\nvec3 applyContrast(vec3 rgb) {\n return clamp((rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n}\n\n// Single-component CMYK extractors with contrast built-in, alpha-aware\nfloat getCyan(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.r) / maxRGB : 0.) * rgba.a;\n}\nfloat getMagenta(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.g) / maxRGB : 0.) * rgba.a;\n}\nfloat getYellow(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.b) / maxRGB : 0.) * rgba.a;\n}\nfloat getBlack(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n return (1. - max(max(c.r, c.g), c.b)) * rgba.a;\n}\n\nvec2 cellCenterPos(vec2 uv, vec2 cellOffset, float channelIdx) {\n vec2 cellCenter = floor(uv) + .5 + cellOffset;\n return cellCenter + (randomRG(cellCenter + channelIdx * 50.) - .5) * u_gridNoise;\n}\n\nvec2 gridToImageUV(vec2 cellCenter, float cosA, float sinA, float shift, vec2 pad) {\n vec2 uvGrid = mat2(cosA, -sinA, sinA, cosA) * (cellCenter - shift);\n return uvGrid * pad + 0.5;\n}\n\nvoid colorMask(vec2 pos, vec2 cellCenter, float rad, float outOfFrame, float grain, float channelAddon, float channelgain, float generalComp, bool isJoined, inout float outMask) {\n float dist = length(pos - cellCenter);\n\n float radius = rad;\n radius *= (1. + generalComp);\n radius += channelAddon + channelgain * radius;\n radius += .15;\n radius = max(0., radius);\n radius = mix(0., radius, outOfFrame);\n radius *= (1. - grain);\n\n float mask = 1. - sst(0., radius, dist);\n if (isJoined) {\n // ink or sharp (joined)\n mask = pow(mask, 1.2);\n } else {\n // dots (separate)\n mask = sst(.5 - .5 * u_softness, .51 + .49 * u_softness, mask);\n }\n\n mask *= mix(1., mix(.5, 1., 1.5 * radius), u_softness);\n outMask += mask;\n}\n\nvec3 applyInk(vec3 paper, vec3 inkColor, float cov) {\n vec3 inkEffect = mix(vec3(1.0), inkColor, clamp(cov, 0.0, 1.0));\n return paper * inkEffect;\n}\n\nvoid main() {\n vec2 uv = v_imageUV;\n\n float cellsPerSide = mix(400.0, 7.0, pow(u_size, 0.7));\n float cellSizeY = 1.0 / cellsPerSide;\n vec2 pad = cellSizeY * vec2(1.0 / u_imageAspectRatio, 1.0);\n vec2 uvGrid = (uv - .5) / pad;\n float outOfFrame = getUvFrame(uv, pad);\n\n float generalComp = .1 * u_softness + .1 * u_gridNoise + .1 * (1. - step(0.5, u_type)) * (1.5 - u_softness);\n\n vec2 uvC = mat2(cosC, sinC, -sinC, cosC) * uvGrid + shiftC;\n vec2 uvM = mat2(cosM, sinM, -sinM, cosM) * uvGrid + shiftM;\n vec2 uvY = mat2(cosY, sinY, -sinY, cosY) * uvGrid + shiftY;\n vec2 uvK = mat2(cosK, sinK, -sinK, cosK) * uvGrid + shiftK;\n\n vec2 grainSize = mix(2000., 200., u_grainSize) * vec2(1., 1. / u_imageAspectRatio);\n vec2 grainUV = (v_imageUV - .5) * grainSize + .5;\n vec3 noiseValues = valueNoise3(grainUV);\n float grain = sst(.55, 1., noiseValues.r);\n grain *= u_grainMixer;\n\n vec4 outMask = vec4(0.);\n bool isJoined = u_type > 0.5;\n\n if (u_type < 1.5) {\n // dots or ink: per-cell color sampling\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 cellOffset = vec2(float(dx), float(dy));\n\n vec2 cellCenterC = cellCenterPos(uvC, cellOffset, 0.);\n vec4 texC = texture(u_image, gridToImageUV(cellCenterC, cosC, sinC, shiftC, pad));\n colorMask(uvC, cellCenterC, getCyan(texC), outOfFrame, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);\n\n vec2 cellCenterM = cellCenterPos(uvM, cellOffset, 1.);\n vec4 texM = texture(u_image, gridToImageUV(cellCenterM, cosM, sinM, shiftM, pad));\n colorMask(uvM, cellCenterM, getMagenta(texM), outOfFrame, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);\n\n vec2 cellCenterY = cellCenterPos(uvY, cellOffset, 2.);\n vec4 texY = texture(u_image, gridToImageUV(cellCenterY, cosY, sinY, shiftY, pad));\n colorMask(uvY, cellCenterY, getYellow(texY), outOfFrame, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);\n\n vec2 cellCenterK = cellCenterPos(uvK, cellOffset, 3.);\n vec4 texK = texture(u_image, gridToImageUV(cellCenterK, cosK, sinK, shiftK, pad));\n colorMask(uvK, cellCenterK, getBlack(texK), outOfFrame, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);\n }\n }\n } else {\n // sharp: direct px color sampling\n vec4 tex = texture(u_image, uv);\n tex.rgb = applyContrast(tex.rgb);\n vec4 cmykOriginal = RGBAtoCMYK(tex);\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 cellOffset = vec2(float(dx), float(dy));\n\n colorMask(uvC, cellCenterPos(uvC, cellOffset, 0.), cmykOriginal.x, outOfFrame, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);\n colorMask(uvM, cellCenterPos(uvM, cellOffset, 1.), cmykOriginal.y, outOfFrame, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);\n colorMask(uvY, cellCenterPos(uvY, cellOffset, 2.), cmykOriginal.z, outOfFrame, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);\n colorMask(uvK, cellCenterPos(uvK, cellOffset, 3.), cmykOriginal.w, outOfFrame, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);\n }\n }\n }\n\n float shape;\n\n float C = outMask[0];\n float M = outMask[1];\n float Y = outMask[2];\n float K = outMask[3];\n\n if (isJoined) {\n // ink or sharp: apply threshold for joined dots\n float th = .5;\n float sLeft = th * u_softness;\n float sRight = (1. - th) * u_softness + .01;\n C = smoothstep(th - sLeft - fwidth(C), th + sRight, C);\n M = smoothstep(th - sLeft - fwidth(M), th + sRight, M);\n Y = smoothstep(th - sLeft - fwidth(Y), th + sRight, Y);\n K = smoothstep(th - sLeft - fwidth(K), th + sRight, K);\n }\n\n C *= u_colorC.a;\n M *= u_colorM.a;\n Y *= u_colorY.a;\n K *= u_colorK.a;\n\n vec3 ink = vec3(1.);\n ink = applyInk(ink, u_colorK.rgb, K);\n ink = applyInk(ink, u_colorC.rgb, C);\n ink = applyInk(ink, u_colorM.rgb, M);\n ink = applyInk(ink, u_colorY.rgb, Y);\n\n shape = clamp(max(max(C, M), max(Y, K)), 0., 1.);\n\n vec3 color = u_colorBack.rgb * u_colorBack.a;\n float opacity = u_colorBack.a;\n color = mix(color, ink, shape);\n opacity += shape;\n opacity = clamp(opacity, 0., 1.);\n\n float grainOverlay = mix(noiseValues.g, noiseValues.b, .5);\n grainOverlay = pow(grainOverlay, 1.3);\n\n float grainOverlayV = grainOverlay * 2. - 1.;\n vec3 grainOverlayColor = vec3(step(0., grainOverlayV));\n float grainOverlayStrength = u_grainOverlay * abs(grainOverlayV);\n grainOverlayStrength = pow(grainOverlayStrength, .8);\n color = mix(color, grainOverlayColor, .5 * grainOverlayStrength);\n\n opacity += .5 * grainOverlayStrength;\n opacity = clamp(opacity, 0., 1.);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface HalftoneCmykUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string | undefined;\n u_noiseTexture?: HTMLImageElement;\n u_colorBack: [number, number, number, number];\n u_colorC: [number, number, number, number];\n u_colorM: [number, number, number, number];\n u_colorY: [number, number, number, number];\n u_colorK: [number, number, number, number];\n u_size: number;\n u_contrast: number;\n u_softness: number;\n u_grainSize: number;\n u_grainMixer: number;\n u_grainOverlay: number;\n u_gridNoise: number;\n u_floodC: number;\n u_floodM: number;\n u_floodY: number;\n u_floodK: number;\n u_gainC: number;\n u_gainM: number;\n u_gainY: number;\n u_gainK: number;\n u_type: (typeof HalftoneCmykTypes)[HalftoneCmykType];\n}\n\nexport interface HalftoneCmykParams extends ShaderSizingParams, ShaderMotionParams {\n image?: HTMLImageElement | string;\n colorBack?: string;\n colorC?: string;\n colorM?: string;\n colorY?: string;\n colorK?: string;\n size?: number;\n contrast?: number;\n softness?: number;\n grainSize?: number;\n grainMixer?: number;\n grainOverlay?: number;\n gridNoise?: number;\n floodC?: number;\n floodM?: number;\n floodY?: number;\n floodK?: number;\n gainC?: number;\n gainM?: number;\n gainY?: number;\n gainK?: number;\n type?: HalftoneCmykType;\n}\n\nexport const HalftoneCmykTypes = {\n dots: 0,\n ink: 1,\n sharp: 2,\n} as const;\n\nexport type HalftoneCmykType = keyof typeof HalftoneCmykTypes;\n\n"],
|
|
5
|
-
"mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,iBAAiB;AAmDnB,MAAM,6BAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4C/C,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { declarePI } from '../shader-utils.js';\n\n/**\n * CMYK halftone printing effect applied to images with customizable dot patterns\n * and ink colors for each channel (Cyan, Magenta, Yellow, Black).\n *\n * Fragment shader uniforms:\n * - u_image (sampler2D): Source image texture\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n * - u_colorBack (vec4): Background (paper) color in RGBA\n * - u_colorC (vec4): Cyan ink color in RGBA\n * - u_colorM (vec4): Magenta ink color in RGBA\n * - u_colorY (vec4): Yellow ink color in RGBA\n * - u_colorK (vec4): Black ink color in RGBA\n * - u_size (float): Halftone cell size (0 to 1)\n * - u_minDot (float): Minimum dot thickness (0 to 1)\n * - u_contrast (float): Image contrast adjustment (0 to 2)\n * - u_softness (float): Edge softness of dots (0 to 1)\n * - u_grainSize (float): Size of grain overlay texture (0 to 1)\n * - u_grainMixer (float): Strength of grain affecting dot size (0 to 1)\n * - u_grainOverlay (float): Strength of grain overlay on final output (0 to 1)\n * - u_gridNoise (float): Strength of smooth noise applied to both dot positions and color sampling (0 to 1)\n * - u_floodC (float): Flat cyan dot size adjustment applied uniformly (-1 to 1)\n * - u_floodM (float): Flat magenta dot size adjustment applied uniformly (-1 to 1)\n * - u_floodY (float): Flat yellow dot size adjustment applied uniformly (-1 to 1)\n * - u_floodK (float): Flat black dot size adjustment applied uniformly (-1 to 1)\n * - u_gainC (float): Proportional cyan dot size gain (enhances existing dots, -1 to 1)\n * - u_gainM (float): Proportional magenta dot size gain (enhances existing dots, -1 to 1)\n * - u_gainY (float): Proportional yellow dot size gain (enhances existing dots, -1 to 1)\n * - u_gainK (float): Proportional black dot size gain (enhances existing dots, -1 to 1)\n * - u_type (float): Dot shape style (0 = dots, 1 = ink, 2 = sharp)\n * - u_noiseTexture (sampler2D): Pre-computed randomizer source texture\n *\n * Vertex shader outputs (used in fragment shader):\n * - v_imageUV (vec2): UV coordinates for sampling the source image, with fit, scale, rotation, and offset applied\n *\n * Vertex shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n *\n */\n\n// language=GLSL\nexport const halftoneCmykFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform vec4 u_colorBack;\nuniform vec4 u_colorC;\nuniform vec4 u_colorM;\nuniform vec4 u_colorY;\nuniform vec4 u_colorK;\nuniform float u_size;\nuniform float u_minDot;\nuniform float u_contrast;\nuniform float u_grainSize;\nuniform float u_grainMixer;\nuniform float u_grainOverlay;\nuniform float u_gridNoise;\nuniform float u_softness;\nuniform float u_floodC;\nuniform float u_floodM;\nuniform float u_floodY;\nuniform float u_floodK;\nuniform float u_gainC;\nuniform float u_gainM;\nuniform float u_gainY;\nuniform float u_gainK;\nuniform float u_type;\nuniform sampler2D u_noiseTexture;\n\nin vec2 v_imageUV;\nout vec4 fragColor;\n\nconst float shiftC = -.5;\nconst float shiftM = -.25;\nconst float shiftY = .2;\nconst float shiftK = 0.;\n\n// Precomputed sin/cos for rotation angles (15\u00B0, 75\u00B0, 0\u00B0, 45\u00B0)\nconst float cosC = 0.9659258; const float sinC = 0.2588190; // 15\u00B0\nconst float cosM = 0.2588190; const float sinM = 0.9659258; // 75\u00B0\nconst float cosY = 1.0; const float sinY = 0.0; // 0\u00B0\nconst float cosK = 0.7071068; const float sinK = 0.7071068; // 45\u00B0\n\n${ declarePI }\n\nvec2 randomRG(vec2 p) {\n vec2 uv = floor(p) / 100. + .5;\n return texture(u_noiseTexture, fract(uv)).rg;\n}\nvec3 hash23(vec2 p) {\n vec3 p3 = fract(vec3(p.xyx) * vec3(0.3183099, 0.3678794, 0.3141592)) + 0.1;\n p3 += dot(p3, p3.yzx + 19.19);\n return fract(vec3(p3.x * p3.y, p3.y * p3.z, p3.z * p3.x));\n}\n\nfloat sst(float edge0, float edge1, float x) {\n return smoothstep(edge0, edge1, x);\n}\n\nvec3 valueNoise3(vec2 st) {\n vec2 i = floor(st);\n vec2 f = fract(st);\n vec3 a = hash23(i);\n vec3 b = hash23(i + vec2(1.0, 0.0));\n vec3 c = hash23(i + vec2(0.0, 1.0));\n vec3 d = hash23(i + vec2(1.0, 1.0));\n vec2 u = f * f * (3.0 - 2.0 * f);\n vec3 x1 = mix(a, b, u.x);\n vec3 x2 = mix(c, d, u.x);\n return mix(x1, x2, u.y);\n}\n\nfloat getUvFrame(vec2 uv, vec2 pad) {\n float left = smoothstep(-pad.x, 0., uv.x);\n float right = smoothstep(1. + pad.x, 1., uv.x);\n float bottom = smoothstep(-pad.y, 0., uv.y);\n float top = smoothstep(1. + pad.y, 1., uv.y);\n\n return left * right * bottom * top;\n}\n\nvec4 RGBAtoCMYK(vec4 rgba) {\n float k = 1. - max(max(rgba.r, rgba.g), rgba.b);\n float denom = 1. - k;\n vec3 cmy = vec3(0.);\n if (denom > 1e-5) {\n cmy = (1. - rgba.rgb - vec3(k)) / denom;\n }\n return vec4(cmy, k) * rgba.a;\n}\n\nvec3 applyContrast(vec3 rgb) {\n return clamp((rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n}\n\n// Single-component CMYK extractors with contrast built-in, alpha-aware\nfloat getCyan(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.r) / maxRGB : 0.) * rgba.a;\n}\nfloat getMagenta(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.g) / maxRGB : 0.) * rgba.a;\n}\nfloat getYellow(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n float maxRGB = max(max(c.r, c.g), c.b);\n return (maxRGB > 1e-5 ? (maxRGB - c.b) / maxRGB : 0.) * rgba.a;\n}\nfloat getBlack(vec4 rgba) {\n vec3 c = clamp((rgba.rgb - 0.5) * u_contrast + 0.5, 0.0, 1.0);\n return (1. - max(max(c.r, c.g), c.b)) * rgba.a;\n}\n\nvec2 cellCenterPos(vec2 uv, vec2 cellOffset, float channelIdx) {\n vec2 cellCenter = floor(uv) + .5 + cellOffset;\n return cellCenter + (randomRG(cellCenter + channelIdx * 50.) - .5) * u_gridNoise;\n}\n\nvec2 gridToImageUV(vec2 cellCenter, float cosA, float sinA, float shift, vec2 pad) {\n vec2 uvGrid = mat2(cosA, -sinA, sinA, cosA) * (cellCenter - shift);\n return uvGrid * pad + 0.5;\n}\n\nvoid colorMask(vec2 pos, vec2 cellCenter, float rad, float transparency, float grain, float channelAddon, float channelgain, float generalComp, bool isJoined, inout float outMask) {\n float dist = length(pos - cellCenter);\n\n float radius = rad;\n radius *= (1. + generalComp);\n radius += (.15 + channelgain * radius);\n radius = max(0., radius);\n radius = mix(0., radius, transparency);\n radius += channelAddon;\n radius *= (1. - grain);\n\n float mask = 1. - sst(0., radius, dist);\n if (isJoined) {\n // ink or sharp (joined)\n mask = pow(mask, 1.2);\n } else {\n // dots (separate)\n mask = sst(.5 - .5 * u_softness, .51 + .49 * u_softness, mask);\n }\n\n mask *= mix(1., mix(.5, 1., 1.5 * radius), u_softness);\n outMask += mask;\n}\n\nvec3 applyInk(vec3 paper, vec3 inkColor, float cov) {\n vec3 inkEffect = mix(vec3(1.0), inkColor, clamp(cov, 0.0, 1.0));\n return paper * inkEffect;\n}\n\nvoid main() {\n vec2 uv = v_imageUV;\n\n float cellsPerSide = mix(400.0, 7.0, pow(u_size, 0.7));\n float cellSizeY = 1.0 / cellsPerSide;\n vec2 pad = cellSizeY * vec2(1.0 / u_imageAspectRatio, 1.0);\n vec2 uvGrid = (uv - .5) / pad;\n float insideImageBox = getUvFrame(uv, pad);\n\n float generalComp = .1 * u_softness + .1 * u_gridNoise + .1 * (1. - step(0.5, u_type)) * (1.5 - u_softness);\n\n vec2 uvC = mat2(cosC, sinC, -sinC, cosC) * uvGrid + shiftC;\n vec2 uvM = mat2(cosM, sinM, -sinM, cosM) * uvGrid + shiftM;\n vec2 uvY = mat2(cosY, sinY, -sinY, cosY) * uvGrid + shiftY;\n vec2 uvK = mat2(cosK, sinK, -sinK, cosK) * uvGrid + shiftK;\n\n vec2 grainSize = mix(2000., 200., u_grainSize) * vec2(1., 1. / u_imageAspectRatio);\n vec2 grainUV = (v_imageUV - .5) * grainSize + .5;\n vec3 noiseValues = valueNoise3(grainUV);\n float grain = sst(.55, 1., noiseValues.r);\n grain *= u_grainMixer;\n\n vec4 outMask = vec4(0.);\n bool isJoined = u_type > 0.5;\n\n if (u_type < 1.5) {\n // dots or ink: per-cell color sampling\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 cellOffset = vec2(float(dx), float(dy));\n\n vec2 cellCenterC = cellCenterPos(uvC, cellOffset, 0.);\n vec4 texC = texture(u_image, gridToImageUV(cellCenterC, cosC, sinC, shiftC, pad));\n colorMask(uvC, cellCenterC, getCyan(texC), insideImageBox * texC.a, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);\n\n vec2 cellCenterM = cellCenterPos(uvM, cellOffset, 1.);\n vec4 texM = texture(u_image, gridToImageUV(cellCenterM, cosM, sinM, shiftM, pad));\n colorMask(uvM, cellCenterM, getMagenta(texM), insideImageBox * texM.a, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);\n\n vec2 cellCenterY = cellCenterPos(uvY, cellOffset, 2.);\n vec4 texY = texture(u_image, gridToImageUV(cellCenterY, cosY, sinY, shiftY, pad));\n colorMask(uvY, cellCenterY, getYellow(texY), insideImageBox * texY.a, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);\n\n vec2 cellCenterK = cellCenterPos(uvK, cellOffset, 3.);\n vec4 texK = texture(u_image, gridToImageUV(cellCenterK, cosK, sinK, shiftK, pad));\n colorMask(uvK, cellCenterK, getBlack(texK), insideImageBox * texK.a, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);\n }\n }\n } else {\n // sharp: direct px color sampling\n vec4 tex = texture(u_image, uv);\n tex.rgb = applyContrast(tex.rgb);\n insideImageBox *= tex.a;\n vec4 cmykOriginal = RGBAtoCMYK(tex);\n for (int dy = -1; dy <= 1; dy++) {\n for (int dx = -1; dx <= 1; dx++) {\n vec2 cellOffset = vec2(float(dx), float(dy));\n\n colorMask(uvC, cellCenterPos(uvC, cellOffset, 0.), cmykOriginal.x, insideImageBox, grain, u_floodC, u_gainC, generalComp, isJoined, outMask[0]);\n colorMask(uvM, cellCenterPos(uvM, cellOffset, 1.), cmykOriginal.y, insideImageBox, grain, u_floodM, u_gainM, generalComp, isJoined, outMask[1]);\n colorMask(uvY, cellCenterPos(uvY, cellOffset, 2.), cmykOriginal.z, insideImageBox, grain, u_floodY, u_gainY, generalComp, isJoined, outMask[2]);\n colorMask(uvK, cellCenterPos(uvK, cellOffset, 3.), cmykOriginal.w, insideImageBox, grain, u_floodK, u_gainK, generalComp, isJoined, outMask[3]);\n }\n }\n }\n\n float shape;\n\n float C = outMask[0];\n float M = outMask[1];\n float Y = outMask[2];\n float K = outMask[3];\n\n if (isJoined) {\n // ink or sharp: apply threshold for joined dots\n float th = .5;\n float sLeft = th * u_softness;\n float sRight = (1. - th) * u_softness + .01;\n C = smoothstep(th - sLeft - fwidth(C), th + sRight, C);\n M = smoothstep(th - sLeft - fwidth(M), th + sRight, M);\n Y = smoothstep(th - sLeft - fwidth(Y), th + sRight, Y);\n K = smoothstep(th - sLeft - fwidth(K), th + sRight, K);\n }\n\n C *= u_colorC.a;\n M *= u_colorM.a;\n Y *= u_colorY.a;\n K *= u_colorK.a;\n\n vec3 ink = vec3(1.);\n ink = applyInk(ink, u_colorK.rgb, K);\n ink = applyInk(ink, u_colorC.rgb, C);\n ink = applyInk(ink, u_colorM.rgb, M);\n ink = applyInk(ink, u_colorY.rgb, Y);\n\n shape = clamp(max(max(C, M), max(Y, K)), 0., 1.);\n\n vec3 color = u_colorBack.rgb * u_colorBack.a;\n\n float opacity = u_colorBack.a;\n color = mix(color, ink, shape);\n opacity += shape;\n opacity = clamp(opacity, 0., 1.);\n\n float grainOverlay = mix(noiseValues.g, noiseValues.b, .5);\n grainOverlay = pow(grainOverlay, 1.3);\n\n float grainOverlayV = grainOverlay * 2. - 1.;\n vec3 grainOverlayColor = vec3(step(0., grainOverlayV));\n float grainOverlayStrength = u_grainOverlay * abs(grainOverlayV);\n grainOverlayStrength = pow(grainOverlayStrength, .8);\n color = mix(color, grainOverlayColor, .5 * grainOverlayStrength);\n\n opacity += .5 * grainOverlayStrength;\n opacity = clamp(opacity, 0., 1.);\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface HalftoneCmykUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string | undefined;\n u_noiseTexture?: HTMLImageElement;\n u_colorBack: [number, number, number, number];\n u_colorC: [number, number, number, number];\n u_colorM: [number, number, number, number];\n u_colorY: [number, number, number, number];\n u_colorK: [number, number, number, number];\n u_size: number;\n u_contrast: number;\n u_softness: number;\n u_grainSize: number;\n u_grainMixer: number;\n u_grainOverlay: number;\n u_gridNoise: number;\n u_floodC: number;\n u_floodM: number;\n u_floodY: number;\n u_floodK: number;\n u_gainC: number;\n u_gainM: number;\n u_gainY: number;\n u_gainK: number;\n u_type: (typeof HalftoneCmykTypes)[HalftoneCmykType];\n}\n\nexport interface HalftoneCmykParams extends ShaderSizingParams, ShaderMotionParams {\n image?: HTMLImageElement | string;\n colorBack?: string;\n colorC?: string;\n colorM?: string;\n colorY?: string;\n colorK?: string;\n size?: number;\n contrast?: number;\n softness?: number;\n grainSize?: number;\n grainMixer?: number;\n grainOverlay?: number;\n gridNoise?: number;\n floodC?: number;\n floodM?: number;\n floodY?: number;\n floodK?: number;\n gainC?: number;\n gainM?: number;\n gainY?: number;\n gainK?: number;\n type?: HalftoneCmykType;\n}\n\nexport const HalftoneCmykTypes = {\n dots: 0,\n ink: 1,\n sharp: 2,\n} as const;\n\nexport type HalftoneCmykType = keyof typeof HalftoneCmykTypes;\n\n"],
|
|
5
|
+
"mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,iBAAiB;AAmDnB,MAAM,6BAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA4C/C,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA2RN,MAAM,oBAAoB;AAAA,EAC/B,MAAM;AAAA,EACN,KAAK;AAAA,EACL,OAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -28,6 +28,7 @@ import { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-si
|
|
|
28
28
|
* - u_colorBack (vec4): Background color in RGBA
|
|
29
29
|
* - u_colorHighlight (vec4): Secondary foreground color in RGBA (set same as colorFront for classic 2-color dithering)
|
|
30
30
|
* - u_originalColors (bool): Use the original colors of the image instead of the color palette
|
|
31
|
+
* - u_inverted (bool): Inverts the image luminance, doesn't affect the color scheme; not effective at zero contrast
|
|
31
32
|
* - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)
|
|
32
33
|
* - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)
|
|
33
34
|
* - u_colorSteps (float): Number of colors to use, applies to both color modes (1 to 7)
|
|
@@ -43,6 +44,7 @@ export interface ImageDitheringUniforms extends ShaderSizingUniforms {
|
|
|
43
44
|
u_pxSize: number;
|
|
44
45
|
u_colorSteps: number;
|
|
45
46
|
u_originalColors: boolean;
|
|
47
|
+
u_inverted: boolean;
|
|
46
48
|
}
|
|
47
49
|
export interface ImageDitheringParams extends ShaderSizingParams, ShaderMotionParams {
|
|
48
50
|
image: HTMLImageElement | string;
|
|
@@ -53,6 +55,7 @@ export interface ImageDitheringParams extends ShaderSizingParams, ShaderMotionPa
|
|
|
53
55
|
size?: number;
|
|
54
56
|
colorSteps?: number;
|
|
55
57
|
originalColors?: boolean;
|
|
58
|
+
inverted?: boolean;
|
|
56
59
|
}
|
|
57
60
|
export declare const DitheringTypes: {
|
|
58
61
|
readonly random: 1;
|
|
@@ -31,6 +31,7 @@ uniform float u_imageAspectRatio;
|
|
|
31
31
|
uniform float u_type;
|
|
32
32
|
uniform float u_pxSize;
|
|
33
33
|
uniform bool u_originalColors;
|
|
34
|
+
uniform bool u_inverted;
|
|
34
35
|
uniform float u_colorSteps;
|
|
35
36
|
|
|
36
37
|
out vec4 fragColor;
|
|
@@ -133,6 +134,7 @@ void main() {
|
|
|
133
134
|
float dithering = 0.0;
|
|
134
135
|
|
|
135
136
|
float lum = dot(vec3(.2126, .7152, .0722), image.rgb);
|
|
137
|
+
lum = u_inverted ? (1. - lum) : lum;
|
|
136
138
|
|
|
137
139
|
switch (type) {
|
|
138
140
|
case 1: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/shaders/image-dithering.ts"],
|
|
4
|
-
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { proceduralHash21, declarePI } from '../shader-utils.js';\n\n/**\n * A dithering image filter with support for 4 dithering modes and multiple color palettes\n * (2-color, 3-color, and multicolor options, using either predefined colors or colors sampled\n * from the original image).\n *\n * SIZING NOTE: This shader performs sizing in the fragment shader (not vertex shader) to keep\n * u_pxSize in consistent actual pixels. The pixel grid is computed from gl_FragCoord before any\n * transforms, so scaling/rotating only affects the underlying image.\n * No vertex shader outputs (v_imageUV, v_objectUV, etc.) are used.\n *\n * Fragment shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_image (sampler2D): Source image texture\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n * - u_colorFront (vec4): Foreground color in RGBA\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorHighlight (vec4): Secondary foreground color in RGBA (set same as colorFront for classic 2-color dithering)\n * - u_originalColors (bool): Use the original colors of the image instead of the color palette\n * - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)\n * - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)\n * - u_colorSteps (float): Number of colors to use, applies to both color modes (1 to 7)\n *\n */\n\n// language=GLSL\nexport const imageDitheringFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\nuniform float u_originX;\nuniform float u_originY;\nuniform float u_worldWidth;\nuniform float u_worldHeight;\nuniform float u_fit;\n\nuniform float u_scale;\nuniform float u_rotation;\nuniform float u_offsetX;\nuniform float u_offsetY;\n\nuniform vec4 u_colorFront;\nuniform vec4 u_colorBack;\nuniform vec4 u_colorHighlight;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform float u_type;\nuniform float u_pxSize;\nuniform bool u_originalColors;\nuniform float u_colorSteps;\n\nout vec4 fragColor;\n\n\n${ proceduralHash21 }\n${ declarePI }\n\nfloat getUvFrame(vec2 uv, vec2 pad) {\n float aa = 0.0001;\n\n float left = smoothstep(-pad.x, -pad.x + aa, uv.x);\n float right = smoothstep(1.0 + pad.x, 1.0 + pad.x - aa, uv.x);\n float bottom = smoothstep(-pad.y, -pad.y + aa, uv.y);\n float top = smoothstep(1.0 + pad.y, 1.0 + pad.y - aa, uv.y);\n\n return left * right * bottom * top;\n}\n\nvec2 getImageUV(vec2 uv) {\n vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);\n float r = u_rotation * PI / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n\n vec2 imageBoxSize;\n if (u_fit == 1.) { // contain\n imageBoxSize.x = min(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n } else if (u_fit == 2.) { // cover\n imageBoxSize.x = max(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n } else {\n imageBoxSize.x = min(10.0, 10.0 / u_imageAspectRatio * u_imageAspectRatio);\n }\n imageBoxSize.y = imageBoxSize.x / u_imageAspectRatio;\n vec2 imageBoxScale = u_resolution.xy / imageBoxSize;\n\n vec2 imageUV = uv;\n imageUV *= imageBoxScale;\n imageUV += boxOrigin * (imageBoxScale - 1.);\n imageUV += graphicOffset;\n imageUV /= u_scale;\n imageUV.x *= u_imageAspectRatio;\n imageUV = graphicRotation * imageUV;\n imageUV.x /= u_imageAspectRatio;\n\n imageUV += .5;\n imageUV.y = 1. - imageUV.y;\n\n return imageUV;\n}\n\nconst int bayer2x2[4] = int[4](0, 2, 3, 1);\nconst int bayer4x4[16] = int[16](\n0, 8, 2, 10,\n12, 4, 14, 6,\n3, 11, 1, 9,\n15, 7, 13, 5\n);\n\nconst int bayer8x8[64] = int[64](\n0, 32, 8, 40, 2, 34, 10, 42,\n48, 16, 56, 24, 50, 18, 58, 26,\n12, 44, 4, 36, 14, 46, 6, 38,\n60, 28, 52, 20, 62, 30, 54, 22,\n3, 35, 11, 43, 1, 33, 9, 41,\n51, 19, 59, 27, 49, 17, 57, 25,\n15, 47, 7, 39, 13, 45, 5, 37,\n63, 31, 55, 23, 61, 29, 53, 21\n);\n\nfloat getBayerValue(vec2 uv, int size) {\n ivec2 pos = ivec2(fract(uv / float(size)) * float(size));\n int index = pos.y * size + pos.x;\n\n if (size == 2) {\n return float(bayer2x2[index]) / 4.0;\n } else if (size == 4) {\n return float(bayer4x4[index]) / 16.0;\n } else if (size == 8) {\n return float(bayer8x8[index]) / 64.0;\n }\n return 0.0;\n}\n\n\nvoid main() {\n\n float pxSize = u_pxSize * u_pixelRatio;\n vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;\n pxSizeUV /= pxSize;\n vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;\n vec2 normalizedUV = canvasPixelizedUV / u_resolution;\n\n vec2 imageUV = getImageUV(normalizedUV);\n vec2 ditheringNoiseUV = canvasPixelizedUV;\n vec4 image = texture(u_image, imageUV);\n float frame = getUvFrame(imageUV, pxSize / u_resolution);\n\n int type = int(floor(u_type));\n float dithering = 0.0;\n\n float lum = dot(vec3(.2126, .7152, .0722), image.rgb);\n\n switch (type) {\n case 1: {\n dithering = step(hash21(ditheringNoiseUV), lum);\n } break;\n case 2:\n dithering = getBayerValue(pxSizeUV, 2);\n break;\n case 3:\n dithering = getBayerValue(pxSizeUV, 4);\n break;\n default :\n dithering = getBayerValue(pxSizeUV, 8);\n break;\n }\n\n float colorSteps = max(floor(u_colorSteps), 1.);\n vec3 color = vec3(0.0);\n float opacity = 1.;\n\n dithering -= .5;\n float brightness = clamp(lum + dithering / colorSteps, 0.0, 1.0);\n brightness = mix(0.0, brightness, frame);\n brightness = mix(0.0, brightness, image.a);\n float quantLum = floor(brightness * colorSteps + 0.5) / colorSteps;\n quantLum = mix(0.0, quantLum, frame);\n\n if (u_originalColors == true) {\n vec3 normColor = image.rgb / max(lum, 0.001);\n color = normColor * quantLum;\n\n float quantAlpha = floor(image.a * colorSteps + 0.5) / colorSteps;\n opacity = mix(quantLum, 1., quantAlpha);\n } else {\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\n float fgOpacity = u_colorFront.a;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n float bgOpacity = u_colorBack.a;\n vec3 hlColor = u_colorHighlight.rgb * u_colorHighlight.a;\n float hlOpacity = u_colorHighlight.a;\n\n fgColor = mix(fgColor, hlColor, step(1.02 - .02 * u_colorSteps, brightness));\n fgOpacity = mix(fgOpacity, hlOpacity, step(1.02 - .02 * u_colorSteps, brightness));\n\n color = fgColor * quantLum;\n opacity = fgOpacity * quantLum;\n color += bgColor * (1.0 - opacity);\n opacity += bgOpacity * (1.0 - opacity);\n }\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface ImageDitheringUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string;\n u_colorFront: [number, number, number, number];\n u_colorBack: [number, number, number, number];\n u_colorHighlight: [number, number, number, number];\n u_type: (typeof DitheringTypes)[DitheringType];\n u_pxSize: number;\n u_colorSteps: number;\n u_originalColors: boolean;\n}\n\nexport interface ImageDitheringParams extends ShaderSizingParams, ShaderMotionParams {\n image: HTMLImageElement | string;\n colorFront?: string;\n colorBack?: string;\n colorHighlight?: string;\n type?: DitheringType;\n size?: number;\n colorSteps?: number;\n originalColors?: boolean;\n}\n\nexport const DitheringTypes = {\n 'random': 1,\n '2x2': 2,\n '4x4': 3,\n '8x8': 4,\n} as const;\n\nexport type DitheringType = keyof typeof DitheringTypes;\n"],
|
|
5
|
-
"mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,kBAAkB,iBAAiB;
|
|
4
|
+
"sourcesContent": ["import type { ShaderMotionParams } from '../shader-mount.js';\nimport { type ShaderSizingParams, type ShaderSizingUniforms } from '../shader-sizing.js';\nimport { proceduralHash21, declarePI } from '../shader-utils.js';\n\n/**\n * A dithering image filter with support for 4 dithering modes and multiple color palettes\n * (2-color, 3-color, and multicolor options, using either predefined colors or colors sampled\n * from the original image).\n *\n * SIZING NOTE: This shader performs sizing in the fragment shader (not vertex shader) to keep\n * u_pxSize in consistent actual pixels. The pixel grid is computed from gl_FragCoord before any\n * transforms, so scaling/rotating only affects the underlying image.\n * No vertex shader outputs (v_imageUV, v_objectUV, etc.) are used.\n *\n * Fragment shader uniforms:\n * - u_resolution (vec2): Canvas resolution in pixels\n * - u_pixelRatio (float): Device pixel ratio\n * - u_originX (float): Reference point for positioning world width in the canvas (0 to 1)\n * - u_originY (float): Reference point for positioning world height in the canvas (0 to 1)\n * - u_worldWidth (float): Virtual width of the graphic before it's scaled to fit the canvas\n * - u_worldHeight (float): Virtual height of the graphic before it's scaled to fit the canvas\n * - u_fit (float): How to fit the rendered shader into the canvas dimensions (0 = none, 1 = contain, 2 = cover)\n * - u_scale (float): Overall zoom level of the graphics (0.01 to 4)\n * - u_rotation (float): Overall rotation angle of the graphics in degrees (0 to 360)\n * - u_offsetX (float): Horizontal offset of the graphics center (-1 to 1)\n * - u_offsetY (float): Vertical offset of the graphics center (-1 to 1)\n * - u_image (sampler2D): Source image texture\n * - u_imageAspectRatio (float): Aspect ratio of the source image\n * - u_colorFront (vec4): Foreground color in RGBA\n * - u_colorBack (vec4): Background color in RGBA\n * - u_colorHighlight (vec4): Secondary foreground color in RGBA (set same as colorFront for classic 2-color dithering)\n * - u_originalColors (bool): Use the original colors of the image instead of the color palette\n * - u_inverted (bool): Inverts the image luminance, doesn't affect the color scheme; not effective at zero contrast\n * - u_type (float): Dithering type (1 = random, 2 = 2x2 Bayer, 3 = 4x4 Bayer, 4 = 8x8 Bayer)\n * - u_pxSize (float): Pixel size of dithering grid (0.5 to 20)\n * - u_colorSteps (float): Number of colors to use, applies to both color modes (1 to 7)\n *\n */\n\n// language=GLSL\nexport const imageDitheringFragmentShader: string = `#version 300 es\nprecision mediump float;\n\nuniform vec2 u_resolution;\nuniform float u_pixelRatio;\nuniform float u_originX;\nuniform float u_originY;\nuniform float u_worldWidth;\nuniform float u_worldHeight;\nuniform float u_fit;\n\nuniform float u_scale;\nuniform float u_rotation;\nuniform float u_offsetX;\nuniform float u_offsetY;\n\nuniform vec4 u_colorFront;\nuniform vec4 u_colorBack;\nuniform vec4 u_colorHighlight;\n\nuniform sampler2D u_image;\nuniform float u_imageAspectRatio;\n\nuniform float u_type;\nuniform float u_pxSize;\nuniform bool u_originalColors;\nuniform bool u_inverted;\nuniform float u_colorSteps;\n\nout vec4 fragColor;\n\n\n${ proceduralHash21 }\n${ declarePI }\n\nfloat getUvFrame(vec2 uv, vec2 pad) {\n float aa = 0.0001;\n\n float left = smoothstep(-pad.x, -pad.x + aa, uv.x);\n float right = smoothstep(1.0 + pad.x, 1.0 + pad.x - aa, uv.x);\n float bottom = smoothstep(-pad.y, -pad.y + aa, uv.y);\n float top = smoothstep(1.0 + pad.y, 1.0 + pad.y - aa, uv.y);\n\n return left * right * bottom * top;\n}\n\nvec2 getImageUV(vec2 uv) {\n vec2 boxOrigin = vec2(.5 - u_originX, u_originY - .5);\n float r = u_rotation * PI / 180.;\n mat2 graphicRotation = mat2(cos(r), sin(r), -sin(r), cos(r));\n vec2 graphicOffset = vec2(-u_offsetX, u_offsetY);\n\n vec2 imageBoxSize;\n if (u_fit == 1.) { // contain\n imageBoxSize.x = min(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n } else if (u_fit == 2.) { // cover\n imageBoxSize.x = max(u_resolution.x / u_imageAspectRatio, u_resolution.y) * u_imageAspectRatio;\n } else {\n imageBoxSize.x = min(10.0, 10.0 / u_imageAspectRatio * u_imageAspectRatio);\n }\n imageBoxSize.y = imageBoxSize.x / u_imageAspectRatio;\n vec2 imageBoxScale = u_resolution.xy / imageBoxSize;\n\n vec2 imageUV = uv;\n imageUV *= imageBoxScale;\n imageUV += boxOrigin * (imageBoxScale - 1.);\n imageUV += graphicOffset;\n imageUV /= u_scale;\n imageUV.x *= u_imageAspectRatio;\n imageUV = graphicRotation * imageUV;\n imageUV.x /= u_imageAspectRatio;\n\n imageUV += .5;\n imageUV.y = 1. - imageUV.y;\n\n return imageUV;\n}\n\nconst int bayer2x2[4] = int[4](0, 2, 3, 1);\nconst int bayer4x4[16] = int[16](\n0, 8, 2, 10,\n12, 4, 14, 6,\n3, 11, 1, 9,\n15, 7, 13, 5\n);\n\nconst int bayer8x8[64] = int[64](\n0, 32, 8, 40, 2, 34, 10, 42,\n48, 16, 56, 24, 50, 18, 58, 26,\n12, 44, 4, 36, 14, 46, 6, 38,\n60, 28, 52, 20, 62, 30, 54, 22,\n3, 35, 11, 43, 1, 33, 9, 41,\n51, 19, 59, 27, 49, 17, 57, 25,\n15, 47, 7, 39, 13, 45, 5, 37,\n63, 31, 55, 23, 61, 29, 53, 21\n);\n\nfloat getBayerValue(vec2 uv, int size) {\n ivec2 pos = ivec2(fract(uv / float(size)) * float(size));\n int index = pos.y * size + pos.x;\n\n if (size == 2) {\n return float(bayer2x2[index]) / 4.0;\n } else if (size == 4) {\n return float(bayer4x4[index]) / 16.0;\n } else if (size == 8) {\n return float(bayer8x8[index]) / 64.0;\n }\n return 0.0;\n}\n\n\nvoid main() {\n\n float pxSize = u_pxSize * u_pixelRatio;\n vec2 pxSizeUV = gl_FragCoord.xy - .5 * u_resolution;\n pxSizeUV /= pxSize;\n vec2 canvasPixelizedUV = (floor(pxSizeUV) + .5) * pxSize;\n vec2 normalizedUV = canvasPixelizedUV / u_resolution;\n\n vec2 imageUV = getImageUV(normalizedUV);\n vec2 ditheringNoiseUV = canvasPixelizedUV;\n vec4 image = texture(u_image, imageUV);\n float frame = getUvFrame(imageUV, pxSize / u_resolution);\n\n int type = int(floor(u_type));\n float dithering = 0.0;\n\n float lum = dot(vec3(.2126, .7152, .0722), image.rgb);\n lum = u_inverted ? (1. - lum) : lum;\n\n switch (type) {\n case 1: {\n dithering = step(hash21(ditheringNoiseUV), lum);\n } break;\n case 2:\n dithering = getBayerValue(pxSizeUV, 2);\n break;\n case 3:\n dithering = getBayerValue(pxSizeUV, 4);\n break;\n default :\n dithering = getBayerValue(pxSizeUV, 8);\n break;\n }\n\n float colorSteps = max(floor(u_colorSteps), 1.);\n vec3 color = vec3(0.0);\n float opacity = 1.;\n\n dithering -= .5;\n float brightness = clamp(lum + dithering / colorSteps, 0.0, 1.0);\n brightness = mix(0.0, brightness, frame);\n brightness = mix(0.0, brightness, image.a);\n float quantLum = floor(brightness * colorSteps + 0.5) / colorSteps;\n quantLum = mix(0.0, quantLum, frame);\n\n if (u_originalColors == true) {\n vec3 normColor = image.rgb / max(lum, 0.001);\n color = normColor * quantLum;\n\n float quantAlpha = floor(image.a * colorSteps + 0.5) / colorSteps;\n opacity = mix(quantLum, 1., quantAlpha);\n } else {\n vec3 fgColor = u_colorFront.rgb * u_colorFront.a;\n float fgOpacity = u_colorFront.a;\n vec3 bgColor = u_colorBack.rgb * u_colorBack.a;\n float bgOpacity = u_colorBack.a;\n vec3 hlColor = u_colorHighlight.rgb * u_colorHighlight.a;\n float hlOpacity = u_colorHighlight.a;\n\n fgColor = mix(fgColor, hlColor, step(1.02 - .02 * u_colorSteps, brightness));\n fgOpacity = mix(fgOpacity, hlOpacity, step(1.02 - .02 * u_colorSteps, brightness));\n\n color = fgColor * quantLum;\n opacity = fgOpacity * quantLum;\n color += bgColor * (1.0 - opacity);\n opacity += bgOpacity * (1.0 - opacity);\n }\n\n fragColor = vec4(color, opacity);\n}\n`;\n\nexport interface ImageDitheringUniforms extends ShaderSizingUniforms {\n u_image: HTMLImageElement | string;\n u_colorFront: [number, number, number, number];\n u_colorBack: [number, number, number, number];\n u_colorHighlight: [number, number, number, number];\n u_type: (typeof DitheringTypes)[DitheringType];\n u_pxSize: number;\n u_colorSteps: number;\n u_originalColors: boolean;\n u_inverted: boolean;\n}\n\nexport interface ImageDitheringParams extends ShaderSizingParams, ShaderMotionParams {\n image: HTMLImageElement | string;\n colorFront?: string;\n colorBack?: string;\n colorHighlight?: string;\n type?: DitheringType;\n size?: number;\n colorSteps?: number;\n originalColors?: boolean;\n inverted?: boolean;\n}\n\nexport const DitheringTypes = {\n 'random': 1,\n '2x2': 2,\n '4x4': 3,\n '8x8': 4,\n} as const;\n\nexport type DitheringType = keyof typeof DitheringTypes;\n"],
|
|
5
|
+
"mappings": ";;;;;AACA,eAAmE;AACnE,SAAS,kBAAkB,iBAAiB;AAsCrC,MAAM,+BAAuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCjD,gBAAiB;AAAA,EACjB,SAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA+KN,MAAM,iBAAiB;AAAA,EAC5B,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|