@johnfmorton/some-shade 0.1.1-beta → 0.1.4-beta
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.
- package/dist/some-shade.cjs.js +43 -13
- package/dist/some-shade.es.js +217 -201
- package/dist/some-shade.umd.js +45 -15
- package/package.json +1 -1
- package/dist/index.d.ts +0 -82
package/dist/some-shade.cjs.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("lit"),l=require("lit/decorators.js");function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const _=require("lit"),l=require("lit/decorators.js");function k(t){return t.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function E(t,o,r){const i=t.createShader(o);if(!i)throw new Error("Failed to create shader");if(t.shaderSource(i,r),t.compileShader(i),!t.getShaderParameter(i,t.COMPILE_STATUS)){const e=t.getShaderInfoLog(i);throw t.deleteShader(i),new Error(`Shader compile error: ${e}`)}return i}function D(t,o,r){const i=E(t,t.VERTEX_SHADER,o),e=E(t,t.FRAGMENT_SHADER,r),n=t.createProgram();if(!n)throw new Error("Failed to create program");if(t.attachShader(n,i),t.attachShader(n,e),t.linkProgram(n),!t.getProgramParameter(n,t.LINK_STATUS)){const d=t.getProgramInfoLog(n);throw t.deleteProgram(n),new Error(`Program link error: ${d}`)}t.deleteShader(i),t.deleteShader(e);const c=new Map,h=t.getProgramParameter(n,t.ACTIVE_ATTRIBUTES);for(let d=0;d<h;d++){const f=t.getActiveAttrib(n,d);f&&c.set(f.name,t.getAttribLocation(n,f.name))}const s=new Map,g=t.getProgramParameter(n,t.ACTIVE_UNIFORMS);for(let d=0;d<g;d++){const f=t.getActiveUniform(n,d);if(f){const m=t.getUniformLocation(n,f.name);m&&s.set(f.name,m)}}return{program:n,attribLocations:c,uniformLocations:s}}function L(t,o,r){for(const[i,e]of Object.entries(r)){const n=o.uniformLocations.get(i);if(n){if(typeof e=="number")t.uniform1f(n,e);else if(Array.isArray(e))switch(e.length){case 2:t.uniform2fv(n,e);break;case 3:t.uniform3fv(n,e);break;case 4:t.uniform4fv(n,e);break}}}}function z(t,o){const r=t.createTexture();if(!r)throw new Error("Failed to create texture");return t.bindTexture(t.TEXTURE_2D,r),t.texImage2D(t.TEXTURE_2D,0,t.RGBA,t.RGBA,t.UNSIGNED_BYTE,o),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MIN_FILTER,t.LINEAR),t.texParameteri(t.TEXTURE_2D,t.TEXTURE_MAG_FILTER,t.LINEAR),{texture:r,width:o.naturalWidth,height:o.naturalHeight}}function M(t,o){const r=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),i=t.createBuffer();if(!i)throw new Error("Failed to create buffer");t.bindBuffer(t.ARRAY_BUFFER,i),t.bufferData(t.ARRAY_BUFFER,r,t.STATIC_DRAW);const e=4*Float32Array.BYTES_PER_ELEMENT,n=o.attribLocations.get("a_position");n!==void 0&&n!==-1&&(t.enableVertexAttribArray(n),t.vertexAttribPointer(n,2,t.FLOAT,!1,e,0));const c=o.attribLocations.get("a_texCoord");return c!==void 0&&c!==-1&&(t.enableVertexAttribArray(c),t.vertexAttribPointer(c,2,t.FLOAT,!1,e,2*Float32Array.BYTES_PER_ELEMENT)),i}function P(t){t.drawArrays(t.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
|
|
2
2
|
|
|
3
3
|
varying vec2 v_texCoord;
|
|
4
4
|
|
|
@@ -14,6 +14,7 @@ uniform float u_showC;
|
|
|
14
14
|
uniform float u_showM;
|
|
15
15
|
uniform float u_showY;
|
|
16
16
|
uniform float u_showK;
|
|
17
|
+
uniform float u_intensityK;
|
|
17
18
|
|
|
18
19
|
// Returns the texture-space UV of the cell center for a given rotation angle
|
|
19
20
|
vec2 cellCenterUV(vec2 uv, float angle) {
|
|
@@ -68,6 +69,7 @@ void main() {
|
|
|
68
69
|
float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
|
|
69
70
|
|
|
70
71
|
float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
|
|
72
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
71
73
|
|
|
72
74
|
// Compute halftone dots for each channel
|
|
73
75
|
float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
|
|
@@ -90,7 +92,7 @@ void main() {
|
|
|
90
92
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
91
93
|
v_texCoord = a_texCoord;
|
|
92
94
|
}
|
|
93
|
-
`,I={name:"halftone-cmyk",fragmentShader:
|
|
95
|
+
`,I={name:"halftone-cmyk",fragmentShader:O,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},V=`precision mediump float;
|
|
94
96
|
|
|
95
97
|
varying vec2 v_texCoord;
|
|
96
98
|
|
|
@@ -132,7 +134,7 @@ void main() {
|
|
|
132
134
|
|
|
133
135
|
gl_FragColor = vec4(result, color.a);
|
|
134
136
|
}
|
|
135
|
-
`,
|
|
137
|
+
`,W={name:"halftone-duotone",fragmentShader:V,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},N=`precision mediump float;
|
|
136
138
|
|
|
137
139
|
varying vec2 v_texCoord;
|
|
138
140
|
|
|
@@ -188,7 +190,7 @@ void main() {
|
|
|
188
190
|
|
|
189
191
|
gl_FragColor = vec4(result, 1.0);
|
|
190
192
|
}
|
|
191
|
-
`,
|
|
193
|
+
`,F={name:"dot-grid",fragmentShader:N,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},B=`precision mediump float;
|
|
192
194
|
|
|
193
195
|
varying vec2 v_texCoord;
|
|
194
196
|
|
|
@@ -204,6 +206,8 @@ uniform float u_showCool;
|
|
|
204
206
|
uniform float u_showK;
|
|
205
207
|
uniform vec3 u_warmColor;
|
|
206
208
|
uniform vec3 u_coolColor;
|
|
209
|
+
uniform float u_blendMode;
|
|
210
|
+
uniform float u_intensityK;
|
|
207
211
|
|
|
208
212
|
float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
|
|
209
213
|
float rad = radians(angle);
|
|
@@ -230,32 +234,58 @@ void main() {
|
|
|
230
234
|
|
|
231
235
|
// Black channel: derived from overall darkness
|
|
232
236
|
float k = 1.0 - max(warmSep, coolSep);
|
|
237
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
233
238
|
|
|
234
239
|
// Halftone dots for each channel
|
|
235
240
|
float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
|
|
236
241
|
float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
|
|
237
242
|
float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
|
|
238
243
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
// Blend modes affect how warm and cool dots combine where they overlap.
|
|
245
|
+
// All modes use white paper; individual dots look the same.
|
|
246
|
+
// Only the overlap regions differ between modes.
|
|
247
|
+
vec3 overlap;
|
|
248
|
+
if (u_blendMode < 0.5) {
|
|
249
|
+
// Subtractive: dye overlap absorbs more light (darker)
|
|
250
|
+
overlap = u_warmColor + u_coolColor - vec3(1.0);
|
|
251
|
+
} else if (u_blendMode < 1.5) {
|
|
252
|
+
// Additive: light overlap adds up (brighter)
|
|
253
|
+
overlap = u_warmColor + u_coolColor;
|
|
254
|
+
} else {
|
|
255
|
+
// Screen: soft additive overlap with natural clamping
|
|
256
|
+
overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Decompose into four halftone regions
|
|
260
|
+
float onlyWarm = warmDot * (1.0 - coolDot);
|
|
261
|
+
float onlyCool = coolDot * (1.0 - warmDot);
|
|
262
|
+
float both = warmDot * coolDot;
|
|
263
|
+
float neither = (1.0 - warmDot) * (1.0 - coolDot);
|
|
264
|
+
|
|
265
|
+
// Composite: white paper base, colored dots, blend-mode-dependent overlap
|
|
266
|
+
vec3 result = neither * vec3(1.0)
|
|
267
|
+
+ onlyWarm * u_warmColor
|
|
268
|
+
+ onlyCool * u_coolColor
|
|
269
|
+
+ both * overlap;
|
|
270
|
+
|
|
271
|
+
// K channel darkening with intensity control
|
|
272
|
+
result *= (1.0 - kDot);
|
|
244
273
|
|
|
245
|
-
gl_FragColor = vec4(clamp(
|
|
274
|
+
gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
|
|
246
275
|
}
|
|
247
|
-
`,
|
|
276
|
+
`,Y={name:"technicolor-2strip",fragmentShader:B,vertexShader:y,uniforms:[{name:"u_dotRadius",type:"float",default:7,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:10,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"},{name:"u_blendMode",type:"float",default:1,attribute:"blend-mode"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},w=new Map;function p(t){w.set(t.name,t)}function U(t){return w.get(t)}function X(){return Array.from(w.keys())}p(I);p(W);p(F);p(Y);var $=Object.defineProperty,u=(t,o,r,i)=>{for(var e=void 0,n=t.length-1,c;n>=0;n--)(c=t[n])&&(e=c(o,r,e)||e);return e&&$(o,r,e),e};const G=2;let T=Promise.resolve();function A(t){const o=T.then(t,t);return T=o,o}const H=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","intensityK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor","blendMode"]),C=class C extends _.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.intensityK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.blendMode=1,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1}render(){if(!this._webglAvailable)return _.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return _.html`
|
|
248
277
|
<img src=${this.src} alt="" style=${o} />
|
|
249
278
|
${this._snapshotUrl?_.html`<img
|
|
250
279
|
class="snapshot${this._snapshotLoaded?" loaded":""}"
|
|
251
280
|
src=${this._snapshotUrl}
|
|
252
281
|
@load=${this._onSnapshotLoad}
|
|
253
282
|
alt="" />`:""}
|
|
254
|
-
`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var
|
|
283
|
+
`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var i;const r=this._visible;this._visible=((i=o[0])==null?void 0:i.isIntersecting)??!1,this._visible&&!r&&this._needsRender&&(this._needsRender=!1,A(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(i=>H.has(i))&&this._scheduleRender()}disconnectedCallback(){var o,r;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(r=this._resizeObserver)==null||r.disconnect(),this._revokeSnapshot()}_loadImage(o){const r=new Image;r.crossOrigin="anonymous",r.onload=()=>{this._image=r,this._scheduleRender()},r.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},r.src=o}_scheduleRender(){this._visible?A(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var g;if(!this._image)return;const o=U(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const r=Math.min(window.devicePixelRatio||1,G),i=this._image.naturalWidth,e=this._image.naturalHeight,n=this.clientWidth||i,c=Math.max(1,i/n);this._lastClientWidth=this.clientWidth;const h=document.createElement("canvas");h.width=i*r,h.height=e*r;const s=k(h);if(!s){this._webglAvailable=!1;return}try{const d=D(s,o.vertexShader,o.fragmentShader);s.useProgram(d.program);const f=z(s,this._image),m=M(s,d);s.viewport(0,0,h.width,h.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,f.texture);const R=d.uniformLocations.get("u_image");R&&s.uniform1i(R,0),L(s,d,this._getUniformValues(f,r,c)),s.bindBuffer(s.ARRAY_BUFFER,m);const S=4*Float32Array.BYTES_PER_ELEMENT,b=d.attribLocations.get("a_position");b!==void 0&&b!==-1&&(s.enableVertexAttribArray(b),s.vertexAttribPointer(b,2,s.FLOAT,!1,S,0));const v=d.attribLocations.get("a_texCoord");v!==void 0&&v!==-1&&(s.enableVertexAttribArray(v),s.vertexAttribPointer(v,2,s.FLOAT,!1,S,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const x=await new Promise(K=>h.toBlob(K));s.deleteTexture(f.texture),s.deleteProgram(d.program),s.deleteBuffer(m),x&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(x))}finally{(g=s.getExtension("WEBGL_lose_context"))==null||g.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,r,i){const e={};return e.u_resolution=[o.width*r,o.height*r],e.u_dotRadius=this.dotRadius*i,e.u_gridSize=this.gridSize*i,this.effect==="halftone-cmyk"?(e.u_angleC=this.angleC,e.u_angleM=this.angleM,e.u_angleY=this.angleY,e.u_angleK=this.angleK,e.u_showC=this.showC,e.u_showM=this.showM,e.u_showY=this.showY,e.u_showK=this.showK,e.u_intensityK=this.intensityK):this.effect==="halftone-duotone"?(e.u_duotoneColor=this._parseHexColor(this.duotoneColor),e.u_angle=this.angle):this.effect==="dot-grid"?(e.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],e.u_bgColor=this._parseHexColor(this.bgColor),e.u_angle=this.angle):this.effect==="technicolor-2strip"&&(e.u_angleWarm=this.angleWarm,e.u_angleCool=this.angleCool,e.u_angleK=this.angleK,e.u_showWarm=this.showWarm,e.u_showCool=this.showCool,e.u_showK=this.showK,e.u_warmColor=this._parseHexColor(this.warmColor),e.u_coolColor=this._parseHexColor(this.coolColor),e.u_blendMode=this.blendMode,e.u_intensityK=this.intensityK),e}_parseHexColor(o){const r=o.replace("#",""),i=parseInt(r.substring(0,2),16)/255,e=parseInt(r.substring(2,4),16)/255,n=parseInt(r.substring(4,6),16)/255;return[i,e,n]}};C.styles=_.css`
|
|
255
284
|
:host {
|
|
256
285
|
display: block;
|
|
257
286
|
position: relative;
|
|
258
287
|
overflow: hidden;
|
|
288
|
+
max-width: 100%;
|
|
259
289
|
}
|
|
260
290
|
img {
|
|
261
291
|
display: block;
|
|
@@ -273,4 +303,4 @@ void main() {
|
|
|
273
303
|
img.snapshot.loaded {
|
|
274
304
|
opacity: 1;
|
|
275
305
|
}
|
|
276
|
-
`;let
|
|
306
|
+
`;let a=C;u([l.property()],a.prototype,"src");u([l.property()],a.prototype,"effect");u([l.property({type:Number,attribute:"dot-radius"})],a.prototype,"dotRadius");u([l.property({type:Number,attribute:"grid-size"})],a.prototype,"gridSize");u([l.property({type:Number,attribute:"angle-c"})],a.prototype,"angleC");u([l.property({type:Number,attribute:"angle-m"})],a.prototype,"angleM");u([l.property({type:Number,attribute:"angle-y"})],a.prototype,"angleY");u([l.property({type:Number,attribute:"angle-k"})],a.prototype,"angleK");u([l.property({type:Number,attribute:"show-c"})],a.prototype,"showC");u([l.property({type:Number,attribute:"show-m"})],a.prototype,"showM");u([l.property({type:Number,attribute:"show-y"})],a.prototype,"showY");u([l.property({type:Number,attribute:"show-k"})],a.prototype,"showK");u([l.property({type:Number,attribute:"intensity-k"})],a.prototype,"intensityK");u([l.property({attribute:"duotone-color"})],a.prototype,"duotoneColor");u([l.property({type:Number})],a.prototype,"angle");u([l.property({type:Number,attribute:"dot-offset-x"})],a.prototype,"dotOffsetX");u([l.property({type:Number,attribute:"dot-offset-y"})],a.prototype,"dotOffsetY");u([l.property({attribute:"bg-color"})],a.prototype,"bgColor");u([l.property({type:Number,attribute:"angle-warm"})],a.prototype,"angleWarm");u([l.property({type:Number,attribute:"angle-cool"})],a.prototype,"angleCool");u([l.property({type:Number,attribute:"show-warm"})],a.prototype,"showWarm");u([l.property({type:Number,attribute:"show-cool"})],a.prototype,"showCool");u([l.property({attribute:"warm-color"})],a.prototype,"warmColor");u([l.property({attribute:"cool-color"})],a.prototype,"coolColor");u([l.property({type:Number,attribute:"blend-mode"})],a.prototype,"blendMode");u([l.property({type:Number,attribute:"loading-blur"})],a.prototype,"loadingBlur");u([l.state()],a.prototype,"_webglAvailable");u([l.state()],a.prototype,"_snapshotUrl");u([l.state()],a.prototype,"_snapshotLoaded");customElements.get("some-shade-image")||customElements.define("some-shade-image",a);exports.SomeShadeImage=a;exports.get=U;exports.list=X;exports.register=p;
|
package/dist/some-shade.es.js
CHANGED
|
@@ -1,72 +1,72 @@
|
|
|
1
|
-
import { LitElement as
|
|
1
|
+
import { LitElement as k, css as D, html as y } from "lit";
|
|
2
2
|
import { property as u, state as w } from "lit/decorators.js";
|
|
3
|
-
function
|
|
4
|
-
return
|
|
3
|
+
function L(t) {
|
|
4
|
+
return t.getContext("webgl", {
|
|
5
5
|
alpha: !0,
|
|
6
6
|
premultipliedAlpha: !1,
|
|
7
7
|
preserveDrawingBuffer: !0
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
|
-
function T(
|
|
11
|
-
const
|
|
12
|
-
if (!
|
|
13
|
-
if (
|
|
14
|
-
const
|
|
15
|
-
throw
|
|
10
|
+
function T(t, o, n) {
|
|
11
|
+
const i = t.createShader(o);
|
|
12
|
+
if (!i) throw new Error("Failed to create shader");
|
|
13
|
+
if (t.shaderSource(i, n), t.compileShader(i), !t.getShaderParameter(i, t.COMPILE_STATUS)) {
|
|
14
|
+
const e = t.getShaderInfoLog(i);
|
|
15
|
+
throw t.deleteShader(i), new Error(`Shader compile error: ${e}`);
|
|
16
16
|
}
|
|
17
|
-
return
|
|
17
|
+
return i;
|
|
18
18
|
}
|
|
19
|
-
function z(
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
22
|
-
if (
|
|
23
|
-
const
|
|
24
|
-
throw
|
|
19
|
+
function z(t, o, n) {
|
|
20
|
+
const i = T(t, t.VERTEX_SHADER, o), e = T(t, t.FRAGMENT_SHADER, n), r = t.createProgram();
|
|
21
|
+
if (!r) throw new Error("Failed to create program");
|
|
22
|
+
if (t.attachShader(r, i), t.attachShader(r, e), t.linkProgram(r), !t.getProgramParameter(r, t.LINK_STATUS)) {
|
|
23
|
+
const d = t.getProgramInfoLog(r);
|
|
24
|
+
throw t.deleteProgram(r), new Error(`Program link error: ${d}`);
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
for (let
|
|
29
|
-
const f =
|
|
30
|
-
f &&
|
|
26
|
+
t.deleteShader(i), t.deleteShader(e);
|
|
27
|
+
const c = /* @__PURE__ */ new Map(), h = t.getProgramParameter(r, t.ACTIVE_ATTRIBUTES);
|
|
28
|
+
for (let d = 0; d < h; d++) {
|
|
29
|
+
const f = t.getActiveAttrib(r, d);
|
|
30
|
+
f && c.set(f.name, t.getAttribLocation(r, f.name));
|
|
31
31
|
}
|
|
32
|
-
const
|
|
33
|
-
for (let
|
|
34
|
-
const f =
|
|
32
|
+
const s = /* @__PURE__ */ new Map(), _ = t.getProgramParameter(r, t.ACTIVE_UNIFORMS);
|
|
33
|
+
for (let d = 0; d < _; d++) {
|
|
34
|
+
const f = t.getActiveUniform(r, d);
|
|
35
35
|
if (f) {
|
|
36
|
-
const m =
|
|
37
|
-
m &&
|
|
36
|
+
const m = t.getUniformLocation(r, f.name);
|
|
37
|
+
m && s.set(f.name, m);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
return { program:
|
|
40
|
+
return { program: r, attribLocations: c, uniformLocations: s };
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
for (const [
|
|
44
|
-
const
|
|
45
|
-
if (
|
|
46
|
-
if (typeof
|
|
47
|
-
|
|
48
|
-
else if (Array.isArray(
|
|
49
|
-
switch (
|
|
42
|
+
function M(t, o, n) {
|
|
43
|
+
for (const [i, e] of Object.entries(n)) {
|
|
44
|
+
const r = o.uniformLocations.get(i);
|
|
45
|
+
if (r) {
|
|
46
|
+
if (typeof e == "number")
|
|
47
|
+
t.uniform1f(r, e);
|
|
48
|
+
else if (Array.isArray(e))
|
|
49
|
+
switch (e.length) {
|
|
50
50
|
case 2:
|
|
51
|
-
|
|
51
|
+
t.uniform2fv(r, e);
|
|
52
52
|
break;
|
|
53
53
|
case 3:
|
|
54
|
-
|
|
54
|
+
t.uniform3fv(r, e);
|
|
55
55
|
break;
|
|
56
56
|
case 4:
|
|
57
|
-
|
|
57
|
+
t.uniform4fv(r, e);
|
|
58
58
|
break;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
|
-
function P(
|
|
64
|
-
const
|
|
65
|
-
if (!
|
|
66
|
-
return
|
|
63
|
+
function P(t, o) {
|
|
64
|
+
const n = t.createTexture();
|
|
65
|
+
if (!n) throw new Error("Failed to create texture");
|
|
66
|
+
return t.bindTexture(t.TEXTURE_2D, n), t.texImage2D(t.TEXTURE_2D, 0, t.RGBA, t.RGBA, t.UNSIGNED_BYTE, o), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_S, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_WRAP_T, t.CLAMP_TO_EDGE), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MIN_FILTER, t.LINEAR), t.texParameteri(t.TEXTURE_2D, t.TEXTURE_MAG_FILTER, t.LINEAR), { texture: n, width: o.naturalWidth, height: o.naturalHeight };
|
|
67
67
|
}
|
|
68
|
-
function
|
|
69
|
-
const
|
|
68
|
+
function O(t, o) {
|
|
69
|
+
const n = new Float32Array([
|
|
70
70
|
// pos.x pos.y tex.s tex.t
|
|
71
71
|
-1,
|
|
72
72
|
-1,
|
|
@@ -84,18 +84,18 @@ function M(e, o) {
|
|
|
84
84
|
1,
|
|
85
85
|
1,
|
|
86
86
|
0
|
|
87
|
-
]),
|
|
88
|
-
if (!
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
return
|
|
87
|
+
]), i = t.createBuffer();
|
|
88
|
+
if (!i) throw new Error("Failed to create buffer");
|
|
89
|
+
t.bindBuffer(t.ARRAY_BUFFER, i), t.bufferData(t.ARRAY_BUFFER, n, t.STATIC_DRAW);
|
|
90
|
+
const e = 4 * Float32Array.BYTES_PER_ELEMENT, r = o.attribLocations.get("a_position");
|
|
91
|
+
r !== void 0 && r !== -1 && (t.enableVertexAttribArray(r), t.vertexAttribPointer(r, 2, t.FLOAT, !1, e, 0));
|
|
92
|
+
const c = o.attribLocations.get("a_texCoord");
|
|
93
|
+
return c !== void 0 && c !== -1 && (t.enableVertexAttribArray(c), t.vertexAttribPointer(c, 2, t.FLOAT, !1, e, 2 * Float32Array.BYTES_PER_ELEMENT)), i;
|
|
94
94
|
}
|
|
95
|
-
function I(
|
|
96
|
-
|
|
95
|
+
function I(t) {
|
|
96
|
+
t.drawArrays(t.TRIANGLE_STRIP, 0, 4);
|
|
97
97
|
}
|
|
98
|
-
const
|
|
98
|
+
const V = `precision mediump float;
|
|
99
99
|
|
|
100
100
|
varying vec2 v_texCoord;
|
|
101
101
|
|
|
@@ -111,6 +111,7 @@ uniform float u_showC;
|
|
|
111
111
|
uniform float u_showM;
|
|
112
112
|
uniform float u_showY;
|
|
113
113
|
uniform float u_showK;
|
|
114
|
+
uniform float u_intensityK;
|
|
114
115
|
|
|
115
116
|
// Returns the texture-space UV of the cell center for a given rotation angle
|
|
116
117
|
vec2 cellCenterUV(vec2 uv, float angle) {
|
|
@@ -165,6 +166,7 @@ void main() {
|
|
|
165
166
|
float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
|
|
166
167
|
|
|
167
168
|
float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
|
|
169
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
168
170
|
|
|
169
171
|
// Compute halftone dots for each channel
|
|
170
172
|
float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
|
|
@@ -179,7 +181,7 @@ void main() {
|
|
|
179
181
|
|
|
180
182
|
gl_FragColor = vec4(outR, outG, outB, texture2D(u_image, v_texCoord).a);
|
|
181
183
|
}
|
|
182
|
-
`,
|
|
184
|
+
`, b = `attribute vec2 a_position;
|
|
183
185
|
attribute vec2 a_texCoord;
|
|
184
186
|
varying vec2 v_texCoord;
|
|
185
187
|
|
|
@@ -187,10 +189,10 @@ void main() {
|
|
|
187
189
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
188
190
|
v_texCoord = a_texCoord;
|
|
189
191
|
}
|
|
190
|
-
`,
|
|
192
|
+
`, W = {
|
|
191
193
|
name: "halftone-cmyk",
|
|
192
|
-
fragmentShader:
|
|
193
|
-
vertexShader:
|
|
194
|
+
fragmentShader: V,
|
|
195
|
+
vertexShader: b,
|
|
194
196
|
uniforms: [
|
|
195
197
|
{ name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
|
|
196
198
|
{ name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
|
|
@@ -201,9 +203,10 @@ void main() {
|
|
|
201
203
|
{ name: "u_showC", type: "float", default: 1, attribute: "show-c" },
|
|
202
204
|
{ name: "u_showM", type: "float", default: 1, attribute: "show-m" },
|
|
203
205
|
{ name: "u_showY", type: "float", default: 1, attribute: "show-y" },
|
|
204
|
-
{ name: "u_showK", type: "float", default: 1, attribute: "show-k" }
|
|
206
|
+
{ name: "u_showK", type: "float", default: 1, attribute: "show-k" },
|
|
207
|
+
{ name: "u_intensityK", type: "float", default: 1, attribute: "intensity-k" }
|
|
205
208
|
]
|
|
206
|
-
},
|
|
209
|
+
}, N = `precision mediump float;
|
|
207
210
|
|
|
208
211
|
varying vec2 v_texCoord;
|
|
209
212
|
|
|
@@ -245,17 +248,17 @@ void main() {
|
|
|
245
248
|
|
|
246
249
|
gl_FragColor = vec4(result, color.a);
|
|
247
250
|
}
|
|
248
|
-
`,
|
|
251
|
+
`, F = {
|
|
249
252
|
name: "halftone-duotone",
|
|
250
|
-
fragmentShader:
|
|
251
|
-
vertexShader:
|
|
253
|
+
fragmentShader: N,
|
|
254
|
+
vertexShader: b,
|
|
252
255
|
uniforms: [
|
|
253
256
|
{ name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
|
|
254
257
|
{ name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
|
|
255
258
|
{ name: "u_duotoneColor", type: "vec3", default: [0, 0.6, 0.8], attribute: "duotone-color" },
|
|
256
259
|
{ name: "u_angle", type: "float", default: 0, attribute: "angle" }
|
|
257
260
|
]
|
|
258
|
-
},
|
|
261
|
+
}, B = `precision mediump float;
|
|
259
262
|
|
|
260
263
|
varying vec2 v_texCoord;
|
|
261
264
|
|
|
@@ -311,10 +314,10 @@ void main() {
|
|
|
311
314
|
|
|
312
315
|
gl_FragColor = vec4(result, 1.0);
|
|
313
316
|
}
|
|
314
|
-
`,
|
|
317
|
+
`, Y = {
|
|
315
318
|
name: "dot-grid",
|
|
316
|
-
fragmentShader:
|
|
317
|
-
vertexShader:
|
|
319
|
+
fragmentShader: B,
|
|
320
|
+
vertexShader: b,
|
|
318
321
|
uniforms: [
|
|
319
322
|
{ name: "u_dotRadius", type: "float", default: 4, attribute: "dot-radius" },
|
|
320
323
|
{ name: "u_gridSize", type: "float", default: 8, attribute: "grid-size" },
|
|
@@ -322,7 +325,7 @@ void main() {
|
|
|
322
325
|
{ name: "u_bgColor", type: "vec3", default: [1, 1, 1], attribute: "bg-color" },
|
|
323
326
|
{ name: "u_angle", type: "float", default: 0, attribute: "angle" }
|
|
324
327
|
]
|
|
325
|
-
},
|
|
328
|
+
}, X = `precision mediump float;
|
|
326
329
|
|
|
327
330
|
varying vec2 v_texCoord;
|
|
328
331
|
|
|
@@ -338,6 +341,8 @@ uniform float u_showCool;
|
|
|
338
341
|
uniform float u_showK;
|
|
339
342
|
uniform vec3 u_warmColor;
|
|
340
343
|
uniform vec3 u_coolColor;
|
|
344
|
+
uniform float u_blendMode;
|
|
345
|
+
uniform float u_intensityK;
|
|
341
346
|
|
|
342
347
|
float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
|
|
343
348
|
float rad = radians(angle);
|
|
@@ -364,27 +369,52 @@ void main() {
|
|
|
364
369
|
|
|
365
370
|
// Black channel: derived from overall darkness
|
|
366
371
|
float k = 1.0 - max(warmSep, coolSep);
|
|
372
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
367
373
|
|
|
368
374
|
// Halftone dots for each channel
|
|
369
375
|
float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
|
|
370
376
|
float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
|
|
371
377
|
float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
|
|
372
378
|
|
|
373
|
-
//
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
379
|
+
// Blend modes affect how warm and cool dots combine where they overlap.
|
|
380
|
+
// All modes use white paper; individual dots look the same.
|
|
381
|
+
// Only the overlap regions differ between modes.
|
|
382
|
+
vec3 overlap;
|
|
383
|
+
if (u_blendMode < 0.5) {
|
|
384
|
+
// Subtractive: dye overlap absorbs more light (darker)
|
|
385
|
+
overlap = u_warmColor + u_coolColor - vec3(1.0);
|
|
386
|
+
} else if (u_blendMode < 1.5) {
|
|
387
|
+
// Additive: light overlap adds up (brighter)
|
|
388
|
+
overlap = u_warmColor + u_coolColor;
|
|
389
|
+
} else {
|
|
390
|
+
// Screen: soft additive overlap with natural clamping
|
|
391
|
+
overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Decompose into four halftone regions
|
|
395
|
+
float onlyWarm = warmDot * (1.0 - coolDot);
|
|
396
|
+
float onlyCool = coolDot * (1.0 - warmDot);
|
|
397
|
+
float both = warmDot * coolDot;
|
|
398
|
+
float neither = (1.0 - warmDot) * (1.0 - coolDot);
|
|
399
|
+
|
|
400
|
+
// Composite: white paper base, colored dots, blend-mode-dependent overlap
|
|
401
|
+
vec3 result = neither * vec3(1.0)
|
|
402
|
+
+ onlyWarm * u_warmColor
|
|
403
|
+
+ onlyCool * u_coolColor
|
|
404
|
+
+ both * overlap;
|
|
378
405
|
|
|
379
|
-
|
|
406
|
+
// K channel darkening with intensity control
|
|
407
|
+
result *= (1.0 - kDot);
|
|
408
|
+
|
|
409
|
+
gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
|
|
380
410
|
}
|
|
381
|
-
`,
|
|
411
|
+
`, $ = {
|
|
382
412
|
name: "technicolor-2strip",
|
|
383
|
-
fragmentShader:
|
|
384
|
-
vertexShader:
|
|
413
|
+
fragmentShader: X,
|
|
414
|
+
vertexShader: b,
|
|
385
415
|
uniforms: [
|
|
386
|
-
{ name: "u_dotRadius", type: "float", default:
|
|
387
|
-
{ name: "u_gridSize", type: "float", default:
|
|
416
|
+
{ name: "u_dotRadius", type: "float", default: 7, attribute: "dot-radius" },
|
|
417
|
+
{ name: "u_gridSize", type: "float", default: 10, attribute: "grid-size" },
|
|
388
418
|
{ name: "u_angleWarm", type: "float", default: 15, attribute: "angle-warm" },
|
|
389
419
|
{ name: "u_angleCool", type: "float", default: 75, attribute: "angle-cool" },
|
|
390
420
|
{ name: "u_angleK", type: "float", default: 45, attribute: "angle-k" },
|
|
@@ -392,31 +422,33 @@ void main() {
|
|
|
392
422
|
{ name: "u_showCool", type: "float", default: 1, attribute: "show-cool" },
|
|
393
423
|
{ name: "u_showK", type: "float", default: 1, attribute: "show-k" },
|
|
394
424
|
{ name: "u_warmColor", type: "vec3", default: [0.85, 0.25, 0.06], attribute: "warm-color" },
|
|
395
|
-
{ name: "u_coolColor", type: "vec3", default: [0.05, 0.65, 0.6], attribute: "cool-color" }
|
|
425
|
+
{ name: "u_coolColor", type: "vec3", default: [0.05, 0.65, 0.6], attribute: "cool-color" },
|
|
426
|
+
{ name: "u_blendMode", type: "float", default: 1, attribute: "blend-mode" },
|
|
427
|
+
{ name: "u_intensityK", type: "float", default: 1, attribute: "intensity-k" }
|
|
396
428
|
]
|
|
397
|
-
},
|
|
398
|
-
function
|
|
399
|
-
|
|
429
|
+
}, C = /* @__PURE__ */ new Map();
|
|
430
|
+
function v(t) {
|
|
431
|
+
C.set(t.name, t);
|
|
400
432
|
}
|
|
401
|
-
function
|
|
402
|
-
return
|
|
433
|
+
function G(t) {
|
|
434
|
+
return C.get(t);
|
|
403
435
|
}
|
|
404
436
|
function Z() {
|
|
405
|
-
return Array.from(
|
|
437
|
+
return Array.from(C.keys());
|
|
406
438
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
var H = Object.defineProperty, l = (
|
|
412
|
-
for (var
|
|
413
|
-
(
|
|
414
|
-
return
|
|
439
|
+
v(W);
|
|
440
|
+
v(F);
|
|
441
|
+
v(Y);
|
|
442
|
+
v($);
|
|
443
|
+
var H = Object.defineProperty, l = (t, o, n, i) => {
|
|
444
|
+
for (var e = void 0, r = t.length - 1, c; r >= 0; r--)
|
|
445
|
+
(c = t[r]) && (e = c(o, n, e) || e);
|
|
446
|
+
return e && H(o, n, e), e;
|
|
415
447
|
};
|
|
416
448
|
const q = 2;
|
|
417
449
|
let A = Promise.resolve();
|
|
418
|
-
function U(
|
|
419
|
-
const o = A.then(
|
|
450
|
+
function U(t) {
|
|
451
|
+
const o = A.then(t, t);
|
|
420
452
|
return A = o, o;
|
|
421
453
|
}
|
|
422
454
|
const j = /* @__PURE__ */ new Set([
|
|
@@ -431,6 +463,7 @@ const j = /* @__PURE__ */ new Set([
|
|
|
431
463
|
"showM",
|
|
432
464
|
"showY",
|
|
433
465
|
"showK",
|
|
466
|
+
"intensityK",
|
|
434
467
|
"duotoneColor",
|
|
435
468
|
"angle",
|
|
436
469
|
"dotOffsetX",
|
|
@@ -441,10 +474,11 @@ const j = /* @__PURE__ */ new Set([
|
|
|
441
474
|
"showWarm",
|
|
442
475
|
"showCool",
|
|
443
476
|
"warmColor",
|
|
444
|
-
"coolColor"
|
|
445
|
-
|
|
477
|
+
"coolColor",
|
|
478
|
+
"blendMode"
|
|
479
|
+
]), R = class R extends k {
|
|
446
480
|
constructor() {
|
|
447
|
-
super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.showC = 1, this.showM = 1, this.showY = 1, this.showK = 1, this.duotoneColor = "#0099cc", this.angle = 0, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this.angleWarm = 15, this.angleCool = 75, this.showWarm = 1, this.showCool = 1, this.warmColor = "#d94010", this.coolColor = "#0da699", this.
|
|
481
|
+
super(...arguments), this.src = "", this.effect = "halftone-cmyk", this.dotRadius = 4, this.gridSize = 8, this.angleC = 15, this.angleM = 75, this.angleY = 0, this.angleK = 45, this.showC = 1, this.showM = 1, this.showY = 1, this.showK = 1, this.intensityK = 1, this.duotoneColor = "#0099cc", this.angle = 0, this.dotOffsetX = 0.5, this.dotOffsetY = 0.5, this.bgColor = "#ffffff", this.angleWarm = 15, this.angleCool = 75, this.showWarm = 1, this.showCool = 1, this.warmColor = "#d94010", this.coolColor = "#0da699", this.blendMode = 1, this.loadingBlur = 0, this._webglAvailable = !0, this._snapshotUrl = "", this._snapshotLoaded = !1, this._image = null, this._observer = null, this._resizeObserver = null, this._lastClientWidth = 0, this._visible = !1, this._needsRender = !1;
|
|
448
482
|
}
|
|
449
483
|
render() {
|
|
450
484
|
if (!this._webglAvailable)
|
|
@@ -462,9 +496,9 @@ const j = /* @__PURE__ */ new Set([
|
|
|
462
496
|
connectedCallback() {
|
|
463
497
|
super.connectedCallback(), this._observer = new IntersectionObserver(
|
|
464
498
|
(o) => {
|
|
465
|
-
var
|
|
466
|
-
const
|
|
467
|
-
this._visible = ((
|
|
499
|
+
var i;
|
|
500
|
+
const n = this._visible;
|
|
501
|
+
this._visible = ((i = o[0]) == null ? void 0 : i.isIntersecting) ?? !1, this._visible && !n && this._needsRender && (this._needsRender = !1, U(() => this._renderEffect()));
|
|
468
502
|
},
|
|
469
503
|
// Start rendering slightly before the element scrolls into view.
|
|
470
504
|
{ rootMargin: "200px" }
|
|
@@ -481,23 +515,23 @@ const j = /* @__PURE__ */ new Set([
|
|
|
481
515
|
}
|
|
482
516
|
if (!this._image) return;
|
|
483
517
|
[...o.keys()].some(
|
|
484
|
-
(
|
|
485
|
-
) && this._scheduleRender()
|
|
518
|
+
(i) => j.has(i)
|
|
519
|
+
) && this._scheduleRender();
|
|
486
520
|
}
|
|
487
521
|
disconnectedCallback() {
|
|
488
|
-
var o,
|
|
489
|
-
super.disconnectedCallback(), (o = this._observer) == null || o.disconnect(), (
|
|
522
|
+
var o, n;
|
|
523
|
+
super.disconnectedCallback(), (o = this._observer) == null || o.disconnect(), (n = this._resizeObserver) == null || n.disconnect(), this._revokeSnapshot();
|
|
490
524
|
}
|
|
491
525
|
// ---------------------------------------------------------------------------
|
|
492
526
|
// Image loading
|
|
493
527
|
// ---------------------------------------------------------------------------
|
|
494
528
|
_loadImage(o) {
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
this._image =
|
|
498
|
-
},
|
|
529
|
+
const n = new Image();
|
|
530
|
+
n.crossOrigin = "anonymous", n.onload = () => {
|
|
531
|
+
this._image = n, this._scheduleRender();
|
|
532
|
+
}, n.onerror = () => {
|
|
499
533
|
console.warn(`[some-shade] Failed to load image: ${o}`);
|
|
500
|
-
},
|
|
534
|
+
}, n.src = o;
|
|
501
535
|
}
|
|
502
536
|
// ---------------------------------------------------------------------------
|
|
503
537
|
// Render scheduling
|
|
@@ -511,52 +545,52 @@ const j = /* @__PURE__ */ new Set([
|
|
|
511
545
|
async _renderEffect() {
|
|
512
546
|
var _;
|
|
513
547
|
if (!this._image) return;
|
|
514
|
-
const o =
|
|
548
|
+
const o = G(this.effect);
|
|
515
549
|
if (!o) {
|
|
516
550
|
console.warn(`[some-shade] Unknown effect: ${this.effect}`);
|
|
517
551
|
return;
|
|
518
552
|
}
|
|
519
|
-
const
|
|
553
|
+
const n = Math.min(window.devicePixelRatio || 1, q), i = this._image.naturalWidth, e = this._image.naturalHeight, r = this.clientWidth || i, c = Math.max(1, i / r);
|
|
520
554
|
this._lastClientWidth = this.clientWidth;
|
|
521
555
|
const h = document.createElement("canvas");
|
|
522
|
-
h.width =
|
|
523
|
-
const
|
|
524
|
-
if (!
|
|
556
|
+
h.width = i * n, h.height = e * n;
|
|
557
|
+
const s = L(h);
|
|
558
|
+
if (!s) {
|
|
525
559
|
this._webglAvailable = !1;
|
|
526
560
|
return;
|
|
527
561
|
}
|
|
528
562
|
try {
|
|
529
|
-
const
|
|
530
|
-
|
|
563
|
+
const d = z(
|
|
564
|
+
s,
|
|
531
565
|
o.vertexShader,
|
|
532
566
|
o.fragmentShader
|
|
533
567
|
);
|
|
534
|
-
|
|
535
|
-
const f = P(
|
|
536
|
-
|
|
537
|
-
const S =
|
|
538
|
-
S &&
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
this._getUniformValues(f,
|
|
542
|
-
),
|
|
543
|
-
const x = 4 * Float32Array.BYTES_PER_ELEMENT, g =
|
|
544
|
-
g !== void 0 && g !== -1 && (
|
|
545
|
-
const p =
|
|
546
|
-
p !== void 0 && p !== -1 && (
|
|
568
|
+
s.useProgram(d.program);
|
|
569
|
+
const f = P(s, this._image), m = O(s, d);
|
|
570
|
+
s.viewport(0, 0, h.width, h.height), s.clearColor(0, 0, 0, 0), s.clear(s.COLOR_BUFFER_BIT), s.activeTexture(s.TEXTURE0), s.bindTexture(s.TEXTURE_2D, f.texture);
|
|
571
|
+
const S = d.uniformLocations.get("u_image");
|
|
572
|
+
S && s.uniform1i(S, 0), M(
|
|
573
|
+
s,
|
|
574
|
+
d,
|
|
575
|
+
this._getUniformValues(f, n, c)
|
|
576
|
+
), s.bindBuffer(s.ARRAY_BUFFER, m);
|
|
577
|
+
const x = 4 * Float32Array.BYTES_PER_ELEMENT, g = d.attribLocations.get("a_position");
|
|
578
|
+
g !== void 0 && g !== -1 && (s.enableVertexAttribArray(g), s.vertexAttribPointer(g, 2, s.FLOAT, !1, x, 0));
|
|
579
|
+
const p = d.attribLocations.get("a_texCoord");
|
|
580
|
+
p !== void 0 && p !== -1 && (s.enableVertexAttribArray(p), s.vertexAttribPointer(
|
|
547
581
|
p,
|
|
548
582
|
2,
|
|
549
|
-
|
|
583
|
+
s.FLOAT,
|
|
550
584
|
!1,
|
|
551
585
|
x,
|
|
552
586
|
2 * Float32Array.BYTES_PER_ELEMENT
|
|
553
|
-
)), I(
|
|
587
|
+
)), I(s);
|
|
554
588
|
const E = await new Promise(
|
|
555
|
-
(
|
|
589
|
+
(K) => h.toBlob(K)
|
|
556
590
|
);
|
|
557
|
-
|
|
591
|
+
s.deleteTexture(f.texture), s.deleteProgram(d.program), s.deleteBuffer(m), E && (this._snapshotLoaded = !1, this._revokeSnapshot(), this._snapshotUrl = URL.createObjectURL(E));
|
|
558
592
|
} finally {
|
|
559
|
-
(_ =
|
|
593
|
+
(_ = s.getExtension("WEBGL_lose_context")) == null || _.loseContext();
|
|
560
594
|
}
|
|
561
595
|
}
|
|
562
596
|
// ---------------------------------------------------------------------------
|
|
@@ -577,45 +611,24 @@ const j = /* @__PURE__ */ new Set([
|
|
|
577
611
|
_revokeSnapshot() {
|
|
578
612
|
this._snapshotUrl && (URL.revokeObjectURL(this._snapshotUrl), this._snapshotUrl = "");
|
|
579
613
|
}
|
|
580
|
-
_getUniformValues(o,
|
|
581
|
-
const
|
|
582
|
-
return
|
|
583
|
-
o.width *
|
|
584
|
-
o.height *
|
|
585
|
-
],
|
|
586
|
-
}
|
|
587
|
-
_updateGateWeave() {
|
|
588
|
-
if (this._stopGateWeave(), this.gateWeave <= 0) {
|
|
589
|
-
const r = this.renderRoot.querySelector("img.snapshot");
|
|
590
|
-
r && (r.style.transform = "");
|
|
591
|
-
return;
|
|
592
|
-
}
|
|
593
|
-
const o = 1e3 / 12, a = (r) => {
|
|
594
|
-
if (r - this._gateWeaveTime >= o) {
|
|
595
|
-
this._gateWeaveTime = r;
|
|
596
|
-
const t = this.renderRoot.querySelector("img.snapshot");
|
|
597
|
-
if (t) {
|
|
598
|
-
const n = (Math.random() - 0.5) * 2 * this.gateWeave, d = (Math.random() - 0.5) * 2 * this.gateWeave, h = 1 + this.gateWeave * 3e-3;
|
|
599
|
-
t.style.transform = `translate(${n}px, ${d}px) scale(${h})`;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
this._gateWeaveRaf = requestAnimationFrame(a);
|
|
603
|
-
};
|
|
604
|
-
this._gateWeaveRaf = requestAnimationFrame(a);
|
|
605
|
-
}
|
|
606
|
-
_stopGateWeave() {
|
|
607
|
-
this._gateWeaveRaf && (cancelAnimationFrame(this._gateWeaveRaf), this._gateWeaveRaf = 0);
|
|
614
|
+
_getUniformValues(o, n, i) {
|
|
615
|
+
const e = {};
|
|
616
|
+
return e.u_resolution = [
|
|
617
|
+
o.width * n,
|
|
618
|
+
o.height * n
|
|
619
|
+
], e.u_dotRadius = this.dotRadius * i, e.u_gridSize = this.gridSize * i, this.effect === "halftone-cmyk" ? (e.u_angleC = this.angleC, e.u_angleM = this.angleM, e.u_angleY = this.angleY, e.u_angleK = this.angleK, e.u_showC = this.showC, e.u_showM = this.showM, e.u_showY = this.showY, e.u_showK = this.showK, e.u_intensityK = this.intensityK) : this.effect === "halftone-duotone" ? (e.u_duotoneColor = this._parseHexColor(this.duotoneColor), e.u_angle = this.angle) : this.effect === "dot-grid" ? (e.u_dotOffset = [this.dotOffsetX, this.dotOffsetY], e.u_bgColor = this._parseHexColor(this.bgColor), e.u_angle = this.angle) : this.effect === "technicolor-2strip" && (e.u_angleWarm = this.angleWarm, e.u_angleCool = this.angleCool, e.u_angleK = this.angleK, e.u_showWarm = this.showWarm, e.u_showCool = this.showCool, e.u_showK = this.showK, e.u_warmColor = this._parseHexColor(this.warmColor), e.u_coolColor = this._parseHexColor(this.coolColor), e.u_blendMode = this.blendMode, e.u_intensityK = this.intensityK), e;
|
|
608
620
|
}
|
|
609
621
|
_parseHexColor(o) {
|
|
610
|
-
const
|
|
611
|
-
return [
|
|
622
|
+
const n = o.replace("#", ""), i = parseInt(n.substring(0, 2), 16) / 255, e = parseInt(n.substring(2, 4), 16) / 255, r = parseInt(n.substring(4, 6), 16) / 255;
|
|
623
|
+
return [i, e, r];
|
|
612
624
|
}
|
|
613
625
|
};
|
|
614
|
-
|
|
626
|
+
R.styles = D`
|
|
615
627
|
:host {
|
|
616
628
|
display: block;
|
|
617
629
|
position: relative;
|
|
618
630
|
overflow: hidden;
|
|
631
|
+
max-width: 100%;
|
|
619
632
|
}
|
|
620
633
|
img {
|
|
621
634
|
display: block;
|
|
@@ -634,95 +647,98 @@ C.styles = k`
|
|
|
634
647
|
opacity: 1;
|
|
635
648
|
}
|
|
636
649
|
`;
|
|
637
|
-
let
|
|
650
|
+
let a = R;
|
|
638
651
|
l([
|
|
639
652
|
u()
|
|
640
|
-
],
|
|
653
|
+
], a.prototype, "src");
|
|
641
654
|
l([
|
|
642
655
|
u()
|
|
643
|
-
],
|
|
656
|
+
], a.prototype, "effect");
|
|
644
657
|
l([
|
|
645
658
|
u({ type: Number, attribute: "dot-radius" })
|
|
646
|
-
],
|
|
659
|
+
], a.prototype, "dotRadius");
|
|
647
660
|
l([
|
|
648
661
|
u({ type: Number, attribute: "grid-size" })
|
|
649
|
-
],
|
|
662
|
+
], a.prototype, "gridSize");
|
|
650
663
|
l([
|
|
651
664
|
u({ type: Number, attribute: "angle-c" })
|
|
652
|
-
],
|
|
665
|
+
], a.prototype, "angleC");
|
|
653
666
|
l([
|
|
654
667
|
u({ type: Number, attribute: "angle-m" })
|
|
655
|
-
],
|
|
668
|
+
], a.prototype, "angleM");
|
|
656
669
|
l([
|
|
657
670
|
u({ type: Number, attribute: "angle-y" })
|
|
658
|
-
],
|
|
671
|
+
], a.prototype, "angleY");
|
|
659
672
|
l([
|
|
660
673
|
u({ type: Number, attribute: "angle-k" })
|
|
661
|
-
],
|
|
674
|
+
], a.prototype, "angleK");
|
|
662
675
|
l([
|
|
663
676
|
u({ type: Number, attribute: "show-c" })
|
|
664
|
-
],
|
|
677
|
+
], a.prototype, "showC");
|
|
665
678
|
l([
|
|
666
679
|
u({ type: Number, attribute: "show-m" })
|
|
667
|
-
],
|
|
680
|
+
], a.prototype, "showM");
|
|
668
681
|
l([
|
|
669
682
|
u({ type: Number, attribute: "show-y" })
|
|
670
|
-
],
|
|
683
|
+
], a.prototype, "showY");
|
|
671
684
|
l([
|
|
672
685
|
u({ type: Number, attribute: "show-k" })
|
|
673
|
-
],
|
|
686
|
+
], a.prototype, "showK");
|
|
687
|
+
l([
|
|
688
|
+
u({ type: Number, attribute: "intensity-k" })
|
|
689
|
+
], a.prototype, "intensityK");
|
|
674
690
|
l([
|
|
675
691
|
u({ attribute: "duotone-color" })
|
|
676
|
-
],
|
|
692
|
+
], a.prototype, "duotoneColor");
|
|
677
693
|
l([
|
|
678
694
|
u({ type: Number })
|
|
679
|
-
],
|
|
695
|
+
], a.prototype, "angle");
|
|
680
696
|
l([
|
|
681
697
|
u({ type: Number, attribute: "dot-offset-x" })
|
|
682
|
-
],
|
|
698
|
+
], a.prototype, "dotOffsetX");
|
|
683
699
|
l([
|
|
684
700
|
u({ type: Number, attribute: "dot-offset-y" })
|
|
685
|
-
],
|
|
701
|
+
], a.prototype, "dotOffsetY");
|
|
686
702
|
l([
|
|
687
703
|
u({ attribute: "bg-color" })
|
|
688
|
-
],
|
|
704
|
+
], a.prototype, "bgColor");
|
|
689
705
|
l([
|
|
690
706
|
u({ type: Number, attribute: "angle-warm" })
|
|
691
|
-
],
|
|
707
|
+
], a.prototype, "angleWarm");
|
|
692
708
|
l([
|
|
693
709
|
u({ type: Number, attribute: "angle-cool" })
|
|
694
|
-
],
|
|
710
|
+
], a.prototype, "angleCool");
|
|
695
711
|
l([
|
|
696
712
|
u({ type: Number, attribute: "show-warm" })
|
|
697
|
-
],
|
|
713
|
+
], a.prototype, "showWarm");
|
|
698
714
|
l([
|
|
699
715
|
u({ type: Number, attribute: "show-cool" })
|
|
700
|
-
],
|
|
716
|
+
], a.prototype, "showCool");
|
|
701
717
|
l([
|
|
702
718
|
u({ attribute: "warm-color" })
|
|
703
|
-
],
|
|
719
|
+
], a.prototype, "warmColor");
|
|
704
720
|
l([
|
|
705
721
|
u({ attribute: "cool-color" })
|
|
706
|
-
],
|
|
722
|
+
], a.prototype, "coolColor");
|
|
707
723
|
l([
|
|
708
|
-
u({ type: Number, attribute: "
|
|
709
|
-
],
|
|
724
|
+
u({ type: Number, attribute: "blend-mode" })
|
|
725
|
+
], a.prototype, "blendMode");
|
|
710
726
|
l([
|
|
711
727
|
u({ type: Number, attribute: "loading-blur" })
|
|
712
|
-
],
|
|
728
|
+
], a.prototype, "loadingBlur");
|
|
713
729
|
l([
|
|
714
730
|
w()
|
|
715
|
-
],
|
|
731
|
+
], a.prototype, "_webglAvailable");
|
|
716
732
|
l([
|
|
717
733
|
w()
|
|
718
|
-
],
|
|
734
|
+
], a.prototype, "_snapshotUrl");
|
|
719
735
|
l([
|
|
720
736
|
w()
|
|
721
|
-
],
|
|
722
|
-
customElements.get("some-shade-image") || customElements.define("some-shade-image",
|
|
737
|
+
], a.prototype, "_snapshotLoaded");
|
|
738
|
+
customElements.get("some-shade-image") || customElements.define("some-shade-image", a);
|
|
723
739
|
export {
|
|
724
|
-
|
|
725
|
-
|
|
740
|
+
a as SomeShadeImage,
|
|
741
|
+
G as get,
|
|
726
742
|
Z as list,
|
|
727
|
-
|
|
743
|
+
v as register
|
|
728
744
|
};
|
package/dist/some-shade.umd.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
(function(c,
|
|
1
|
+
(function(c,m){typeof exports=="object"&&typeof module<"u"?m(exports,require("lit"),require("lit/decorators.js")):typeof define=="function"&&define.amd?define(["exports","lit","lit/decorators.js"],m):(c=typeof globalThis<"u"?globalThis:c||self,m(c.SomeShade={},c.Lit,c.LitDecorators))})(this,(function(c,m,l){"use strict";function k(e){return e.getContext("webgl",{alpha:!0,premultipliedAlpha:!1,preserveDrawingBuffer:!0})}function S(e,o,n){const i=e.createShader(o);if(!i)throw new Error("Failed to create shader");if(e.shaderSource(i,n),e.compileShader(i),!e.getShaderParameter(i,e.COMPILE_STATUS)){const t=e.getShaderInfoLog(i);throw e.deleteShader(i),new Error(`Shader compile error: ${t}`)}return i}function D(e,o,n){const i=S(e,e.VERTEX_SHADER,o),t=S(e,e.FRAGMENT_SHADER,n),a=e.createProgram();if(!a)throw new Error("Failed to create program");if(e.attachShader(a,i),e.attachShader(a,t),e.linkProgram(a),!e.getProgramParameter(a,e.LINK_STATUS)){const d=e.getProgramInfoLog(a);throw e.deleteProgram(a),new Error(`Program link error: ${d}`)}e.deleteShader(i),e.deleteShader(t);const f=new Map,p=e.getProgramParameter(a,e.ACTIVE_ATTRIBUTES);for(let d=0;d<p;d++){const h=e.getActiveAttrib(a,d);h&&f.set(h.name,e.getAttribLocation(a,h.name))}const s=new Map,v=e.getProgramParameter(a,e.ACTIVE_UNIFORMS);for(let d=0;d<v;d++){const h=e.getActiveUniform(a,d);if(h){const g=e.getUniformLocation(a,h.name);g&&s.set(h.name,g)}}return{program:a,attribLocations:f,uniformLocations:s}}function L(e,o,n){for(const[i,t]of Object.entries(n)){const a=o.uniformLocations.get(i);if(a){if(typeof t=="number")e.uniform1f(a,t);else if(Array.isArray(t))switch(t.length){case 2:e.uniform2fv(a,t);break;case 3:e.uniform3fv(a,t);break;case 4:e.uniform4fv(a,t);break}}}}function z(e,o){const n=e.createTexture();if(!n)throw new Error("Failed to create texture");return e.bindTexture(e.TEXTURE_2D,n),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,e.RGBA,e.UNSIGNED_BYTE,o),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),{texture:n,width:o.naturalWidth,height:o.naturalHeight}}function M(e,o){const n=new Float32Array([-1,-1,0,1,1,-1,1,1,-1,1,0,0,1,1,1,0]),i=e.createBuffer();if(!i)throw new Error("Failed to create buffer");e.bindBuffer(e.ARRAY_BUFFER,i),e.bufferData(e.ARRAY_BUFFER,n,e.STATIC_DRAW);const t=4*Float32Array.BYTES_PER_ELEMENT,a=o.attribLocations.get("a_position");a!==void 0&&a!==-1&&(e.enableVertexAttribArray(a),e.vertexAttribPointer(a,2,e.FLOAT,!1,t,0));const f=o.attribLocations.get("a_texCoord");return f!==void 0&&f!==-1&&(e.enableVertexAttribArray(f),e.vertexAttribPointer(f,2,e.FLOAT,!1,t,2*Float32Array.BYTES_PER_ELEMENT)),i}function P(e){e.drawArrays(e.TRIANGLE_STRIP,0,4)}const O=`precision mediump float;
|
|
2
2
|
|
|
3
3
|
varying vec2 v_texCoord;
|
|
4
4
|
|
|
@@ -14,6 +14,7 @@ uniform float u_showC;
|
|
|
14
14
|
uniform float u_showM;
|
|
15
15
|
uniform float u_showY;
|
|
16
16
|
uniform float u_showK;
|
|
17
|
+
uniform float u_intensityK;
|
|
17
18
|
|
|
18
19
|
// Returns the texture-space UV of the cell center for a given rotation angle
|
|
19
20
|
vec2 cellCenterUV(vec2 uv, float angle) {
|
|
@@ -68,6 +69,7 @@ void main() {
|
|
|
68
69
|
float ye = yInvK > 0.001 ? (yInvK - yRgb.b) / yInvK : 0.0;
|
|
69
70
|
|
|
70
71
|
float k = 1.0 - max(max(kRgb.r, kRgb.g), kRgb.b);
|
|
72
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
71
73
|
|
|
72
74
|
// Compute halftone dots for each channel
|
|
73
75
|
float cDot = halftone(uv, u_angleC, cy, u_gridSize, u_dotRadius) * u_showC;
|
|
@@ -82,7 +84,7 @@ void main() {
|
|
|
82
84
|
|
|
83
85
|
gl_FragColor = vec4(outR, outG, outB, texture2D(u_image, v_texCoord).a);
|
|
84
86
|
}
|
|
85
|
-
`,
|
|
87
|
+
`,b=`attribute vec2 a_position;
|
|
86
88
|
attribute vec2 a_texCoord;
|
|
87
89
|
varying vec2 v_texCoord;
|
|
88
90
|
|
|
@@ -90,7 +92,7 @@ void main() {
|
|
|
90
92
|
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
91
93
|
v_texCoord = a_texCoord;
|
|
92
94
|
}
|
|
93
|
-
`,I={name:"halftone-cmyk",fragmentShader:
|
|
95
|
+
`,I={name:"halftone-cmyk",fragmentShader:O,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_angleC",type:"float",default:15,attribute:"angle-c"},{name:"u_angleM",type:"float",default:75,attribute:"angle-m"},{name:"u_angleY",type:"float",default:0,attribute:"angle-y"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showC",type:"float",default:1,attribute:"show-c"},{name:"u_showM",type:"float",default:1,attribute:"show-m"},{name:"u_showY",type:"float",default:1,attribute:"show-y"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},V={name:"halftone-duotone",fragmentShader:`precision mediump float;
|
|
94
96
|
|
|
95
97
|
varying vec2 v_texCoord;
|
|
96
98
|
|
|
@@ -132,7 +134,7 @@ void main() {
|
|
|
132
134
|
|
|
133
135
|
gl_FragColor = vec4(result, color.a);
|
|
134
136
|
}
|
|
135
|
-
`,vertexShader:
|
|
137
|
+
`,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_duotoneColor",type:"vec3",default:[0,.6,.8],attribute:"duotone-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},W={name:"dot-grid",fragmentShader:`precision mediump float;
|
|
136
138
|
|
|
137
139
|
varying vec2 v_texCoord;
|
|
138
140
|
|
|
@@ -188,7 +190,7 @@ void main() {
|
|
|
188
190
|
|
|
189
191
|
gl_FragColor = vec4(result, 1.0);
|
|
190
192
|
}
|
|
191
|
-
`,vertexShader:
|
|
193
|
+
`,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:4,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:8,attribute:"grid-size"},{name:"u_dotOffset",type:"vec2",default:[.5,.5],attribute:"dot-offset"},{name:"u_bgColor",type:"vec3",default:[1,1,1],attribute:"bg-color"},{name:"u_angle",type:"float",default:0,attribute:"angle"}]},N={name:"technicolor-2strip",fragmentShader:`precision mediump float;
|
|
192
194
|
|
|
193
195
|
varying vec2 v_texCoord;
|
|
194
196
|
|
|
@@ -204,6 +206,8 @@ uniform float u_showCool;
|
|
|
204
206
|
uniform float u_showK;
|
|
205
207
|
uniform vec3 u_warmColor;
|
|
206
208
|
uniform vec3 u_coolColor;
|
|
209
|
+
uniform float u_blendMode;
|
|
210
|
+
uniform float u_intensityK;
|
|
207
211
|
|
|
208
212
|
float halftone(vec2 uv, float angle, float channelValue, float gridSize, float dotRadius) {
|
|
209
213
|
float rad = radians(angle);
|
|
@@ -230,32 +234,58 @@ void main() {
|
|
|
230
234
|
|
|
231
235
|
// Black channel: derived from overall darkness
|
|
232
236
|
float k = 1.0 - max(warmSep, coolSep);
|
|
237
|
+
k = clamp(k * u_intensityK, 0.0, 1.0);
|
|
233
238
|
|
|
234
239
|
// Halftone dots for each channel
|
|
235
240
|
float warmDot = halftone(uv, u_angleWarm, warmSep, u_gridSize, u_dotRadius) * u_showWarm;
|
|
236
241
|
float coolDot = halftone(uv, u_angleCool, coolSep, u_gridSize, u_dotRadius) * u_showCool;
|
|
237
242
|
float kDot = halftone(uv, u_angleK, k, u_gridSize, u_dotRadius) * u_showK;
|
|
238
243
|
|
|
239
|
-
//
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
+
// Blend modes affect how warm and cool dots combine where they overlap.
|
|
245
|
+
// All modes use white paper; individual dots look the same.
|
|
246
|
+
// Only the overlap regions differ between modes.
|
|
247
|
+
vec3 overlap;
|
|
248
|
+
if (u_blendMode < 0.5) {
|
|
249
|
+
// Subtractive: dye overlap absorbs more light (darker)
|
|
250
|
+
overlap = u_warmColor + u_coolColor - vec3(1.0);
|
|
251
|
+
} else if (u_blendMode < 1.5) {
|
|
252
|
+
// Additive: light overlap adds up (brighter)
|
|
253
|
+
overlap = u_warmColor + u_coolColor;
|
|
254
|
+
} else {
|
|
255
|
+
// Screen: soft additive overlap with natural clamping
|
|
256
|
+
overlap = vec3(1.0) - (vec3(1.0) - u_warmColor) * (vec3(1.0) - u_coolColor);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Decompose into four halftone regions
|
|
260
|
+
float onlyWarm = warmDot * (1.0 - coolDot);
|
|
261
|
+
float onlyCool = coolDot * (1.0 - warmDot);
|
|
262
|
+
float both = warmDot * coolDot;
|
|
263
|
+
float neither = (1.0 - warmDot) * (1.0 - coolDot);
|
|
264
|
+
|
|
265
|
+
// Composite: white paper base, colored dots, blend-mode-dependent overlap
|
|
266
|
+
vec3 result = neither * vec3(1.0)
|
|
267
|
+
+ onlyWarm * u_warmColor
|
|
268
|
+
+ onlyCool * u_coolColor
|
|
269
|
+
+ both * overlap;
|
|
270
|
+
|
|
271
|
+
// K channel darkening with intensity control
|
|
272
|
+
result *= (1.0 - kDot);
|
|
244
273
|
|
|
245
|
-
gl_FragColor = vec4(clamp(
|
|
274
|
+
gl_FragColor = vec4(clamp(result, 0.0, 1.0), color.a);
|
|
246
275
|
}
|
|
247
|
-
`,vertexShader:
|
|
276
|
+
`,vertexShader:b,uniforms:[{name:"u_dotRadius",type:"float",default:7,attribute:"dot-radius"},{name:"u_gridSize",type:"float",default:10,attribute:"grid-size"},{name:"u_angleWarm",type:"float",default:15,attribute:"angle-warm"},{name:"u_angleCool",type:"float",default:75,attribute:"angle-cool"},{name:"u_angleK",type:"float",default:45,attribute:"angle-k"},{name:"u_showWarm",type:"float",default:1,attribute:"show-warm"},{name:"u_showCool",type:"float",default:1,attribute:"show-cool"},{name:"u_showK",type:"float",default:1,attribute:"show-k"},{name:"u_warmColor",type:"vec3",default:[.85,.25,.06],attribute:"warm-color"},{name:"u_coolColor",type:"vec3",default:[.05,.65,.6],attribute:"cool-color"},{name:"u_blendMode",type:"float",default:1,attribute:"blend-mode"},{name:"u_intensityK",type:"float",default:1,attribute:"intensity-k"}]},C=new Map;function _(e){C.set(e.name,e)}function x(e){return C.get(e)}function F(){return Array.from(C.keys())}_(I),_(V),_(W),_(N);var B=Object.defineProperty,u=(e,o,n,i)=>{for(var t=void 0,a=e.length-1,f;a>=0;a--)(f=e[a])&&(t=f(o,n,t)||t);return t&&B(o,n,t),t};const Y=2;let E=Promise.resolve();function T(e){const o=E.then(e,e);return E=o,o}const X=new Set(["effect","dotRadius","gridSize","angleC","angleM","angleY","angleK","showC","showM","showY","showK","intensityK","duotoneColor","angle","dotOffsetX","dotOffsetY","bgColor","angleWarm","angleCool","showWarm","showCool","warmColor","coolColor","blendMode"]),R=class R extends m.LitElement{constructor(){super(...arguments),this.src="",this.effect="halftone-cmyk",this.dotRadius=4,this.gridSize=8,this.angleC=15,this.angleM=75,this.angleY=0,this.angleK=45,this.showC=1,this.showM=1,this.showY=1,this.showK=1,this.intensityK=1,this.duotoneColor="#0099cc",this.angle=0,this.dotOffsetX=.5,this.dotOffsetY=.5,this.bgColor="#ffffff",this.angleWarm=15,this.angleCool=75,this.showWarm=1,this.showCool=1,this.warmColor="#d94010",this.coolColor="#0da699",this.blendMode=1,this.loadingBlur=0,this._webglAvailable=!0,this._snapshotUrl="",this._snapshotLoaded=!1,this._image=null,this._observer=null,this._resizeObserver=null,this._lastClientWidth=0,this._visible=!1,this._needsRender=!1}render(){if(!this._webglAvailable)return m.html`<img src=${this.src} alt="" />`;const o=this.loadingBlur>0?`filter: blur(${this.loadingBlur}px)`:"";return m.html`
|
|
248
277
|
<img src=${this.src} alt="" style=${o} />
|
|
249
|
-
${this._snapshotUrl?
|
|
278
|
+
${this._snapshotUrl?m.html`<img
|
|
250
279
|
class="snapshot${this._snapshotLoaded?" loaded":""}"
|
|
251
280
|
src=${this._snapshotUrl}
|
|
252
281
|
@load=${this._onSnapshotLoad}
|
|
253
282
|
alt="" />`:""}
|
|
254
|
-
`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var
|
|
283
|
+
`}connectedCallback(){super.connectedCallback(),this._observer=new IntersectionObserver(o=>{var i;const n=this._visible;this._visible=((i=o[0])==null?void 0:i.isIntersecting)??!1,this._visible&&!n&&this._needsRender&&(this._needsRender=!1,T(()=>this._renderEffect()))},{rootMargin:"200px"}),this._observer.observe(this),this._resizeObserver=new ResizeObserver(()=>{if(!this._image)return;const o=this.clientWidth;o>0&&o!==this._lastClientWidth&&(this._lastClientWidth=o,this._scheduleRender())}),this._resizeObserver.observe(this)}updated(o){if(o.has("src")&&this.src){this._loadImage(this.src);return}if(!this._image)return;[...o.keys()].some(i=>X.has(i))&&this._scheduleRender()}disconnectedCallback(){var o,n;super.disconnectedCallback(),(o=this._observer)==null||o.disconnect(),(n=this._resizeObserver)==null||n.disconnect(),this._revokeSnapshot()}_loadImage(o){const n=new Image;n.crossOrigin="anonymous",n.onload=()=>{this._image=n,this._scheduleRender()},n.onerror=()=>{console.warn(`[some-shade] Failed to load image: ${o}`)},n.src=o}_scheduleRender(){this._visible?T(()=>this._renderEffect()):this._needsRender=!0}async _renderEffect(){var v;if(!this._image)return;const o=x(this.effect);if(!o){console.warn(`[some-shade] Unknown effect: ${this.effect}`);return}const n=Math.min(window.devicePixelRatio||1,Y),i=this._image.naturalWidth,t=this._image.naturalHeight,a=this.clientWidth||i,f=Math.max(1,i/a);this._lastClientWidth=this.clientWidth;const p=document.createElement("canvas");p.width=i*n,p.height=t*n;const s=k(p);if(!s){this._webglAvailable=!1;return}try{const d=D(s,o.vertexShader,o.fragmentShader);s.useProgram(d.program);const h=z(s,this._image),g=M(s,d);s.viewport(0,0,p.width,p.height),s.clearColor(0,0,0,0),s.clear(s.COLOR_BUFFER_BIT),s.activeTexture(s.TEXTURE0),s.bindTexture(s.TEXTURE_2D,h.texture);const A=d.uniformLocations.get("u_image");A&&s.uniform1i(A,0),L(s,d,this._getUniformValues(h,n,f)),s.bindBuffer(s.ARRAY_BUFFER,g);const U=4*Float32Array.BYTES_PER_ELEMENT,y=d.attribLocations.get("a_position");y!==void 0&&y!==-1&&(s.enableVertexAttribArray(y),s.vertexAttribPointer(y,2,s.FLOAT,!1,U,0));const w=d.attribLocations.get("a_texCoord");w!==void 0&&w!==-1&&(s.enableVertexAttribArray(w),s.vertexAttribPointer(w,2,s.FLOAT,!1,U,2*Float32Array.BYTES_PER_ELEMENT)),P(s);const K=await new Promise($=>p.toBlob($));s.deleteTexture(h.texture),s.deleteProgram(d.program),s.deleteBuffer(g),K&&(this._snapshotLoaded=!1,this._revokeSnapshot(),this._snapshotUrl=URL.createObjectURL(K))}finally{(v=s.getExtension("WEBGL_lose_context"))==null||v.loseContext()}}_onSnapshotLoad(){this._snapshotLoaded=!0}replayTransition(o=500){this._snapshotUrl&&(this._snapshotLoaded=!1,this.updateComplete.then(()=>{setTimeout(()=>{this._snapshotLoaded=!0},o)}))}_revokeSnapshot(){this._snapshotUrl&&(URL.revokeObjectURL(this._snapshotUrl),this._snapshotUrl="")}_getUniformValues(o,n,i){const t={};return t.u_resolution=[o.width*n,o.height*n],t.u_dotRadius=this.dotRadius*i,t.u_gridSize=this.gridSize*i,this.effect==="halftone-cmyk"?(t.u_angleC=this.angleC,t.u_angleM=this.angleM,t.u_angleY=this.angleY,t.u_angleK=this.angleK,t.u_showC=this.showC,t.u_showM=this.showM,t.u_showY=this.showY,t.u_showK=this.showK,t.u_intensityK=this.intensityK):this.effect==="halftone-duotone"?(t.u_duotoneColor=this._parseHexColor(this.duotoneColor),t.u_angle=this.angle):this.effect==="dot-grid"?(t.u_dotOffset=[this.dotOffsetX,this.dotOffsetY],t.u_bgColor=this._parseHexColor(this.bgColor),t.u_angle=this.angle):this.effect==="technicolor-2strip"&&(t.u_angleWarm=this.angleWarm,t.u_angleCool=this.angleCool,t.u_angleK=this.angleK,t.u_showWarm=this.showWarm,t.u_showCool=this.showCool,t.u_showK=this.showK,t.u_warmColor=this._parseHexColor(this.warmColor),t.u_coolColor=this._parseHexColor(this.coolColor),t.u_blendMode=this.blendMode,t.u_intensityK=this.intensityK),t}_parseHexColor(o){const n=o.replace("#",""),i=parseInt(n.substring(0,2),16)/255,t=parseInt(n.substring(2,4),16)/255,a=parseInt(n.substring(4,6),16)/255;return[i,t,a]}};R.styles=m.css`
|
|
255
284
|
:host {
|
|
256
285
|
display: block;
|
|
257
286
|
position: relative;
|
|
258
287
|
overflow: hidden;
|
|
288
|
+
max-width: 100%;
|
|
259
289
|
}
|
|
260
290
|
img {
|
|
261
291
|
display: block;
|
|
@@ -273,4 +303,4 @@ void main() {
|
|
|
273
303
|
img.snapshot.loaded {
|
|
274
304
|
opacity: 1;
|
|
275
305
|
}
|
|
276
|
-
`;let
|
|
306
|
+
`;let r=R;u([l.property()],r.prototype,"src"),u([l.property()],r.prototype,"effect"),u([l.property({type:Number,attribute:"dot-radius"})],r.prototype,"dotRadius"),u([l.property({type:Number,attribute:"grid-size"})],r.prototype,"gridSize"),u([l.property({type:Number,attribute:"angle-c"})],r.prototype,"angleC"),u([l.property({type:Number,attribute:"angle-m"})],r.prototype,"angleM"),u([l.property({type:Number,attribute:"angle-y"})],r.prototype,"angleY"),u([l.property({type:Number,attribute:"angle-k"})],r.prototype,"angleK"),u([l.property({type:Number,attribute:"show-c"})],r.prototype,"showC"),u([l.property({type:Number,attribute:"show-m"})],r.prototype,"showM"),u([l.property({type:Number,attribute:"show-y"})],r.prototype,"showY"),u([l.property({type:Number,attribute:"show-k"})],r.prototype,"showK"),u([l.property({type:Number,attribute:"intensity-k"})],r.prototype,"intensityK"),u([l.property({attribute:"duotone-color"})],r.prototype,"duotoneColor"),u([l.property({type:Number})],r.prototype,"angle"),u([l.property({type:Number,attribute:"dot-offset-x"})],r.prototype,"dotOffsetX"),u([l.property({type:Number,attribute:"dot-offset-y"})],r.prototype,"dotOffsetY"),u([l.property({attribute:"bg-color"})],r.prototype,"bgColor"),u([l.property({type:Number,attribute:"angle-warm"})],r.prototype,"angleWarm"),u([l.property({type:Number,attribute:"angle-cool"})],r.prototype,"angleCool"),u([l.property({type:Number,attribute:"show-warm"})],r.prototype,"showWarm"),u([l.property({type:Number,attribute:"show-cool"})],r.prototype,"showCool"),u([l.property({attribute:"warm-color"})],r.prototype,"warmColor"),u([l.property({attribute:"cool-color"})],r.prototype,"coolColor"),u([l.property({type:Number,attribute:"blend-mode"})],r.prototype,"blendMode"),u([l.property({type:Number,attribute:"loading-blur"})],r.prototype,"loadingBlur"),u([l.state()],r.prototype,"_webglAvailable"),u([l.state()],r.prototype,"_snapshotUrl"),u([l.state()],r.prototype,"_snapshotLoaded"),customElements.get("some-shade-image")||customElements.define("some-shade-image",r),c.SomeShadeImage=r,c.get=x,c.list=F,c.register=_,Object.defineProperty(c,Symbol.toStringTag,{value:"Module"})}));
|
package/package.json
CHANGED
package/dist/index.d.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { CSSResult } from 'lit';
|
|
2
|
-
import { LitElement } from 'lit';
|
|
3
|
-
import { PropertyValues } from 'lit';
|
|
4
|
-
import { TemplateResult } from 'lit';
|
|
5
|
-
|
|
6
|
-
export declare interface EffectDefinition {
|
|
7
|
-
name: string;
|
|
8
|
-
fragmentShader: string;
|
|
9
|
-
vertexShader: string;
|
|
10
|
-
uniforms: UniformDefinition[];
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export declare function get(name: string): EffectDefinition | undefined;
|
|
14
|
-
|
|
15
|
-
export declare function list(): string[];
|
|
16
|
-
|
|
17
|
-
export declare function register(effect: EffectDefinition): void;
|
|
18
|
-
|
|
19
|
-
export declare class SomeShadeImage extends LitElement {
|
|
20
|
-
static styles: CSSResult;
|
|
21
|
-
src: string;
|
|
22
|
-
effect: string;
|
|
23
|
-
dotRadius: number;
|
|
24
|
-
gridSize: number;
|
|
25
|
-
angleC: number;
|
|
26
|
-
angleM: number;
|
|
27
|
-
angleY: number;
|
|
28
|
-
angleK: number;
|
|
29
|
-
showC: number;
|
|
30
|
-
showM: number;
|
|
31
|
-
showY: number;
|
|
32
|
-
showK: number;
|
|
33
|
-
duotoneColor: string;
|
|
34
|
-
angle: number;
|
|
35
|
-
dotOffsetX: number;
|
|
36
|
-
dotOffsetY: number;
|
|
37
|
-
bgColor: string;
|
|
38
|
-
angleWarm: number;
|
|
39
|
-
angleCool: number;
|
|
40
|
-
showWarm: number;
|
|
41
|
-
showCool: number;
|
|
42
|
-
warmColor: string;
|
|
43
|
-
coolColor: string;
|
|
44
|
-
gateWeave: number;
|
|
45
|
-
loadingBlur: number;
|
|
46
|
-
private _webglAvailable;
|
|
47
|
-
private _snapshotUrl;
|
|
48
|
-
private _snapshotLoaded;
|
|
49
|
-
private _image;
|
|
50
|
-
private _observer;
|
|
51
|
-
private _resizeObserver;
|
|
52
|
-
private _lastClientWidth;
|
|
53
|
-
private _visible;
|
|
54
|
-
private _needsRender;
|
|
55
|
-
private _gateWeaveRaf;
|
|
56
|
-
private _gateWeaveTime;
|
|
57
|
-
render(): TemplateResult<1>;
|
|
58
|
-
connectedCallback(): void;
|
|
59
|
-
updated(changed: PropertyValues): void;
|
|
60
|
-
disconnectedCallback(): void;
|
|
61
|
-
private _loadImage;
|
|
62
|
-
private _scheduleRender;
|
|
63
|
-
private _renderEffect;
|
|
64
|
-
private _onSnapshotLoad;
|
|
65
|
-
/** Hide the rendered snapshot momentarily, then fade it back in.
|
|
66
|
-
* Useful for previewing the loading-blur transition. */
|
|
67
|
-
replayTransition(delay?: number): void;
|
|
68
|
-
private _revokeSnapshot;
|
|
69
|
-
private _getUniformValues;
|
|
70
|
-
private _updateGateWeave;
|
|
71
|
-
private _stopGateWeave;
|
|
72
|
-
private _parseHexColor;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export declare interface UniformDefinition {
|
|
76
|
-
name: string;
|
|
77
|
-
type: 'float' | 'vec2' | 'vec3' | 'vec4';
|
|
78
|
-
default: number | number[];
|
|
79
|
-
attribute?: string;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export { }
|