mirror of
https://github.com/billsonnn/nitro-renderer.git
synced 2025-02-07 22:32:35 +01:00
5201 lines
1.7 MiB
JavaScript
5201 lines
1.7 MiB
JavaScript
|
"use strict";var B=(i=>(i.Application="application",i.WebGLPipes="webgl-pipes",i.WebGLPipesAdaptor="webgl-pipes-adaptor",i.WebGLSystem="webgl-system",i.WebGPUPipes="webgpu-pipes",i.WebGPUPipesAdaptor="webgpu-pipes-adaptor",i.WebGPUSystem="webgpu-system",i.CanvasSystem="canvas-system",i.CanvasPipesAdaptor="canvas-pipes-adaptor",i.CanvasPipes="canvas-pipes",i.Asset="asset",i.LoadParser="load-parser",i.ResolveParser="resolve-parser",i.CacheParser="cache-parser",i.DetectionParser="detection-parser",i.MaskEffect="mask-effect",i.BlendMode="blend-mode",i.TextureSource="texture-source",i.Environment="environment",i.ShapeBuilder="shape-builder",i.Batcher="batcher",i))(B||{});const tT=i=>{if(typeof i=="function"||typeof i=="object"&&i.extension){if(!i.extension)throw new Error("Extension class must have an extension object");i={...typeof i.extension!="object"?{type:i.extension}:i.extension,ref:i}}if(typeof i=="object")i={...i};else throw new Error("Invalid extension type");return typeof i.type=="string"&&(i.type=[i.type]),i},cc=(i,t)=>tT(i).priority??t,fe={_addHandlers:{},_removeHandlers:{},_queue:{},remove(...i){return i.map(tT).forEach(t=>{t.type.forEach(e=>{var s,r;return(r=(s=this._removeHandlers)[e])==null?void 0:r.call(s,t)})}),this},add(...i){return i.map(tT).forEach(t=>{t.type.forEach(e=>{var n,a;const s=this._addHandlers,r=this._queue;s[e]?(a=s[e])==null||a.call(s,t):(r[e]=r[e]||[],(n=r[e])==null||n.push(t))})}),this},handle(i,t,e){var a;const s=this._addHandlers,r=this._removeHandlers;if(s[i]||r[i])throw new Error(`Extension type ${i} already has a handler`);s[i]=t,r[i]=e;const n=this._queue;return n[i]&&((a=n[i])==null||a.forEach(o=>t(o)),delete n[i]),this},handleByMap(i,t){return this.handle(i,e=>{e.name&&(t[e.name]=e.ref)},e=>{e.name&&delete t[e.name]})},handleByNamedList(i,t,e=-1){return this.handle(i,s=>{t.findIndex(n=>n.name===s.name)>=0||(t.push({name:s.name,value:s.ref}),t.sort((n,a)=>cc(a.value,e)-cc(n.value,e)))},s=>{const r=t.findIndex(n=>n.name===s.name);r!==-1&&t.splice(r,1)})},handleByList(i,t,e=-1){return this.handle(i,s=>{t.includes(s.ref)||(t.push(s.ref),t.sort((r,n)=>cc(n,e)-cc(r,e)))},s=>{const r=t.indexOf(s.ref);r!==-1&&t.splice(r,1)})}},YX={extension:{type:B.Environment,name:"browser",priority:-1},test:()=>!0,load:async()=>{await Promise.resolve().then(()=>require("./browserAll-tpr82i3Q.cjs"))}},WX={extension:{type:B.Environment,name:"webworker",priority:0},test:()=>typeof self<"u"&&self.WorkerGlobalScope!==void 0,load:async()=>{await Promise.resolve().then(()=>require("./webworkerAll-CuC225D_.cjs"))}};class Pe{constructor(t,e,s){this._x=e||0,this._y=s||0,this._observer=t}clone(t){return new Pe(t??this._observer,this._x,this._y)}set(t=0,e=t){return(this._x!==t||this._y!==e)&&(this._x=t,this._y=e,this._observer._onUpdate(this)),this}copyFrom(t){return(this._x!==t.x||this._y!==t.y)&&(this._x=t.x,this._y=t.y,this._observer._onUpdate(this)),this}copyTo(t){return t.set(this._x,this._y),t}equals(t){return t.x===this._x&&t.y===this._y}toString(){return`[pixi.js/math:ObservablePoint x=0 y=0 scope=${this._observer}]`}get x(){return this._x}set x(t){this._x!==t&&(this._x=t,this._observer._onUpdate(this))}get y(){return this._y}set y(t){this._y!==t&&(this._y=t,this._observer._onUpdate(this))}}var yu=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function UI(i){return i&&i.__esModule&&Object.prototype.hasOwnProperty.call(i,"default")?i.default:i}var Zy={exports:{}};(function(i){var t=Object.prototype.hasOwnProperty,e="~";function s(){}Object.create&&(s.prototype=Object.create(null),new s().__proto__||(e=!1));function r(u,l,c){this.fn=u,this.context=l,this.once=c||!1}function n(u,l,c,h,_){if(typeof c!="function")throw new TypeError("The listener must be a function");var d=new r(c,h||u,_),f=e?e+l:l;return u._events[f]?u._events[f].fn?u._events[f]=[u._events[f],d]:u._events[f].push(d):(u._events[f]=d,u._eventsCount++),u}function a(u,l){--u._eventsCount===0?u._events=new s:delete u._events[l]}function o(){this._events=new s,this._eventsCount=0}o.prototype.
|
||
|
Deprecated since v${i}`):(s=s.split(`
|
||
|
`).splice(e).join(`
|
||
|
`),console.groupCollapsed?(console.groupCollapsed("%cPixiJS Deprecation Warning: %c%s","color:#614108;background:#fffbe6","font-weight:normal;color:#614108;background:#fffbe6",`${t}
|
||
|
Deprecated since v${i}`),console.warn(s),console.groupEnd()):(console.warn("PixiJS Deprecation Warning: ",`${t}
|
||
|
Deprecated since v${i}`),console.warn(s))),_O[t]=!0}const tv=()=>{};function Dl(i){return i+=i===0?1:0,--i,i|=i>>>1,i|=i>>>2,i|=i>>>4,i|=i>>>8,i|=i>>>16,i+1}function dO(i){return!(i&i-1)&&!!i}function JX(i){const t={};for(const e in i)i[e]!==void 0&&(t[e]=i[e]);return t}const fO=Object.create(null);function t7(i){const t=fO[i];return t===void 0&&(fO[i]=Se("resource")),t}const ev=class sv extends ks{constructor(t={}){super(),this._resourceType="textureSampler",this._touched=0,this._maxAnisotropy=1,this.destroyed=!1,t={...sv.defaultOptions,...t},this.addressMode=t.addressMode,this.addressModeU=t.addressModeU??this.addressModeU,this.addressModeV=t.addressModeV??this.addressModeV,this.addressModeW=t.addressModeW??this.addressModeW,this.scaleMode=t.scaleMode,this.magFilter=t.magFilter??this.magFilter,this.minFilter=t.minFilter??this.minFilter,this.mipmapFilter=t.mipmapFilter??this.mipmapFilter,this.lodMinClamp=t.lodMinClamp,this.lodMaxClamp=t.lodMaxClamp,this.compare=t.compare,this.maxAnisotropy=t.maxAnisotropy??1}set addressMode(t){this.addressModeU=t,this.addressModeV=t,this.addressModeW=t}get addressMode(){return this.addressModeU}set wrapMode(t){ct(Te,"TextureStyle.wrapMode is now TextureStyle.addressMode"),this.addressMode=t}get wrapMode(){return this.addressMode}set scaleMode(t){this.magFilter=t,this.minFilter=t,this.mipmapFilter=t}get scaleMode(){return this.magFilter}set maxAnisotropy(t){this._maxAnisotropy=Math.min(t,16),this._maxAnisotropy>1&&(this.scaleMode="linear")}get maxAnisotropy(){return this._maxAnisotropy}get _resourceId(){return this._sharedResourceId||this._generateResourceId()}update(){this.emit("change",this),this._sharedResourceId=null}_generateResourceId(){const t=`${this.addressModeU}-${this.addressModeV}-${this.addressModeW}-${this.magFilter}-${this.minFilter}-${this.mipmapFilter}-${this.lodMinClamp}-${this.lodMaxClamp}-${this.compare}-${this._maxAnisotropy}`;return this._sharedResourceId=t7(t),this._resourceId}destroy(){this.destroyed=!0,this.emit("destroy",this),this.emit("change",this),this.removeAllListeners()}};ev.defaultOptions={addressMode:"clamp-to-edge",scaleMode:"linear"};let iv=ev;const rv=class nv extends ks{constructor(t={}){super(),this.options=t,this.uid=Se("textureSource"),this._resourceType="textureSource",this._resourceId=Se("resource"),this.uploadMethodId="unknown",this._resolution=1,this.pixelWidth=1,this.pixelHeight=1,this.width=1,this.height=1,this.sampleCount=1,this.mipLevelCount=1,this.autoGenerateMipmaps=!1,this.format="rgba8unorm",this.dimension="2d",this.antialias=!1,this._touched=0,this._batchTick=-1,this._textureBindLocation=-1,t={...nv.defaultOptions,...t},this.label=t.label??"",this.resource=t.resource,this.autoGarbageCollect=t.autoGarbageCollect,this._resolution=t.resolution,t.width?this.pixelWidth=t.width*this._resolution:this.pixelWidth=this.resource?this.resourceWidth??1:1,t.height?this.pixelHeight=t.height*this._resolution:this.pixelHeight=this.resource?this.resourceHeight??1:1,this.width=this.pixelWidth/this._resolution,this.height=this.pixelHeight/this._resolution,this.format=t.format,this.dimension=t.dimensions,this.mipLevelCount=t.mipLevelCount,this.autoGenerateMipmaps=t.autoGenerateMipmaps,this.sampleCount=t.sampleCount,this.antialias=t.antialias,this.alphaMode=t.alphaMode,this.style=new iv(JX(t)),this.destroyed=!1,this._refreshPOT()}get source(){return this}get style(){return this._style}set style(t){var e,s;this.style!==t&&((e=this._style)==null||e.off("change",this._onStyleChange,this),this._style=t,(s=this._style)==null||s.on("change",this._onStyleChange,this),this._onStyleChange())}get addressMode(){return this._style.addressMode}set addressMode(t){this._style.addressMode=t}get repeatMode(){return this._style.addressMode}set repeatMode(t){this._style.addressMode=t}get magFilter(){return this._style.magFilter}set magFilter(t){this._style.magFilter=t}get minFilter(){return this._style.minFilter}set minFilter(t){this._style.minFilter=t}get mipmapFilter(){return this._style.mipmapFilter}set mipmapFilter(t){this._style.mipmapFilter=t}get lodMinClamp(){return
|
||
|
|
||
|
#ifdef GL_ES // This checks if it is WebGL1
|
||
|
#define in varying
|
||
|
#define finalColor gl_FragColor
|
||
|
#define texture texture2D
|
||
|
#endif
|
||
|
${i}
|
||
|
`):`
|
||
|
|
||
|
#ifdef GL_ES // This checks if it is WebGL1
|
||
|
#define in attribute
|
||
|
#define out varying
|
||
|
#endif
|
||
|
${i}
|
||
|
`}function G7(i,t,e){const s=e?t.maxSupportedFragmentPrecision:t.maxSupportedVertexPrecision;if(i.substring(0,9)!=="precision"){let r=e?t.requestedFragmentPrecision:t.requestedVertexPrecision;return r==="highp"&&s!=="highp"&&(r="mediump"),`precision ${r} float;
|
||
|
${i}`}else if(s!=="highp"&&i.substring(0,15)==="precision highp")return i.replace("precision highp","precision mediump");return i}function B7(i,t){return t?`#version 300 es
|
||
|
${i}`:i}const k7={},z7={};function V7(i,{name:t="pixi-program"},e=!0){t=t.replace(/\s+/g,"-"),t+=e?"-fragment":"-vertex";const s=e?k7:z7;return s[t]?(s[t]++,t+=`-${s[t]}`):s[t]=1,i.indexOf("#define SHADER_NAME")!==-1?i:`${`#define SHADER_NAME ${t}`}
|
||
|
${i}`}function H7(i,t){return t?i.replace("#version 300 es",""):i}const mE={stripVersion:H7,ensurePrecision:G7,addProgramDefines:w7,setProgramName:V7,insertVersion:B7},EE=Object.create(null),bv=class uT{constructor(t){t={...uT.defaultOptions,...t};const e=t.fragment.indexOf("#version 300 es")!==-1,s={stripVersion:e,ensurePrecision:{requestedFragmentPrecision:t.preferredFragmentPrecision,requestedVertexPrecision:t.preferredVertexPrecision,maxSupportedVertexPrecision:"highp",maxSupportedFragmentPrecision:F7()},setProgramName:{name:t.name},addProgramDefines:e,insertVersion:e};let r=t.fragment,n=t.vertex;Object.keys(mE).forEach(a=>{const o=s[a];r=mE[a](r,o,!0),n=mE[a](n,o,!1)}),this.fragment=r,this.vertex=n,this._key=Fl(`${this.vertex}:${this.fragment}`,"gl-program")}destroy(){this.fragment=null,this.vertex=null,this._attributeData=null,this._uniformData=null,this._uniformBlockData=null,this.transformFeedbackVaryings=null}static from(t){const e=`${t.vertex}:${t.fragment}`;return EE[e]||(EE[e]=new uT(t)),EE[e]}};bv.defaultOptions={preferredVertexPrecision:"highp",preferredFragmentPrecision:"mediump"};let Tt=bv;const CO={uint8x2:{size:2,stride:2,normalised:!1},uint8x4:{size:4,stride:4,normalised:!1},sint8x2:{size:2,stride:2,normalised:!1},sint8x4:{size:4,stride:4,normalised:!1},unorm8x2:{size:2,stride:2,normalised:!0},unorm8x4:{size:4,stride:4,normalised:!0},snorm8x2:{size:2,stride:2,normalised:!0},snorm8x4:{size:4,stride:4,normalised:!0},uint16x2:{size:2,stride:4,normalised:!1},uint16x4:{size:4,stride:8,normalised:!1},sint16x2:{size:2,stride:4,normalised:!1},sint16x4:{size:4,stride:8,normalised:!1},unorm16x2:{size:2,stride:4,normalised:!0},unorm16x4:{size:4,stride:8,normalised:!0},snorm16x2:{size:2,stride:4,normalised:!0},snorm16x4:{size:4,stride:8,normalised:!0},float16x2:{size:2,stride:4,normalised:!1},float16x4:{size:4,stride:8,normalised:!1},float32:{size:1,stride:4,normalised:!1},float32x2:{size:2,stride:8,normalised:!1},float32x3:{size:3,stride:12,normalised:!1},float32x4:{size:4,stride:16,normalised:!1},uint32:{size:1,stride:4,normalised:!1},uint32x2:{size:2,stride:8,normalised:!1},uint32x3:{size:3,stride:12,normalised:!1},uint32x4:{size:4,stride:16,normalised:!1},sint32:{size:1,stride:4,normalised:!1},sint32x2:{size:2,stride:8,normalised:!1},sint32x3:{size:3,stride:12,normalised:!1},sint32x4:{size:4,stride:16,normalised:!1}};function t_(i){return CO[i]??CO.float32}const Y7={f32:"float32","vec2<f32>":"float32x2","vec3<f32>":"float32x3","vec4<f32>":"float32x4",vec2f:"float32x2",vec3f:"float32x3",vec4f:"float32x4",i32:"sint32","vec2<i32>":"sint32x2","vec3<i32>":"sint32x3","vec4<i32>":"sint32x4",u32:"uint32","vec2<u32>":"uint32x2","vec3<u32>":"uint32x3","vec4<u32>":"uint32x4",bool:"uint32","vec2<bool>":"uint32x2","vec3<bool>":"uint32x3","vec4<bool>":"uint32x4"};function W7({source:i,entryPoint:t}){const e={},s=i.indexOf(`fn ${t}`);if(s!==-1){const r=i.indexOf("->",s);if(r!==-1){const n=i.substring(s,r),a=/@location\((\d+)\)\s+([a-zA-Z0-9_]+)\s*:\s*([a-zA-Z0-9_<>]+)(?:,|\s|$)/g;let o;for(;(o=a.exec(n))!==null;){const u=Y7[o[3]]??"float32";e[o[2]]={location:parseInt(o[1],10),format:u,stride:t_(u).stride,offset:0,instance:!1,start:0}}}}return e}function TE(i){var h,_;const t=/(^|[^/])@(group|binding)\(\d+\)[^;]+;/g,e=/@group\((\d+)\)/,s=/@binding\((\d+)\)/,r=/var(<[^>]+>)? (\w+)/,n=/:\s*(\w+)/,a=/struct\s+(\w+)\s*{([^}]+)}/g,o=/(\w+)\s*:\s*([\w\<\>]+)/g,u=/struct\s+(\w+)/,l=(h=i.match(t))==null?void 0:h.map(d=>({group:parseInt(d.match(e)[1],10),binding:parseInt(d.match(s)[1],10),name:d.match(r)[2],isUniform:d.match(r)[1]==="<uniform>",type:d.match(n)[1]}));if(!l)return{groups:[],structs:[]};const c=((_=i.match(a))==null?void 0:_.map(d=>{const f=d.match(u)[1],p=d.match(o).reduce((g,m)=>{const[O,y]=m.split(":");return g[O.trim()]=y.trim(),g},{});return p?{name:f,members:p}:null}).filter(({name:d})=>l.some(f=>f.type===d)))??[];return{groups:l,structs:c}}var Du=(i=>(i[i.VERTEX=1]="VERTEX",i[i.FRAGMENT=2]="FRAGMENT",i[i.COMPUTE=4]="COMPUTE",i))(Du||{});function j7({groups:i}){const t=[];for(let e=0;e<i.length;e++){const s=i[e];t
|
||
|
`);function M9(i){let t="";for(let e=0;e<i;++e)e>0&&(t+=`
|
||
|
else `),e<i-1&&(t+=`if(test == ${e}.0){}`);return t}function x9(i,t){if(i===0)throw new Error("Invalid value of `0` passed to `checkMaxIfStatementsInShader`");const e=t.createShader(t.FRAGMENT_SHADER);try{for(;;){const s=C9.replace(/%forloop%/gi,M9(i));if(t.shaderSource(e,s),t.compileShader(e),!t.getShaderParameter(e,t.COMPILE_STATUS))i=i/2|0;else break}}finally{t.deleteShader(e)}return i}let so=null;function Im(){var t;if(so)return so;const i=Pv();return so=i.getParameter(i.MAX_TEXTURE_IMAGE_UNITS),so=x9(so,i),(t=i.getExtension("WEBGL_lose_context"))==null||t.loseContext(),so}const Qv={};function VI(i,t){let e=2166136261;for(let s=0;s<t;s++)e^=i[s].uid,e=Math.imul(e,16777619),e>>>=0;return Qv[e]||P9(i,t,e)}let ME=0;function P9(i,t,e){const s={};let r=0;ME||(ME=Im());for(let a=0;a<ME;a++){const o=a<t?i[a]:W.EMPTY.source;s[r++]=o.source,s[r++]=o.style}const n=new Sn(s);return Qv[e]=n,n}class mT{constructor(t){typeof t=="number"?this.rawBinaryData=new ArrayBuffer(t):t instanceof Uint8Array?this.rawBinaryData=t.buffer:this.rawBinaryData=t,this.uint32View=new Uint32Array(this.rawBinaryData),this.float32View=new Float32Array(this.rawBinaryData),this.size=this.rawBinaryData.byteLength}get int8View(){return this._int8View||(this._int8View=new Int8Array(this.rawBinaryData)),this._int8View}get uint8View(){return this._uint8View||(this._uint8View=new Uint8Array(this.rawBinaryData)),this._uint8View}get int16View(){return this._int16View||(this._int16View=new Int16Array(this.rawBinaryData)),this._int16View}get int32View(){return this._int32View||(this._int32View=new Int32Array(this.rawBinaryData)),this._int32View}get float64View(){return this._float64Array||(this._float64Array=new Float64Array(this.rawBinaryData)),this._float64Array}get bigUint64View(){return this._bigUint64Array||(this._bigUint64Array=new BigUint64Array(this.rawBinaryData)),this._bigUint64Array}view(t){return this[`${t}View`]}destroy(){this.rawBinaryData=null,this._int8View=null,this._uint8View=null,this._int16View=null,this.uint16View=null,this._int32View=null,this.uint32View=null,this.float32View=null}static sizeOf(t){switch(t){case"int8":case"uint8":return 1;case"int16":case"uint16":return 2;case"int32":case"uint32":case"float32":return 4;default:throw new Error(`${t} isn't a valid view type`)}}}function ET(i,t){const e=i.byteLength/8|0,s=new Float64Array(i,0,e);new Float64Array(t,0,e).set(s);const n=i.byteLength-e*8;if(n>0){const a=new Uint8Array(i,e*8,n);new Uint8Array(t,e*8,n).set(a)}}const b9={normal:"normal-npm",add:"add-npm",screen:"screen-npm"};var He=(i=>(i[i.DISABLED=0]="DISABLED",i[i.RENDERING_MASK_ADD=1]="RENDERING_MASK_ADD",i[i.MASK_ACTIVE=2]="MASK_ACTIVE",i[i.INVERSE_MASK_ACTIVE=3]="INVERSE_MASK_ACTIVE",i[i.RENDERING_MASK_REMOVE=4]="RENDERING_MASK_REMOVE",i[i.NONE=5]="NONE",i))(He||{});function TT(i,t){return t.alphaMode==="no-premultiply-alpha"&&b9[i]||i}class N9{constructor(){this.ids=Object.create(null),this.textures=[],this.count=0}clear(){for(let t=0;t<this.count;t++){const e=this.textures[t];this.textures[t]=null,this.ids[e.uid]=null}this.count=0}}class U9{constructor(){this.renderPipeId="batch",this.action="startBatch",this.start=0,this.size=0,this.textures=new N9,this.blendMode="normal",this.canBundle=!0}destroy(){this.textures=null,this.gpuBindGroup=null,this.bindGroup=null,this.batcher=null}}const Zv=[];let IT=0;function bO(){return IT>0?Zv[--IT]:new U9}function NO(i){Zv[IT++]=i}let Mu=0;const Jv=class bc{constructor(t={}){this.uid=Se("batcher"),this.dirty=!0,this.batchIndex=0,this.batches=[],this._elements=[],bc.defaultOptions.maxTextures=bc.defaultOptions.maxTextures??Im(),t={...bc.defaultOptions,...t};const{maxTextures:e,attributesInitialSize:s,indicesInitialSize:r}=t;this.attributeBuffer=new mT(s*4),this.indexBuffer=new Uint16Array(r),this.maxTextures=e}begin(){this.elementSize=0,this.elementStart=0,this.indexSize=0,this.attributeSize=0;for(let t=0;t<this.batchIndex;t++)NO(this.batches[t]);this.batchIndex=0,this._batchIndexStart=0,this._batchIndexSize=0,this.dirty=!0}add(t){this._elements[this.elementSize++]=t,t._indexStart=this.index
|
||
|
`);let a=t.replace(/@in\s+[^;]+;\s*/g,"");return a=a.replace("{{in}}",`
|
||
|
${n}
|
||
|
`),a}function wO(i,t){let e;const s=/@out\s+([^;]+);/g;for(;(e=s.exec(i))!==null;)t.push(e[1])}function z9(i){const e=/\b(\w+)\s*:/g.exec(i);return e?e[1]:""}function V9(i){const t=/@.*?\s+/g;return i.replace(t,"")}function H9(i,t){const e=[];wO(t,e),i.forEach(u=>{u.header&&wO(u.header,e)});let s=0;const r=e.sort().map(u=>u.indexOf("builtin")>-1?u:`@location(${s++}) ${u}`).join(`,
|
||
|
`),n=e.sort().map(u=>` var ${V9(u)};`).join(`
|
||
|
`),a=`return VSOutput(
|
||
|
${e.sort().map(u=>` ${z9(u)}`).join(`,
|
||
|
`)});`;let o=t.replace(/@out\s+[^;]+;\s*/g,"");return o=o.replace("{{struct}}",`
|
||
|
${r}
|
||
|
`),o=o.replace("{{start}}",`
|
||
|
${n}
|
||
|
`),o=o.replace("{{return}}",`
|
||
|
${a}
|
||
|
`),o}function GO(i,t){let e=i;for(const s in t){const r=t[s];r.join(`
|
||
|
`).length?e=e.replace(`{{${s}}}`,`//-----${s} START-----//
|
||
|
${r.join(`
|
||
|
`)}
|
||
|
//----${s} FINISH----//`):e=e.replace(`{{${s}}}`,"")}return e}const En=Object.create(null),xE=new Map;let Y9=0;function W9({template:i,bits:t}){const e=sC(i,t);if(En[e])return En[e];const{vertex:s,fragment:r}=K9(i,t);return En[e]=iC(s,r,t),En[e]}function j9({template:i,bits:t}){const e=sC(i,t);return En[e]||(En[e]=iC(i.vertex,i.fragment,t)),En[e]}function K9(i,t){const e=t.map(a=>a.vertex).filter(a=>!!a),s=t.map(a=>a.fragment).filter(a=>!!a);let r=FO(e,i.vertex,!0);r=H9(e,r);const n=FO(s,i.fragment,!0);return{vertex:r,fragment:n}}function sC(i,t){return t.map(e=>(xE.has(e)||xE.set(e,Y9++),xE.get(e))).sort((e,s)=>e-s).join("-")+i.vertex+i.fragment}function iC(i,t,e){const s=DO(i),r=DO(t);return e.forEach(n=>{UO(n.vertex,s,n.name),UO(n.fragment,r,n.name)}),{vertex:GO(i,s),fragment:GO(t,r)}}const X9=`
|
||
|
@in aPosition: vec2<f32>;
|
||
|
@in aUV: vec2<f32>;
|
||
|
|
||
|
@out @builtin(position) vPosition: vec4<f32>;
|
||
|
@out vUV : vec2<f32>;
|
||
|
@out vColor : vec4<f32>;
|
||
|
|
||
|
{{header}}
|
||
|
|
||
|
struct VSOutput {
|
||
|
{{struct}}
|
||
|
};
|
||
|
|
||
|
@vertex
|
||
|
fn main( {{in}} ) -> VSOutput {
|
||
|
|
||
|
var worldTransformMatrix = globalUniforms.uWorldTransformMatrix;
|
||
|
var modelMatrix = mat3x3<f32>(
|
||
|
1.0, 0.0, 0.0,
|
||
|
0.0, 1.0, 0.0,
|
||
|
0.0, 0.0, 1.0
|
||
|
);
|
||
|
var position = aPosition;
|
||
|
var uv = aUV;
|
||
|
|
||
|
{{start}}
|
||
|
|
||
|
vColor = vec4<f32>(1., 1., 1., 1.);
|
||
|
|
||
|
{{main}}
|
||
|
|
||
|
vUV = uv;
|
||
|
|
||
|
var modelViewProjectionMatrix = globalUniforms.uProjectionMatrix * worldTransformMatrix * modelMatrix;
|
||
|
|
||
|
vPosition = vec4<f32>((modelViewProjectionMatrix * vec3<f32>(position, 1.0)).xy, 0.0, 1.0);
|
||
|
|
||
|
vColor *= globalUniforms.uWorldColorAlpha;
|
||
|
|
||
|
{{end}}
|
||
|
|
||
|
{{return}}
|
||
|
};
|
||
|
`,q9=`
|
||
|
@in vUV : vec2<f32>;
|
||
|
@in vColor : vec4<f32>;
|
||
|
|
||
|
{{header}}
|
||
|
|
||
|
@fragment
|
||
|
fn main(
|
||
|
{{in}}
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
{{start}}
|
||
|
|
||
|
var outColor:vec4<f32>;
|
||
|
|
||
|
{{main}}
|
||
|
|
||
|
var finalColor:vec4<f32> = outColor * vColor;
|
||
|
|
||
|
{{end}}
|
||
|
|
||
|
return finalColor;
|
||
|
};
|
||
|
`,$9=`
|
||
|
in vec2 aPosition;
|
||
|
in vec2 aUV;
|
||
|
|
||
|
out vec4 vColor;
|
||
|
out vec2 vUV;
|
||
|
|
||
|
{{header}}
|
||
|
|
||
|
void main(void){
|
||
|
|
||
|
mat3 worldTransformMatrix = uWorldTransformMatrix;
|
||
|
mat3 modelMatrix = mat3(
|
||
|
1.0, 0.0, 0.0,
|
||
|
0.0, 1.0, 0.0,
|
||
|
0.0, 0.0, 1.0
|
||
|
);
|
||
|
vec2 position = aPosition;
|
||
|
vec2 uv = aUV;
|
||
|
|
||
|
{{start}}
|
||
|
|
||
|
vColor = vec4(1.);
|
||
|
|
||
|
{{main}}
|
||
|
|
||
|
vUV = uv;
|
||
|
|
||
|
mat3 modelViewProjectionMatrix = uProjectionMatrix * worldTransformMatrix * modelMatrix;
|
||
|
|
||
|
gl_Position = vec4((modelViewProjectionMatrix * vec3(position, 1.0)).xy, 0.0, 1.0);
|
||
|
|
||
|
vColor *= uWorldColorAlpha;
|
||
|
|
||
|
{{end}}
|
||
|
}
|
||
|
`,Q9=`
|
||
|
|
||
|
in vec4 vColor;
|
||
|
in vec2 vUV;
|
||
|
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
{{header}}
|
||
|
|
||
|
void main(void) {
|
||
|
|
||
|
{{start}}
|
||
|
|
||
|
vec4 outColor;
|
||
|
|
||
|
{{main}}
|
||
|
|
||
|
finalColor = outColor * vColor;
|
||
|
|
||
|
{{end}}
|
||
|
}
|
||
|
`,Z9={name:"global-uniforms-bit",vertex:{header:`
|
||
|
struct GlobalUniforms {
|
||
|
uProjectionMatrix:mat3x3<f32>,
|
||
|
uWorldTransformMatrix:mat3x3<f32>,
|
||
|
uWorldColorAlpha: vec4<f32>,
|
||
|
uResolution: vec2<f32>,
|
||
|
}
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> globalUniforms : GlobalUniforms;
|
||
|
`}},J9={name:"global-uniforms-bit",vertex:{header:`
|
||
|
uniform mat3 uProjectionMatrix;
|
||
|
uniform mat3 uWorldTransformMatrix;
|
||
|
uniform vec4 uWorldColorAlpha;
|
||
|
uniform vec2 uResolution;
|
||
|
`}};function Sm({bits:i,name:t}){const e=W9({template:{fragment:q9,vertex:X9},bits:[Z9,...i]});return At.from({name:t,vertex:{source:e.vertex,entryPoint:"main"},fragment:{source:e.fragment,entryPoint:"main"}})}function rC({bits:i,name:t}){return new Tt({name:t,...j9({template:{vertex:$9,fragment:Q9},bits:[J9,...i]})})}const HI={name:"color-bit",vertex:{header:`
|
||
|
@in aColor: vec4<f32>;
|
||
|
`,main:`
|
||
|
vColor *= vec4<f32>(aColor.rgb * aColor.a, aColor.a);
|
||
|
`}},nC={name:"color-bit",vertex:{header:`
|
||
|
in vec4 aColor;
|
||
|
`,main:`
|
||
|
vColor *= vec4(aColor.rgb * aColor.a, aColor.a);
|
||
|
`}},PE={};function tq(i){const t=[];if(i===1)t.push("@group(1) @binding(0) var textureSource1: texture_2d<f32>;"),t.push("@group(1) @binding(1) var textureSampler1: sampler;");else{let e=0;for(let s=0;s<i;s++)t.push(`@group(1) @binding(${e++}) var textureSource${s+1}: texture_2d<f32>;`),t.push(`@group(1) @binding(${e++}) var textureSampler${s+1}: sampler;`)}return t.join(`
|
||
|
`)}function eq(i){const t=[];if(i===1)t.push("outColor = textureSampleGrad(textureSource1, textureSampler1, vUV, uvDx, uvDy);");else{t.push("switch vTextureId {");for(let e=0;e<i;e++)e===i-1?t.push(" default:{"):t.push(` case ${e}:{`),t.push(` outColor = textureSampleGrad(textureSource${e+1}, textureSampler${e+1}, vUV, uvDx, uvDy);`),t.push(" break;}");t.push("}")}return t.join(`
|
||
|
`)}function YI(i){return PE[i]||(PE[i]={name:"texture-batch-bit",vertex:{header:`
|
||
|
@in aTextureIdAndRound: vec2<u32>;
|
||
|
@out @interpolate(flat) vTextureId : u32;
|
||
|
`,main:`
|
||
|
vTextureId = aTextureIdAndRound.y;
|
||
|
`,end:`
|
||
|
if(aTextureIdAndRound.x == 1)
|
||
|
{
|
||
|
vPosition = vec4<f32>(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
|
||
|
}
|
||
|
`},fragment:{header:`
|
||
|
@in @interpolate(flat) vTextureId: u32;
|
||
|
|
||
|
${tq(i)}
|
||
|
`,main:`
|
||
|
var uvDx = dpdx(vUV);
|
||
|
var uvDy = dpdy(vUV);
|
||
|
|
||
|
${eq(i)}
|
||
|
`}}),PE[i]}const bE={};function sq(i){const t=[];for(let e=0;e<i;e++)e>0&&t.push("else"),e<i-1&&t.push(`if(vTextureId < ${e}.5)`),t.push("{"),t.push(` outColor = texture(uTextures[${e}], vUV);`),t.push("}");return t.join(`
|
||
|
`)}function aC(i){return bE[i]||(bE[i]={name:"texture-batch-bit",vertex:{header:`
|
||
|
in vec2 aTextureIdAndRound;
|
||
|
out float vTextureId;
|
||
|
|
||
|
`,main:`
|
||
|
vTextureId = aTextureIdAndRound.y;
|
||
|
`,end:`
|
||
|
if(aTextureIdAndRound.x == 1.)
|
||
|
{
|
||
|
gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
|
||
|
}
|
||
|
`},fragment:{header:`
|
||
|
in float vTextureId;
|
||
|
|
||
|
uniform sampler2D uTextures[${i}];
|
||
|
|
||
|
`,main:`
|
||
|
|
||
|
${sq(i)}
|
||
|
`}}),bE[i]}const Rm={name:"round-pixels-bit",vertex:{header:`
|
||
|
fn roundPixels(position: vec2<f32>, targetSize: vec2<f32>) -> vec2<f32>
|
||
|
{
|
||
|
return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
|
||
|
}
|
||
|
`}},oC={name:"round-pixels-bit",vertex:{header:`
|
||
|
vec2 roundPixels(vec2 position, vec2 targetSize)
|
||
|
{
|
||
|
return (floor(((position * 0.5 + 0.5) * targetSize) + 0.5) / targetSize) * 2.0 - 1.0;
|
||
|
}
|
||
|
`}},BO={};function uC(i){let t=BO[i];if(t)return t;const e=new Int32Array(i);for(let s=0;s<i;s++)e[s]=s;return t=BO[i]=new Yr({uTextures:{value:e,type:"i32",size:i}},{isStatic:!0}),t}class iq extends $a{constructor(t){const e=rC({name:"batch",bits:[nC,aC(t),oC]}),s=Sm({name:"batch",bits:[HI,YI(t),Rm]});super({glProgram:e,gpuProgram:s,resources:{batchSamplers:uC(t)}})}}let kO=null;const lC=class hC extends D9{constructor(){super(...arguments),this.geometry=new B9,this.shader=kO||(kO=new iq(this.maxTextures)),this.name=hC.extension.name,this.vertexSize=6}packAttributes(t,e,s,r,n){const a=n<<16|t.roundPixels&65535,o=t.transform,u=o.a,l=o.b,c=o.c,h=o.d,_=o.tx,d=o.ty,{positions:f,uvs:p}=t,g=t.color,m=t.attributeOffset,O=m+t.attributeSize;for(let y=m;y<O;y++){const C=y*2,P=f[C],L=f[C+1];e[r++]=u*P+c*L+_,e[r++]=h*L+l*P+d,e[r++]=p[C],e[r++]=p[C+1],s[r++]=g,s[r++]=a}}packQuadAttributes(t,e,s,r,n){const a=t.texture,o=t.transform,u=o.a,l=o.b,c=o.c,h=o.d,_=o.tx,d=o.ty,f=t.bounds,p=f.maxX,g=f.minX,m=f.maxY,O=f.minY,y=a.uvs,C=t.color,P=n<<16|t.roundPixels&65535;e[r+0]=u*g+c*O+_,e[r+1]=h*O+l*g+d,e[r+2]=y.x0,e[r+3]=y.y0,s[r+4]=C,s[r+5]=P,e[r+6]=u*p+c*O+_,e[r+7]=h*O+l*p+d,e[r+8]=y.x1,e[r+9]=y.y1,s[r+10]=C,s[r+11]=P,e[r+12]=u*p+c*m+_,e[r+13]=h*m+l*p+d,e[r+14]=y.x2,e[r+15]=y.y2,s[r+16]=C,s[r+17]=P,e[r+18]=u*g+c*m+_,e[r+19]=h*m+l*g+d,e[r+20]=y.x3,e[r+21]=y.y3,s[r+22]=C,s[r+23]=P}};lC.extension={type:[B.Batcher],name:"default"};let WI=lC;function rq(i,t,e,s,r,n,a,o=null){let u=0;e*=t,r*=n;const l=o.a,c=o.b,h=o.c,_=o.d,d=o.tx,f=o.ty;for(;u<a;){const p=i[e],g=i[e+1];s[r]=l*p+h*g+d,s[r+1]=c*p+_*g+f,r+=n,e+=t,u++}}function nq(i,t,e,s){let r=0;for(t*=e;r<s;)i[t]=0,i[t+1]=0,t+=e,r++}function cC(i,t,e,s,r){const n=t.a,a=t.b,o=t.c,u=t.d,l=t.tx,c=t.ty;e=e||0,s=s||2,r=r||i.length/s-e;let h=e*s;for(let _=0;_<r;_++){const d=i[h],f=i[h+1];i[h]=n*d+o*f+l,i[h+1]=a*d+u*f+c,h+=s}}function aq(i,t){if(i===16777215||!t)return t;if(t===16777215||!i)return i;const e=i>>16&255,s=i>>8&255,r=i&255,n=t>>16&255,a=t>>8&255,o=t&255,u=e*n/255,l=s*a/255,c=r*o/255;return(u<<16)+(l<<8)+c}const oq=new ot;class jI{constructor(){this.packAsQuad=!1,this.batcherName="default",this.applyTransform=!0,this.roundPixels=0,this._batcher=null,this._batch=null}get uvs(){return this.geometryData.uvs}get positions(){return this.geometryData.vertices}get indices(){return this.geometryData.indices}get blendMode(){return this.applyTransform?this.renderable.groupBlendMode:"normal"}get color(){const t=this.baseColor,e=t>>16|t&65280|(t&255)<<16,s=this.renderable;return s?aq(e,s.groupColor)+(this.alpha*s.groupAlpha*255<<24):e+(this.alpha*255<<24)}get transform(){var t;return((t=this.renderable)==null?void 0:t.groupTransform)||oq}copyTo(t){t.indexOffset=this.indexOffset,t.indexSize=this.indexSize,t.attributeOffset=this.attributeOffset,t.attributeSize=this.attributeSize,t.baseColor=this.baseColor,t.alpha=this.alpha,t.texture=this.texture,t.geometryData=this.geometryData}reset(){this.applyTransform=!0,this.renderable=null}}const zl={extension:{type:B.ShapeBuilder,name:"circle"},build(i,t){let e,s,r,n,a,o;if(i.type==="circle"){const C=i;e=C.x,s=C.y,a=o=C.radius,r=n=0}else if(i.type==="ellipse"){const C=i;e=C.x,s=C.y,a=C.halfWidth,o=C.halfHeight,r=n=0}else{const C=i,P=C.width/2,L=C.height/2;e=C.x+P,s=C.y+L,a=o=Math.max(0,Math.min(C.radius,Math.min(P,L))),r=P-a,n=L-o}if(!(a>=0&&o>=0&&r>=0&&n>=0))return t;const u=Math.ceil(2.3*Math.sqrt(a+o)),l=u*8+(r?4:0)+(n?4:0);if(l===0)return t;if(u===0)return t[0]=t[6]=e+r,t[1]=t[3]=s+n,t[2]=t[4]=e-r,t[5]=t[7]=s-n,t;let c=0,h=u*4+(r?2:0)+2,_=h,d=l,f=r+a,p=n,g=e+f,m=e-f,O=s+p;if(t[c++]=g,t[c++]=O,t[--h]=O,t[--h]=m,n){const C=s-p;t[_++]=m,t[_++]=C,t[--d]=C,t[--d]=g}for(let C=1;C<u;C++){const P=Math.PI/2*(C/u),L=r+Math.cos(P)*a,N=n+Math.sin(P)*o,F=e+L,x=e-L,U=s+N,k=s-N;t[c++]=F,t[c++]=U,t[--h]=U,t[--h]=x,t[_++]=x,t[_++]=k,t[--d]=k,t[--d]=F}f=r,p=n+o,g=e+f,m=e-f,O=s+p;const y=s-p;return t[c++]=g,t[c++]=O,t[--d]=y,t[--d]=g,r&&(t[c++]=m,t[c++]=O,t[--d]=y,t[--d]=m),t},triangulate(i,t,e,s,r,n){if(i.length===0)return;let a=0,o=0;for(let c=0;c<i.length;c+=2)a+=i[c]
|
||
|
`:t,t}static _getFromCache(t,e,s,r){let n=s[t];return typeof n!="number"&&(n=rt._measureText(t,e,r)+e,s[t]=n),n}static _collapseSpaces(t){return t==="normal"||t==="pre-line"}static _collapseNewlines(t){return t==="normal"}static _trimRight(t){if(typeof t!="string")return"";for(let e=t.length-1;e>=0;e--){const s=t[e];if(!rt.isBreakingSpace(s))break;t=t.slice(0,-1)}return t}static _isNewline(t){return typeof t!="string"?!1:rt._newlines.includes(t.charCodeAt(0))}static isBreakingSpace(t,e){return typeof t!="string"?!1:rt._breakingSpaces.includes(t.charCodeAt(0))}static _tokenize(t){const e=[];let s="";if(typeof t!="string")return e;for(let r=0;r<t.length;r++){const n=t[r],a=t[r+1];if(rt.isBreakingSpace(n,a)||rt._isNewline(n)){s!==""&&(e.push(s),s=""),e.push(n);continue}s+=n}return s!==""&&e.push(s),e}static canBreakWords(t,e){return e}static canBreakChars(t,e,s,r,n){return!0}static wordWrapSplit(t){return rt.graphemeSegmenter(t)}static measureFont(t){if(rt._fonts[t])return rt._fonts[t];const e=rt._context;e.font=t;const s=e.measureText(rt.METRICS_STRING+rt.BASELINE_SYMBOL),r={ascent:s.actualBoundingBoxAscent,descent:s.actualBoundingBoxDescent,fontSize:s.actualBoundingBoxAscent+s.actualBoundingBoxDescent};return rt._fonts[t]=r,r}static clearMetrics(t=""){t?delete rt._fonts[t]:rt._fonts={}}static get _canvas(){if(!rt.__canvas){let t;try{const e=new OffscreenCanvas(0,0),s=e.getContext("2d",DE);if(s!=null&&s.measureText)return rt.__canvas=e,e;t=Wt.get().createCanvas()}catch{t=Wt.get().createCanvas()}t.width=t.height=10,rt.__canvas=t}return rt.__canvas}static get _context(){return rt.__context||(rt.__context=rt._canvas.getContext("2d",DE)),rt.__context}};Oi.METRICS_STRING="|ÉqÅ";Oi.BASELINE_SYMBOL="M";Oi.BASELINE_MULTIPLIER=1.4;Oi.HEIGHT_MULTIPLIER=2;Oi.graphemeSegmenter=(()=>{if(typeof(Intl==null?void 0:Intl.Segmenter)=="function"){const i=new Intl.Segmenter;return t=>[...i.segment(t)].map(e=>e.segment)}return i=>[...i]})();Oi.experimentalLetterSpacing=!1;Oi._fonts={};Oi._newlines=[10,13];Oi._breakingSpaces=[9,32,8192,8193,8194,8195,8196,8197,8198,8200,8201,8202,8287,12288];Oi._measurementCache={};let r_=Oi;function OT(i,t){if(i.texture===W.WHITE&&!i.fill)return Mt.shared.setValue(i.color).setAlpha(i.alpha??1).toHexa();if(i.fill){if(i.fill instanceof Tm){const e=i.fill,s=t.createPattern(e.texture.source.resource,"repeat"),r=e.transform.copyTo(ot.shared);return r.scale(e.texture.frame.width,e.texture.frame.height),s.setTransform(r),s}else if(i.fill instanceof kl){const e=i.fill;if(e.type==="linear"){const s=t.createLinearGradient(e.x0,e.y0,e.x1,e.y1);return e.gradientStops.forEach(r=>{s.addColorStop(r.offset,Mt.shared.setValue(r.color).toHex())}),s}}}else{const e=t.createPattern(i.texture.source.resource,"repeat"),s=i.matrix.copyTo(ot.shared);return s.scale(i.texture.frame.width,i.texture.frame.height),e.setTransform(s),e}return le("FillStyle not recognised",i),"red"}function EC(i){if(i==="")return[];typeof i=="string"&&(i=[i]);const t=[];for(let e=0,s=i.length;e<s;e++){const r=i[e];if(Array.isArray(r)){if(r.length!==2)throw new Error(`[BitmapFont]: Invalid character range length, expecting 2 got ${r.length}.`);if(r[0].length===0||r[1].length===0)throw new Error("[BitmapFont]: Invalid character delimiter.");const n=r[0].charCodeAt(0),a=r[1].charCodeAt(0);if(a<n)throw new Error("[BitmapFont]: Invalid character range.");for(let o=n,u=a;o<=u;o++)t.push(String.fromCharCode(o))}else t.push(...Array.from(r))}if(t.length===0)throw new Error("[BitmapFont]: Empty set when resolving characters.");return t}const TC=class IC extends qv{constructor(t){super(),this.resolution=1,this.pages=[],this._padding=0,this._measureCache=Object.create(null),this._currentChars=[],this._currentX=0,this._currentY=0,this._currentPageIndex=-1,this._skipKerning=!1;const e={...IC.defaultOptions,...t};this._textureSize=e.textureSize,this._mipmap=e.mipmap;const s=e.style.clone();e.overrideFill&&(s._fill.color=16777215,s._fill.alpha=1,s._fill.texture=W.WHITE,s._fill.fill=null),this.applyFillAsTint=e.overrideFill;const r=s.fontSize;s.fontSize=this.baseMeasuremen
|
||
|
`&&m!=="\r"&&m!==" "&&m!==" "&&(d=!0,_=Math.ceil(Math.max(N,_))),u+L>this._textureSize&&(l+=_,_=N,u=0,l+_>this._textureSize)){a.update();const x=this._nextPage();r=x.canvasAndContext.canvas,n=x.canvasAndContext.context,a=x.texture.source,l=0}const F=C/c-(((f=o.dropShadow)==null?void 0:f.distance)??0)-(((p=o._stroke)==null?void 0:p.width)??0);if(this.chars[m]={id:m.codePointAt(0),xOffset:-this._padding,yOffset:-this._padding,xAdvance:F,kerning:{}},d){this._drawGlyph(n,O,u+h,l+h,c,o);const x=a.width*c,U=a.height*c,k=new Kt(u/x*a.width,l/U*a.height,L/x*a.width,N/U*a.height);this.chars[m].texture=new W({source:a,frame:k}),u+=Math.ceil(L)}}a.update(),this._currentX=u,this._currentY=l,this._skipKerning&&this._applyKerning(e,n)}get pageTextures(){return ct(Te,"BitmapFont.pageTextures is deprecated, please use BitmapFont.pages instead."),this.pages}_applyKerning(t,e){const s=this._measureCache;for(let r=0;r<t.length;r++){const n=t[r];for(let a=0;a<this._currentChars.length;a++){const o=this._currentChars[a];let u=s[n];u||(u=s[n]=e.measureText(n).width);let l=s[o];l||(l=s[o]=e.measureText(o).width);let c=e.measureText(n+o).width,h=c-(u+l);h&&(this.chars[n].kerning[o]=h),c=e.measureText(n+o).width,h=c-(u+l),h&&(this.chars[o].kerning[n]=h)}}}_nextPage(){this._currentPageIndex++;const t=this.resolution,e=Vl.getOptimalCanvasAndContext(this._textureSize,this._textureSize,t);this._setupContext(e.context,this._style,t);const s=t*(this.baseRenderedFontSize/this.baseMeasurementFontSize),r=new W({source:new qa({resource:e.canvas,resolution:s,alphaMode:"premultiply-alpha-on-upload",autoGenerateMipmaps:this._mipmap})}),n={canvasAndContext:e,texture:r};return this.pages[this._currentPageIndex]=n,n}_setupContext(t,e,s){e.fontSize=this.baseRenderedFontSize,t.scale(s,s),t.font=i_(e),e.fontSize=this.baseMeasurementFontSize,t.textBaseline=e.textBaseline;const r=e._stroke,n=(r==null?void 0:r.width)??0;if(r&&(t.lineWidth=n,t.lineJoin=r.join,t.miterLimit=r.miterLimit,t.strokeStyle=OT(r,t)),e._fill&&(t.fillStyle=OT(e._fill,t)),e.dropShadow){const a=e.dropShadow,o=Mt.shared.setValue(a.color).toArray(),u=a.blur*s,l=a.distance*s;t.shadowColor=`rgba(${o[0]*255},${o[1]*255},${o[2]*255},${a.alpha})`,t.shadowBlur=u,t.shadowOffsetX=Math.cos(a.angle)*l,t.shadowOffsetY=Math.sin(a.angle)*l}else t.shadowColor="black",t.shadowBlur=0,t.shadowOffsetX=0,t.shadowOffsetY=0}_drawGlyph(t,e,s,r,n,a){const o=e.text,u=e.fontProperties,l=a._stroke,c=((l==null?void 0:l.width)??0)*n,h=s+c/2,_=r-c/2,d=u.descent*n,f=e.lineHeight*n;a.stroke&&c&&t.strokeText(o,h,_+f-d),a._fill&&t.fillText(o,h,_+f-d)}destroy(){super.destroy();for(let t=0;t<this.pages.length;t++){const{canvasAndContext:e,texture:s}=this.pages[t];Vl.returnCanvasAndContext(e),s.destroy(!0)}this.pages=null}};TC.defaultOptions={textureSize:512,style:new vn,mipmap:!0};let QO=TC;function SC(i,t,e,s){const r={width:0,height:0,offsetY:0,scale:t.fontSize/e.baseMeasurementFontSize,lines:[{width:0,charPositions:[],spaceWidth:0,spacesIndex:[],chars:[]}]};r.offsetY=e.baseLineOffset;let n=r.lines[0],a=null,o=!0;const u={spaceWord:!1,width:0,start:0,index:0,positions:[],chars:[]},l=f=>{const p=n.width;for(let g=0;g<u.index;g++){const m=f.positions[g];n.chars.push(f.chars[g]),n.charPositions.push(m+p)}n.width+=f.width,o=!1,u.width=0,u.index=0,u.chars.length=0},c=()=>{let f=n.chars.length-1;if(s){let p=n.chars[f];for(;p===" ";)n.width-=e.chars[p].xAdvance,p=n.chars[--f]}r.width=Math.max(r.width,n.width),n={width:0,charPositions:[],chars:[],spaceWidth:0,spacesIndex:[]},o=!0,r.lines.push(n),r.height+=e.lineHeight},h=e.baseMeasurementFontSize/t.fontSize,_=t.letterSpacing*h,d=t.wordWrapWidth*h;for(let f=0;f<i.length+1;f++){let p;const g=f===i.length;g||(p=i[f]);const m=e.chars[p]||e.chars[" "];if(/(?:\s)/.test(p)||p==="\r"||p===`
|
||
|
`||g){if(!o&&t.wordWrap&&n.width+u.width-_>d?(c(),l(u),g||n.charPositions.push(0)):(u.start=n.width,l(u),g||n.charPositions.push(0)),p==="\r"||p===`
|
||
|
`)n.width!==0&&c();else if(!g){const P=m.xAdvance+(m.kerning[a]||0)+_;n.width+=P,n.spaceWidth=P,n.spacesIndex.push(n.charPositions.length),n.chars.push(p)}}else{const C=m.kerning[a]||0,P=m.xAdvance+C+_;u.positions[u.index++]=u.width+C,u.chars.push(p),u.width+=P}a=p}return c(),t.align==="center"?$q(r):t.align==="right"?Qq(r):t.align==="justify"&&Zq(r),r}function $q(i){for(let t=0;t<i.lines.length;t++){const e=i.lines[t],s=i.width/2-e.width/2;for(let r=0;r<e.charPositions.length;r++)e.charPositions[r]+=s}}function Qq(i){for(let t=0;t<i.lines.length;t++){const e=i.lines[t],s=i.width-e.width;for(let r=0;r<e.charPositions.length;r++)e.charPositions[r]+=s}}function Zq(i){const t=i.width;for(let e=0;e<i.lines.length;e++){const s=i.lines[e];let r=0,n=s.spacesIndex[r++],a=0;const o=s.spacesIndex.length,l=(t-s.width)/o;for(let c=0;c<s.charPositions.length;c++)c===n&&(n=s.spacesIndex[r++],a+=l),s.charPositions[c]+=a}}let Rc=0;class Jq{constructor(){this.ALPHA=[["a","z"],["A","Z"]," "],this.NUMERIC=[["0","9"]],this.ALPHANUMERIC=[["a","z"],["A","Z"],["0","9"]," "],this.ASCII=[[" ","~"]],this.defaultOptions={chars:this.ALPHANUMERIC,resolution:1,padding:4,skipKerning:!1}}getFont(t,e){var a;let s=`${e.fontFamily}-bitmap`,r=!0;if(e._fill.fill&&!e._stroke)s+=e._fill.fill.styleKey,r=!1;else if(e._stroke||e.dropShadow){let o=e.styleKey;o=o.substring(0,o.lastIndexOf("-")),s=`${o}-bitmap`,r=!1}if(!de.has(s)){const o=new QO({style:e,overrideFill:r,overrideSize:!0,...this.defaultOptions});Rc++,Rc>50&&le("BitmapText",`You have dynamically created ${Rc} bitmap fonts, this can be inefficient. Try pre installing your font styles using \`BitmapFont.install({name:"style1", style})\``),o.once("destroy",()=>{Rc--,de.remove(s)}),de.set(s,o)}const n=de.get(s);return(a=n.ensureCharacters)==null||a.call(n,t),n}getLayout(t,e,s=!0){const r=this.getFont(t,e);return SC([...t],e,r,s)}measureText(t,e,s=!0){return this.getLayout(t,e,s)}install(...t){var l,c,h,_;let e=t[0];typeof e=="string"&&(e={name:e,style:t[1],chars:(l=t[2])==null?void 0:l.chars,resolution:(c=t[2])==null?void 0:c.resolution,padding:(h=t[2])==null?void 0:h.padding,skipKerning:(_=t[2])==null?void 0:_.skipKerning},ct(Te,"BitmapFontManager.install(name, style, options) is deprecated, use BitmapFontManager.install({name, style, ...options})"));const s=e==null?void 0:e.name;if(!s)throw new Error("[BitmapFontManager] Property `name` is required.");e={...this.defaultOptions,...e};const r=e.style,n=r instanceof vn?r:new vn(r),a=n._fill.fill!==null&&n._fill.fill!==void 0,o=new QO({style:n,overrideFill:a,skipKerning:e.skipKerning,padding:e.padding,resolution:e.resolution,overrideSize:!1}),u=EC(e.chars);return o.ensureCharacters(u.join("")),de.set(`${s}-bitmap`,o),o.once("destroy",()=>de.remove(`${s}-bitmap`)),o}uninstall(t){const e=`${t}-bitmap`,s=de.get(e);s&&s.destroy()}}const yT=new Jq;class RC extends qv{constructor(t,e){super();const{textures:s,data:r}=t;Object.keys(r.pages).forEach(n=>{const a=r.pages[parseInt(n,10)],o=s[a.id];this.pages.push({texture:o})}),Object.keys(r.chars).forEach(n=>{const a=r.chars[n],{frame:o,source:u}=s[a.page],l=new Kt(a.x+o.x,a.y+o.y,a.width,a.height),c=new W({source:u,frame:l});this.chars[n]={id:n.codePointAt(0),xOffset:a.xOffset,yOffset:a.yOffset,xAdvance:a.xAdvance,kerning:a.kerning??{},texture:c}}),this.baseRenderedFontSize=r.fontSize,this.baseMeasurementFontSize=r.fontSize,this.fontMetrics={ascent:0,descent:0,fontSize:r.fontSize},this.baseLineOffset=r.baseLineOffset,this.lineHeight=r.lineHeight,this.fontFamily=r.fontFamily,this.distanceField=r.distanceField??{type:"none",range:0},this.url=e}destroy(){super.destroy();for(let t=0;t<this.pages.length;t++){const{texture:e}=this.pages[t];e.destroy(!0)}this.pages=null}static install(t){yT.install(t)}static uninstall(t){yT.uninstall(t)}}const LE={test(i){return typeof i=="string"&&i.startsWith("info face=")},parse(i){const t=i.match(/^[a-z]+\s+.+$/gm),e={info:[],common:[],page:[],char:[],chars:[],kerning:[],kernings:[],distanceField:[]};for(const h in t){const _=t[h].match(/^[a-z]+/gm)[0],d=t[h].match(/[a-zA-Z]+=([^\s"']+
|
||
|
${h}`)}});return await Promise.all(u),n?r[a[0].src]:r}async unload(t){const s=mi(t,r=>({alias:[r],src:r})).map(async r=>{var o,u;const n=Os.toAbsolute(r.src),a=this.promiseCache[n];if(a){const l=await a.promise;delete this.promiseCache[n],await((u=(o=a.parser)==null?void 0:o.unload)==null?void 0:u.call(o,l,r,this))}});await Promise.all(s)}_validateParsers(){this._parsersValidated=!0,this._parserHash=this._parsers.filter(t=>t.name).reduce((t,e)=>(e.name?t[e.name]&&le(`[Assets] loadParser name conflict "${e.name}"`):le("[Assets] loadParser should have a name"),{...t,[e.name]:e}),{})}}function pu(i,t){if(Array.isArray(t)){for(const e of t)if(i.startsWith(`data:${e}`))return!0;return!1}return i.startsWith(`data:${t}`)}function mu(i,t){const e=i.split("?")[0],s=Os.extname(e).toLowerCase();return Array.isArray(t)?t.includes(s):s===t}const d$=".json",f$="application/json",g$={extension:{type:B.LoadParser,priority:Nn.Low},name:"loadJson",test(i){return pu(i,f$)||mu(i,d$)},async load(i){return await(await Wt.get().fetch(i)).json()}},p$=".txt",m$="text/plain",E$={name:"loadTxt",extension:{type:B.LoadParser,priority:Nn.Low,name:"loadTxt"},test(i){return pu(i,m$)||mu(i,p$)},async load(i){return await(await Wt.get().fetch(i)).text()}},T$=["normal","bold","100","200","300","400","500","600","700","800","900"],I$=[".ttf",".otf",".woff",".woff2"],S$=["font/ttf","font/otf","font/woff","font/woff2"],R$=/^(--|-?[A-Z_])[0-9A-Z_-]*$/i;function A$(i){const t=Os.extname(i),r=Os.basename(i,t).replace(/(-|_)/g," ").toLowerCase().split(" ").map(o=>o.charAt(0).toUpperCase()+o.slice(1));let n=r.length>0;for(const o of r)if(!o.match(R$)){n=!1;break}let a=r.join(" ");return n||(a=`"${a.replace(/[\\"]/g,"\\$&")}"`),a}const O$=/^[0-9A-Za-z%:/?#\[\]@!\$&'()\*\+,;=\-._~]*$/;function y$(i){return O$.test(i)?i:encodeURI(i)}const v$={extension:{type:B.LoadParser,priority:Nn.Low},name:"loadWebFont",test(i){return pu(i,S$)||mu(i,I$)},async load(i,t){var s,r,n;const e=Wt.get().getFontFaceSet();if(e){const a=[],o=((s=t.data)==null?void 0:s.family)??A$(i),u=((n=(r=t.data)==null?void 0:r.weights)==null?void 0:n.filter(c=>T$.includes(c)))??["normal"],l=t.data??{};for(let c=0;c<u.length;c++){const h=u[c],_=new FontFace(o,`url(${y$(i)})`,{...l,weight:h});await _.load(),e.add(_),a.push(_)}return de.set(`${o}-and-url`,{url:i,fontFaces:a}),a.length===1?a[0]:a}return le("[loadWebFont] FontFace API is not supported. Skipping loading font"),null},unload(i){(Array.isArray(i)?i:[i]).forEach(t=>{de.remove(t.family),Wt.get().getFontFaceSet().delete(t)})}};function ZI(i,t=1){var s;const e=(s=gu.RETINA_PREFIX)==null?void 0:s.exec(i);return e?parseFloat(e[1]):t}function JI(i,t,e){i.label=e,i._sourceOrigin=e;const s=new W({source:i,label:e}),r=()=>{delete t.promiseCache[e],de.has(e)&&de.remove(e)};return s.source.once("destroy",()=>{t.promiseCache[e]&&(le("[Assets] A TextureSource managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the TextureSource."),r())}),s.once("destroy",()=>{i.destroyed||(le("[Assets] A Texture managed by Assets was destroyed instead of unloaded! Use Assets.unload() instead of destroying the Texture."),r())}),s}const C$=".svg",M$="image/svg+xml",x$={extension:{type:B.LoadParser,priority:Nn.Low,name:"loadSVG"},name:"loadSVG",config:{crossOrigin:"anonymous",parseAsGraphicsContext:!1},test(i){return pu(i,M$)||mu(i,C$)},async load(i,t,e){return t.data.parseAsGraphicsContext??this.config.parseAsGraphicsContext?b$(i):P$(i,t,e,this.config.crossOrigin)},unload(i){i.destroy(!0)}};async function P$(i,t,e,s){var g,m,O;const n=await(await Wt.get().fetch(i)).blob(),a=URL.createObjectURL(n),o=new Image;o.src=a,o.crossOrigin=s,await o.decode(),URL.revokeObjectURL(a);const u=document.createElement("canvas"),l=u.getContext("2d"),c=((g=t.data)==null?void 0:g.resolution)||ZI(i),h=((m=t.data)==null?void 0:m.width)??o.width,_=((O=t.data)==null?void 0:O.height)??o.height;u.width=h*c,u.height=_*c,l.drawImage(o,0,0,h*c,_*c);const{parseAsGraphicsContext:d,...f}=t.data,p=new qa({resource:u,alphaMode:"premultiply-alpha-on-upload",resolution
|
||
|
'use strict';
|
||
|
|
||
|
const WHITE_PNG = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=";
|
||
|
async function checkImageBitmap() {
|
||
|
try {
|
||
|
if (typeof createImageBitmap !== "function")
|
||
|
return false;
|
||
|
const response = await fetch(WHITE_PNG);
|
||
|
const imageBlob = await response.blob();
|
||
|
const imageBitmap = await createImageBitmap(imageBlob);
|
||
|
return imageBitmap.width === 1 && imageBitmap.height === 1;
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
void checkImageBitmap().then((result) => {
|
||
|
self.postMessage(result);
|
||
|
});
|
||
|
|
||
|
})();
|
||
|
`;let Vo=null,vT=class{constructor(){Vo||(Vo=URL.createObjectURL(new Blob([N$],{type:"application/javascript"}))),this.worker=new Worker(Vo)}};vT.revokeObjectURL=function(){Vo&&(URL.revokeObjectURL(Vo),Vo=null)};const U$=`(function () {
|
||
|
'use strict';
|
||
|
|
||
|
async function loadImageBitmap(url, alphaMode) {
|
||
|
const response = await fetch(url);
|
||
|
if (!response.ok) {
|
||
|
throw new Error(\`[WorkerManager.loadImageBitmap] Failed to fetch \${url}: \${response.status} \${response.statusText}\`);
|
||
|
}
|
||
|
const imageBlob = await response.blob();
|
||
|
return alphaMode === "premultiplied-alpha" ? createImageBitmap(imageBlob, { premultiplyAlpha: "none" }) : createImageBitmap(imageBlob);
|
||
|
}
|
||
|
self.onmessage = async (event) => {
|
||
|
try {
|
||
|
const imageBitmap = await loadImageBitmap(event.data.data[0], event.data.data[1]);
|
||
|
self.postMessage({
|
||
|
data: imageBitmap,
|
||
|
uuid: event.data.uuid,
|
||
|
id: event.data.id
|
||
|
}, [imageBitmap]);
|
||
|
} catch (e) {
|
||
|
self.postMessage({
|
||
|
error: e,
|
||
|
uuid: event.data.uuid,
|
||
|
id: event.data.id
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
})();
|
||
|
`;let Ho=null;class OC{constructor(){Ho||(Ho=URL.createObjectURL(new Blob([U$],{type:"application/javascript"}))),this.worker=new Worker(Ho)}}OC.revokeObjectURL=function(){Ho&&(URL.revokeObjectURL(Ho),Ho=null)};let ey=0,FE;class D${constructor(){this._initialized=!1,this._createdWorkers=0,this._workerPool=[],this._queue=[],this._resolveHash={}}isImageBitmapSupported(){return this._isImageBitmapSupported!==void 0?this._isImageBitmapSupported:(this._isImageBitmapSupported=new Promise(t=>{const{worker:e}=new vT;e.addEventListener("message",s=>{e.terminate(),vT.revokeObjectURL(),t(s.data)})}),this._isImageBitmapSupported)}loadImageBitmap(t,e){var s;return this._run("loadImageBitmap",[t,(s=e==null?void 0:e.data)==null?void 0:s.alphaMode])}async _initWorkers(){this._initialized||(this._initialized=!0)}_getWorker(){FE===void 0&&(FE=navigator.hardwareConcurrency||4);let t=this._workerPool.pop();return!t&&this._createdWorkers<FE&&(this._createdWorkers++,t=new OC().worker,t.addEventListener("message",e=>{this._complete(e.data),this._returnWorker(e.target),this._next()})),t}_returnWorker(t){this._workerPool.push(t)}_complete(t){t.error!==void 0?this._resolveHash[t.uuid].reject(t.error):this._resolveHash[t.uuid].resolve(t.data),this._resolveHash[t.uuid]=null}async _run(t,e){await this._initWorkers();const s=new Promise((r,n)=>{this._queue.push({id:t,arguments:e,resolve:r,reject:n})});return this._next(),s}_next(){if(!this._queue.length)return;const t=this._getWorker();if(!t)return;const e=this._queue.pop(),s=e.id;this._resolveHash[ey]={resolve:e.resolve,reject:e.reject},t.postMessage({data:e.arguments,uuid:ey++,id:s})}}const sy=new D$,L$=[".jpeg",".jpg",".png",".webp",".avif"],F$=["image/jpeg","image/png","image/webp","image/avif"];async function w$(i,t){var r;const e=await Wt.get().fetch(i);if(!e.ok)throw new Error(`[loadImageBitmap] Failed to fetch ${i}: ${e.status} ${e.statusText}`);const s=await e.blob();return((r=t==null?void 0:t.data)==null?void 0:r.alphaMode)==="premultiplied-alpha"?createImageBitmap(s,{premultiplyAlpha:"none"}):createImageBitmap(s)}const yC={name:"loadTextures",extension:{type:B.LoadParser,priority:Nn.High,name:"loadTextures"},config:{preferWorkers:!0,preferCreateImageBitmap:!0,crossOrigin:"anonymous"},test(i){return pu(i,F$)||mu(i,L$)},async load(i,t,e){var n;let s=null;globalThis.createImageBitmap&&this.config.preferCreateImageBitmap?this.config.preferWorkers&&await sy.isImageBitmapSupported()?s=await sy.loadImageBitmap(i,t):s=await w$(i,t):s=await new Promise(a=>{s=new Image,s.crossOrigin=this.config.crossOrigin,s.src=i,s.complete?a(s):s.onload=()=>{a(s)}});const r=new qa({resource:s,alphaMode:"premultiply-alpha-on-upload",resolution:((n=t.data)==null?void 0:n.resolution)||ZI(i),...t.data});return JI(r,e,i)},unload(i){i.destroy(!0)}},vC=[".mp4",".m4v",".webm",".ogg",".ogv",".h264",".avi",".mov"],G$=vC.map(i=>`video/${i.substring(1)}`);function B$(i,t,e){e===void 0&&!t.startsWith("data:")?i.crossOrigin=z$(t):e!==!1&&(i.crossOrigin=typeof e=="string"?e:"anonymous")}function k$(i){return new Promise((t,e)=>{i.addEventListener("canplaythrough",s),i.addEventListener("error",r),i.load();function s(){n(),t()}function r(a){n(),e(a)}function n(){i.removeEventListener("canplaythrough",s),i.removeEventListener("error",r)}})}function z$(i,t=globalThis.location){if(i.startsWith("data:"))return"";t=t||globalThis.location;const e=new URL(i,document.baseURI);return e.hostname!==t.hostname||e.port!==t.port||e.protocol!==t.protocol?"anonymous":""}const V$={name:"loadVideo",extension:{type:B.LoadParser,name:"loadVideo"},test(i){const t=pu(i,G$),e=mu(i,vC);return t||e},async load(i,t,e){var u,l;const s={...Pc.defaultOptions,resolution:((u=t.data)==null?void 0:u.resolution)||ZI(i),alphaMode:((l=t.data)==null?void 0:l.alphaMode)||await Ov(),...t.data},r=document.createElement("video"),n={preload:s.autoLoad!==!1?"auto":void 0,"webkit-playsinline":s.playsinline!==!1?"":void 0,playsinline:s.playsinline!==!1?"":void 0,muted:s.muted===!0?"":void 0,loop:s.loop===!0?"":void 0,autoplay:s.autoPlay!==!1?"":void 0};Object.keys(n).forEac
|
||
|
out vec2 vTextureCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
}
|
||
|
`,W$=`
|
||
|
in vec2 vTextureCoord;
|
||
|
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform float uAlpha;
|
||
|
uniform sampler2D uTexture;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
finalColor = texture(uTexture, vTextureCoord) * uAlpha;
|
||
|
}
|
||
|
`,ry=`struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
struct AlphaUniforms {
|
||
|
uAlpha:f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler : sampler;
|
||
|
|
||
|
@group(1) @binding(0) var<uniform> alphaUniforms : AlphaUniforms;
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
|
||
|
}
|
||
|
|
||
|
fn getSize() -> vec2<f32>
|
||
|
{
|
||
|
return gfu.uGlobalFrame.zw;
|
||
|
}
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
filterTextureCoord(aPosition)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
var sample = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
return sample * alphaUniforms.uAlpha;
|
||
|
}`;const xC=class PC extends xt{constructor(t){t={...PC.defaultOptions,...t};const e=At.from({vertex:{source:ry,entryPoint:"mainVertex"},fragment:{source:ry,entryPoint:"mainFragment"}}),s=Tt.from({vertex:MC,fragment:W$,name:"alpha-filter"}),{alpha:r,...n}=t,a=new Yr({uAlpha:{value:r,type:"f32"}});super({...n,gpuProgram:e,glProgram:s,resources:{alphaUniforms:a}})}get alpha(){return this.resources.alphaUniforms.uniforms.uAlpha}set alpha(t){this.resources.alphaUniforms.uniforms.uAlpha=t}};xC.defaultOptions={alpha:1};let n_=xC,j$=0;class K${constructor(t){this._poolKeyHash=Object.create(null),this._texturePool={},this.textureOptions=t||{},this.enableFullScreen=!1}createTexture(t,e,s){const r=new De({...this.textureOptions,width:t,height:e,resolution:1,antialias:s,autoGarbageCollect:!0});return new W({source:r,label:`texturePool_${j$++}`})}getOptimalTexture(t,e,s=1,r){let n=Math.ceil(t*s-1e-6),a=Math.ceil(e*s-1e-6);n=Dl(n),a=Dl(a);const o=(n<<17)+(a<<1)+(r?1:0);this._texturePool[o]||(this._texturePool[o]=[]);let u=this._texturePool[o].pop();return u||(u=this.createTexture(n,a,r)),u.source._resolution=s,u.source.width=n/s,u.source.height=a/s,u.source.pixelWidth=n,u.source.pixelHeight=a,u.frame.x=0,u.frame.y=0,u.frame.width=t,u.frame.height=e,u.updateUvs(),this._poolKeyHash[u.uid]=o,u}getSameSizeTexture(t,e=!1){const s=t.source;return this.getOptimalTexture(t.width,t.height,s._resolution,e)}returnTexture(t){const e=this._poolKeyHash[t.uid];this._texturePool[e].push(t)}clear(t){if(t=t!==!1,t)for(const e in this._texturePool){const s=this._texturePool[e];if(s)for(let r=0;r<s.length;r++)s[r].destroy(!0)}this._texturePool={}}}const os=new K$,bC={5:[.153388,.221461,.250301],7:[.071303,.131514,.189879,.214607],9:[.028532,.067234,.124009,.179044,.20236],11:[.0093,.028002,.065984,.121703,.175713,.198596],13:[.002406,.009255,.027867,.065666,.121117,.174868,.197641],15:[489e-6,.002403,.009246,.02784,.065602,.120999,.174697,.197448]},X$=["in vec2 vBlurTexCoords[%size%];","uniform sampler2D uTexture;","out vec4 finalColor;","void main(void)","{"," finalColor = vec4(0.0);"," %blur%","}"].join(`
|
||
|
`);function q$(i){const t=bC[i],e=t.length;let s=X$,r="";const n="finalColor += texture(uTexture, vBlurTexCoords[%index%]) * %value%;";let a;for(let o=0;o<i;o++){let u=n.replace("%index%",o.toString());a=o,o>=e&&(a=i-o-1),u=u.replace("%value%",t[a].toString()),r+=u,r+=`
|
||
|
`}return s=s.replace("%blur%",r),s=s.replace("%size%",i.toString()),s}const $$=`
|
||
|
in vec2 aPosition;
|
||
|
|
||
|
uniform float uStrength;
|
||
|
|
||
|
out vec2 vBlurTexCoords[%size%];
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
|
||
|
float pixelStrength = uInputSize.%dimension% * uStrength;
|
||
|
|
||
|
vec2 textureCoord = filterTextureCoord();
|
||
|
%blur%
|
||
|
}`;function Q$(i,t){const e=Math.ceil(i/2);let s=$$,r="",n;t?n="vBlurTexCoords[%index%] = textureCoord + vec2(%sampleIndex% * pixelStrength, 0.0);":n="vBlurTexCoords[%index%] = textureCoord + vec2(0.0, %sampleIndex% * pixelStrength);";for(let a=0;a<i;a++){let o=n.replace("%index%",a.toString());o=o.replace("%sampleIndex%",`${a-(e-1)}.0`),r+=o,r+=`
|
||
|
`}return s=s.replace("%blur%",r),s=s.replace("%size%",i.toString()),s=s.replace("%dimension%",t?"z":"w"),s}function Z$(i,t){const e=Q$(t,i),s=q$(t);return Tt.from({vertex:e,fragment:s,name:`blur-${i?"horizontal":"vertical"}-pass-filter`})}var J$=`
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
struct BlurUniforms {
|
||
|
uStrength:f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler : sampler;
|
||
|
|
||
|
@group(1) @binding(0) var<uniform> blurUniforms : BlurUniforms;
|
||
|
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
%blur-struct%
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
|
||
|
}
|
||
|
|
||
|
fn getSize() -> vec2<f32>
|
||
|
{
|
||
|
return gfu.uGlobalFrame.zw;
|
||
|
}
|
||
|
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
|
||
|
let filteredCord = filterTextureCoord(aPosition);
|
||
|
|
||
|
let pixelStrength = gfu.uInputSize.%dimension% * blurUniforms.uStrength;
|
||
|
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
%blur-vertex-out%
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
%blur-fragment-in%
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
var finalColor = vec4(0.0);
|
||
|
|
||
|
%blur-sampling%
|
||
|
|
||
|
return finalColor;
|
||
|
}`;function tQ(i,t){const e=bC[t],s=e.length,r=[],n=[],a=[];for(let h=0;h<t;h++){r[h]=`@location(${h}) offset${h}: vec2<f32>,`,i?n[h]=`filteredCord + vec2(${h-s+1} * pixelStrength, 0.0),`:n[h]=`filteredCord + vec2(0.0, ${h-s+1} * pixelStrength),`;const _=h<s?h:t-h-1,d=e[_].toString();a[h]=`finalColor += textureSample(uTexture, uSampler, offset${h}) * ${d};`}const o=r.join(`
|
||
|
`),u=n.join(`
|
||
|
`),l=a.join(`
|
||
|
`),c=J$.replace("%blur-struct%",o).replace("%blur-vertex-out%",u).replace("%blur-fragment-in%",o).replace("%blur-sampling%",l).replace("%dimension%",i?"z":"w");return At.from({vertex:{source:c,entryPoint:"mainVertex"},fragment:{source:c,entryPoint:"mainFragment"}})}const NC=class UC extends xt{constructor(t){t={...UC.defaultOptions,...t};const e=Z$(t.horizontal,t.kernelSize),s=tQ(t.horizontal,t.kernelSize);super({glProgram:e,gpuProgram:s,resources:{blurUniforms:{uStrength:{value:0,type:"f32"}}},...t}),this.horizontal=t.horizontal,this._quality=0,this.quality=t.quality,this.blur=t.strength,this._uniforms=this.resources.blurUniforms.uniforms}apply(t,e,s,r){if(this._uniforms.uStrength=this.strength/this.passes,this.passes===1)t.applyFilter(this,e,s,r);else{const n=os.getSameSizeTexture(e);let a=e,o=n;this._state.blend=!1;const u=t.renderer.type===ir.WEBGPU;for(let l=0;l<this.passes-1;l++){t.applyFilter(this,a,o,l===0?!0:u);const c=o;o=a,a=c}this._state.blend=!0,t.applyFilter(this,a,s,r),os.returnTexture(n)}}get blur(){return this.strength}set blur(t){this.padding=1+Math.abs(t)*2,this.strength=t}get quality(){return this._quality}set quality(t){this._quality=t,this.passes=t}};NC.defaultOptions={strength:8,quality:4,kernelSize:5};let ny=NC;var eQ=`
|
||
|
in vec2 vTextureCoord;
|
||
|
in vec4 vColor;
|
||
|
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform float uColorMatrix[20];
|
||
|
uniform float uAlpha;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
|
||
|
float rand(vec2 co)
|
||
|
{
|
||
|
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
float randomValue = rand(gl_FragCoord.xy * 0.2);
|
||
|
float diff = (randomValue - 0.5) * 0.5;
|
||
|
|
||
|
if (uAlpha == 0.0) {
|
||
|
finalColor = color;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (color.a > 0.0) {
|
||
|
color.rgb /= color.a;
|
||
|
}
|
||
|
|
||
|
vec4 result;
|
||
|
|
||
|
result.r = (uColorMatrix[0] * color.r);
|
||
|
result.r += (uColorMatrix[1] * color.g);
|
||
|
result.r += (uColorMatrix[2] * color.b);
|
||
|
result.r += (uColorMatrix[3] * color.a);
|
||
|
result.r += uColorMatrix[4];
|
||
|
|
||
|
result.g = (uColorMatrix[5] * color.r);
|
||
|
result.g += (uColorMatrix[6] * color.g);
|
||
|
result.g += (uColorMatrix[7] * color.b);
|
||
|
result.g += (uColorMatrix[8] * color.a);
|
||
|
result.g += uColorMatrix[9];
|
||
|
|
||
|
result.b = (uColorMatrix[10] * color.r);
|
||
|
result.b += (uColorMatrix[11] * color.g);
|
||
|
result.b += (uColorMatrix[12] * color.b);
|
||
|
result.b += (uColorMatrix[13] * color.a);
|
||
|
result.b += uColorMatrix[14];
|
||
|
|
||
|
result.a = (uColorMatrix[15] * color.r);
|
||
|
result.a += (uColorMatrix[16] * color.g);
|
||
|
result.a += (uColorMatrix[17] * color.b);
|
||
|
result.a += (uColorMatrix[18] * color.a);
|
||
|
result.a += uColorMatrix[19];
|
||
|
|
||
|
vec3 rgb = mix(color.rgb, result.rgb, uAlpha);
|
||
|
|
||
|
// Premultiply alpha again.
|
||
|
rgb *= result.a;
|
||
|
|
||
|
finalColor = vec4(rgb, result.a);
|
||
|
}
|
||
|
`,ay=`struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
struct ColorMatrixUniforms {
|
||
|
uColorMatrix:array<vec4<f32>, 5>,
|
||
|
uAlpha:f32,
|
||
|
};
|
||
|
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler : sampler;
|
||
|
@group(1) @binding(0) var<uniform> colorMatrixUniforms : ColorMatrixUniforms;
|
||
|
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>,
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
filterTextureCoord(aPosition),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
|
||
|
var c = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
if (colorMatrixUniforms.uAlpha == 0.0) {
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
|
||
|
// Un-premultiply alpha before applying the color matrix. See issue #3539.
|
||
|
if (c.a > 0.0) {
|
||
|
c.r /= c.a;
|
||
|
c.g /= c.a;
|
||
|
c.b /= c.a;
|
||
|
}
|
||
|
|
||
|
var cm = colorMatrixUniforms.uColorMatrix;
|
||
|
|
||
|
|
||
|
var result = vec4<f32>(0.);
|
||
|
|
||
|
result.r = (cm[0][0] * c.r);
|
||
|
result.r += (cm[0][1] * c.g);
|
||
|
result.r += (cm[0][2] * c.b);
|
||
|
result.r += (cm[0][3] * c.a);
|
||
|
result.r += cm[1][0];
|
||
|
|
||
|
result.g = (cm[1][1] * c.r);
|
||
|
result.g += (cm[1][2] * c.g);
|
||
|
result.g += (cm[1][3] * c.b);
|
||
|
result.g += (cm[2][0] * c.a);
|
||
|
result.g += cm[2][1];
|
||
|
|
||
|
result.b = (cm[2][2] * c.r);
|
||
|
result.b += (cm[2][3] * c.g);
|
||
|
result.b += (cm[3][0] * c.b);
|
||
|
result.b += (cm[3][1] * c.a);
|
||
|
result.b += cm[3][2];
|
||
|
|
||
|
result.a = (cm[3][3] * c.r);
|
||
|
result.a += (cm[4][0] * c.g);
|
||
|
result.a += (cm[4][1] * c.b);
|
||
|
result.a += (cm[4][2] * c.a);
|
||
|
result.a += cm[4][3];
|
||
|
|
||
|
var rgb = mix(c.rgb, result.rgb, colorMatrixUniforms.uAlpha);
|
||
|
|
||
|
rgb.r *= result.a;
|
||
|
rgb.g *= result.a;
|
||
|
rgb.b *= result.a;
|
||
|
|
||
|
return vec4(rgb, result.a);
|
||
|
}`;class ju extends xt{constructor(t={}){const e=new Yr({uColorMatrix:{value:[1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0],type:"f32",size:20},uAlpha:{value:1,type:"f32"}}),s=At.from({vertex:{source:ay,entryPoint:"mainVertex"},fragment:{source:ay,entryPoint:"mainFragment"}}),r=Tt.from({vertex:MC,fragment:eQ,name:"color-matrix-filter"});super({...t,gpuProgram:s,glProgram:r,resources:{colorMatrixUniforms:e}}),this.alpha=1}_loadMatrix(t,e=!1){let s=t;e&&(this._multiply(s,this.matrix,t),s=this._colorMatrix(s)),this.resources.colorMatrixUniforms.uniforms.uColorMatrix=s,this.resources.colorMatrixUniforms.update()}_multiply(t,e,s){return t[0]=e[0]*s[0]+e[1]*s[5]+e[2]*s[10]+e[3]*s[15],t[1]=e[0]*s[1]+e[1]*s[6]+e[2]*s[11]+e[3]*s[16],t[2]=e[0]*s[2]+e[1]*s[7]+e[2]*s[12]+e[3]*s[17],t[3]=e[0]*s[3]+e[1]*s[8]+e[2]*s[13]+e[3]*s[18],t[4]=e[0]*s[4]+e[1]*s[9]+e[2]*s[14]+e[3]*s[19]+e[4],t[5]=e[5]*s[0]+e[6]*s[5]+e[7]*s[10]+e[8]*s[15],t[6]=e[5]*s[1]+e[6]*s[6]+e[7]*s[11]+e[8]*s[16],t[7]=e[5]*s[2]+e[6]*s[7]+e[7]*s[12]+e[8]*s[17],t[8]=e[5]*s[3]+e[6]*s[8]+e[7]*s[13]+e[8]*s[18],t[9]=e[5]*s[4]+e[6]*s[9]+e[7]*s[14]+e[8]*s[19]+e[9],t[10]=e[10]*s[0]+e[11]*s[5]+e[12]*s[10]+e[13]*s[15],t[11]=e[10]*s[1]+e[11]*s[6]+e[12]*s[11]+e[13]*s[16],t[12]=e[10]*s[2]+e[11]*s[7]+e[12]*s[12]+e[13]*s[17],t[13]=e[10]*s[3]+e[11]*s[8]+e[12]*s[13]+e[13]*s[18],t[14]=e[10]*s[4]+e[11]*s[9]+e[12]*s[14]+e[13]*s[19]+e[14],t[15]=e[15]*s[0]+e[16]*s[5]+e[17]*s[10]+e[18]*s[15],t[16]=e[15]*s[1]+e[16]*s[6]+e[17]*s[11]+e[18]*s[16],t[17]=e[15]*s[2]+e[16]*s[7]+e[17]*s[12]+e[18]*s[17],t[18]=e[15]*s[3]+e[16]*s[8]+e[17]*s[13]+e[18]*s[18],t[19]=e[15]*s[4]+e[16]*s[9]+e[17]*s[14]+e[18]*s[19]+e[19],t}_colorMatrix(t){const e=new Float32Array(t);return e[4]/=255,e[9]/=255,e[14]/=255,e[19]/=255,e}brightness(t,e){const s=[t,0,0,0,0,0,t,0,0,0,0,0,t,0,0,0,0,0,1,0];this._loadMatrix(s,e)}tint(t,e){const[s,r,n]=Mt.shared.setValue(t).toArray(),a=[s,0,0,0,0,0,r,0,0,0,0,0,n,0,0,0,0,0,1,0];this._loadMatrix(a,e)}greyscale(t,e){const s=[t,t,t,0,0,t,t,t,0,0,t,t,t,0,0,0,0,0,1,0];this._loadMatrix(s,e)}grayscale(t,e){this.greyscale(t,e)}blackAndWhite(t){const e=[.3,.6,.1,0,0,.3,.6,.1,0,0,.3,.6,.1,0,0,0,0,0,1,0];this._loadMatrix(e,t)}hue(t,e){t=(t||0)/180*Math.PI;const s=Math.cos(t),r=Math.sin(t),n=Math.sqrt,a=1/3,o=n(a),u=s+(1-s)*a,l=a*(1-s)-o*r,c=a*(1-s)+o*r,h=a*(1-s)+o*r,_=s+a*(1-s),d=a*(1-s)-o*r,f=a*(1-s)-o*r,p=a*(1-s)+o*r,g=s+a*(1-s),m=[u,l,c,0,0,h,_,d,0,0,f,p,g,0,0,0,0,0,1,0];this._loadMatrix(m,e)}contrast(t,e){const s=(t||0)+1,r=-.5*(s-1),n=[s,0,0,0,r,0,s,0,0,r,0,0,s,0,r,0,0,0,1,0];this._loadMatrix(n,e)}saturate(t=0,e){const s=t*2/3+1,r=(s-1)*-.5,n=[s,r,r,0,0,r,s,r,0,0,r,r,s,0,0,0,0,0,1,0];this._loadMatrix(n,e)}desaturate(){this.saturate(-1)}negative(t){const e=[-1,0,0,1,0,0,-1,0,1,0,0,0,-1,1,0,0,0,0,1,0];this._loadMatrix(e,t)}sepia(t){const e=[.393,.7689999,.18899999,0,0,.349,.6859999,.16799999,0,0,.272,.5339999,.13099999,0,0,0,0,0,1,0];this._loadMatrix(e,t)}technicolor(t){const e=[1.9125277891456083,-.8545344976951645,-.09155508482755585,0,11.793603434377337,-.3087833385928097,1.7658908555458428,-.10601743074722245,0,-70.35205161461398,-.231103377548616,-.7501899197440212,1.847597816108189,0,30.950940869491138,0,0,0,1,0];this._loadMatrix(e,t)}polaroid(t){const e=[1.438,-.062,-.062,0,0,-.122,1.378,-.122,0,0,-.016,-.016,1.483,0,0,0,0,0,1,0];this._loadMatrix(e,t)}toBGR(t){const e=[0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,0];this._loadMatrix(e,t)}kodachrome(t){const e=[1.1285582396593525,-.3967382283601348,-.03992559172921793,0,63.72958762196502,-.16404339962244616,1.0835251566291304,-.05498805115633132,0,24.732407896706203,-.16786010706155763,-.5603416277695248,1.6014850761964943,0,35.62982807460946,0,0,0,1,0];this._loadMatrix(e,t)}browni(t){const e=[.5997023498159715,.34553243048391263,-.2708298674538042,0,47.43192855600873,-.037703249837783157,.8609577587992641,.15059552388459913,0,-36.96841498319127,.24113635128153335,-.07441037908422492,.44972182064877153,0,-7.562075277591283,0,0,0,1,0];this._loadMatrix(e,t)}vintage(t){const e=[.6279345635605994,.3202183420819367,-.03965408211312453,0,9.651285835294123,.02578397
|
||
|
in vec2 vTextureCoord;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uMaskTexture;
|
||
|
|
||
|
uniform float uAlpha;
|
||
|
uniform vec4 uMaskClamp;
|
||
|
uniform float uInverse;
|
||
|
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
float clip = step(3.5,
|
||
|
step(uMaskClamp.x, vMaskCoord.x) +
|
||
|
step(uMaskClamp.y, vMaskCoord.y) +
|
||
|
step(vMaskCoord.x, uMaskClamp.z) +
|
||
|
step(vMaskCoord.y, uMaskClamp.w));
|
||
|
|
||
|
// TODO look into why this is needed
|
||
|
float npmAlpha = uAlpha;
|
||
|
vec4 original = texture(uTexture, vTextureCoord);
|
||
|
vec4 masky = texture(uMaskTexture, vMaskCoord);
|
||
|
float alphaMul = 1.0 - npmAlpha * (1.0 - masky.a);
|
||
|
|
||
|
float a = alphaMul * masky.r * npmAlpha * clip;
|
||
|
|
||
|
if (uInverse == 1.0) {
|
||
|
a = 1.0 - a;
|
||
|
}
|
||
|
|
||
|
finalColor = original * a;
|
||
|
}
|
||
|
`,iQ=`in vec2 aPosition;
|
||
|
|
||
|
out vec2 vTextureCoord;
|
||
|
out vec2 vMaskCoord;
|
||
|
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
uniform mat3 uFilterMatrix;
|
||
|
|
||
|
vec4 filterVertexPosition( vec2 aPosition )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( vec2 aPosition )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
vec2 getFilterCoord( vec2 aPosition )
|
||
|
{
|
||
|
return ( uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0) ).xy;
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition(aPosition);
|
||
|
vTextureCoord = filterTextureCoord(aPosition);
|
||
|
vMaskCoord = getFilterCoord(aPosition);
|
||
|
}
|
||
|
`,oy=`struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
struct MaskUniforms {
|
||
|
uFilterMatrix:mat3x3<f32>,
|
||
|
uMaskClamp:vec4<f32>,
|
||
|
uAlpha:f32,
|
||
|
uInverse:f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler : sampler;
|
||
|
|
||
|
@group(1) @binding(0) var<uniform> filterUniforms : MaskUniforms;
|
||
|
@group(1) @binding(1) var uMaskTexture: texture_2d<f32>;
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>,
|
||
|
@location(1) filterUv : vec2<f32>,
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
|
||
|
}
|
||
|
|
||
|
fn getFilterCoord(aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return ( filterUniforms.uFilterMatrix * vec3( filterTextureCoord(aPosition), 1.0) ).xy;
|
||
|
}
|
||
|
|
||
|
fn getSize() -> vec2<f32>
|
||
|
{
|
||
|
return gfu.uGlobalFrame.zw;
|
||
|
}
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
filterTextureCoord(aPosition),
|
||
|
getFilterCoord(aPosition)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@location(1) filterUv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
var maskClamp = filterUniforms.uMaskClamp;
|
||
|
var uAlpha = filterUniforms.uAlpha;
|
||
|
|
||
|
var clip = step(3.5,
|
||
|
step(maskClamp.x, filterUv.x) +
|
||
|
step(maskClamp.y, filterUv.y) +
|
||
|
step(filterUv.x, maskClamp.z) +
|
||
|
step(filterUv.y, maskClamp.w));
|
||
|
|
||
|
var mask = textureSample(uMaskTexture, uSampler, filterUv);
|
||
|
var source = textureSample(uTexture, uSampler, uv);
|
||
|
var alphaMul = 1.0 - uAlpha * (1.0 - mask.a);
|
||
|
|
||
|
var a: f32 = alphaMul * mask.r * uAlpha * clip;
|
||
|
|
||
|
if (filterUniforms.uInverse == 1.0) {
|
||
|
a = 1.0 - a;
|
||
|
}
|
||
|
|
||
|
return source * a;
|
||
|
}
|
||
|
`;class rQ extends xt{constructor(t){const{sprite:e,...s}=t,r=new av(e.texture),n=new Yr({uFilterMatrix:{value:new ot,type:"mat3x3<f32>"},uMaskClamp:{value:r.uClampFrame,type:"vec4<f32>"},uAlpha:{value:1,type:"f32"},uInverse:{value:t.inverse?1:0,type:"f32"}}),a=At.from({vertex:{source:oy,entryPoint:"mainVertex"},fragment:{source:oy,entryPoint:"mainFragment"}}),o=Tt.from({vertex:iQ,fragment:sQ,name:"mask-filter"});super({...s,gpuProgram:a,glProgram:o,resources:{filterUniforms:n,uMaskTexture:e.texture.source}}),this.sprite=e,this._textureMatrix=r}set inverse(t){this.resources.filterUniforms.uniforms.uInverse=t?1:0}get inverse(){return this.resources.filterUniforms.uniforms.uInverse===1}apply(t,e,s,r){this._textureMatrix.texture=this.sprite.texture,t.calculateSpriteMatrix(this.resources.filterUniforms.uniforms.uFilterMatrix,this.sprite).prepend(this._textureMatrix.mapCoord),this.resources.uMaskTexture=this.sprite.texture.source,t.applyFilter(this,e,s,r)}}class nQ{constructor({matrix:t,observer:e}={}){this.dirty=!0,this._matrix=t??new ot,this.observer=e,this.position=new Pe(this,0,0),this.scale=new Pe(this,1,1),this.pivot=new Pe(this,0,0),this.skew=new Pe(this,0,0),this._rotation=0,this._cx=1,this._sx=0,this._cy=0,this._sy=1}get matrix(){const t=this._matrix;return this.dirty&&(t.a=this._cx*this.scale.x,t.b=this._sx*this.scale.x,t.c=this._cy*this.scale.y,t.d=this._sy*this.scale.y,t.tx=this.position.x-(this.pivot.x*t.a+this.pivot.y*t.c),t.ty=this.position.y-(this.pivot.x*t.b+this.pivot.y*t.d),this.dirty=!1),t}_onUpdate(t){var e;this.dirty=!0,t===this.skew&&this.updateSkew(),(e=this.observer)==null||e._onUpdate(this)}updateSkew(){this._cx=Math.cos(this._rotation+this.skew.y),this._sx=Math.sin(this._rotation+this.skew.y),this._cy=-Math.sin(this._rotation-this.skew.x),this._sy=Math.cos(this._rotation-this.skew.x),this.dirty=!0}toString(){return`[pixi.js/math:Transform position=(${this.position.x}, ${this.position.y}) rotation=${this.rotation} scale=(${this.scale.x}, ${this.scale.y}) skew=(${this.skew.x}, ${this.skew.y}) ]`}setFromMatrix(t){t.decompose(this),this.dirty=!0}get rotation(){return this._rotation}set rotation(t){this._rotation!==t&&(this._rotation=t,this._onUpdate(this.skew))}}const DC=class Nc extends fm{constructor(...t){let e=t[0]||{};e instanceof W&&(e={texture:e}),t.length>1&&(ct(Te,"use new TilingSprite({ texture, width:100, height:100 }) instead"),e.width=t[1],e.height=t[2]),e={...Nc.defaultOptions,...e};const{texture:s,anchor:r,tilePosition:n,tileScale:a,tileRotation:o,width:u,height:l,applyAnchorToTexture:c,roundPixels:h,..._}=e??{};super({label:"TilingSprite",..._}),this.renderPipeId="tilingSprite",this.batched=!0,this.allowChildren=!1,this._anchor=new Pe({_onUpdate:()=>{this.onViewUpdate()}}),this._applyAnchorToTexture=c,this.texture=s,this._width=u??s.width,this._height=l??s.height,this._tileTransform=new nQ({observer:{_onUpdate:()=>this.onViewUpdate()}}),r&&(this.anchor=r),this.tilePosition=n,this.tileScale=a,this.tileRotation=o,this.roundPixels=h??!1}static from(t,e={}){return typeof t=="string"?new Nc({texture:de.get(t),...e}):new Nc({texture:t,...e})}get clampMargin(){return this._texture.textureMatrix.clampMargin}set clampMargin(t){this._texture.textureMatrix.clampMargin=t}get anchor(){return this._anchor}set anchor(t){typeof t=="number"?this._anchor.set(t):this._anchor.copyFrom(t)}get tilePosition(){return this._tileTransform.position}set tilePosition(t){this._tileTransform.position.copyFrom(t)}get tileScale(){return this._tileTransform.scale}set tileScale(t){typeof t=="number"?this._tileTransform.scale.set(t):this._tileTransform.scale.copyFrom(t)}set tileRotation(t){this._tileTransform.rotation=t}get tileRotation(){return this._tileTransform.rotation}get tileTransform(){return this._tileTransform}get bounds(){return this._boundsDirty&&(this._updateBounds(),this._boundsDirty=!1),this._bounds}set texture(t){t||(t=W.EMPTY);const e=this._texture;e!==t&&(e&&e.dynamic&&e.off("update",this.onViewUpdate,this),t.dynamic&&t.on("update",this.onViewUpdate,this),this._texture=t,this.onViewUpdate())}get texture(
|
||
|
|
||
|
struct LocalUniforms {
|
||
|
uTransformMatrix:mat3x3<f32>,
|
||
|
uColor:vec4<f32>,
|
||
|
uRound:f32,
|
||
|
}
|
||
|
|
||
|
@group(1) @binding(0) var<uniform> localUniforms : LocalUniforms;
|
||
|
`,main:`
|
||
|
vColor *= localUniforms.uColor;
|
||
|
modelMatrix *= localUniforms.uTransformMatrix;
|
||
|
`,end:`
|
||
|
if(localUniforms.uRound == 1)
|
||
|
{
|
||
|
vPosition = vec4(roundPixels(vPosition.xy, globalUniforms.uResolution), vPosition.zw);
|
||
|
}
|
||
|
`}},lQ={...Ku,vertex:{...Ku.vertex,header:Ku.vertex.header.replace("group(1)","group(2)")}},hQ={name:"local-uniform-bit",vertex:{header:`
|
||
|
|
||
|
uniform mat3 uTransformMatrix;
|
||
|
uniform vec4 uColor;
|
||
|
uniform float uRound;
|
||
|
`,main:`
|
||
|
vColor *= uColor;
|
||
|
modelMatrix = uTransformMatrix;
|
||
|
`,end:`
|
||
|
if(uRound == 1.)
|
||
|
{
|
||
|
gl_Position.xy = roundPixels(gl_Position.xy, uResolution);
|
||
|
}
|
||
|
`}},cQ={name:"texture-bit",vertex:{header:`
|
||
|
|
||
|
struct TextureUniforms {
|
||
|
uTextureMatrix:mat3x3<f32>,
|
||
|
}
|
||
|
|
||
|
@group(2) @binding(2) var<uniform> textureUniforms : TextureUniforms;
|
||
|
`,main:`
|
||
|
uv = (textureUniforms.uTextureMatrix * vec3(uv, 1.0)).xy;
|
||
|
`},fragment:{header:`
|
||
|
@group(2) @binding(0) var uTexture: texture_2d<f32>;
|
||
|
@group(2) @binding(1) var uSampler: sampler;
|
||
|
|
||
|
|
||
|
`,main:`
|
||
|
outColor = textureSample(uTexture, uSampler, vUV);
|
||
|
`}},_Q={name:"texture-bit",vertex:{header:`
|
||
|
uniform mat3 uTextureMatrix;
|
||
|
`,main:`
|
||
|
uv = (uTextureMatrix * vec3(uv, 1.0)).xy;
|
||
|
`},fragment:{header:`
|
||
|
uniform sampler2D uTexture;
|
||
|
|
||
|
|
||
|
`,main:`
|
||
|
outColor = texture(uTexture, vUV);
|
||
|
`}};function dQ(i,t){const e=i.root,s=i.instructionSet;s.reset();const r=t.renderPipes?t:t.batch.renderer,n=r.renderPipes;n.batch.buildStart(s),n.blendMode.buildStart(),n.colorMask.buildStart(),e.sortableChildren&&e.sortChildren(),GC(e,s,r,!0),n.batch.buildEnd(s),n.blendMode.buildEnd(s)}function Om(i,t,e){const s=e.renderPipes?e:e.batch.renderer;i.globalDisplayStatus<7||!i.includeInBuild||(i.sortableChildren&&i.sortChildren(),i.isSimple?fQ(i,t,s):GC(i,t,s,!1))}function fQ(i,t,e){if(i.renderPipeId){const s=i,{renderPipes:r,renderableGC:n}=e;r.blendMode.setBlendMode(s,i.groupBlendMode,t),r[s.renderPipeId].addRenderable(s,t),n.addRenderable(s,t),s.didViewUpdate=!1}if(!i.renderGroup){const s=i.children,r=s.length;for(let n=0;n<r;n++)Om(s[n],t,e)}}function GC(i,t,e,s){const{renderPipes:r,renderableGC:n}=e;if(!s&&i.renderGroup)r.renderGroup.addRenderGroup(i.renderGroup,t);else{for(let l=0;l<i.effects.length;l++){const c=i.effects[l];r[c.pipe].push(c,i,t)}const a=i,o=a.renderPipeId;o&&(r.blendMode.setBlendMode(a,a.groupBlendMode,t),r[o].addRenderable(a,t),n.addRenderable(a,t),a.didViewUpdate=!1);const u=i.children;if(u.length)for(let l=0;l<u.length;l++)Om(u[l],t,e);for(let l=i.effects.length-1;l>=0;l--){const c=i.effects[l];r[c.pipe].pop(c,i,t)}}}const gQ=new Bs;class pQ extends $c{constructor(){super(),this.filters=[new rQ({sprite:new wt(W.EMPTY),inverse:!1,resolution:"inherit",antialias:"inherit"})]}get sprite(){return this.filters[0].sprite}set sprite(t){this.filters[0].sprite=t}get inverse(){return this.filters[0].inverse}set inverse(t){this.filters[0].inverse=t}}class BC{constructor(t){this._activeMaskStage=[],this._renderer=t}push(t,e,s){const r=this._renderer;if(r.renderPipes.batch.break(s),s.add({renderPipeId:"alphaMask",action:"pushMaskBegin",mask:t,inverse:e._maskOptions.inverse,canBundle:!1,maskedContainer:e}),t.inverse=e._maskOptions.inverse,t.renderMaskToTexture){const n=t.mask;n.includeInBuild=!0,Om(n,s,r),n.includeInBuild=!1}r.renderPipes.batch.break(s),s.add({renderPipeId:"alphaMask",action:"pushMaskEnd",mask:t,maskedContainer:e,inverse:e._maskOptions.inverse,canBundle:!1})}pop(t,e,s){this._renderer.renderPipes.batch.break(s),s.add({renderPipeId:"alphaMask",action:"popMaskEnd",mask:t,inverse:e._maskOptions.inverse,canBundle:!1})}execute(t){const e=this._renderer,s=t.mask.renderMaskToTexture;if(t.action==="pushMaskBegin"){const r=ls.get(pQ);if(r.inverse=t.inverse,s){t.mask.mask.measurable=!0;const n=LI(t.mask.mask,!0,gQ);t.mask.mask.measurable=!1,n.ceil();const a=e.renderTarget.renderTarget.colorTexture.source,o=os.getOptimalTexture(n.width,n.height,a._resolution,a.antialias);e.renderTarget.push(o,!0),e.globalUniforms.push({offset:n,worldColor:4294967295});const u=r.sprite;u.texture=o,u.worldTransform.tx=n.minX,u.worldTransform.ty=n.minY,this._activeMaskStage.push({filterEffect:r,maskedContainer:t.maskedContainer,filterTexture:o})}else r.sprite=t.mask.mask,this._activeMaskStage.push({filterEffect:r,maskedContainer:t.maskedContainer})}else if(t.action==="pushMaskEnd"){const r=this._activeMaskStage[this._activeMaskStage.length-1];s&&(e.type===ir.WEBGL&&e.renderTarget.finishRenderPass(),e.renderTarget.pop(),e.globalUniforms.pop()),e.filter.push({renderPipeId:"filter",action:"pushFilter",container:r.maskedContainer,filterEffect:r.filterEffect,canBundle:!1})}else if(t.action==="popMaskEnd"){e.filter.pop();const r=this._activeMaskStage.pop();s&&os.returnTexture(r.filterTexture),ls.return(r.filterEffect)}}destroy(){this._renderer=null,this._activeMaskStage=null}}BC.extension={type:[B.WebGLPipes,B.WebGPUPipes,B.CanvasPipes],name:"alphaMask"};class kC{constructor(t){this._colorStack=[],this._colorStackIndex=0,this._currentColor=0,this._renderer=t}buildStart(){this._colorStack[0]=15,this._colorStackIndex=1,this._currentColor=15}push(t,e,s){this._renderer.renderPipes.batch.break(s);const n=this._colorStack;n[this._colorStackIndex]=n[this._colorStackIndex-1]&t.mask;const a=this._colorStack[this._colorStackIndex];a!==this._currentColor&&(this._currentColor=a,s.add({renderPipeId:"colorMask",colorMask:a,canBundle:!1}))
|
||
|
var matrix = uv[name].toArray(true);
|
||
|
data[offset] = matrix[0];
|
||
|
data[offset + 1] = matrix[1];
|
||
|
data[offset + 2] = matrix[2];
|
||
|
data[offset + 4] = matrix[3];
|
||
|
data[offset + 5] = matrix[4];
|
||
|
data[offset + 6] = matrix[5];
|
||
|
data[offset + 8] = matrix[6];
|
||
|
data[offset + 9] = matrix[7];
|
||
|
data[offset + 10] = matrix[8];
|
||
|
`,uniform:`
|
||
|
gl.uniformMatrix3fv(ud[name].location, false, uv[name].toArray(true));
|
||
|
`},{type:"vec4<f32>",test:i=>i.type==="vec4<f32>"&&i.size===1&&i.value.width!==void 0,ubo:`
|
||
|
v = uv[name];
|
||
|
data[offset] = v.x;
|
||
|
data[offset + 1] = v.y;
|
||
|
data[offset + 2] = v.width;
|
||
|
data[offset + 3] = v.height;
|
||
|
`,uniform:`
|
||
|
cv = ud[name].value;
|
||
|
v = uv[name];
|
||
|
if (cv[0] !== v.x || cv[1] !== v.y || cv[2] !== v.width || cv[3] !== v.height) {
|
||
|
cv[0] = v.x;
|
||
|
cv[1] = v.y;
|
||
|
cv[2] = v.width;
|
||
|
cv[3] = v.height;
|
||
|
gl.uniform4f(ud[name].location, v.x, v.y, v.width, v.height);
|
||
|
}
|
||
|
`},{type:"vec2<f32>",test:i=>i.type==="vec2<f32>"&&i.size===1&&i.value.x!==void 0,ubo:`
|
||
|
v = uv[name];
|
||
|
data[offset] = v.x;
|
||
|
data[offset + 1] = v.y;
|
||
|
`,uniform:`
|
||
|
cv = ud[name].value;
|
||
|
v = uv[name];
|
||
|
if (cv[0] !== v.x || cv[1] !== v.y) {
|
||
|
cv[0] = v.x;
|
||
|
cv[1] = v.y;
|
||
|
gl.uniform2f(ud[name].location, v.x, v.y);
|
||
|
}
|
||
|
`},{type:"vec4<f32>",test:i=>i.type==="vec4<f32>"&&i.size===1&&i.value.red!==void 0,ubo:`
|
||
|
v = uv[name];
|
||
|
data[offset] = v.red;
|
||
|
data[offset + 1] = v.green;
|
||
|
data[offset + 2] = v.blue;
|
||
|
data[offset + 3] = v.alpha;
|
||
|
`,uniform:`
|
||
|
cv = ud[name].value;
|
||
|
v = uv[name];
|
||
|
if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue || cv[3] !== v.alpha) {
|
||
|
cv[0] = v.red;
|
||
|
cv[1] = v.green;
|
||
|
cv[2] = v.blue;
|
||
|
cv[3] = v.alpha;
|
||
|
gl.uniform4f(ud[name].location, v.red, v.green, v.blue, v.alpha);
|
||
|
}
|
||
|
`},{type:"vec3<f32>",test:i=>i.type==="vec3<f32>"&&i.size===1&&i.value.red!==void 0,ubo:`
|
||
|
v = uv[name];
|
||
|
data[offset] = v.red;
|
||
|
data[offset + 1] = v.green;
|
||
|
data[offset + 2] = v.blue;
|
||
|
`,uniform:`
|
||
|
cv = ud[name].value;
|
||
|
v = uv[name];
|
||
|
if (cv[0] !== v.red || cv[1] !== v.green || cv[2] !== v.blue) {
|
||
|
cv[0] = v.red;
|
||
|
cv[1] = v.green;
|
||
|
cv[2] = v.blue;
|
||
|
gl.uniform3f(ud[name].location, v.red, v.green, v.blue);
|
||
|
}
|
||
|
`}];function YC(i,t,e,s){const r=[`
|
||
|
var v = null;
|
||
|
var v2 = null;
|
||
|
var t = 0;
|
||
|
var index = 0;
|
||
|
var name = null;
|
||
|
var arrayOffset = null;
|
||
|
`];let n=0;for(let o=0;o<i.length;o++){const u=i[o],l=u.data.name;let c=!1,h=0;for(let _=0;_<Lu.length;_++)if(Lu[_].test(u.data)){h=u.offset/4,r.push(`name = "${l}";`,`offset += ${h-n};`,Lu[_][t]||Lu[_].ubo),c=!0;break}if(!c)if(u.data.size>1)h=u.offset/4,r.push(e(u,h-n));else{const _=s[u.data.type];h=u.offset/4,r.push(`
|
||
|
v = uv.${l};
|
||
|
offset += ${h-n};
|
||
|
${_};
|
||
|
`)}n=h}const a=r.join(`
|
||
|
`);return new Function("uv","data","offset",a)}function io(i,t){return`
|
||
|
for (let i = 0; i < ${i*t}; i++) {
|
||
|
data[offset + (((i / ${i})|0) * 4) + (i % ${i})] = v[i];
|
||
|
}
|
||
|
`}const WC={f32:`
|
||
|
data[offset] = v;`,i32:`
|
||
|
data[offset] = v;`,"vec2<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];`,"vec3<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];
|
||
|
data[offset + 2] = v[2];`,"vec4<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];
|
||
|
data[offset + 2] = v[2];
|
||
|
data[offset + 3] = v[3];`,"mat2x2<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];
|
||
|
data[offset + 4] = v[2];
|
||
|
data[offset + 5] = v[3];`,"mat3x3<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];
|
||
|
data[offset + 2] = v[2];
|
||
|
data[offset + 4] = v[3];
|
||
|
data[offset + 5] = v[4];
|
||
|
data[offset + 6] = v[5];
|
||
|
data[offset + 8] = v[6];
|
||
|
data[offset + 9] = v[7];
|
||
|
data[offset + 10] = v[8];`,"mat4x4<f32>":`
|
||
|
for (let i = 0; i < 16; i++) {
|
||
|
data[offset + i] = v[i];
|
||
|
}`,"mat3x2<f32>":io(3,2),"mat4x2<f32>":io(4,2),"mat2x3<f32>":io(2,3),"mat4x3<f32>":io(4,3),"mat2x4<f32>":io(2,4),"mat3x4<f32>":io(3,4)},EQ={...WC,"mat2x2<f32>":`
|
||
|
data[offset] = v[0];
|
||
|
data[offset + 1] = v[1];
|
||
|
data[offset + 2] = v[2];
|
||
|
data[offset + 3] = v[3];
|
||
|
`};function TQ(i,t,e,s,r,n){const a=n?1:-1;return i.identity(),i.a=1/s*2,i.d=a*(1/r*2),i.tx=-1-t*i.a,i.ty=-a-e*i.d,i}const Pu=new Map;function jC(i,t){if(!Pu.has(i)){const e=new W({source:new La({resource:i,...t})}),s=()=>{Pu.get(i)===e&&Pu.delete(i)};e.once("destroy",s),e.source.once("destroy",s),Pu.set(i,e)}return Pu.get(i)}function IQ(i){const t=i.colorTexture.source.resource;return globalThis.HTMLCanvasElement&&t instanceof HTMLCanvasElement&&document.body.contains(t)}const KC=class XC{constructor(t={}){if(this.uid=Se("renderTarget"),this.colorTextures=[],this.dirtyId=0,this.isRoot=!1,this._size=new Float32Array(2),this._managedColorTextures=!1,t={...XC.defaultOptions,...t},this.stencil=t.stencil,this.depth=t.depth,this.isRoot=t.isRoot,typeof t.colorTextures=="number"){this._managedColorTextures=!0;for(let e=0;e<t.colorTextures;e++)this.colorTextures.push(new De({width:t.width,height:t.height,resolution:t.resolution,antialias:t.antialias}))}else{this.colorTextures=[...t.colorTextures.map(s=>s.source)];const e=this.colorTexture.source;this.resize(e.width,e.height,e._resolution)}this.colorTexture.source.on("resize",this.onSourceResize,this),(t.depthStencilTexture||this.stencil)&&(t.depthStencilTexture instanceof W||t.depthStencilTexture instanceof De?this.depthStencilTexture=t.depthStencilTexture.source:this.ensureDepthStencilTexture())}get size(){const t=this._size;return t[0]=this.pixelWidth,t[1]=this.pixelHeight,t}get width(){return this.colorTexture.source.width}get height(){return this.colorTexture.source.height}get pixelWidth(){return this.colorTexture.source.pixelWidth}get pixelHeight(){return this.colorTexture.source.pixelHeight}get resolution(){return this.colorTexture.source._resolution}get colorTexture(){return this.colorTextures[0]}onSourceResize(t){this.resize(t.width,t.height,t._resolution,!0)}ensureDepthStencilTexture(){this.depthStencilTexture||(this.depthStencilTexture=new De({width:this.width,height:this.height,resolution:this.resolution,format:"depth24plus-stencil8",autoGenerateMipmaps:!1,antialias:!1,mipLevelCount:1}))}resize(t,e,s=this.resolution,r=!1){this.dirtyId++,this.colorTextures.forEach((n,a)=>{r&&a===0||n.source.resize(t,e,s)}),this.depthStencilTexture&&this.depthStencilTexture.source.resize(t,e,s)}destroy(){this.colorTexture.source.off("resize",this.onSourceResize,this),this._managedColorTextures&&this.colorTextures.forEach(t=>{t.destroy()}),this.depthStencilTexture&&(this.depthStencilTexture.destroy(),delete this.depthStencilTexture)}};KC.defaultOptions={width:0,height:0,resolution:1,colorTextures:1,stencil:!1,depth:!1,antialias:!1,isRoot:!1};let CT=KC;class qC{constructor(t){this.rootViewPort=new Kt,this.viewport=new Kt,this.onRenderTargetChange=new zv("onRenderTargetChange"),this.projectionMatrix=new ot,this.defaultClearColor=[0,0,0,0],this._renderSurfaceToRenderTargetHash=new Map,this._gpuRenderTargetHash=Object.create(null),this._renderTargetStack=[],this._renderer=t,t.renderableGC.addManagedHash(this,"_gpuRenderTargetHash")}finishRenderPass(){this.adaptor.finishRenderPass(this.renderTarget)}renderStart({target:t,clear:e,clearColor:s,frame:r}){this._renderTargetStack.length=0,this.push(t,e,s,r),this.rootViewPort.copyFrom(this.viewport),this.rootRenderTarget=this.renderTarget,this.renderingToScreen=IQ(this.rootRenderTarget)}postrender(){var t,e;(e=(t=this.adaptor).postrender)==null||e.call(t,this.rootRenderTarget)}bind(t,e=!0,s,r){const n=this.getRenderTarget(t),a=this.renderTarget!==n;this.renderTarget=n,this.renderSurface=t;const o=this.getGpuRenderTarget(n);(n.pixelWidth!==o.width||n.pixelHeight!==o.height)&&(this.adaptor.resizeGpuRenderTarget(n),o.width=n.pixelWidth,o.height=n.pixelHeight);const u=n.colorTexture,l=this.viewport,c=u.pixelWidth,h=u.pixelHeight;if(!r&&t instanceof W&&(r=t.frame),r){const _=u._resolution;l.x=r.x*_+.5|0,l.y=r.y*_+.5|0,l.width=r.width*_+.5|0,l.height=r.height*_+.5|0}else l.x=0,l.y=0,l.width=c,l.height=h;return TQ(this.projectionMatrix,0,0,l.width/u.resolution,l.height/u.resolution,!n.isRoot),this.adaptor.startRenderPass(n,e,s,l),a&&this.onRenderTarg
|
||
|
|
||
|
`,"background: #E72264; padding:5px 0;","background: #6CA2EA; padding:5px 0;","background: #B5D33D; padding:5px 0;","background: #FED23F; padding:5px 0;","color: #FFFFFF; background: #E72264; padding:5px 0;","color: #E72264; background: #FFFFFF; padding:5px 0;"];globalThis.console.log(...t)}else globalThis.console&&globalThis.console.log(`PixiJS ${e_} - ${i} - http://www.pixijs.com/`);hy=!0}}class ym{constructor(t){this._renderer=t}init(t){if(t.hello){let e=this._renderer.name;this._renderer.type===ir.WEBGL&&(e+=` ${this._renderer.context.webGLVersion}`),UQ(e)}}}ym.extension={type:[B.WebGLSystem,B.WebGPUSystem,B.CanvasSystem],name:"hello",priority:-2};ym.defaultOptions={hello:!1};function DQ(i){let t=!1;for(const s in i)if(i[s]==null){t=!0;break}if(!t)return i;const e=Object.create(null);for(const s in i){const r=i[s];r&&(e[s]=r)}return e}function LQ(i){let t=0;for(let e=0;e<i.length;e++)i[e]==null?t++:i[e-t]=i[e];return i.length=i.length-t,i}const rS=class fM{constructor(t){this._managedRenderables=[],this._managedHashes=[],this._managedArrays=[],this._renderer=t}init(t){t={...fM.defaultOptions,...t},this.maxUnusedTime=t.renderableGCMaxUnusedTime,this._frequency=t.renderableGCFrequency,this.enabled=t.renderableGCActive}get enabled(){return!!this._handler}set enabled(t){this.enabled!==t&&(t?(this._handler=this._renderer.scheduler.repeat(()=>this.run(),this._frequency,!1),this._hashHandler=this._renderer.scheduler.repeat(()=>{for(const e of this._managedHashes)e.context[e.hash]=DQ(e.context[e.hash])},this._frequency),this._arrayHandler=this._renderer.scheduler.repeat(()=>{for(const e of this._managedArrays)LQ(e.context[e.hash])},this._frequency)):(this._renderer.scheduler.cancel(this._handler),this._renderer.scheduler.cancel(this._hashHandler),this._renderer.scheduler.cancel(this._arrayHandler)))}addManagedHash(t,e){this._managedHashes.push({context:t,hash:e})}addManagedArray(t,e){this._managedArrays.push({context:t,hash:e})}prerender(){this._now=performance.now()}addRenderable(t,e){this.enabled&&(t._lastUsed=this._now,t._lastInstructionTick===-1&&(this._managedRenderables.push(t),t.once("destroyed",this._removeRenderable,this)),t._lastInstructionTick=e.tick)}run(){var n;const t=performance.now(),e=this._managedRenderables,s=this._renderer.renderPipes;let r=0;for(let a=0;a<e.length;a++){const o=e[a];if(o===null){r++;continue}const u=o.renderGroup??o.parentRenderGroup,l=((n=u==null?void 0:u.instructionSet)==null?void 0:n.tick)??-1;o._lastInstructionTick!==l&&t-o._lastUsed>this.maxUnusedTime?(o.destroyed||s[o.renderPipeId].destroyRenderable(o),o._lastInstructionTick=-1,r++,o.off("destroyed",this._removeRenderable,this)):e[a-r]=o}e.length=e.length-r}destroy(){this.enabled=!1,this._renderer=null,this._managedRenderables.length=0,this._managedHashes.length=0,this._managedArrays.length=0}_removeRenderable(t){const e=this._managedRenderables.indexOf(t);e>=0&&(t.off("destroyed",this._removeRenderable,this),this._managedRenderables[e]=null)}};rS.extension={type:[B.WebGLSystem,B.WebGPUSystem],name:"renderableGC",priority:0};rS.defaultOptions={renderableGCActive:!0,renderableGCMaxUnusedTime:6e4,renderableGCFrequency:3e4};let FQ=rS;const nS=class gM{constructor(t){this._renderer=t,this.count=0,this.checkCount=0}init(t){t={...gM.defaultOptions,...t},this.checkCountMax=t.textureGCCheckCountMax,this.maxIdle=t.textureGCAMaxIdle??t.textureGCMaxIdle,this.active=t.textureGCActive}postrender(){this._renderer.renderingToScreen&&(this.count++,this.active&&(this.checkCount++,this.checkCount>this.checkCountMax&&(this.checkCount=0,this.run())))}run(){const t=this._renderer.texture.managedTextures;for(let e=0;e<t.length;e++){const s=t[e];s.autoGarbageCollect&&s.resource&&s._touched>-1&&this.count-s._touched>this.maxIdle&&(s._touched=-1,s.unload())}}destroy(){this._renderer=null}};nS.extension={type:[B.WebGLSystem,B.WebGPUSystem],name:"textureGC"};nS.defaultOptions={textureGCActive:!0,textureGCAMaxIdle:null,textureGCMaxIdle:60*60,textureGCCheckCountMax:600};let wQ=nS;const aS=class pM{get autoDensity(){return this.texture.source.autoDensity}set au
|
||
|
v = uv.${i.data.name};
|
||
|
${t!==0?`offset += ${t};`:""}
|
||
|
|
||
|
arrayOffset = offset;
|
||
|
|
||
|
t = 0;
|
||
|
|
||
|
for(var i=0; i < ${i.data.size*(e/4)}; i++)
|
||
|
{
|
||
|
for(var j = 0; j < ${e/4}; j++)
|
||
|
{
|
||
|
data[arrayOffset++] = v[t++];
|
||
|
}
|
||
|
${r!==0?`arrayOffset += ${r};`:""}
|
||
|
}
|
||
|
`}function zQ(i){return YC(i,"uboWgsl",kQ,EQ)}class yM extends HC{constructor(){super({createUboElements:BQ,generateUboSync:zQ})}}yM.extension={type:[B.WebGPUSystem],name:"ubo"};const Xr=128;class vM{constructor(t){this._bindGroupHash=Object.create(null),this._buffers=[],this._bindGroups=[],this._bufferResources=[],this._renderer=t,this._renderer.renderableGC.addManagedHash(this,"_bindGroupHash"),this._batchBuffer=new GQ({minUniformOffsetAlignment:Xr});const e=256/Xr;for(let s=0;s<e;s++){let r=Oe.UNIFORM|Oe.COPY_DST;s===0&&(r|=Oe.COPY_SRC),this._buffers.push(new Hr({data:this._batchBuffer.data,usage:r}))}}renderEnd(){this._uploadBindGroups(),this._resetBindGroups()}_resetBindGroups(){for(const t in this._bindGroupHash)this._bindGroupHash[t]=null;this._batchBuffer.clear()}getUniformBindGroup(t,e){if(!e&&this._bindGroupHash[t.uid])return this._bindGroupHash[t.uid];this._renderer.ubo.ensureUniformGroup(t);const s=t.buffer.data,r=this._batchBuffer.addEmptyGroup(s.length);return this._renderer.ubo.syncUniformGroup(t,this._batchBuffer.data,r/4),this._bindGroupHash[t.uid]=this._getBindGroup(r/Xr),this._bindGroupHash[t.uid]}getUboResource(t){this._renderer.ubo.updateUniformGroup(t);const e=t.buffer.data,s=this._batchBuffer.addGroup(e);return this._getBufferResource(s/Xr)}getArrayBindGroup(t){const e=this._batchBuffer.addGroup(t);return this._getBindGroup(e/Xr)}getArrayBufferResource(t){const s=this._batchBuffer.addGroup(t)/Xr;return this._getBufferResource(s)}_getBufferResource(t){if(!this._bufferResources[t]){const e=this._buffers[t%2];this._bufferResources[t]=new $C({buffer:e,offset:(t/2|0)*256,size:Xr})}return this._bufferResources[t]}_getBindGroup(t){if(!this._bindGroups[t]){const e=new Sn({0:this._getBufferResource(t)});this._bindGroups[t]=e}return this._bindGroups[t]}_uploadBindGroups(){const t=this._renderer.buffer,e=this._buffers[0];e.update(this._batchBuffer.byteIndex),t.updateBuffer(e);const s=this._renderer.gpu.device.createCommandEncoder();for(let r=1;r<this._buffers.length;r++){const n=this._buffers[r];s.copyBufferToBuffer(t.getGPUBuffer(e),Xr,t.getGPUBuffer(n),0,this._batchBuffer.byteIndex)}this._renderer.gpu.device.queue.submit([s.finish()])}destroy(){for(let t=0;t<this._bindGroups.length;t++)this._bindGroups[t].destroy();this._bindGroups=null,this._bindGroupHash=null;for(let t=0;t<this._buffers.length;t++)this._buffers[t].destroy();this._buffers=null;for(let t=0;t<this._bufferResources.length;t++)this._bufferResources[t].destroy();this._bufferResources=null,this._batchBuffer.destroy(),this._bindGroupHash=null,this._renderer=null}}vM.extension={type:[B.WebGPUPipes],name:"uniformBatch"};const VQ={"point-list":0,"line-list":1,"line-strip":2,"triangle-list":3,"triangle-strip":4};function HQ(i,t,e,s,r){return i<<24|t<<16|e<<10|s<<5|r}function YQ(i,t,e,s){return e<<6|i<<3|s<<1|t}class CM{constructor(t){this._moduleCache=Object.create(null),this._bufferLayoutsCache=Object.create(null),this._bindingNamesCache=Object.create(null),this._pipeCache=Object.create(null),this._pipeStateCaches=Object.create(null),this._colorMask=15,this._multisampleCount=1,this._renderer=t}contextChange(t){this._gpu=t,this.setStencilMode(He.DISABLED),this._updatePipeHash()}setMultisampleCount(t){this._multisampleCount!==t&&(this._multisampleCount=t,this._updatePipeHash())}setRenderTarget(t){this._multisampleCount=t.msaaSamples,this._depthStencilAttachment=t.descriptor.depthStencilAttachment?1:0,this._updatePipeHash()}setColorMask(t){this._colorMask!==t&&(this._colorMask=t,this._updatePipeHash())}setStencilMode(t){this._stencilMode!==t&&(this._stencilMode=t,this._stencilState=Un[t],this._updatePipeHash())}setPipeline(t,e,s,r){const n=this.getPipeline(t,e,s);r.setPipeline(n)}getPipeline(t,e,s,r){t._layoutKey||(VC(t,e.attributeData),this._generateBufferKey(t)),r=r||t.topology;const n=HQ(t._layoutKey,e._layoutKey,s.data,s._blendModeId,VQ[r]);return this._pipeCache[n]?this._pipeCache[n]:(this._pipeCache[n]=this._createPipeline(t,e,s,r),this._pipeCache[n])}_createPipeline(t,e,s,r){const n=this._gpu.device,a=this._createVertexBufferLayouts(t,e),o
|
||
|
var<private> pos : array<vec2<f32>, 3> = array<vec2<f32>, 3>(
|
||
|
vec2<f32>(-1.0, -1.0), vec2<f32>(-1.0, 3.0), vec2<f32>(3.0, -1.0));
|
||
|
|
||
|
struct VertexOutput {
|
||
|
@builtin(position) position : vec4<f32>,
|
||
|
@location(0) texCoord : vec2<f32>,
|
||
|
};
|
||
|
|
||
|
@vertex
|
||
|
fn vertexMain(@builtin(vertex_index) vertexIndex : u32) -> VertexOutput {
|
||
|
var output : VertexOutput;
|
||
|
output.texCoord = pos[vertexIndex] * vec2<f32>(0.5, -0.5) + vec2<f32>(0.5);
|
||
|
output.position = vec4<f32>(pos[vertexIndex], 0.0, 1.0);
|
||
|
return output;
|
||
|
}
|
||
|
|
||
|
@group(0) @binding(0) var imgSampler : sampler;
|
||
|
@group(0) @binding(1) var img : texture_2d<f32>;
|
||
|
|
||
|
@fragment
|
||
|
fn fragmentMain(@location(0) texCoord : vec2<f32>) -> @location(0) vec4<f32> {
|
||
|
return textureSample(img, imgSampler, texCoord);
|
||
|
}
|
||
|
`})),e=this.device.createRenderPipeline({layout:"auto",vertex:{module:this.mipmapShaderModule,entryPoint:"vertexMain"},fragment:{module:this.mipmapShaderModule,entryPoint:"fragmentMain",targets:[{format:t}]}}),this.pipelines[t]=e),e}generateMipmap(t){const e=this._getMipmapPipeline(t.format);if(t.dimension==="3d"||t.dimension==="1d")throw new Error("Generating mipmaps for non-2d textures is currently unsupported!");let s=t;const r=t.depthOrArrayLayers||1,n=t.usage&GPUTextureUsage.RENDER_ATTACHMENT;if(!n){const u={size:{width:Math.ceil(t.width/2),height:Math.ceil(t.height/2),depthOrArrayLayers:r},format:t.format,usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_SRC|GPUTextureUsage.RENDER_ATTACHMENT,mipLevelCount:t.mipLevelCount-1};s=this.device.createTexture(u)}const a=this.device.createCommandEncoder({}),o=e.getBindGroupLayout(0);for(let u=0;u<r;++u){let l=t.createView({baseMipLevel:0,mipLevelCount:1,dimension:"2d",baseArrayLayer:u,arrayLayerCount:1}),c=n?1:0;for(let h=1;h<t.mipLevelCount;++h){const _=s.createView({baseMipLevel:c++,mipLevelCount:1,dimension:"2d",baseArrayLayer:u,arrayLayerCount:1}),d=a.beginRenderPass({colorAttachments:[{view:_,storeOp:"store",loadOp:"clear",clearValue:{r:0,g:0,b:0,a:0}}]}),f=this.device.createBindGroup({layout:o,entries:[{binding:0,resource:this.sampler},{binding:1,resource:l}]});d.setPipeline(e),d.setBindGroup(0,f),d.draw(3,1,0,0),d.end(),l=_}}if(!n){const u={width:Math.ceil(t.width/2),height:Math.ceil(t.height/2),depthOrArrayLayers:r};for(let l=1;l<t.mipLevelCount;++l)a.copyTextureToTexture({texture:s,mipLevel:l-1},{texture:t,mipLevel:l},u),u.width=Math.ceil(u.width/2),u.height=Math.ceil(u.height/2)}return this.device.queue.submit([a.finish()]),n||s.destroy(),t}}class UM{constructor(t){this.managedTextures=[],this._gpuSources=Object.create(null),this._gpuSamplers=Object.create(null),this._bindGroupHash=Object.create(null),this._textureViewHash=Object.create(null),this._uploads={image:NM,buffer:KQ,video:$Q,compressed:qQ},this._renderer=t,t.renderableGC.addManagedHash(this,"_gpuSources"),t.renderableGC.addManagedHash(this,"_gpuSamplers"),t.renderableGC.addManagedHash(this,"_bindGroupHash"),t.renderableGC.addManagedHash(this,"_textureViewHash")}contextChange(t){this._gpu=t}initSource(t){if(t.autoGenerateMipmaps){const u=Math.max(t.pixelWidth,t.pixelHeight);t.mipLevelCount=Math.floor(Math.log2(u))+1}let e=GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST;t.uploadMethodId!=="compressed"&&(e|=GPUTextureUsage.RENDER_ATTACHMENT,e|=GPUTextureUsage.COPY_SRC);const s=bM[t.format]||{blockBytes:4,blockWidth:1,blockHeight:1},r=Math.ceil(t.pixelWidth/s.blockWidth)*s.blockWidth,n=Math.ceil(t.pixelHeight/s.blockHeight)*s.blockHeight,a={label:t.label,size:{width:r,height:n},format:t.format,sampleCount:t.sampleCount,mipLevelCount:t.mipLevelCount,dimension:t.dimension,usage:e},o=this._gpu.device.createTexture(a);return this._gpuSources[t.uid]=o,this.managedTextures.includes(t)||(t.on("update",this.onSourceUpdate,this),t.on("resize",this.onSourceResize,this),t.on("destroy",this.onSourceDestroy,this),t.on("unload",this.onSourceUnload,this),t.on("updateMipmaps",this.onUpdateMipmaps,this),this.managedTextures.push(t)),this.onSourceUpdate(t),o}onSourceUpdate(t){const e=this.getGpuSource(t);e&&(this._uploads[t.uploadMethodId]&&this._uploads[t.uploadMethodId].upload(t,e,this._gpu),t.autoGenerateMipmaps&&t.mipLevelCount>1&&this.onUpdateMipmaps(t))}onSourceUnload(t){const e=this._gpuSources[t.uid];e&&(this._gpuSources[t.uid]=null,e.destroy())}onUpdateMipmaps(t){this._mipmapGenerator||(this._mipmapGenerator=new QQ(this._gpu.device));const e=this.getGpuSource(t);this._mipmapGenerator.generateMipmap(e)}onSourceDestroy(t){t.off("update",this.onSourceUpdate,this),t.off("unload",this.onSourceUnload,this),t.off("destroy",this.onSourceDestroy,this),t.off("resize",this.onSourceResize,this),t.off("updateMipmaps",this.onUpdateMipmaps,this),this.managedTextures.splice(this.managedTextures.indexOf(t),1),this.onSourceUnload(t)}onSourceResize(t){const e=this._gpuSources[t.uid];e?(e.width!==t
|
||
|
%c %c %c Nitro ${rn.UI_VERSION} - Renderer ${rn.RENDERER_VERSION} %c %c %c https://discord.nitrodev.co %c %c
|
||
|
|
||
|
`,"background: #ffffff; padding:5px 0;","background: #ffffff; padding:5px 0;","color: #ffffff; background: #000000; padding:5px 0;","background: #ffffff; padding:5px 0;","background: #ffffff; padding:5px 0;","background: #000000; padding:5px 0;","background: #ffffff; padding:5px 0;","background: #ffffff; padding:5px 0;"];self.console.log(...t)}else self.console&&self.console.log(`Nitro ${rn.UI_VERSION} - Renderer ${rn.RENDERER_VERSION} `)}};rn.RENDERER_VERSION="2.0.0",rn.UI_VERSION="";let oh=rn;class mS{constructor(t,e,s){this._location=null,this._transformedLocation=new v,this._needsTransformation=!1,this._location=new v(t,e,s),(t!==0||e!==0||s!==0)&&(this._needsTransformation=!0)}get location(){return this._location}get transformedLocation(){return this._transformedLocation}applyTransform(t){this._needsTransformation&&(this._transformedLocation=t.vectorMultiplication(this._location))}}class qT{constructor(t){t<0&&(t=0),this._reservedNumbers=[],this._freeNumbers=[];let e=0;for(;e<t;)this._freeNumbers.push(e),e++}dispose(){this._reservedNumbers=null,this._freeNumbers=null}reserveNumber(){if(this._freeNumbers.length>0){const t=this._freeNumbers.pop();return this._reservedNumbers.push(t),t}return-1}freeNumber(t){const e=this._reservedNumbers.indexOf(t);e>=0&&(this._reservedNumbers.splice(e,1),this._freeNumbers.push(t))}}class Gtt{static sum(t,e){return new st(t.x+e.x,t.y+e.y)}static sub(t,e){return new st(t.x-e.x,t.y-e.y)}static mul(t,e){return new st(t.x*e,t.y*e)}}const ul=class ul{static makeRoomPreviewerId(t){return(t&65535)+ul.PREVIEW_ROOM_ID_BASE}static isRoomPreviewerId(t){return t>=ul.PREVIEW_ROOM_ID_BASE}};ul.PREVIEW_ROOM_ID_BASE=2147418112;let uh=ul;class ue{static generateTexture(t){return this.getRenderer().textureGenerator.generateTexture(t)}static generateTextureFromImage(t){return W.from(t)}static async generateImage(t){return this.getExtractor().image(t)}static async generateImageUrl(t){return this.getExtractor().base64(t)}static generateCanvas(t){return this.getExtractor().canvas(t)}static clearRenderTexture(t){return this.writeToTexture(new wt(W.EMPTY),t)}static createRenderTexture(t,e){return t<0||e<0?null:Zh.create({width:t,height:e})}static createAndFillRenderTexture(t,e,s=16777215){return t<0||e<0?null:this.clearAndFillRenderTexture(this.createRenderTexture(t,e),s)}static createAndWriteRenderTexture(t,e,s,r=null){return t<0||e<0?null:this.writeToTexture(s,this.createRenderTexture(t,e),!0,r)}static clearAndFillRenderTexture(t,e=16777215){if(!t)return null;const s=new wt(W.WHITE);return s.tint=e,s.width=t.width,s.height=t.height,this.writeToTexture(s,t)}static writeToTexture(t,e,s=!0,r=null){return!t||!e?null:(this.getRenderer().render({container:t,target:e,clear:s,transform:r}),e)}static flipTextureHorizontal(t){if(!t)return null;const e=new ot;return e.scale(-1,1),e.translate(t.width,0),this.createAndWriteRenderTexture(t.width,t.height,new wt(t),e)}static flipTextureVertical(t){if(!t)return null;const e=new ot;return e.scale(1,-1),e.translate(0,t.height),this.createAndWriteRenderTexture(t.width,t.height,new wt(t),e)}static flipTextureHorizontalAndVertical(t){if(!t)return null;const e=new ot;return e.scale(-1,-1),e.translate(t.width,t.height),this.createAndWriteRenderTexture(t.width,t.height,new wt(t),e)}static getPixels(t){return this.getExtractor().pixels(t)}static getRenderer(){return Mn()}static getExtractor(){return this.getRenderer().extract}}const yx=(i=Ar.CHANNELS_EQUAL)=>{let t=.33,e=.33,s=.33;switch(i){case Ar.CHANNELS_UNIQUE:t=.3,e=.59,s=.11;break;case Ar.CHANNELS_RED:t=1,e=0,s=0;break;case Ar.CHANNELS_GREEN:t=0,e=1,s=0;break;case Ar.CHANNELS_BLUE:t=0,e=0,s=1;break;case Ar.CHANNELS_DESATURATED:t=.3086,e=.6094,s=.082;break}const r=new ju;return r.matrix=[t,e,s,0,0,t,e,s,0,0,t,e,s,0,0,0,0,0,1,0],r},Btt=i=>{const t=[];for(let e=0;e<i.length;e++)t[e*4+0]=i[e]>>16&255,t[e*4+1]=i[e]>>8&255,t[e*4+2]=i[e]&255,t[e*4+3]=i[e]>>24&255;return t},Hg=class Hg extends xt{constructor(t){t={...Hg.DEFAULT_OPTIONS,...t};const e=Btt(t.palette),s=dm.from({width:e.length/4,height:1,resource:Uint8Array.from(e),scal
|
||
|
in vec2 aPosition;
|
||
|
out vec2 vTextureCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
}`,fragment:`
|
||
|
in vec2 vTextureCoord;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uPaletteTexture;
|
||
|
uniform float uChannel;
|
||
|
|
||
|
void main() {
|
||
|
vec4 currentColor = texture2D(uTexture, vTextureCoord);
|
||
|
vec4 paletteColor = currentColor;
|
||
|
|
||
|
if(currentColor.a > 0.0) {
|
||
|
paletteColor = texture2D(uPaletteTexture, vec2((currentColor.r * 255.0 + 0.5) / 256.0, 0.5));
|
||
|
}
|
||
|
|
||
|
gl_FragColor = vec4(paletteColor.r, paletteColor.g, paletteColor.b, currentColor.a);
|
||
|
}`,name:"palette-map-filter"});console.log(r),super({gpuProgram:n,glProgram:a,resources:{paletteMapUniforms:{uChannel:{value:t.channel,type:"f32"}},uPaletteTexture:r.source,uPaletteSampler:r.source.style}}),this.uniforms=this.resources.paletteMapUniforms.uniforms,this.resources.uPaletteTexture=r.source,this.resources.uPaletteSampler=r.source.style,Object.assign(this,t)}};Hg.DEFAULT_OPTIONS={palette:[],channel:0};let I_=Hg;const Yg=class Yg extends xt{constructor(t){t={...Yg.DEFAULT_OPTIONS,...t};const e=Tt.from({vertex:`in vec2 aPosition;
|
||
|
out vec2 vTextureCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
}`,fragment:`
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
|
||
|
void main(void) {
|
||
|
vec4 c = texture(uTexture, vTextureCoord);
|
||
|
finalColor = c;
|
||
|
|
||
|
if(c.r == 0.0 && c.g == 0.0 && c.b == 0.0) {
|
||
|
finalColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||
|
}
|
||
|
}
|
||
|
`,name:"plane-mask-filter"});super({gpuProgram:null,glProgram:e,resources:{planeMaskUniforms:{}}}),this.uniforms=this.resources.planeMaskUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){t.applyFilter(this,e,s,r)}};Yg.DEFAULT_OPTIONS={};let S_=Yg;const Wg=class Wg extends xt{constructor(t){t={...Wg.DEFAULT_OPTIONS,...t};const e=Tt.from({vertex:`in vec2 aPosition;
|
||
|
out vec2 vTextureCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
}`,fragment:`
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec3 uLineColor;
|
||
|
uniform vec3 uColor;
|
||
|
|
||
|
void main(void) {
|
||
|
vec4 currentColor = texture(uTexture, vTextureCoord);
|
||
|
vec3 colorLine = uLineColor * currentColor.a;
|
||
|
vec3 colorOverlay = uColor * currentColor.a;
|
||
|
|
||
|
if(currentColor.r == 0.0 && currentColor.g == 0.0 && currentColor.b == 0.0 && currentColor.a > 0.0) {
|
||
|
finalColor = vec4(colorLine.r, colorLine.g, colorLine.b, currentColor.a);
|
||
|
} else if(currentColor.a > 0.0) {
|
||
|
finalColor = vec4(colorOverlay.r, colorOverlay.g, colorOverlay.b, currentColor.a);
|
||
|
}
|
||
|
}
|
||
|
`,name:"wired-filter"});super({gpuProgram:null,glProgram:e,resources:{planeMaskUniforms:{uLineColor:{value:new Float32Array(3),type:"vec3<f32>"},uColor:{value:new Float32Array(3),type:"vec3<f32>"}}}}),this.uniforms=this.resources.planeMaskUniforms.uniforms,this._lineColor=new Mt,this.lineColor=t.lineColor??0,this._color=new Mt,this.color=t.color??0,Object.assign(this,t)}apply(t,e,s,r){t.applyFilter(this,e,s,r)}get lineColor(){return this._lineColor.value}set lineColor(t){this._lineColor.setValue(t);const[e,s,r]=this._lineColor.toArray();this.uniforms.uLineColor[0]=e,this.uniforms.uLineColor[1]=s,this.uniforms.uLineColor[2]=r}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}};Wg.DEFAULT_OPTIONS={lineColor:0,color:0};let $T=Wg;class Za{constructor(t){this._complete=!0,this._target=t}get running(){return this._running&&!!this._target}get complete(){return this._complete}set target(t){this._target=t}get target(){return this._target}set tag(t){this._tag=t}get tag(){return this._tag}start(){this._running=!0}update(t){}stop(){this._target=null,this._running=!1}tick(t){}}class ktt extends Za{constructor(t){super(null),this._callback=t}get running(){return this._running&&!!this._callback}tick(t){super.tick(t),this._callback&&(this._callback(),this._callback=null)}}class ztt extends Za{constructor(...t){super(t&&t.length?t[0].target:null),this._runningMotions=[],this._removedMotions=[];for(const e of t)this._runningMotions.push(e)}start(){super.start();for(const t of this._runningMotions)t.start()}tick(t){super.tick(t);let e=null;for(;(e=this._removedMotions.pop())!==null;)this._runningMotions.splice(this._removedMotions.indexOf(e),1),e.running&&e.stop();for(const s of this._runningMotions)s.running&&s.tick(t),s.complete&&this._removedMotions.push(s);if(this._runningMotions.length>0){for(const s of this._runningMotions)if(this._target=s.target,this._target)break;this._complete=!1}else this._complete=!0}}class Vtt extends Za{constructor(t){super(t)}tick(t){super.tick(t),this.target&&(this.target.remove(),this.target=null)}}class Su extends Za{constructor(t,e){super(t),this._complete=!1,this._duration=e}get duration(){return this._duration}start(){super.start(),this._complete=!1,this._startTimeMs=Nt()}tick(t){super.tick(t);const e=(t-this._startTimeMs)/this._duration;e<1?this.update(e):(this.update(1),this._complete=!0)}}class Htt extends Su{constructor(t,e,s){super(t,e),this._height=s}start(){super.start(),this._offset=0,this.target.style.top=this._offset-this._height+"px"}update(t){super.update(t),this.target.style.top=this._offset-this._height+this.getBounceOffset(t)*this._height+"px"}getBounceOffset(t){return t<.364?7.5625*t*t:t<.727?(t=t-.545,7.5625*t*t+.75):t<.909?(t=t-.9091,7.5625*t*t+.9375):(t=t-.955,7.5625*t*t+.984375)}stop(){this.target.style.top=this._offset+"px",super.stop()}}class vx extends Su{constructor(t){super(t.target,t.duration),this._interval=t}start(){super.start(),this._interval.start()}update(t){super.update(t),this._interval.update(t)}stop(){super.stop(),this._interval.stop()}}class Cx extends vx{constructor(t,e){super(t),this._rate=e}}class Ytt extends Cx{constructor(t,e){super(t,e)}update(t){this._interval.update(Math.pow(t,1/this._rate))}}class Wtt extends Su{constructor(t,e,s,r,n,a){super(t,e),this._deltaX=s,this._deltaY=r,this._height=-n,this._numJumps=a}start(){super.start(),this._startX=this.target.offsetLeft,this._startY=this.target.offsetTop}update(t){super.update(t),this.target.style.left=this._startX+this._deltaX*t+"px",this.target.style.top=this._startY+this._height*Math.abs(Math.sin(t*Math.PI*this._numJumps))+this._deltaY*t+"px"}}const _t=class _t{static get TIMER_TIME(){return 1e3/HM()}static runMotion(t){return _t._RUNNING_MOTIONS.indexOf(t)===-1&&_t._QUEUED_MOTIONS.indexOf(t)===-1&&(_t._IS_UPDATING?_t._QUEUED_MOTIONS.push(t):(_t._RUNNING_MOTIONS.push(t),t.start()),_t.startTimer()),t}static removeMotion(t){let e=_t._RUNNING_MOTIONS.indexOf(t);e>
|
||
|
out vec2 vTextureCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
}
|
||
|
`,Zt=`struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
|
||
|
}
|
||
|
|
||
|
fn getSize() -> vec2<f32>
|
||
|
{
|
||
|
return gfu.uGlobalFrame.zw;
|
||
|
}
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
filterTextureCoord(aPosition)
|
||
|
);
|
||
|
}`,Oet=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uGamma;
|
||
|
uniform float uContrast;
|
||
|
uniform float uSaturation;
|
||
|
uniform float uBrightness;
|
||
|
uniform vec4 uColor;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec4 c = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
if (c.a > 0.0) {
|
||
|
c.rgb /= c.a;
|
||
|
|
||
|
vec3 rgb = pow(c.rgb, vec3(1. / uGamma));
|
||
|
rgb = mix(vec3(.5), mix(vec3(dot(vec3(.2125, .7154, .0721), rgb)), rgb, uSaturation), uContrast);
|
||
|
rgb.r *= uColor.r;
|
||
|
rgb.g *= uColor.g;
|
||
|
rgb.b *= uColor.b;
|
||
|
c.rgb = rgb * uBrightness;
|
||
|
|
||
|
c.rgb *= c.a;
|
||
|
}
|
||
|
|
||
|
finalColor = c * uColor.a;
|
||
|
}
|
||
|
`,yet=`struct AdjustmentUniforms {
|
||
|
uGamma: f32,
|
||
|
uContrast: f32,
|
||
|
uSaturation: f32,
|
||
|
uBrightness: f32,
|
||
|
uColor: vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> adjustmentUniforms : AdjustmentUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
var sample = textureSample(uTexture, uSampler, uv);
|
||
|
let color = adjustmentUniforms.uColor;
|
||
|
|
||
|
if (sample.a > 0.0)
|
||
|
{
|
||
|
sample = vec4<f32>(sample.rgb / sample.a, sample.a);
|
||
|
var rgb: vec3<f32> = pow(sample.rgb, vec3<f32>(1. / adjustmentUniforms.uGamma));
|
||
|
rgb = mix(vec3<f32>(.5), mix(vec3<f32>(dot(vec3<f32>(.2125, .7154, .0721), rgb)), rgb, adjustmentUniforms.uSaturation), adjustmentUniforms.uContrast);
|
||
|
rgb.r *= color.r;
|
||
|
rgb.g *= color.g;
|
||
|
rgb.b *= color.b;
|
||
|
sample = vec4<f32>(rgb.rgb * adjustmentUniforms.uBrightness, sample.a);
|
||
|
sample = vec4<f32>(sample.rgb * sample.a, sample.a);
|
||
|
}
|
||
|
|
||
|
return sample * color.a;
|
||
|
}`,vet=Object.defineProperty,Cet=(i,t,e)=>t in i?vet(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,$x=(i,t,e)=>(Cet(i,typeof t!="symbol"?t+"":t,e),e);const Qx=class Zx extends xt{constructor(t){t={...Zx.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:yet,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Oet,name:"adjustment-filter"});super({gpuProgram:e,glProgram:s,resources:{adjustmentUniforms:{uGamma:{value:t.gamma,type:"f32"},uContrast:{value:t.contrast,type:"f32"},uSaturation:{value:t.saturation,type:"f32"},uBrightness:{value:t.brightness,type:"f32"},uColor:{value:[t.red,t.green,t.blue,t.alpha],type:"vec4<f32>"}}}}),$x(this,"uniforms"),this.uniforms=this.resources.adjustmentUniforms.uniforms}get gamma(){return this.uniforms.uGamma}set gamma(t){this.uniforms.uGamma=t}get contrast(){return this.uniforms.uContrast}set contrast(t){this.uniforms.uContrast=t}get saturation(){return this.uniforms.uSaturation}set saturation(t){this.uniforms.uSaturation=t}get brightness(){return this.uniforms.uBrightness}set brightness(t){this.uniforms.uBrightness=t}get red(){return this.uniforms.uColor[0]}set red(t){this.uniforms.uColor[0]=t}get green(){return this.uniforms.uColor[1]}set green(t){this.uniforms.uColor[1]=t}get blue(){return this.uniforms.uColor[2]}set blue(t){this.uniforms.uColor[2]=t}get alpha(){return this.uniforms.uColor[3]}set alpha(t){this.uniforms.uColor[3]=t}};$x(Qx,"DEFAULT_OPTIONS",{gamma:1,contrast:1,saturation:1,brightness:1,red:1,green:1,blue:1,alpha:1});let Jx=Qx;var Met=`
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uOffset;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 color = vec4(0.0);
|
||
|
|
||
|
// Sample top left pixel
|
||
|
color += texture(uTexture, vec2(vTextureCoord.x - uOffset.x, vTextureCoord.y + uOffset.y));
|
||
|
|
||
|
// Sample top right pixel
|
||
|
color += texture(uTexture, vec2(vTextureCoord.x + uOffset.x, vTextureCoord.y + uOffset.y));
|
||
|
|
||
|
// Sample bottom right pixel
|
||
|
color += texture(uTexture, vec2(vTextureCoord.x + uOffset.x, vTextureCoord.y - uOffset.y));
|
||
|
|
||
|
// Sample bottom left pixel
|
||
|
color += texture(uTexture, vec2(vTextureCoord.x - uOffset.x, vTextureCoord.y - uOffset.y));
|
||
|
|
||
|
// Average
|
||
|
color *= 0.25;
|
||
|
|
||
|
finalColor = color;
|
||
|
}`,xet=`struct KawaseBlurUniforms {
|
||
|
uOffset:vec2<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> kawaseBlurUniforms : KawaseBlurUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uOffset = kawaseBlurUniforms.uOffset;
|
||
|
var color: vec4<f32> = vec4<f32>(0.0);
|
||
|
|
||
|
// Sample top left pixel
|
||
|
color += textureSample(uTexture, uSampler, vec2<f32>(uv.x - uOffset.x, uv.y + uOffset.y));
|
||
|
// Sample top right pixel
|
||
|
color += textureSample(uTexture, uSampler, vec2<f32>(uv.x + uOffset.x, uv.y + uOffset.y));
|
||
|
// Sample bottom right pixel
|
||
|
color += textureSample(uTexture, uSampler, vec2<f32>(uv.x + uOffset.x, uv.y - uOffset.y));
|
||
|
// Sample bottom left pixel
|
||
|
color += textureSample(uTexture, uSampler, vec2<f32>(uv.x - uOffset.x, uv.y - uOffset.y));
|
||
|
// Average
|
||
|
color *= 0.25;
|
||
|
|
||
|
return color;
|
||
|
}`,Pet=`
|
||
|
precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uOffset;
|
||
|
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 color = vec4(0.0);
|
||
|
|
||
|
// Sample top left pixel
|
||
|
color += texture(uTexture, clamp(vec2(vTextureCoord.x - uOffset.x, vTextureCoord.y + uOffset.y), uInputClamp.xy, uInputClamp.zw));
|
||
|
|
||
|
// Sample top right pixel
|
||
|
color += texture(uTexture, clamp(vec2(vTextureCoord.x + uOffset.x, vTextureCoord.y + uOffset.y), uInputClamp.xy, uInputClamp.zw));
|
||
|
|
||
|
// Sample bottom right pixel
|
||
|
color += texture(uTexture, clamp(vec2(vTextureCoord.x + uOffset.x, vTextureCoord.y - uOffset.y), uInputClamp.xy, uInputClamp.zw));
|
||
|
|
||
|
// Sample bottom left pixel
|
||
|
color += texture(uTexture, clamp(vec2(vTextureCoord.x - uOffset.x, vTextureCoord.y - uOffset.y), uInputClamp.xy, uInputClamp.zw));
|
||
|
|
||
|
// Average
|
||
|
color *= 0.25;
|
||
|
|
||
|
finalColor = color;
|
||
|
}
|
||
|
`,bet=`struct KawaseBlurUniforms {
|
||
|
uOffset:vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> kawaseBlurUniforms : KawaseBlurUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uOffset = kawaseBlurUniforms.uOffset;
|
||
|
var color: vec4<f32> = vec4(0.0);
|
||
|
|
||
|
// Sample top left pixel
|
||
|
color += textureSample(uTexture, uSampler, clamp(vec2<f32>(uv.x - uOffset.x, uv.y + uOffset.y), gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
// Sample top right pixel
|
||
|
color += textureSample(uTexture, uSampler, clamp(vec2<f32>(uv.x + uOffset.x, uv.y + uOffset.y), gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
// Sample bottom right pixel
|
||
|
color += textureSample(uTexture, uSampler, clamp(vec2<f32>(uv.x + uOffset.x, uv.y - uOffset.y), gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
// Sample bottom left pixel
|
||
|
color += textureSample(uTexture, uSampler, clamp(vec2<f32>(uv.x - uOffset.x, uv.y - uOffset.y), gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
// Average
|
||
|
color *= 0.25;
|
||
|
|
||
|
return color;
|
||
|
}`,Net=Object.defineProperty,Uet=(i,t,e)=>t in i?Net(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Wn=(i,t,e)=>(Uet(i,typeof t!="symbol"?t+"":t,e),e);const tP=class eP extends xt{constructor(...t){let e=t[0]??{};(typeof e=="number"||Array.isArray(e))&&(ct("6.0.0","KawaseBlurFilter constructor params are now options object. See params: { strength, quality, clamp, pixelSize }"),e={strength:e},t[1]!==void 0&&(e.quality=t[1]),t[2]!==void 0&&(e.clamp=t[2])),e={...eP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:e!=null&&e.clamp?bet:xet,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:e!=null&&e.clamp?Pet:Met,name:"kawase-blur-filter"});super({gpuProgram:s,glProgram:r,resources:{kawaseBlurUniforms:{uOffset:{value:new Float32Array(2),type:"vec2<f32>"}}}}),Wn(this,"uniforms"),Wn(this,"_pixelSize",{x:0,y:0}),Wn(this,"_clamp"),Wn(this,"_kernels",[]),Wn(this,"_blur"),Wn(this,"_quality"),this.uniforms=this.resources.kawaseBlurUniforms.uniforms,this.pixelSize=e.pixelSize??{x:1,y:1},Array.isArray(e.strength)?this.kernels=e.strength:typeof e.strength=="number"&&(this._blur=e.strength,this.quality=e.quality??3),this._clamp=!!e.clamp}apply(t,e,s,r){const n=this.pixelSizeX/e.source.width,a=this.pixelSizeY/e.source.height;let o;if(this._quality===1||this._blur===0)o=this._kernels[0]+.5,this.uniforms.uOffset[0]=o*n,this.uniforms.uOffset[1]=o*a,t.applyFilter(this,e,s,r);else{const u=os.getSameSizeTexture(e);let l=e,c=u,h;const _=this._quality-1;for(let d=0;d<_;d++)o=this._kernels[d]+.5,this.uniforms.uOffset[0]=o*n,this.uniforms.uOffset[1]=o*a,t.applyFilter(this,l,c,!0),h=l,l=c,c=h;o=this._kernels[_]+.5,this.uniforms.uOffset[0]=o*n,this.uniforms.uOffset[1]=o*a,t.applyFilter(this,l,s,r),os.returnTexture(u)}}get strength(){return this._blur}set strength(t){this._blur=t,this._generateKernels()}get quality(){return this._quality}set quality(t){this._quality=Math.max(1,Math.round(t)),this._generateKernels()}get kernels(){return this._kernels}set kernels(t){Array.isArray(t)&&t.length>0?(this._kernels=t,this._quality=t.length,this._blur=Math.max(...t)):(this._kernels=[0],this._quality=1)}get pixelSize(){return this._pixelSize}set pixelSize(t){if(typeof t=="number"){this.pixelSizeX=this.pixelSizeY=t;return}if(Array.isArray(t)){this.pixelSizeX=t[0],this.pixelSizeY=t[1];return}this._pixelSize=t}get pixelSizeX(){return this.pixelSize.x}set pixelSizeX(t){this.pixelSize.x=t}get pixelSizeY(){return this.pixelSize.y}set pixelSizeY(t){this.pixelSize.y=t}get clamp(){return this._clamp}_updatePadding(){this.padding=Math.ceil(this._kernels.reduce((t,e)=>t+e+.5,0))}_generateKernels(){const t=this._blur,e=this._quality,s=[t];if(t>0){let r=t;const n=t/e;for(let a=1;a<e;a++)r-=n,s.push(r)}this._kernels=s,this._updatePadding()}};Wn(tP,"DEFAULT_OPTIONS",{strength:4,quality:3,clamp:!1,pixelSize:{x:1,y:1}});let sP=tP;var Det=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uMapTexture;
|
||
|
uniform float uBloomScale;
|
||
|
uniform float uBrightness;
|
||
|
|
||
|
void main() {
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
color.rgb *= uBrightness;
|
||
|
vec4 bloomColor = vec4(texture(uMapTexture, vTextureCoord).rgb, 0.0);
|
||
|
bloomColor.rgb *= uBloomScale;
|
||
|
finalColor = color + bloomColor;
|
||
|
}
|
||
|
`,Let=`struct AdvancedBloomUniforms {
|
||
|
uBloomScale: f32,
|
||
|
uBrightness: f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> advancedBloomUniforms : AdvancedBloomUniforms;
|
||
|
@group(1) @binding(1) var uMapTexture: texture_2d<f32>;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
var color = textureSample(uTexture, uSampler, uv);
|
||
|
color = vec4<f32>(color.rgb * advancedBloomUniforms.uBrightness, color.a);
|
||
|
|
||
|
var bloomColor = vec4<f32>(textureSample(uMapTexture, uSampler, uv).rgb, 0.0);
|
||
|
bloomColor = vec4<f32>(bloomColor.rgb * advancedBloomUniforms.uBloomScale, bloomColor.a);
|
||
|
|
||
|
return color + bloomColor;
|
||
|
}
|
||
|
`,Fet=`
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uThreshold;
|
||
|
|
||
|
void main() {
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
// A simple & fast algorithm for getting brightness.
|
||
|
// It's inaccuracy , but good enought for this feature.
|
||
|
float _max = max(max(color.r, color.g), color.b);
|
||
|
float _min = min(min(color.r, color.g), color.b);
|
||
|
float brightness = (_max + _min) * 0.5;
|
||
|
|
||
|
if(brightness > uThreshold) {
|
||
|
finalColor = color;
|
||
|
} else {
|
||
|
finalColor = vec4(0.0, 0.0, 0.0, 0.0);
|
||
|
}
|
||
|
}
|
||
|
`,wet=`struct ExtractBrightnessUniforms {
|
||
|
uThreshold: f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> extractBrightnessUniforms : ExtractBrightnessUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
// A simple & fast algorithm for getting brightness.
|
||
|
// It's inaccurate, but good enough for this feature.
|
||
|
let max: f32 = max(max(color.r, color.g), color.b);
|
||
|
let min: f32 = min(min(color.r, color.g), color.b);
|
||
|
let brightness: f32 = (max + min) * 0.5;
|
||
|
|
||
|
return select(vec4<f32>(0.), color, brightness > extractBrightnessUniforms.uThreshold);
|
||
|
}
|
||
|
`,Get=Object.defineProperty,Bet=(i,t,e)=>t in i?Get(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,iP=(i,t,e)=>(Bet(i,typeof t!="symbol"?t+"":t,e),e);const rP=class nP extends xt{constructor(t){t={...nP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:wet,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Fet,name:"extract-brightness-filter"});super({gpuProgram:e,glProgram:s,resources:{extractBrightnessUniforms:{uThreshold:{value:t.threshold,type:"f32"}}}}),iP(this,"uniforms"),this.uniforms=this.resources.extractBrightnessUniforms.uniforms}get threshold(){return this.uniforms.uThreshold}set threshold(t){this.uniforms.uThreshold=t}};iP(rP,"DEFAULT_OPTIONS",{threshold:.5});let ket=rP;var zet=Object.defineProperty,Vet=(i,t,e)=>t in i?zet(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,oo=(i,t,e)=>(Vet(i,typeof t!="symbol"?t+"":t,e),e);const Het=class aP extends xt{constructor(t){t={...aP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Let,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Det,name:"advanced-bloom-filter"});super({gpuProgram:e,glProgram:s,resources:{advancedBloomUniforms:{uBloomScale:{value:t.bloomScale,type:"f32"},uBrightness:{value:t.brightness,type:"f32"}},uMapTexture:W.WHITE}}),oo(this,"uniforms"),oo(this,"bloomScale",1),oo(this,"brightness",1),oo(this,"_extractFilter"),oo(this,"_blurFilter"),this.uniforms=this.resources.advancedBloomUniforms.uniforms,this._extractFilter=new ket({threshold:t.threshold}),this._blurFilter=new sP({strength:t.kernels??t.blur,quality:t.kernels?void 0:t.quality}),Object.assign(this,t)}apply(t,e,s,r){const n=os.getSameSizeTexture(e);this._extractFilter.apply(t,e,n,!0);const a=os.getSameSizeTexture(e);this._blurFilter.apply(t,n,a,!0),this.uniforms.uBloomScale=this.bloomScale,this.uniforms.uBrightness=this.brightness,this.resources.uMapTexture=a.source,t.applyFilter(this,e,s,r),os.returnTexture(a),os.returnTexture(n)}get threshold(){return this._extractFilter.threshold}set threshold(t){this._extractFilter.threshold=t}get kernels(){return this._blurFilter.kernels}set kernels(t){this._blurFilter.kernels=t}get blur(){return this._blurFilter.strength}set blur(t){this._blurFilter.strength=t}get quality(){return this._blurFilter.quality}set quality(t){this._blurFilter.quality=t}get pixelSize(){return this._blurFilter.pixelSize}set pixelSize(t){typeof t=="number"&&(t={x:t,y:t}),Array.isArray(t)&&(t={x:t[0],y:t[1]}),this._blurFilter.pixelSize=t}get pixelSizeX(){return this._blurFilter.pixelSizeX}set pixelSizeX(t){this._blurFilter.pixelSizeX=t}get pixelSizeY(){return this._blurFilter.pixelSizeY}set pixelSizeY(t){this._blurFilter.pixelSizeY=t}};oo(Het,"DEFAULT_OPTIONS",{threshold:.5,bloomScale:1,brightness:1,blur:8,quality:4,pixelSize:{x:1,y:1}});var Yet=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uSize;
|
||
|
uniform vec3 uColor;
|
||
|
uniform float uReplaceColor;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
vec2 mapCoord( vec2 coord )
|
||
|
{
|
||
|
coord *= uInputSize.xy;
|
||
|
coord += uInputSize.zw;
|
||
|
|
||
|
return coord;
|
||
|
}
|
||
|
|
||
|
vec2 unmapCoord( vec2 coord )
|
||
|
{
|
||
|
coord -= uInputSize.zw;
|
||
|
coord /= uInputSize.xy;
|
||
|
|
||
|
return coord;
|
||
|
}
|
||
|
|
||
|
vec2 pixelate(vec2 coord, vec2 size)
|
||
|
{
|
||
|
return floor(coord / size) * size;
|
||
|
}
|
||
|
|
||
|
vec2 getMod(vec2 coord, vec2 size)
|
||
|
{
|
||
|
return mod(coord, size) / size;
|
||
|
}
|
||
|
|
||
|
float character(float n, vec2 p)
|
||
|
{
|
||
|
p = floor(p*vec2(4.0, 4.0) + 2.5);
|
||
|
|
||
|
if (clamp(p.x, 0.0, 4.0) == p.x)
|
||
|
{
|
||
|
if (clamp(p.y, 0.0, 4.0) == p.y)
|
||
|
{
|
||
|
if (int(mod(n/exp2(p.x + 5.0*p.y), 2.0)) == 1) return 1.0;
|
||
|
}
|
||
|
}
|
||
|
return 0.0;
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec2 coord = mapCoord(vTextureCoord);
|
||
|
|
||
|
// get the grid position
|
||
|
vec2 pixCoord = pixelate(coord, vec2(uSize));
|
||
|
pixCoord = unmapCoord(pixCoord);
|
||
|
|
||
|
// sample the color at grid position
|
||
|
vec4 color = texture(uTexture, pixCoord);
|
||
|
|
||
|
// brightness of the color as it's perceived by the human eye
|
||
|
float gray = 0.3 * color.r + 0.59 * color.g + 0.11 * color.b;
|
||
|
|
||
|
// determine the character to use
|
||
|
float n = 65536.0; // .
|
||
|
if (gray > 0.2) n = 65600.0; // :
|
||
|
if (gray > 0.3) n = 332772.0; // *
|
||
|
if (gray > 0.4) n = 15255086.0; // o
|
||
|
if (gray > 0.5) n = 23385164.0; // &
|
||
|
if (gray > 0.6) n = 15252014.0; // 8
|
||
|
if (gray > 0.7) n = 13199452.0; // @
|
||
|
if (gray > 0.8) n = 11512810.0; // #
|
||
|
|
||
|
// get the mod..
|
||
|
vec2 modd = getMod(coord, vec2(uSize));
|
||
|
|
||
|
finalColor = (uReplaceColor > 0.5 ? vec4(uColor, 1.) : color) * character( n, vec2(-1.0) + modd * 2.0);
|
||
|
}
|
||
|
`,Wet=`struct AsciiUniforms {
|
||
|
uSize: f32,
|
||
|
uColor: vec3<f32>,
|
||
|
uReplaceColor: f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> asciiUniforms : AsciiUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let pixelSize: f32 = asciiUniforms.uSize;
|
||
|
let coord: vec2<f32> = mapCoord(uv);
|
||
|
|
||
|
// get the rounded color..
|
||
|
var pixCoord: vec2<f32> = pixelate(coord, vec2<f32>(pixelSize));
|
||
|
pixCoord = unmapCoord(pixCoord);
|
||
|
|
||
|
var color = textureSample(uTexture, uSampler, pixCoord);
|
||
|
|
||
|
// determine the character to use
|
||
|
let gray: f32 = 0.3 * color.r + 0.59 * color.g + 0.11 * color.b;
|
||
|
|
||
|
var n: f32 = 65536.0; // .
|
||
|
if (gray > 0.2) {
|
||
|
n = 65600.0; // :
|
||
|
}
|
||
|
if (gray > 0.3) {
|
||
|
n = 332772.0; // *
|
||
|
}
|
||
|
if (gray > 0.4) {
|
||
|
n = 15255086.0; // o
|
||
|
}
|
||
|
if (gray > 0.5) {
|
||
|
n = 23385164.0; // &
|
||
|
}
|
||
|
if (gray > 0.6) {
|
||
|
n = 15252014.0; // 8
|
||
|
}
|
||
|
if (gray > 0.7) {
|
||
|
n = 13199452.0; // @
|
||
|
}
|
||
|
if (gray > 0.8) {
|
||
|
n = 11512810.0; // #
|
||
|
}
|
||
|
|
||
|
// get the mod..
|
||
|
let modd: vec2<f32> = getMod(coord, vec2<f32>(pixelSize));
|
||
|
return select(color, vec4<f32>(asciiUniforms.uColor, 1.), asciiUniforms.uReplaceColor > 0.5) * character(n, vec2<f32>(-1.0) + modd * 2.0);
|
||
|
}
|
||
|
|
||
|
fn pixelate(coord: vec2<f32>, size: vec2<f32>) -> vec2<f32>
|
||
|
{
|
||
|
return floor( coord / size ) * size;
|
||
|
}
|
||
|
|
||
|
fn getMod(coord: vec2<f32>, size: vec2<f32>) -> vec2<f32>
|
||
|
{
|
||
|
return moduloVec2( coord , size) / size;
|
||
|
}
|
||
|
|
||
|
fn character(n: f32, p: vec2<f32>) -> f32
|
||
|
{
|
||
|
var q: vec2<f32> = floor(p*vec2<f32>(4.0, 4.0) + 2.5);
|
||
|
|
||
|
if (clamp(q.x, 0.0, 4.0) == q.x)
|
||
|
{
|
||
|
if (clamp(q.y, 0.0, 4.0) == q.y)
|
||
|
{
|
||
|
if (i32(modulo(n/exp2(q.x + 5.0*q.y), 2.0)) == 1)
|
||
|
{
|
||
|
return 1.0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0.0;
|
||
|
}
|
||
|
|
||
|
fn modulo(x: f32, y: f32) -> f32
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
|
||
|
fn moduloVec2(x: vec2<f32>, y: vec2<f32>) -> vec2<f32>
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
|
||
|
fn mapCoord(coord: vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
var mappedCoord: vec2<f32> = coord;
|
||
|
mappedCoord *= gfu.uInputSize.xy;
|
||
|
mappedCoord += gfu.uOutputFrame.xy;
|
||
|
return mappedCoord;
|
||
|
}
|
||
|
|
||
|
fn unmapCoord(coord: vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
var mappedCoord: vec2<f32> = coord;
|
||
|
mappedCoord -= gfu.uOutputFrame.xy;
|
||
|
mappedCoord /= gfu.uInputSize.xy;
|
||
|
return mappedCoord;
|
||
|
}`,jet=Object.defineProperty,Ket=(i,t,e)=>t in i?jet(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,oI=(i,t,e)=>(Ket(i,typeof t!="symbol"?t+"":t,e),e);const Xet=class oP extends xt{constructor(...t){let e=t[0]??{};typeof e=="number"&&(ct("6.0.0","AsciiFilter constructor params are now options object. See params: { size, color, replaceColor }"),e={size:e});const s=(e==null?void 0:e.color)&&e.replaceColor!==!1;e={...oP.DEFAULT_OPTIONS,...e};const r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Wet,entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:Yet,name:"ascii-filter"});super({gpuProgram:r,glProgram:n,resources:{asciiUniforms:{uSize:{value:e.size,type:"f32"},uColor:{value:new Float32Array(3),type:"vec3<f32>"},uReplaceColor:{value:Number(s),type:"f32"}}}}),oI(this,"uniforms"),oI(this,"_color"),this.uniforms=this.resources.asciiUniforms.uniforms,this._color=new Mt,this.color=e.color??16777215}get size(){return this.uniforms.uSize}set size(t){this.uniforms.uSize=t}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get replaceColor(){return this.uniforms.uReplaceColor>.5}set replaceColor(t){this.uniforms.uReplaceColor=t?1:0}};oI(Xet,"DEFAULT_OPTIONS",{size:8,color:16777215,replaceColor:!1});var qet=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uTransform;
|
||
|
uniform vec3 uLightColor;
|
||
|
uniform float uLightAlpha;
|
||
|
uniform vec3 uShadowColor;
|
||
|
uniform float uShadowAlpha;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
void main(void) {
|
||
|
vec2 transform = vec2(1.0 / uInputSize) * vec2(uTransform.x, uTransform.y);
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
float light = texture(uTexture, vTextureCoord - transform).a;
|
||
|
float shadow = texture(uTexture, vTextureCoord + transform).a;
|
||
|
|
||
|
color.rgb = mix(color.rgb, uLightColor, clamp((color.a - light) * uLightAlpha, 0.0, 1.0));
|
||
|
color.rgb = mix(color.rgb, uShadowColor, clamp((color.a - shadow) * uShadowAlpha, 0.0, 1.0));
|
||
|
finalColor = vec4(color.rgb * color.a, color.a);
|
||
|
}
|
||
|
`,$et=`struct BevelUniforms {
|
||
|
uLightColor: vec3<f32>,
|
||
|
uLightAlpha: f32,
|
||
|
uShadowColor: vec3<f32>,
|
||
|
uShadowAlpha: f32,
|
||
|
uTransform: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> bevelUniforms : BevelUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let transform = vec2<f32>(1.0 / gfu.uInputSize.xy) * vec2<f32>(bevelUniforms.uTransform.x, bevelUniforms.uTransform.y);
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let lightSample: f32 = textureSample(uTexture, uSampler, uv - transform).a;
|
||
|
let shadowSample: f32 = textureSample(uTexture, uSampler, uv + transform).a;
|
||
|
|
||
|
let light = vec4<f32>(bevelUniforms.uLightColor, bevelUniforms.uLightAlpha);
|
||
|
let shadow = vec4<f32>(bevelUniforms.uShadowColor, bevelUniforms.uShadowAlpha);
|
||
|
|
||
|
color = vec4<f32>(mix(color.rgb, light.rgb, clamp((color.a - lightSample) * light.a, 0.0, 1.0)), color.a);
|
||
|
color = vec4<f32>(mix(color.rgb, shadow.rgb, clamp((color.a - shadowSample) * shadow.a, 0.0, 1.0)), color.a);
|
||
|
|
||
|
return vec4<f32>(color.rgb * color.a, color.a);
|
||
|
}`,Qet=Object.defineProperty,Zet=(i,t,e)=>t in i?Qet(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,uo=(i,t,e)=>(Zet(i,typeof t!="symbol"?t+"":t,e),e);const Jet=class uP extends xt{constructor(t){t={...uP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:$et,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:qet,name:"bevel-filter"});super({gpuProgram:e,glProgram:s,resources:{bevelUniforms:{uLightColor:{value:new Float32Array(3),type:"vec3<f32>"},uLightAlpha:{value:t.lightAlpha,type:"f32"},uShadowColor:{value:new Float32Array(3),type:"vec3<f32>"},uShadowAlpha:{value:t.shadowAlpha,type:"f32"},uTransform:{value:new Float32Array(2),type:"vec2<f32>"}}},padding:1}),uo(this,"uniforms"),uo(this,"_thickness"),uo(this,"_rotation"),uo(this,"_lightColor"),uo(this,"_shadowColor"),this.uniforms=this.resources.bevelUniforms.uniforms,this._lightColor=new Mt,this._shadowColor=new Mt,this.lightColor=t.lightColor??16777215,this.shadowColor=t.shadowColor??0,Object.assign(this,t)}get rotation(){return this._rotation/$o}set rotation(t){this._rotation=t*$o,this._updateTransform()}get thickness(){return this._thickness}set thickness(t){this._thickness=t,this._updateTransform()}get lightColor(){return this._lightColor.value}set lightColor(t){this._lightColor.setValue(t);const[e,s,r]=this._lightColor.toArray();this.uniforms.uLightColor[0]=e,this.uniforms.uLightColor[1]=s,this.uniforms.uLightColor[2]=r}get lightAlpha(){return this.uniforms.uLightAlpha}set lightAlpha(t){this.uniforms.uLightAlpha=t}get shadowColor(){return this._shadowColor.value}set shadowColor(t){this._shadowColor.setValue(t);const[e,s,r]=this._shadowColor.toArray();this.uniforms.uShadowColor[0]=e,this.uniforms.uShadowColor[1]=s,this.uniforms.uShadowColor[2]=r}get shadowAlpha(){return this.uniforms.uShadowAlpha}set shadowAlpha(t){this.uniforms.uShadowAlpha=t}_updateTransform(){this.uniforms.uTransform[0]=this.thickness*Math.cos(this._rotation),this.uniforms.uTransform[1]=this.thickness*Math.sin(this._rotation)}};uo(Jet,"DEFAULT_OPTIONS",{rotation:45,thickness:2,lightColor:16777215,lightAlpha:.7,shadowColor:0,shadowAlpha:.7});var tst=Object.defineProperty,est=(i,t,e)=>t in i?tst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Fc=(i,t,e)=>(est(i,typeof t!="symbol"?t+"":t,e),e);const sst=class lP extends n_{constructor(...t){let e=t[0]??{};if(typeof e=="number"||Array.isArray(e)||"x"in e&&"y"in e){ct("6.0.0","BloomFilter constructor params are now options object. See params: { strength, quality, resolution, kernelSize }");let s=e;Array.isArray(s)&&(s={x:s[0],y:s[1]}),e={strength:s},t[1]!==void 0&&(e.quality=t[1]),t[2]!==void 0&&(e.resolution=t[2]),t[3]!==void 0&&(e.kernelSize=t[3])}e={...lP.DEFAULT_OPTIONS,...e},super(),Fc(this,"_blurXFilter"),Fc(this,"_blurYFilter"),Fc(this,"_strength"),this._strength={x:2,y:2},e.strength&&(typeof e.strength=="number"?(this._strength.x=e.strength,this._strength.y=e.strength):(this._strength.x=e.strength.x,this._strength.y=e.strength.y)),this._blurXFilter=new ny({...e,horizontal:!0,strength:this.strengthX}),this._blurYFilter=new ny({...e,horizontal:!1,strength:this.strengthY}),this._blurYFilter.blendMode="screen",Object.assign(this,e)}apply(t,e,s,r){const n=os.getSameSizeTexture(e);t.applyFilter(this,e,s,r),this._blurXFilter.apply(t,e,n,!0),this._blurYFilter.apply(t,n,s,!1),os.returnTexture(n)}get strength(){return this._strength}set strength(t){this._strength=typeof t=="number"?{x:t,y:t}:t,this._updateStrength()}get strengthX(){return this.strength.x}set strengthX(t){this.strength.x=t,this._updateStrength()}get strengthY(){return this.strength.y}set strengthY(t){this.strength.y=t,this._updateStrength()}_updateStrength(){this._blurXFilter.blur=this.strengthX,this._blurYFilter.blur=this.strengthY}get blur(){return ct("6.0.0","BloomFilter.blur is deprecated, please use BloomFilter.strength instead"),this.strengthX}set blur(t){ct("6.0.0","BloomFilter.blur is deprecated, please use BloomFilter.strength instead"),this.strength=t}get blurX(){return ct("6.0.0","Bloom
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uDimensions;
|
||
|
uniform vec2 uCenter;
|
||
|
uniform float uRadius;
|
||
|
uniform float uStrength;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec2 coord = vTextureCoord * uInputSize.xy;
|
||
|
coord -= uCenter * uDimensions.xy;
|
||
|
float distance = length(coord);
|
||
|
|
||
|
if (distance < uRadius) {
|
||
|
float percent = distance / uRadius;
|
||
|
if (uStrength > 0.0) {
|
||
|
coord *= mix(1.0, smoothstep(0.0, uRadius / distance, percent), uStrength * 0.75);
|
||
|
} else {
|
||
|
coord *= mix(1.0, pow(percent, 1.0 + uStrength * 0.75) * uRadius / distance, 1.0 - percent);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
coord += uCenter * uDimensions.xy;
|
||
|
coord /= uInputSize.xy;
|
||
|
vec2 clampedCoord = clamp(coord, uInputClamp.xy, uInputClamp.zw);
|
||
|
vec4 color = texture(uTexture, clampedCoord);
|
||
|
|
||
|
if (coord != clampedCoord) {
|
||
|
color *= max(0.0, 1.0 - length(coord - clampedCoord));
|
||
|
}
|
||
|
|
||
|
finalColor = color;
|
||
|
}
|
||
|
`,rst=`struct BulgePinchUniforms {
|
||
|
uDimensions: vec2<f32>,
|
||
|
uCenter: vec2<f32>,
|
||
|
uRadius: f32,
|
||
|
uStrength: f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> bulgePinchUniforms : BulgePinchUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let dimensions: vec2<f32> = bulgePinchUniforms.uDimensions;
|
||
|
let center: vec2<f32> = bulgePinchUniforms.uCenter;
|
||
|
let radius: f32 = bulgePinchUniforms.uRadius;
|
||
|
let strength: f32 = bulgePinchUniforms.uStrength;
|
||
|
var coord: vec2<f32> = (uv * gfu.uInputSize.xy) - center * dimensions.xy;
|
||
|
|
||
|
let distance: f32 = length(coord);
|
||
|
|
||
|
if (distance < radius) {
|
||
|
let percent: f32 = distance / radius;
|
||
|
if (strength > 0.0) {
|
||
|
coord *= mix(1.0, smoothstep(0.0, radius / distance, percent), strength * 0.75);
|
||
|
} else {
|
||
|
coord *= mix(1.0, pow(percent, 1.0 + strength * 0.75) * radius / distance, 1.0 - percent);
|
||
|
}
|
||
|
}
|
||
|
coord += (center * dimensions.xy);
|
||
|
coord /= gfu.uInputSize.xy;
|
||
|
|
||
|
let clampedCoord: vec2<f32> = clamp(coord, gfu.uInputClamp.xy, gfu.uInputClamp.zw);
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, clampedCoord);
|
||
|
if (coord.x != clampedCoord.x && coord.y != clampedCoord.y) {
|
||
|
color *= max(0.0, 1.0 - length(coord - clampedCoord));
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
fn compareVec2(x: vec2<f32>, y: vec2<f32>) -> bool
|
||
|
{
|
||
|
if (x.x == y.x && x.y == y.y)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}`,nst=Object.defineProperty,ast=(i,t,e)=>t in i?nst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,hP=(i,t,e)=>(ast(i,typeof t!="symbol"?t+"":t,e),e);const ost=class cP extends xt{constructor(t){t={...cP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:rst,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:ist,name:"bulge-pinch-filter"});super({gpuProgram:e,glProgram:s,resources:{bulgePinchUniforms:{uDimensions:{value:[0,0],type:"vec2<f32>"},uCenter:{value:t.center,type:"vec2<f32>"},uRadius:{value:t.radius,type:"f32"},uStrength:{value:t.strength,type:"f32"}}}}),hP(this,"uniforms"),this.uniforms=this.resources.bulgePinchUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){this.uniforms.uDimensions[0]=e.frame.width,this.uniforms.uDimensions[1]=e.frame.height,t.applyFilter(this,e,s,r)}get center(){return this.uniforms.uCenter}set center(t){typeof t=="number"&&(t={x:t,y:t}),Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uCenter=t}get centerX(){return this.uniforms.uCenter.x}set centerX(t){this.uniforms.uCenter.x=t}get centerY(){return this.uniforms.uCenter.y}set centerY(t){this.uniforms.uCenter.y=t}get radius(){return this.uniforms.uRadius}set radius(t){this.uniforms.uRadius=t}get strength(){return this.uniforms.uStrength}set strength(t){this.uniforms.uStrength=t}};hP(ost,"DEFAULT_OPTIONS",{center:{x:.5,y:.5},radius:100,strength:1});var ust=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
in vec2 vFilterCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
const int TYPE_LINEAR = 0;
|
||
|
const int TYPE_RADIAL = 1;
|
||
|
const int TYPE_CONIC = 2;
|
||
|
const int MAX_STOPS = 32;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec4 uOptions;
|
||
|
uniform vec2 uCounts;
|
||
|
uniform vec3 uColors[MAX_STOPS];
|
||
|
uniform vec4 uStops[MAX_STOPS];
|
||
|
|
||
|
const float PI = 3.1415926538;
|
||
|
const float PI_2 = PI*2.;
|
||
|
|
||
|
struct ColorStop {
|
||
|
float offset;
|
||
|
vec3 color;
|
||
|
float alpha;
|
||
|
};
|
||
|
|
||
|
mat2 rotate2d(float angle){
|
||
|
return mat2(cos(angle), -sin(angle),
|
||
|
sin(angle), cos(angle));
|
||
|
}
|
||
|
|
||
|
float projectLinearPosition(vec2 pos, float angle){
|
||
|
vec2 center = vec2(0.5);
|
||
|
vec2 result = pos - center;
|
||
|
result = rotate2d(angle) * result;
|
||
|
result = result + center;
|
||
|
return clamp(result.x, 0., 1.);
|
||
|
}
|
||
|
|
||
|
float projectRadialPosition(vec2 pos) {
|
||
|
float r = distance(pos, vec2(0.5));
|
||
|
return clamp(2.*r, 0., 1.);
|
||
|
}
|
||
|
|
||
|
float projectAnglePosition(vec2 pos, float angle) {
|
||
|
vec2 center = pos - vec2(0.5);
|
||
|
float polarAngle=atan(-center.y, center.x);
|
||
|
return mod(polarAngle + angle, PI_2) / PI_2;
|
||
|
}
|
||
|
|
||
|
float projectPosition(vec2 pos, int type, float angle) {
|
||
|
if (type == TYPE_LINEAR) {
|
||
|
return projectLinearPosition(pos, angle);
|
||
|
} else if (type == TYPE_RADIAL) {
|
||
|
return projectRadialPosition(pos);
|
||
|
} else if (type == TYPE_CONIC) {
|
||
|
return projectAnglePosition(pos, angle);
|
||
|
}
|
||
|
|
||
|
return pos.y;
|
||
|
}
|
||
|
|
||
|
void main(void) {
|
||
|
int uType = int(uOptions[0]);
|
||
|
float uAngle = uOptions[1];
|
||
|
float uAlpha = uOptions[2];
|
||
|
float uReplace = uOptions[3];
|
||
|
|
||
|
int uNumStops = int(uCounts[0]);
|
||
|
float uMaxColors = uCounts[1];
|
||
|
|
||
|
// current/original color
|
||
|
vec4 currentColor = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
// skip calculations if gradient alpha is 0
|
||
|
if (0.0 == uAlpha) {
|
||
|
finalColor = currentColor;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// project position
|
||
|
float y = projectPosition(vFilterCoord, int(uType), radians(uAngle));
|
||
|
|
||
|
// check gradient bounds
|
||
|
float offsetMin = uStops[0][0];
|
||
|
float offsetMax = 0.0;
|
||
|
|
||
|
int numStops = int(uNumStops);
|
||
|
|
||
|
for (int i = 0; i < MAX_STOPS; i++) {
|
||
|
if (i == numStops-1){ // last index
|
||
|
offsetMax = uStops[i][0];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (y < offsetMin || y > offsetMax) {
|
||
|
finalColor = currentColor;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// limit colors
|
||
|
if (uMaxColors > 0.) {
|
||
|
float stepSize = 1./uMaxColors;
|
||
|
float stepNumber = float(floor(y/stepSize));
|
||
|
y = stepSize * (stepNumber + 0.5);// offset by 0.5 to use color from middle of segment
|
||
|
}
|
||
|
|
||
|
// find color stops
|
||
|
ColorStop from;
|
||
|
ColorStop to;
|
||
|
|
||
|
for (int i = 0; i < MAX_STOPS; i++) {
|
||
|
if (y >= uStops[i][0]) {
|
||
|
from = ColorStop(uStops[i][0], uColors[i], uStops[i][1]);
|
||
|
to = ColorStop(uStops[i+1][0], uColors[i+1], uStops[i+1][1]);
|
||
|
}
|
||
|
|
||
|
if (i == numStops-1){ // last index
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// mix colors from stops
|
||
|
vec4 colorFrom = vec4(from.color * from.alpha, from.alpha);
|
||
|
vec4 colorTo = vec4(to.color * to.alpha, to.alpha);
|
||
|
|
||
|
float segmentHeight = to.offset - from.offset;
|
||
|
float relativePos = y - from.offset;// position from 0 to [segmentHeight]
|
||
|
float relativePercent = relativePos / segmentHeight;// position in percent between [from.offset] and [to.offset].
|
||
|
|
||
|
float gradientAlpha = uAlpha * currentColor.a;
|
||
|
vec4 gradientColor = mix(colorFrom, colorTo, relativePercent) * gradientAlpha;
|
||
|
|
||
|
if (uReplace < 0.5) {
|
||
|
// mix resulting color with current color
|
||
|
finalColor = gradientColor + currentColor*(1.-gradientColor.a);
|
||
|
} else {
|
||
|
// replace with gradient color
|
||
|
finalColor = gradientColor;
|
||
|
}
|
||
|
}
|
||
|
`,lst=`in vec2 aPosition;
|
||
|
out vec2 vTextureCoord;
|
||
|
out vec2 vFilterCoord;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uOutputFrame;
|
||
|
uniform vec4 uOutputTexture;
|
||
|
|
||
|
vec4 filterVertexPosition( void )
|
||
|
{
|
||
|
vec2 position = aPosition * uOutputFrame.zw + uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*uOutputTexture.z / uOutputTexture.y) - uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
vec2 filterTextureCoord( void )
|
||
|
{
|
||
|
return aPosition * (uOutputFrame.zw * uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_Position = filterVertexPosition();
|
||
|
vTextureCoord = filterTextureCoord();
|
||
|
vFilterCoord = vTextureCoord * uInputSize.xy / uOutputFrame.zw;
|
||
|
}
|
||
|
`,Qy=`struct BaseUniforms {
|
||
|
uOptions: vec4<f32>,
|
||
|
uCounts: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct StopsUniforms {
|
||
|
uColors: array<vec3<f32>, MAX_STOPS>,
|
||
|
uStops: array<vec4<f32>, MAX_STOPS>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> baseUniforms : BaseUniforms;
|
||
|
@group(1) @binding(1) var<uniform> stopsUniforms : StopsUniforms;
|
||
|
|
||
|
struct VSOutput {
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>,
|
||
|
@location(1) coord : vec2<f32>
|
||
|
};
|
||
|
|
||
|
fn filterVertexPosition(aPosition:vec2<f32>) -> vec4<f32>
|
||
|
{
|
||
|
var position = aPosition * gfu.uOutputFrame.zw + gfu.uOutputFrame.xy;
|
||
|
|
||
|
position.x = position.x * (2.0 / gfu.uOutputTexture.x) - 1.0;
|
||
|
position.y = position.y * (2.0*gfu.uOutputTexture.z / gfu.uOutputTexture.y) - gfu.uOutputTexture.z;
|
||
|
|
||
|
return vec4(position, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn filterTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return aPosition * (gfu.uOutputFrame.zw * gfu.uInputSize.zw);
|
||
|
}
|
||
|
|
||
|
fn filterCoord( vTextureCoord:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return vTextureCoord * gfu.uInputSize.xy / gfu.uOutputFrame.zw;
|
||
|
}
|
||
|
|
||
|
fn globalTextureCoord( aPosition:vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
return (aPosition.xy / gfu.uGlobalFrame.zw) + (gfu.uGlobalFrame.xy / gfu.uGlobalFrame.zw);
|
||
|
}
|
||
|
|
||
|
fn getSize() -> vec2<f32>
|
||
|
{
|
||
|
return gfu.uGlobalFrame.zw;
|
||
|
}
|
||
|
|
||
|
@vertex
|
||
|
fn mainVertex(
|
||
|
@location(0) aPosition : vec2<f32>,
|
||
|
) -> VSOutput {
|
||
|
let vTextureCoord: vec2<f32> = filterTextureCoord(aPosition);
|
||
|
return VSOutput(
|
||
|
filterVertexPosition(aPosition),
|
||
|
vTextureCoord,
|
||
|
filterCoord(vTextureCoord),
|
||
|
);
|
||
|
}
|
||
|
|
||
|
struct ColorStop {
|
||
|
offset: f32,
|
||
|
color: vec3<f32>,
|
||
|
alpha: f32,
|
||
|
};
|
||
|
|
||
|
fn rotate2d(angle: f32) -> mat2x2<f32>{
|
||
|
return mat2x2(cos(angle), -sin(angle),
|
||
|
sin(angle), cos(angle));
|
||
|
}
|
||
|
|
||
|
fn projectLinearPosition(pos: vec2<f32>, angle: f32) -> f32 {
|
||
|
var center: vec2<f32> = vec2<f32>(0.5);
|
||
|
var result: vec2<f32> = pos - center;
|
||
|
result = rotate2d(angle) * result;
|
||
|
result = result + center;
|
||
|
return clamp(result.x, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn projectRadialPosition(pos: vec2<f32>) -> f32 {
|
||
|
var r: f32 = distance(pos, vec2<f32>(0.5));
|
||
|
return clamp(2.0 * r, 0.0, 1.0);
|
||
|
}
|
||
|
|
||
|
fn projectAnglePosition(pos: vec2<f32>, angle: f32) -> f32 {
|
||
|
var center: vec2<f32> = pos - vec2<f32>(0.5, 0.5);
|
||
|
var polarAngle: f32 = atan2(-center.y, center.x);
|
||
|
return ((polarAngle + angle) % PI_2) / PI_2;
|
||
|
}
|
||
|
|
||
|
fn projectPosition(pos: vec2<f32>, gradientType: i32, angle: f32) -> f32 {
|
||
|
if (gradientType == TYPE_LINEAR) {
|
||
|
return projectLinearPosition(pos, angle);
|
||
|
} else if (gradientType == TYPE_RADIAL) {
|
||
|
return projectRadialPosition(pos);
|
||
|
} else if (gradientType == TYPE_CONIC) {
|
||
|
return projectAnglePosition(pos, angle);
|
||
|
}
|
||
|
|
||
|
return pos.y;
|
||
|
}
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>,
|
||
|
@location(1) coord : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uType: i32 = i32(baseUniforms.uOptions[0]);
|
||
|
let uAngle: f32 = baseUniforms.uOptions[1];
|
||
|
let uAlpha: f32 = baseUniforms.uOptions[2];
|
||
|
let uReplace: f32 = baseUniforms.uOptions[3];
|
||
|
|
||
|
let uNumStops: i32 = i32(baseUniforms.uCounts[0]);
|
||
|
let uMaxColors: f32 = baseUniforms.uCounts[1];
|
||
|
|
||
|
// current/original color
|
||
|
var currentColor: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
// skip calculations if gradient alpha is 0
|
||
|
if (uAlpha == 0.0) { return currentColor; }
|
||
|
|
||
|
// project position
|
||
|
var y: f32 = projectPosition(coord, uType, radians(uAngle));
|
||
|
|
||
|
// check gradient bounds
|
||
|
var offsetMin: f32 = stopsUniforms.uStops[0][0];
|
||
|
var offsetMax: f32 = 0.0;
|
||
|
|
||
|
let numStops: i32 = uNumStops;
|
||
|
|
||
|
for (var i: i32 = 0; i < MAX_STOPS; i = i + 1) {
|
||
|
if (i == numStops - 1) { // last index
|
||
|
offsetMax = stopsUniforms.uStops[i][0];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (y < offsetMin || y > offsetMax) { return currentColor; }
|
||
|
|
||
|
// limit colors
|
||
|
if (uMaxColors > 0.0) {
|
||
|
var stepSize: f32 = 1.0 / uMaxColors;
|
||
|
var stepNumber: f32 = floor(y / stepSize);
|
||
|
y = stepSize * (stepNumber + 0.5); // offset by 0.5 to use color from middle of segment
|
||
|
}
|
||
|
|
||
|
// find color stops
|
||
|
var stopFrom: ColorStop;
|
||
|
var stopTo: ColorStop;
|
||
|
|
||
|
for (var i: i32 = 0; i < MAX_STOPS; i = i + 1) {
|
||
|
if (y >= stopsUniforms.uStops[i][0]) {
|
||
|
stopFrom = ColorStop(stopsUniforms.uStops[i][0], stopsUniforms.uColors[i], stopsUniforms.uStops[i][1]);
|
||
|
stopTo = ColorStop(stopsUniforms.uStops[i + 1][0], stopsUniforms.uColors[i + 1], stopsUniforms.uStops[i + 1][1]);
|
||
|
}
|
||
|
|
||
|
if (i == numStops - 1) { // last index
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// mix colors from stops
|
||
|
var colorFrom: vec4<f32> = vec4<f32>(stopFrom.color * stopFrom.alpha, stopFrom.alpha);
|
||
|
var colorTo: vec4<f32> = vec4<f32>(stopTo.color * stopTo.alpha, stopTo.alpha);
|
||
|
|
||
|
var segmentHeight: f32 = stopTo.offset - stopFrom.offset;
|
||
|
var relativePos: f32 = y - stopFrom.offset; // position from 0 to [segmentHeight]
|
||
|
var relativePercent: f32 = relativePos / segmentHeight; // position in percent between [from.offset] and [to.offset].
|
||
|
|
||
|
var gradientAlpha: f32 = uAlpha * currentColor.a;
|
||
|
var gradientColor: vec4<f32> = mix(colorFrom, colorTo, relativePercent) * gradientAlpha;
|
||
|
|
||
|
if (uReplace < 0.5) {
|
||
|
// mix resulting color with current color
|
||
|
return gradientColor + currentColor * (1.0 - gradientColor.a);
|
||
|
} else {
|
||
|
// replace with gradient color
|
||
|
return gradientColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const PI: f32 = 3.14159265358979323846264;
|
||
|
const PI_2: f32 = PI * 2.0;
|
||
|
|
||
|
const TYPE_LINEAR: i32 = 0;
|
||
|
const TYPE_RADIAL: i32 = 1;
|
||
|
const TYPE_CONIC: i32 = 2;
|
||
|
const MAX_STOPS: i32 = 32;`,Ja=Ja||{};Ja.stringify=function(){var i={"visit_linear-gradient":function(t){return i.visit_gradient(t)},"visit_repeating-linear-gradient":function(t){return i.visit_gradient(t)},"visit_radial-gradient":function(t){return i.visit_gradient(t)},"visit_repeating-radial-gradient":function(t){return i.visit_gradient(t)},visit_gradient:function(t){var e=i.visit(t.orientation);return e&&(e+=", "),t.type+"("+e+i.visit(t.colorStops)+")"},visit_shape:function(t){var e=t.value,s=i.visit(t.at),r=i.visit(t.style);return r&&(e+=" "+r),s&&(e+=" at "+s),e},"visit_default-radial":function(t){var e="",s=i.visit(t.at);return s&&(e+=s),e},"visit_extent-keyword":function(t){var e=t.value,s=i.visit(t.at);return s&&(e+=" at "+s),e},"visit_position-keyword":function(t){return t.value},visit_position:function(t){return i.visit(t.value.x)+" "+i.visit(t.value.y)},"visit_%":function(t){return t.value+"%"},visit_em:function(t){return t.value+"em"},visit_px:function(t){return t.value+"px"},visit_literal:function(t){return i.visit_color(t.value,t)},visit_hex:function(t){return i.visit_color("#"+t.value,t)},visit_rgb:function(t){return i.visit_color("rgb("+t.value.join(", ")+")",t)},visit_rgba:function(t){return i.visit_color("rgba("+t.value.join(", ")+")",t)},visit_color:function(t,e){var s=t,r=i.visit(e.length);return r&&(s+=" "+r),s},visit_angular:function(t){return t.value+"deg"},visit_directional:function(t){return"to "+t.value},visit_array:function(t){var e="",s=t.length;return t.forEach(function(r,n){e+=i.visit(r),n<s-1&&(e+=", ")}),e},visit:function(t){if(!t)return"";var e="";if(t instanceof Array)return i.visit_array(t,e);if(t.type){var s=i["visit_"+t.type];if(s)return s(t);throw Error("Missing visitor visit_"+t.type)}else throw Error("Invalid node.")}};return function(t){return i.visit(t)}}();var Ja=Ja||{};Ja.parse=function(){var i={linearGradient:/^(\-(webkit|o|ms|moz)\-)?(linear\-gradient)/i,repeatingLinearGradient:/^(\-(webkit|o|ms|moz)\-)?(repeating\-linear\-gradient)/i,radialGradient:/^(\-(webkit|o|ms|moz)\-)?(radial\-gradient)/i,repeatingRadialGradient:/^(\-(webkit|o|ms|moz)\-)?(repeating\-radial\-gradient)/i,sideOrCorner:/^to (left (top|bottom)|right (top|bottom)|left|right|top|bottom)/i,extentKeywords:/^(closest\-side|closest\-corner|farthest\-side|farthest\-corner|contain|cover)/,positionKeywords:/^(left|center|right|top|bottom)/i,pixelValue:/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))px/,percentageValue:/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))\%/,emValue:/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))em/,angleValue:/^(-?(([0-9]*\.[0-9]+)|([0-9]+\.?)))deg/,startCall:/^\(/,endCall:/^\)/,comma:/^,/,hexColor:/^\#([0-9a-fA-F]+)/,literalColor:/^([a-zA-Z]+)/,rgbColor:/^rgb/i,rgbaColor:/^rgba/i,number:/^(([0-9]*\.[0-9]+)|([0-9]+\.?))/},t="";function e(V){var Pt=new Error(t+": "+V);throw Pt.source=t,Pt}function s(){var V=r();return t.length>0&&e("Invalid input not EOF"),V}function r(){return y(n)}function n(){return a("linear-gradient",i.linearGradient,u)||a("repeating-linear-gradient",i.repeatingLinearGradient,u)||a("radial-gradient",i.radialGradient,h)||a("repeating-radial-gradient",i.repeatingRadialGradient,h)}function a(V,Pt,K){return o(Pt,function(ut){var Kr=K();return Kr&&(lt(i.comma)||e("Missing comma before color stops")),{type:V,orientation:Kr,colorStops:y(C)}})}function o(V,Pt){var K=lt(V);if(K){lt(i.startCall)||e("Missing (");var ut=Pt(K);return lt(i.endCall)||e("Missing )"),ut}}function u(){return l()||c()}function l(){return Y("directional",i.sideOrCorner,1)}function c(){return Y("angular",i.angleValue,1)}function h(){var V,Pt=_(),K;return Pt&&(V=[],V.push(Pt),K=t,lt(i.comma)&&(Pt=_(),Pt?V.push(Pt):t=K)),V}function _(){var V=d()||f();if(V)V.at=g();else{var Pt=p();if(Pt){V=Pt;var K=g();K&&(V.at=K)}else{var ut=m();ut&&(V={type:"default-radial",at:ut})}}return V}function d(){var V=Y("shape",/^(circle)/i,0);return V&&(V.style=X()||p()),V}function f(){var V=Y("shape",/^(ellipse)/i,0);return V&&(V.style=k()||p()),V}function p(){return Y("extent-keyword",i.extentKeywords,1)}function g(){if(Y("position",/^at/,0)){var V=m();return
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uMapTexture;
|
||
|
uniform float uMix;
|
||
|
uniform float uSize;
|
||
|
uniform float uSliceSize;
|
||
|
uniform float uSlicePixelSize;
|
||
|
uniform float uSliceInnerSize;
|
||
|
|
||
|
void main() {
|
||
|
vec4 color = texture(uTexture, vTextureCoord.xy);
|
||
|
vec4 adjusted;
|
||
|
|
||
|
if (color.a > 0.0) {
|
||
|
color.rgb /= color.a;
|
||
|
float innerWidth = uSize - 1.0;
|
||
|
float zSlice0 = min(floor(color.b * innerWidth), innerWidth);
|
||
|
float zSlice1 = min(zSlice0 + 1.0, innerWidth);
|
||
|
float xOffset = uSlicePixelSize * 0.5 + color.r * uSliceInnerSize;
|
||
|
float s0 = xOffset + (zSlice0 * uSliceSize);
|
||
|
float s1 = xOffset + (zSlice1 * uSliceSize);
|
||
|
float yOffset = uSliceSize * 0.5 + color.g * (1.0 - uSliceSize);
|
||
|
vec4 slice0Color = texture(uMapTexture, vec2(s0,yOffset));
|
||
|
vec4 slice1Color = texture(uMapTexture, vec2(s1,yOffset));
|
||
|
float zOffset = fract(color.b * innerWidth);
|
||
|
adjusted = mix(slice0Color, slice1Color, zOffset);
|
||
|
|
||
|
color.rgb *= color.a;
|
||
|
}
|
||
|
|
||
|
finalColor = vec4(mix(color, adjusted, uMix).rgb, color.a);
|
||
|
|
||
|
}`,Ost=`struct ColorMapUniforms {
|
||
|
uMix: f32,
|
||
|
uSize: f32,
|
||
|
uSliceSize: f32,
|
||
|
uSlicePixelSize: f32,
|
||
|
uSliceInnerSize: f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> colorMapUniforms : ColorMapUniforms;
|
||
|
@group(1) @binding(1) var uMapTexture: texture_2d<f32>;
|
||
|
@group(1) @binding(2) var uMapSampler: sampler;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
var color:vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
var adjusted: vec4<f32>;
|
||
|
|
||
|
var altColor: vec4<f32> = vec4<f32>(color.rgb / color.a, color.a);
|
||
|
let innerWidth: f32 = colorMapUniforms.uSize - 1.0;
|
||
|
let zSlice0: f32 = min(floor(color.b * innerWidth), innerWidth);
|
||
|
let zSlice1: f32 = min(zSlice0 + 1.0, innerWidth);
|
||
|
let xOffset: f32 = colorMapUniforms.uSlicePixelSize * 0.5 + color.r * colorMapUniforms.uSliceInnerSize;
|
||
|
let s0: f32 = xOffset + (zSlice0 * colorMapUniforms.uSliceSize);
|
||
|
let s1: f32 = xOffset + (zSlice1 * colorMapUniforms.uSliceSize);
|
||
|
let yOffset: f32 = colorMapUniforms.uSliceSize * 0.5 + color.g * (1.0 - colorMapUniforms.uSliceSize);
|
||
|
let slice0Color: vec4<f32> = textureSample(uMapTexture, uMapSampler, vec2(s0,yOffset));
|
||
|
let slice1Color: vec4<f32> = textureSample(uMapTexture, uMapSampler, vec2(s1,yOffset));
|
||
|
let zOffset: f32 = fract(color.b * innerWidth);
|
||
|
adjusted = mix(slice0Color, slice1Color, zOffset);
|
||
|
altColor = vec4<f32>(color.rgb * color.a, color.a);
|
||
|
|
||
|
let realColor: vec4<f32> = select(color, altColor, color.a > 0.0);
|
||
|
|
||
|
return vec4<f32>(mix(realColor, adjusted, colorMapUniforms.uMix).rgb, realColor.a);
|
||
|
}`,yst=Object.defineProperty,vst=(i,t,e)=>t in i?yst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,lr=(i,t,e)=>(vst(i,typeof t!="symbol"?t+"":t,e),e);const Cst=class _P extends xt{constructor(...t){let e=t[0]??{};if((e instanceof W||e instanceof De)&&(ct("6.0.0","ColorMapFilter constructor params are now options object. See params: { colorMap, nearest, mix }"),e={colorMap:e},t[1]!==void 0&&(e.nearest=t[1]),t[2]!==void 0&&(e.mix=t[2])),e={..._P.DEFAULT_OPTIONS,...e},!e.colorMap)throw Error("No color map texture source was provided to ColorMapFilter");const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Ost,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:Ast,name:"color-map-filter"});super({gpuProgram:s,glProgram:r,resources:{colorMapUniforms:{uMix:{value:e.mix,type:"f32"},uSize:{value:0,type:"f32"},uSliceSize:{value:0,type:"f32"},uSlicePixelSize:{value:0,type:"f32"},uSliceInnerSize:{value:0,type:"f32"}},uMapTexture:e.colorMap.source,uMapSampler:e.colorMap.source.style}}),lr(this,"uniforms"),lr(this,"_size",0),lr(this,"_sliceSize",0),lr(this,"_slicePixelSize",0),lr(this,"_sliceInnerSize",0),lr(this,"_nearest",!1),lr(this,"_scaleMode","linear"),lr(this,"_colorMap"),this.uniforms=this.resources.colorMapUniforms.uniforms,Object.assign(this,e)}get mix(){return this.uniforms.uMix}set mix(t){this.uniforms.uMix=t}get colorSize(){return this._size}get colorMap(){return this._colorMap}set colorMap(t){if(!t||t===this.colorMap)return;const e=t instanceof W?t.source:t;e.style.scaleMode=this._scaleMode,e.autoGenerateMipmaps=!1,this._size=e.height,this._sliceSize=1/this._size,this._slicePixelSize=this._sliceSize/this._size,this._sliceInnerSize=this._slicePixelSize*(this._size-1),this.uniforms.uSize=this._size,this.uniforms.uSliceSize=this._sliceSize,this.uniforms.uSlicePixelSize=this._slicePixelSize,this.uniforms.uSliceInnerSize=this._sliceInnerSize,this.resources.uMapTexture=e,this._colorMap=t}get nearest(){return this._nearest}set nearest(t){this._nearest=t,this._scaleMode=t?"nearest":"linear";const e=this._colorMap;e&&e.source&&(e.source.scaleMode=this._scaleMode,e.source.autoGenerateMipmaps=!1,e.source.style.update(),e.source.update())}updateColorMap(){const t=this._colorMap;t!=null&&t.source&&(t.source.update(),this.colorMap=t)}destroy(){var t;(t=this._colorMap)==null||t.destroy(),super.destroy()}};lr(Cst,"DEFAULT_OPTIONS",{colorMap:W.WHITE,nearest:!1,mix:1});var Mst=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec3 uColor;
|
||
|
uniform float uAlpha;
|
||
|
|
||
|
void main(void) {
|
||
|
vec4 c = texture(uTexture, vTextureCoord);
|
||
|
finalColor = vec4(mix(c.rgb, uColor.rgb, c.a * uAlpha), c.a);
|
||
|
}
|
||
|
`,xst=`struct ColorOverlayUniforms {
|
||
|
uColor: vec3<f32>,
|
||
|
uAlpha: f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> colorOverlayUniforms : ColorOverlayUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let c = textureSample(uTexture, uSampler, uv);
|
||
|
return vec4<f32>(mix(c.rgb, colorOverlayUniforms.uColor.rgb, c.a * colorOverlayUniforms.uAlpha), c.a);
|
||
|
}
|
||
|
`,Pst=Object.defineProperty,bst=(i,t,e)=>t in i?Pst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,uI=(i,t,e)=>(bst(i,typeof t!="symbol"?t+"":t,e),e);const Nst=class dP extends xt{constructor(...t){let e=t[0]??{};(typeof e=="number"||Array.isArray(e)||e instanceof Float32Array)&&(ct("6.0.0","ColorOverlayFilter constructor params are now options object. See params: { color, alpha }"),e={color:e},t[1]!==void 0&&(e.alpha=t[1])),e={...dP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:xst,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:Mst,name:"color-overlay-filter"});super({gpuProgram:s,glProgram:r,resources:{colorOverlayUniforms:{uColor:{value:new Float32Array(3),type:"vec3<f32>"},uAlpha:{value:e.alpha,type:"f32"}}}}),uI(this,"uniforms"),uI(this,"_color"),this.uniforms=this.resources.colorOverlayUniforms.uniforms,this._color=new Mt,this.color=e.color??0}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}};uI(Nst,"DEFAULT_OPTIONS",{color:0,alpha:1});var Ust=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec3 uOriginalColor;
|
||
|
uniform vec3 uTargetColor;
|
||
|
uniform float uTolerance;
|
||
|
|
||
|
void main(void) {
|
||
|
vec4 c = texture(uTexture, vTextureCoord);
|
||
|
vec3 colorDiff = uOriginalColor - (c.rgb / max(c.a, 0.0000000001));
|
||
|
float colorDistance = length(colorDiff);
|
||
|
float doReplace = step(colorDistance, uTolerance);
|
||
|
finalColor = vec4(mix(c.rgb, (uTargetColor + colorDiff) * c.a, doReplace), c.a);
|
||
|
}
|
||
|
`,Dst=`struct ColorReplaceUniforms {
|
||
|
uOriginalColor: vec3<f32>,
|
||
|
uTargetColor: vec3<f32>,
|
||
|
uTolerance: f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> colorReplaceUniforms : ColorReplaceUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let sample: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
let colorDiff: vec3<f32> = colorReplaceUniforms.uOriginalColor - (sample.rgb / max(sample.a, 0.0000000001));
|
||
|
let colorDistance: f32 = length(colorDiff);
|
||
|
let doReplace: f32 = step(colorDistance, colorReplaceUniforms.uTolerance);
|
||
|
|
||
|
return vec4<f32>(mix(sample.rgb, (colorReplaceUniforms.uTargetColor + colorDiff) * sample.a, doReplace), sample.a);
|
||
|
}`,Lst=Object.defineProperty,Fst=(i,t,e)=>t in i?Lst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Gc=(i,t,e)=>(Fst(i,typeof t!="symbol"?t+"":t,e),e);const wst=class fP extends xt{constructor(...t){let e=t[0]??{};(typeof e=="number"||Array.isArray(e)||e instanceof Float32Array)&&(ct("6.0.0","ColorReplaceFilter constructor params are now options object. See params: { originalColor, targetColor, tolerance }"),e={originalColor:e},t[1]!==void 0&&(e.targetColor=t[1]),t[2]!==void 0&&(e.tolerance=t[2])),e={...fP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Dst,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:Ust,name:"color-replace-filter"});super({gpuProgram:s,glProgram:r,resources:{colorReplaceUniforms:{uOriginalColor:{value:new Float32Array(3),type:"vec3<f32>"},uTargetColor:{value:new Float32Array(3),type:"vec3<f32>"},uTolerance:{value:e.tolerance,type:"f32"}}}}),Gc(this,"uniforms"),Gc(this,"_originalColor"),Gc(this,"_targetColor"),this.uniforms=this.resources.colorReplaceUniforms.uniforms,this._originalColor=new Mt,this._targetColor=new Mt,this.originalColor=e.originalColor??16711680,this.targetColor=e.targetColor??0,Object.assign(this,e)}get originalColor(){return this._originalColor.value}set originalColor(t){this._originalColor.setValue(t);const[e,s,r]=this._originalColor.toArray();this.uniforms.uOriginalColor[0]=e,this.uniforms.uOriginalColor[1]=s,this.uniforms.uOriginalColor[2]=r}get targetColor(){return this._targetColor.value}set targetColor(t){this._targetColor.setValue(t);const[e,s,r]=this._targetColor.toArray();this.uniforms.uTargetColor[0]=e,this.uniforms.uTargetColor[1]=s,this.uniforms.uTargetColor[2]=r}get tolerance(){return this.uniforms.uTolerance}set tolerance(t){this.uniforms.uTolerance=t}set newColor(t){ct("6.0.0","ColorReplaceFilter.newColor is deprecated, please use ColorReplaceFilter.targetColor instead"),this.targetColor=t}get newColor(){return ct("6.0.0","ColorReplaceFilter.newColor is deprecated, please use ColorReplaceFilter.targetColor instead"),this.targetColor}set epsilon(t){ct("6.0.0","ColorReplaceFilter.epsilon is deprecated, please use ColorReplaceFilter.tolerance instead"),this.tolerance=t}get epsilon(){return ct("6.0.0","ColorReplaceFilter.epsilon is deprecated, please use ColorReplaceFilter.tolerance instead"),this.tolerance}};Gc(wst,"DEFAULT_OPTIONS",{originalColor:16711680,targetColor:0,tolerance:.4});var Gst=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uTexelSize;
|
||
|
uniform mat3 uMatrix;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 c11 = texture(uTexture, vTextureCoord - uTexelSize); // top left
|
||
|
vec4 c12 = texture(uTexture, vec2(vTextureCoord.x, vTextureCoord.y - uTexelSize.y)); // top center
|
||
|
vec4 c13 = texture(uTexture, vec2(vTextureCoord.x + uTexelSize.x, vTextureCoord.y - uTexelSize.y)); // top right
|
||
|
|
||
|
vec4 c21 = texture(uTexture, vec2(vTextureCoord.x - uTexelSize.x, vTextureCoord.y)); // mid left
|
||
|
vec4 c22 = texture(uTexture, vTextureCoord); // mid center
|
||
|
vec4 c23 = texture(uTexture, vec2(vTextureCoord.x + uTexelSize.x, vTextureCoord.y)); // mid right
|
||
|
|
||
|
vec4 c31 = texture(uTexture, vec2(vTextureCoord.x - uTexelSize.x, vTextureCoord.y + uTexelSize.y)); // bottom left
|
||
|
vec4 c32 = texture(uTexture, vec2(vTextureCoord.x, vTextureCoord.y + uTexelSize.y)); // bottom center
|
||
|
vec4 c33 = texture(uTexture, vTextureCoord + uTexelSize); // bottom right
|
||
|
|
||
|
finalColor =
|
||
|
c11 * uMatrix[0][0] + c12 * uMatrix[0][1] + c13 * uMatrix[0][2] +
|
||
|
c21 * uMatrix[1][0] + c22 * uMatrix[1][1] + c23 * uMatrix[1][2] +
|
||
|
c31 * uMatrix[2][0] + c32 * uMatrix[2][1] + c33 * uMatrix[2][2];
|
||
|
|
||
|
finalColor.a = c22.a;
|
||
|
}`,Bst=`struct ConvolutionUniforms {
|
||
|
uMatrix: mat3x3<f32>,
|
||
|
uTexelSize: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> convolutionUniforms : ConvolutionUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let texelSize = convolutionUniforms.uTexelSize;
|
||
|
let matrix = convolutionUniforms.uMatrix;
|
||
|
|
||
|
let c11: vec4<f32> = textureSample(uTexture, uSampler, uv - texelSize); // top left
|
||
|
let c12: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x, uv.y - texelSize.y)); // top center
|
||
|
let c13: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x + texelSize.x, uv.y - texelSize.y)); // top right
|
||
|
|
||
|
let c21: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x - texelSize.x, uv.y)); // mid left
|
||
|
let c22: vec4<f32> = textureSample(uTexture, uSampler, uv); // mid center
|
||
|
let c23: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x + texelSize.x, uv.y)); // mid right
|
||
|
|
||
|
let c31: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x - texelSize.x, uv.y + texelSize.y)); // bottom left
|
||
|
let c32: vec4<f32> = textureSample(uTexture, uSampler, vec2<f32>(uv.x, uv.y + texelSize.y)); // bottom center
|
||
|
let c33: vec4<f32> = textureSample(uTexture, uSampler, uv + texelSize); // bottom right
|
||
|
|
||
|
var finalColor: vec4<f32> = vec4<f32>(
|
||
|
c11 * matrix[0][0] + c12 * matrix[0][1] + c13 * matrix[0][2] +
|
||
|
c21 * matrix[1][0] + c22 * matrix[1][1] + c23 * matrix[1][2] +
|
||
|
c31 * matrix[2][0] + c32 * matrix[2][1] + c33 * matrix[2][2]
|
||
|
);
|
||
|
|
||
|
finalColor.a = c22.a;
|
||
|
|
||
|
return finalColor;
|
||
|
}`,kst=Object.defineProperty,zst=(i,t,e)=>t in i?kst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,gP=(i,t,e)=>(zst(i,typeof t!="symbol"?t+"":t,e),e);const Vst=class pP extends xt{constructor(...t){let e=t[0]??{};Array.isArray(e)&&(ct("6.0.0","ConvolutionFilter constructor params are now options object. See params: { matrix, width, height }"),e={matrix:e},t[1]!==void 0&&(e.width=t[1]),t[2]!==void 0&&(e.height=t[2])),e={...pP.DEFAULT_OPTIONS,...e};const s=e.width??200,r=e.height??200,n=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Bst,entryPoint:"mainFragment"}}),a=Tt.from({vertex:Qt,fragment:Gst,name:"convolution-filter"});super({gpuProgram:n,glProgram:a,resources:{convolutionUniforms:{uMatrix:{value:e.matrix,type:"mat3x3<f32>"},uTexelSize:{value:{x:1/s,y:1/r},type:"vec2<f32>"}}}}),gP(this,"uniforms"),this.uniforms=this.resources.convolutionUniforms.uniforms,this.width=s,this.height=r}get matrix(){return this.uniforms.uMatrix}set matrix(t){t.forEach((e,s)=>{this.uniforms.uMatrix[s]=e})}get width(){return 1/this.uniforms.uTexelSize.x}set width(t){this.uniforms.uTexelSize.x=1/t}get height(){return 1/this.uniforms.uTexelSize.y}set height(t){this.uniforms.uTexelSize.y=1/t}};gP(Vst,"DEFAULT_OPTIONS",{matrix:new Float32Array(9),width:200,height:200});var Hst=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec4 uLine;
|
||
|
uniform vec2 uNoise;
|
||
|
uniform vec3 uVignette;
|
||
|
uniform float uSeed;
|
||
|
uniform float uTime;
|
||
|
uniform vec2 uDimensions;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
const float SQRT_2 = 1.414213;
|
||
|
|
||
|
float rand(vec2 co) {
|
||
|
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
float vignette(vec3 co, vec2 coord)
|
||
|
{
|
||
|
float outter = SQRT_2 - uVignette[0] * SQRT_2;
|
||
|
vec2 dir = vec2(0.5) - coord;
|
||
|
dir.y *= uDimensions.y / uDimensions.x;
|
||
|
float darker = clamp((outter - length(dir) * SQRT_2) / ( 0.00001 + uVignette[2] * SQRT_2), 0.0, 1.0);
|
||
|
return darker + (1.0 - darker) * (1.0 - uVignette[1]);
|
||
|
}
|
||
|
|
||
|
float noise(vec2 coord)
|
||
|
{
|
||
|
vec2 pixelCoord = coord * uInputSize.xy;
|
||
|
pixelCoord.x = floor(pixelCoord.x / uNoise[1]);
|
||
|
pixelCoord.y = floor(pixelCoord.y / uNoise[1]);
|
||
|
return (rand(pixelCoord * uNoise[1] * uSeed) - 0.5) * uNoise[0];
|
||
|
}
|
||
|
|
||
|
vec3 interlaceLines(vec3 co, vec2 coord)
|
||
|
{
|
||
|
vec3 color = co;
|
||
|
|
||
|
float curvature = uLine[0];
|
||
|
float lineWidth = uLine[1];
|
||
|
float lineContrast = uLine[2];
|
||
|
float verticalLine = uLine[3];
|
||
|
|
||
|
vec2 dir = vec2(coord * uInputSize.xy / uDimensions - 0.5);
|
||
|
|
||
|
float _c = curvature > 0. ? curvature : 1.;
|
||
|
float k = curvature > 0. ? (length(dir * dir) * 0.25 * _c * _c + 0.935 * _c) : 1.;
|
||
|
vec2 uv = dir * k;
|
||
|
float v = verticalLine > 0.5 ? uv.x * uDimensions.x : uv.y * uDimensions.y;
|
||
|
v *= min(1.0, 2.0 / lineWidth ) / _c;
|
||
|
float j = 1. + cos(v * 1.2 - uTime) * 0.5 * lineContrast;
|
||
|
color *= j;
|
||
|
|
||
|
float segment = verticalLine > 0.5 ? mod((dir.x + .5) * uDimensions.x, 4.) : mod((dir.y + .5) * uDimensions.y, 4.);
|
||
|
color *= 0.99 + ceil(segment) * 0.015;
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
vec2 coord = vTextureCoord * uInputSize.xy / uDimensions;
|
||
|
|
||
|
if (uNoise[0] > 0.0 && uNoise[1] > 0.0)
|
||
|
{
|
||
|
float n = noise(vTextureCoord);
|
||
|
finalColor += vec4(n, n, n, finalColor.a);
|
||
|
}
|
||
|
|
||
|
if (uVignette[0] > 0.)
|
||
|
{
|
||
|
float v = vignette(finalColor.rgb, coord);
|
||
|
finalColor *= vec4(v, v, v, finalColor.a);
|
||
|
}
|
||
|
|
||
|
if (uLine[1] > 0.0)
|
||
|
{
|
||
|
finalColor = vec4(interlaceLines(finalColor.rgb, vTextureCoord), finalColor.a);
|
||
|
}
|
||
|
}
|
||
|
`,Yst=`struct CRTUniforms {
|
||
|
uLine: vec4<f32>,
|
||
|
uNoise: vec2<f32>,
|
||
|
uVignette: vec3<f32>,
|
||
|
uSeed: f32,
|
||
|
uTime: f32,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> crtUniforms : CRTUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let coord: vec2<f32> = uv * gfu.uInputSize.xy / crtUniforms.uDimensions;
|
||
|
|
||
|
let uNoise = crtUniforms.uNoise;
|
||
|
|
||
|
if (uNoise[0] > 0.0 && uNoise[1] > 0.0)
|
||
|
{
|
||
|
color += vec4<f32>(vec3<f32>(noise(uv)), color.a);
|
||
|
}
|
||
|
|
||
|
if (crtUniforms.uVignette[0] > 0.)
|
||
|
{
|
||
|
color *= vec4<f32>(vec3<f32>(vignette(color.rgb, coord)), color.a);
|
||
|
}
|
||
|
|
||
|
if (crtUniforms.uLine[1] > 0.0)
|
||
|
{
|
||
|
color = vec4<f32>(vec3<f32>(interlaceLines(color.rgb, uv)), color.a);
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
const SQRT_2: f32 = 1.414213;
|
||
|
|
||
|
fn modulo(x: f32, y: f32) -> f32
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
|
||
|
fn rand(co: vec2<f32>) -> f32
|
||
|
{
|
||
|
return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
fn vignette(co: vec3<f32>, coord: vec2<f32>) -> f32
|
||
|
{
|
||
|
let uVignette = crtUniforms.uVignette;
|
||
|
let uDimensions = crtUniforms.uDimensions;
|
||
|
|
||
|
let outter: f32 = SQRT_2 - uVignette[0] * SQRT_2;
|
||
|
var dir: vec2<f32> = vec2<f32>(0.5) - coord;
|
||
|
dir.y *= uDimensions.y / uDimensions.x;
|
||
|
let darker: f32 = clamp((outter - length(dir) * SQRT_2) / ( 0.00001 + uVignette[2] * SQRT_2), 0.0, 1.0);
|
||
|
return darker + (1.0 - darker) * (1.0 - uVignette[1]);
|
||
|
}
|
||
|
|
||
|
fn noise(coord: vec2<f32>) -> f32
|
||
|
{
|
||
|
let uNoise = crtUniforms.uNoise;
|
||
|
let uSeed = crtUniforms.uSeed;
|
||
|
|
||
|
var pixelCoord: vec2<f32> = coord * gfu.uInputSize.xy;
|
||
|
pixelCoord.x = floor(pixelCoord.x / uNoise[1]);
|
||
|
pixelCoord.y = floor(pixelCoord.y / uNoise[1]);
|
||
|
return (rand(pixelCoord * uNoise[1] * uSeed) - 0.5) * uNoise[0];
|
||
|
}
|
||
|
|
||
|
fn interlaceLines(co: vec3<f32>, coord: vec2<f32>) -> vec3<f32>
|
||
|
{
|
||
|
var color = co;
|
||
|
|
||
|
let uDimensions = crtUniforms.uDimensions;
|
||
|
|
||
|
let curvature: f32 = crtUniforms.uLine[0];
|
||
|
let lineWidth: f32 = crtUniforms.uLine[1];
|
||
|
let lineContrast: f32 = crtUniforms.uLine[2];
|
||
|
let verticalLine: f32 = crtUniforms.uLine[3];
|
||
|
|
||
|
let dir: vec2<f32> = vec2<f32>(coord * gfu.uInputSize.xy / uDimensions - 0.5);
|
||
|
|
||
|
let _c: f32 = select(1., curvature, curvature > 0.);
|
||
|
let k: f32 = select(1., (length(dir * dir) * 0.25 * _c * _c + 0.935 * _c), curvature > 0.);
|
||
|
let uv: vec2<f32> = dir * k;
|
||
|
let v: f32 = select(uv.y * uDimensions.y, uv.x * uDimensions.x, verticalLine > 0.5) * min(1.0, 2.0 / lineWidth ) / _c;
|
||
|
let j: f32 = 1. + cos(v * 1.2 - crtUniforms.uTime) * 0.5 * lineContrast;
|
||
|
color *= j;
|
||
|
|
||
|
let segment: f32 = select(modulo((dir.y + .5) * uDimensions.y, 4.), modulo((dir.x + .5) * uDimensions.x, 4.), verticalLine > 0.5);
|
||
|
color *= 0.99 + ceil(segment) * 0.015;
|
||
|
|
||
|
return color;
|
||
|
}`,Wst=Object.defineProperty,jst=(i,t,e)=>t in i?Wst(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Bc=(i,t,e)=>(jst(i,typeof t!="symbol"?t+"":t,e),e);const Kst=class mP extends xt{constructor(t){t={...mP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Yst,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Hst,name:"crt-filter"});super({gpuProgram:e,glProgram:s,resources:{crtUniforms:{uLine:{value:new Float32Array(4),type:"vec4<f32>"},uNoise:{value:new Float32Array(2),type:"vec2<f32>"},uVignette:{value:new Float32Array(3),type:"vec3<f32>"},uSeed:{value:t.seed,type:"f32"},uTime:{value:t.time,type:"f32"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"}}}}),Bc(this,"uniforms"),Bc(this,"seed"),Bc(this,"time"),this.uniforms=this.resources.crtUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){this.uniforms.uDimensions[0]=e.frame.width,this.uniforms.uDimensions[1]=e.frame.height,this.uniforms.uSeed=this.seed,this.uniforms.uTime=this.time,t.applyFilter(this,e,s,r)}get curvature(){return this.uniforms.uLine[0]}set curvature(t){this.uniforms.uLine[0]=t}get lineWidth(){return this.uniforms.uLine[1]}set lineWidth(t){this.uniforms.uLine[1]=t}get lineContrast(){return this.uniforms.uLine[2]}set lineContrast(t){this.uniforms.uLine[2]=t}get verticalLine(){return this.uniforms.uLine[3]>.5}set verticalLine(t){this.uniforms.uLine[3]=t?1:0}get noise(){return this.uniforms.uNoise[0]}set noise(t){this.uniforms.uNoise[0]=t}get noiseSize(){return this.uniforms.uNoise[1]}set noiseSize(t){this.uniforms.uNoise[1]=t}get vignetting(){return this.uniforms.uVignette[0]}set vignetting(t){this.uniforms.uVignette[0]=t}get vignettingAlpha(){return this.uniforms.uVignette[1]}set vignettingAlpha(t){this.uniforms.uVignette[1]=t}get vignettingBlur(){return this.uniforms.uVignette[2]}set vignettingBlur(t){this.uniforms.uVignette[2]=t}};Bc(Kst,"DEFAULT_OPTIONS",{curvature:1,lineWidth:1,lineContrast:.25,verticalLine:!1,noise:0,noiseSize:1,vignetting:.3,vignettingAlpha:1,vignettingBlur:.3,time:0,seed:0});var Xst=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uAngle;
|
||
|
uniform float uScale;
|
||
|
uniform bool uGrayScale;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
float pattern()
|
||
|
{
|
||
|
float s = sin(uAngle), c = cos(uAngle);
|
||
|
vec2 tex = vTextureCoord * uInputSize.xy;
|
||
|
vec2 point = vec2(
|
||
|
c * tex.x - s * tex.y,
|
||
|
s * tex.x + c * tex.y
|
||
|
) * uScale;
|
||
|
return (sin(point.x) * sin(point.y)) * 4.0;
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
vec3 colorRGB = vec3(color);
|
||
|
|
||
|
if (uGrayScale)
|
||
|
{
|
||
|
colorRGB = vec3(color.r + color.g + color.b) / 3.0;
|
||
|
}
|
||
|
|
||
|
finalColor = vec4(colorRGB * 10.0 - 5.0 + pattern(), color.a);
|
||
|
}
|
||
|
`,qst=`struct DotUniforms {
|
||
|
uScale:f32,
|
||
|
uAngle:f32,
|
||
|
uGrayScale:f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> dotUniforms : DotUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let gray: vec3<f32> = vec3<f32>(dot(color.rgb, vec3<f32>(0.299, 0.587, 0.114)));
|
||
|
// dotUniforms.uGrayScale == 1 doesn't ever pass so it is converted to a float and compared to 0.5 instead
|
||
|
let finalColor: vec3<f32> = select(color.rgb, gray, f32(dotUniforms.uGrayScale) >= 0.5);
|
||
|
|
||
|
return vec4<f32>(finalColor * 10.0 - 5.0 + pattern(uv), color.a);
|
||
|
}
|
||
|
|
||
|
fn pattern(uv: vec2<f32>) -> f32
|
||
|
{
|
||
|
let s: f32 = sin(dotUniforms.uAngle);
|
||
|
let c: f32 = cos(dotUniforms.uAngle);
|
||
|
|
||
|
let tex: vec2<f32> = uv * gfu.uInputSize.xy;
|
||
|
|
||
|
let p: vec2<f32> = vec2<f32>(
|
||
|
c * tex.x - s * tex.y,
|
||
|
s * tex.x + c * tex.y
|
||
|
) * dotUniforms.uScale;
|
||
|
|
||
|
return (sin(p.x) * sin(p.y)) * 4.0;
|
||
|
}`,$st=Object.defineProperty,Qst=(i,t,e)=>t in i?$st(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Zst=(i,t,e)=>(Qst(i,t+"",e),e);const Jst=class EP extends xt{constructor(...t){let e=t[0]??{};typeof e=="number"&&(ct("6.0.0","DotFilter constructor params are now options object. See params: { scale, angle, grayscale }"),e={scale:e},t[1]!==void 0&&(e.angle=t[1]),t[2]!==void 0&&(e.grayscale=t[2])),e={...EP.DEFAULT_OPTIONS,...e};const s={uScale:{value:e.scale,type:"f32"},uAngle:{value:e.angle,type:"f32"},uGrayScale:{value:e.grayscale?1:0,type:"f32"}},r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:qst,entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:Xst,name:"dot-filter"});super({gpuProgram:r,glProgram:n,resources:{dotUniforms:s}})}get scale(){return this.resources.dotUniforms.uniforms.uScale}set scale(t){this.resources.dotUniforms.uniforms.uScale=t}get angle(){return this.resources.dotUniforms.uniforms.uAngle}set angle(t){this.resources.dotUniforms.uniforms.uAngle=t}get grayscale(){return this.resources.dotUniforms.uniforms.uGrayScale===1}set grayscale(t){this.resources.dotUniforms.uniforms.uGrayScale=t?1:0}};Zst(Jst,"DEFAULT_OPTIONS",{scale:1,angle:5,grayscale:!0});var tit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uAlpha;
|
||
|
uniform vec3 uColor;
|
||
|
uniform vec2 uOffset;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
void main(void){
|
||
|
vec4 sample = texture(uTexture, vTextureCoord - uOffset * uInputSize.zw);
|
||
|
|
||
|
// Premultiply alpha
|
||
|
sample.rgb = uColor.rgb * sample.a;
|
||
|
|
||
|
// alpha user alpha
|
||
|
sample *= uAlpha;
|
||
|
|
||
|
finalColor = sample;
|
||
|
}`,eit=`struct DropShadowUniforms {
|
||
|
uAlpha: f32,
|
||
|
uColor: vec3<f32>,
|
||
|
uOffset: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> dropShadowUniforms : DropShadowUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv - dropShadowUniforms.uOffset * gfu.uInputSize.zw);
|
||
|
|
||
|
// Premultiply alpha
|
||
|
color = vec4<f32>(vec3<f32>(dropShadowUniforms.uColor.rgb * color.a), color.a);
|
||
|
// alpha user alpha
|
||
|
color *= dropShadowUniforms.uAlpha;
|
||
|
|
||
|
return color;
|
||
|
}`,sit=Object.defineProperty,iit=(i,t,e)=>t in i?sit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,lo=(i,t,e)=>(iit(i,typeof t!="symbol"?t+"":t,e),e);const rit=class TP extends xt{constructor(t){t={...TP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:eit,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:tit,name:"drop-shadow-filter"});super({gpuProgram:e,glProgram:s,resources:{dropShadowUniforms:{uAlpha:{value:t.alpha,type:"f32"},uColor:{value:new Float32Array(3),type:"vec3<f32>"},uOffset:{value:t.offset,type:"vec2<f32>"}}},resolution:t.resolution}),lo(this,"uniforms"),lo(this,"shadowOnly",!1),lo(this,"_color"),lo(this,"_blurFilter"),lo(this,"_basePass"),this.uniforms=this.resources.dropShadowUniforms.uniforms,this._color=new Mt,this.color=t.color??0,this._blurFilter=new sP({strength:t.kernels??t.blur,quality:t.kernels?void 0:t.quality}),this._basePass=new xt({gpuProgram:At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:`
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
return textureSample(uTexture, uSampler, uv);
|
||
|
}
|
||
|
`,entryPoint:"mainFragment"}}),glProgram:Tt.from({vertex:Qt,fragment:`
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
uniform sampler2D uTexture;
|
||
|
|
||
|
void main(void){
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
}
|
||
|
`,name:"drop-shadow-filter"}),resources:{}}),Object.assign(this,t)}apply(t,e,s,r){const n=os.getSameSizeTexture(e);t.applyFilter(this,e,n,!0),this._blurFilter.apply(t,n,s,r),this.shadowOnly||t.applyFilter(this._basePass,e,s,!1),os.returnTexture(n)}get offset(){return this.uniforms.uOffset}set offset(t){this.uniforms.uOffset=t,this._updatePadding()}get offsetX(){return this.offset.x}set offsetX(t){this.offset.x=t,this._updatePadding()}get offsetY(){return this.offset.y}set offsetY(t){this.offset.y=t,this._updatePadding()}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}get blur(){return this._blurFilter.strength}set blur(t){this._blurFilter.strength=t,this._updatePadding()}get quality(){return this._blurFilter.quality}set quality(t){this._blurFilter.quality=t,this._updatePadding()}get kernels(){return this._blurFilter.kernels}set kernels(t){this._blurFilter.kernels=t}get pixelSize(){return this._blurFilter.pixelSize}set pixelSize(t){typeof t=="number"&&(t={x:t,y:t}),Array.isArray(t)&&(t={x:t[0],y:t[1]}),this._blurFilter.pixelSize=t}get pixelSizeX(){return this._blurFilter.pixelSizeX}set pixelSizeX(t){this._blurFilter.pixelSizeX=t}get pixelSizeY(){return this._blurFilter.pixelSizeY}set pixelSizeY(t){this._blurFilter.pixelSizeY=t}_updatePadding(){const t=Math.max(Math.abs(this.offsetX),Math.abs(this.offsetY));this.padding=t+this.blur*2+this.quality*4}};lo(rit,"DEFAULT_OPTIONS",{offset:{x:4,y:4},color:0,alpha:.5,shadowOnly:!1,kernels:void 0,blur:2,quality:3,pixelSize:{x:1,y:1},resolution:1});var nit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uDisplacementMap;
|
||
|
uniform float uSeed;
|
||
|
uniform vec2 uDimensions;
|
||
|
uniform float uAspect;
|
||
|
uniform float uFillMode;
|
||
|
uniform float uOffset;
|
||
|
uniform float uDirection;
|
||
|
uniform vec2 uRed;
|
||
|
uniform vec2 uGreen;
|
||
|
uniform vec2 uBlue;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
const int TRANSPARENT = 0;
|
||
|
const int ORIGINAL = 1;
|
||
|
const int LOOP = 2;
|
||
|
const int CLAMP = 3;
|
||
|
const int MIRROR = 4;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec2 coord = (vTextureCoord * uInputSize.xy) / uDimensions;
|
||
|
|
||
|
if (coord.x > 1.0 || coord.y > 1.0) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float sinDir = sin(uDirection);
|
||
|
float cosDir = cos(uDirection);
|
||
|
|
||
|
float cx = coord.x - 0.5;
|
||
|
float cy = (coord.y - 0.5) * uAspect;
|
||
|
float ny = (-sinDir * cx + cosDir * cy) / uAspect + 0.5;
|
||
|
|
||
|
// displacementMap: repeat
|
||
|
// ny = ny > 1.0 ? ny - 1.0 : (ny < 0.0 ? 1.0 + ny : ny);
|
||
|
|
||
|
// displacementMap: mirror
|
||
|
ny = ny > 1.0 ? 2.0 - ny : (ny < 0.0 ? -ny : ny);
|
||
|
|
||
|
vec4 dc = texture(uDisplacementMap, vec2(0.5, ny));
|
||
|
|
||
|
float displacement = (dc.r - dc.g) * (uOffset / uInputSize.x);
|
||
|
|
||
|
coord = vTextureCoord + vec2(cosDir * displacement, sinDir * displacement * uAspect);
|
||
|
|
||
|
int fillMode = int(uFillMode);
|
||
|
|
||
|
if (fillMode == CLAMP) {
|
||
|
coord = clamp(coord, uInputClamp.xy, uInputClamp.zw);
|
||
|
} else {
|
||
|
if( coord.x > uInputClamp.z ) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discard;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.x -= uInputClamp.z;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.x = uInputClamp.z * 2.0 - coord.x;
|
||
|
}
|
||
|
} else if( coord.x < uInputClamp.x ) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discard;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.x += uInputClamp.z;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.x *= -uInputClamp.z;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if( coord.y > uInputClamp.w ) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discard;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.y -= uInputClamp.w;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.y = uInputClamp.w * 2.0 - coord.y;
|
||
|
}
|
||
|
} else if( coord.y < uInputClamp.y ) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discard;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.y += uInputClamp.w;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.y *= -uInputClamp.w;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
finalColor.r = texture(uTexture, coord + uRed * (1.0 - uSeed * 0.4) / uInputSize.xy).r;
|
||
|
finalColor.g = texture(uTexture, coord + uGreen * (1.0 - uSeed * 0.3) / uInputSize.xy).g;
|
||
|
finalColor.b = texture(uTexture, coord + uBlue * (1.0 - uSeed * 0.2) / uInputSize.xy).b;
|
||
|
finalColor.a = texture(uTexture, coord).a;
|
||
|
}
|
||
|
`,ait=`struct GlitchUniforms {
|
||
|
uSeed: f32,
|
||
|
uDimensions: vec2<f32>,
|
||
|
uAspect: f32,
|
||
|
uFillMode: f32,
|
||
|
uOffset: f32,
|
||
|
uDirection: f32,
|
||
|
uRed: vec2<f32>,
|
||
|
uGreen: vec2<f32>,
|
||
|
uBlue: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> glitchUniforms : GlitchUniforms;
|
||
|
@group(1) @binding(1) var uDisplacementMap: texture_2d<f32>;
|
||
|
@group(1) @binding(2) var uDisplacementSampler: sampler;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uSeed: f32 = glitchUniforms.uSeed;
|
||
|
let uDimensions: vec2<f32> = glitchUniforms.uDimensions;
|
||
|
let uAspect: f32 = glitchUniforms.uAspect;
|
||
|
let uOffset: f32 = glitchUniforms.uOffset;
|
||
|
let uDirection: f32 = glitchUniforms.uDirection;
|
||
|
let uRed: vec2<f32> = glitchUniforms.uRed;
|
||
|
let uGreen: vec2<f32> = glitchUniforms.uGreen;
|
||
|
let uBlue: vec2<f32> = glitchUniforms.uBlue;
|
||
|
|
||
|
let uInputSize: vec4<f32> = gfu.uInputSize;
|
||
|
let uInputClamp: vec4<f32> = gfu.uInputClamp;
|
||
|
|
||
|
var discarded: bool = false;
|
||
|
var coord: vec2<f32> = (uv * uInputSize.xy) / uDimensions;
|
||
|
|
||
|
if (coord.x > 1.0 || coord.y > 1.0) {
|
||
|
discarded = true;
|
||
|
}
|
||
|
|
||
|
let sinDir: f32 = sin(uDirection);
|
||
|
let cosDir: f32 = cos(uDirection);
|
||
|
|
||
|
let cx: f32 = coord.x - 0.5;
|
||
|
let cy: f32 = (coord.y - 0.5) * uAspect;
|
||
|
var ny: f32 = (-sinDir * cx + cosDir * cy) / uAspect + 0.5;
|
||
|
|
||
|
ny = select(select(ny, -ny, ny < 0.0), 2.0 - ny, ny > 1.0);
|
||
|
|
||
|
let dc: vec4<f32> = textureSample(uDisplacementMap, uDisplacementSampler, vec2<f32>(0.5, ny));
|
||
|
|
||
|
let displacement: f32 = (dc.r - dc.g) * (uOffset / uInputSize.x);
|
||
|
|
||
|
coord = uv + vec2<f32>(cosDir * displacement, sinDir * displacement * uAspect);
|
||
|
|
||
|
let fillMode: i32 = i32(glitchUniforms.uFillMode);
|
||
|
|
||
|
if (fillMode == CLAMP) {
|
||
|
coord = clamp(coord, uInputClamp.xy, uInputClamp.zw);
|
||
|
} else {
|
||
|
if (coord.x > uInputClamp.z) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discarded = true;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.x = coord.x - uInputClamp.z;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.x = uInputClamp.z * 2.0 - coord.x;
|
||
|
}
|
||
|
} else if (coord.x < uInputClamp.x) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discarded = true;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.x = coord.x + uInputClamp.z;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.x = coord.x * -uInputClamp.z;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (coord.y > uInputClamp.w) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discarded = true;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.y = coord.y - uInputClamp.w;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.y = uInputClamp.w * 2.0 - coord.y;
|
||
|
}
|
||
|
} else if (coord.y < uInputClamp.y) {
|
||
|
if (fillMode == TRANSPARENT) {
|
||
|
discarded = true;
|
||
|
} else if (fillMode == LOOP) {
|
||
|
coord.y = coord.y + uInputClamp.w;
|
||
|
} else if (fillMode == MIRROR) {
|
||
|
coord.y = coord.y * -uInputClamp.w;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let seedR: f32 = 1.0 - uSeed * 0.4;
|
||
|
let seedG: f32 = 1.0 - uSeed * 0.3;
|
||
|
let seedB: f32 = 1.0 - uSeed * 0.2;
|
||
|
|
||
|
let offsetR: vec2<f32> = vec2(uRed.x * seedR / uInputSize.x, uRed.y * seedR / uInputSize.y);
|
||
|
let offsetG: vec2<f32> = vec2(uGreen.x * seedG / uInputSize.x, uGreen.y * seedG / uInputSize.y);
|
||
|
let offsetB: vec2<f32> = vec2(uBlue.x * seedB / uInputSize.x, uBlue.y * seedB / uInputSize.y);
|
||
|
|
||
|
let r = textureSample(uTexture, uSampler, coord + offsetR).r;
|
||
|
let g = textureSample(uTexture, uSampler, coord + offsetG).g;
|
||
|
let b = textureSample(uTexture, uSampler, coord + offsetB).b;
|
||
|
let a = textureSample(uTexture, uSampler, coord).a;
|
||
|
|
||
|
return select(vec4<f32>(r, g, b, a), vec4<f32>(0.0,0.0,0.0,0.0), discarded);
|
||
|
}
|
||
|
|
||
|
const TRANSPARENT: i32 = 0;
|
||
|
const ORIGINAL: i32 = 1;
|
||
|
const LOOP: i32 = 2;
|
||
|
const CLAMP: i32 = 3;
|
||
|
const MIRROR: i32 = 4;`,oit=Object.defineProperty,uit=(i,t,e)=>t in i?oit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,xi=(i,t,e)=>(uit(i,typeof t!="symbol"?t+"":t,e),e);const lit=class IP extends xt{constructor(t){t={...IP.defaults,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:ait,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:nit,name:"glitch-filter"}),r=document.createElement("canvas");r.width=4,r.height=t.sampleSize??512;const n=new W({source:new qa({resource:r})});super({gpuProgram:e,glProgram:s,resources:{glitchUniforms:{uSeed:{value:(t==null?void 0:t.seed)??0,type:"f32"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"},uAspect:{value:1,type:"f32"},uFillMode:{value:(t==null?void 0:t.fillMode)??0,type:"f32"},uOffset:{value:(t==null?void 0:t.offset)??100,type:"f32"},uDirection:{value:(t==null?void 0:t.direction)??0,type:"f32"},uRed:{value:t.red,type:"vec2<f32>"},uGreen:{value:t.green,type:"vec2<f32>"},uBlue:{value:t.blue,type:"vec2<f32>"}},uDisplacementMap:n.source,uDisplacementSampler:n.source.style}}),xi(this,"uniforms"),xi(this,"average",!1),xi(this,"minSize",8),xi(this,"sampleSize",512),xi(this,"_canvas"),xi(this,"texture"),xi(this,"_slices",0),xi(this,"_sizes",new Float32Array(1)),xi(this,"_offsets",new Float32Array(1)),this.uniforms=this.resources.glitchUniforms.uniforms,this._canvas=r,this.texture=n,Object.assign(this,t)}apply(t,e,s,r){const{width:n,height:a}=e.frame;this.uniforms.uDimensions[0]=n,this.uniforms.uDimensions[1]=a,this.uniforms.uAspect=a/n,t.applyFilter(this,e,s,r)}_randomizeSizes(){const t=this._sizes,e=this._slices-1,s=this.sampleSize,r=Math.min(this.minSize/s,.9/this._slices);if(this.average){const n=this._slices;let a=1;for(let o=0;o<e;o++){const u=a/(n-o),l=Math.max(u*(1-Math.random()*.6),r);t[o]=l,a-=l}t[e]=a}else{let n=1;const a=Math.sqrt(1/this._slices);for(let o=0;o<e;o++){const u=Math.max(a*n*Math.random(),r);t[o]=u,n-=u}t[e]=n}this.shuffle()}shuffle(){const t=this._sizes,e=this._slices-1;for(let s=e;s>0;s--){const r=Math.random()*s>>0,n=t[s];t[s]=t[r],t[r]=n}}_randomizeOffsets(){for(let t=0;t<this._slices;t++)this._offsets[t]=Math.random()*(Math.random()<.5?-1:1)}refresh(){this._randomizeSizes(),this._randomizeOffsets(),this.redraw()}redraw(){const t=this.sampleSize,e=this.texture,s=this._canvas.getContext("2d");s.clearRect(0,0,8,t);let r,n=0;for(let a=0;a<this._slices;a++){r=Math.floor(this._offsets[a]*256);const o=this._sizes[a]*t,u=r>0?r:0,l=r<0?-r:0;s.fillStyle=`rgba(${u}, ${l}, 0, 1)`,s.fillRect(0,n>>0,t,o+1>>0),n+=o}e.source.update()}set sizes(t){const e=Math.min(this._slices,t.length);for(let s=0;s<e;s++)this._sizes[s]=t[s]}get sizes(){return this._sizes}set offsets(t){const e=Math.min(this._slices,t.length);for(let s=0;s<e;s++)this._offsets[s]=t[s]}get offsets(){return this._offsets}get slices(){return this._slices}set slices(t){this._slices!==t&&(this._slices=t,this._sizes=new Float32Array(t),this._offsets=new Float32Array(t),this.refresh())}get offset(){return this.uniforms.uOffset}set offset(t){this.uniforms.uOffset=t}get seed(){return this.uniforms.uSeed}set seed(t){this.uniforms.uSeed=t}get fillMode(){return this.uniforms.uFillMode}set fillMode(t){this.uniforms.uFillMode=t}get direction(){return this.uniforms.uDirection/$o}set direction(t){this.uniforms.uDirection=t*$o}get red(){return this.uniforms.uRed}set red(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uRed=t}get green(){return this.uniforms.uGreen}set green(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uGreen=t}get blue(){return this.uniforms.uBlue}set blue(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uBlue=t}destroy(){var t;(t=this.texture)==null||t.destroy(!0),this.texture=this._canvas=this.red=this.green=this.blue=this._sizes=this._offsets=null}};xi(lit,"defaults",{slices:5,offset:100,direction:0,fillMode:0,average:!1,seed:0,red:{x:0,y:0},green:{x:0,y:0},blue:{x:0,y:0},minSize:8,sampleSize:512});var hit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uStrength;
|
||
|
uniform vec3 uColor;
|
||
|
uniform float uKnockout;
|
||
|
uniform float uAlpha;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
const float PI = 3.14159265358979323846264;
|
||
|
|
||
|
// Hard-assignment of DIST and ANGLE_STEP_SIZE instead of using uDistance and uQuality to allow them to be use on GLSL loop conditions
|
||
|
const float DIST = __DIST__;
|
||
|
const float ANGLE_STEP_SIZE = min(__ANGLE_STEP_SIZE__, PI * 2.);
|
||
|
const float ANGLE_STEP_NUM = ceil(PI * 2. / ANGLE_STEP_SIZE);
|
||
|
const float MAX_TOTAL_ALPHA = ANGLE_STEP_NUM * DIST * (DIST + 1.) / 2.;
|
||
|
|
||
|
void main(void) {
|
||
|
vec2 px = vec2(1.) / uInputSize.xy;
|
||
|
|
||
|
float totalAlpha = 0.;
|
||
|
|
||
|
vec2 direction;
|
||
|
vec2 displaced;
|
||
|
vec4 curColor;
|
||
|
|
||
|
for (float angle = 0.; angle < PI * 2.; angle += ANGLE_STEP_SIZE) {
|
||
|
direction = vec2(cos(angle), sin(angle)) * px;
|
||
|
|
||
|
for (float curDistance = 0.; curDistance < DIST; curDistance++) {
|
||
|
displaced = clamp(vTextureCoord + direction * (curDistance + 1.), uInputClamp.xy, uInputClamp.zw);
|
||
|
curColor = texture(uTexture, displaced);
|
||
|
totalAlpha += (DIST - curDistance) * curColor.a;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
curColor = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
vec4 glowColor = vec4(uColor, uAlpha);
|
||
|
bool knockout = uKnockout > .5;
|
||
|
float innerStrength = uStrength[0];
|
||
|
float outerStrength = uStrength[1];
|
||
|
|
||
|
float alphaRatio = totalAlpha / MAX_TOTAL_ALPHA;
|
||
|
float innerGlowAlpha = (1. - alphaRatio) * innerStrength * curColor.a * uAlpha;
|
||
|
float innerGlowStrength = min(1., innerGlowAlpha);
|
||
|
|
||
|
vec4 innerColor = mix(curColor, glowColor, innerGlowStrength);
|
||
|
float outerGlowAlpha = alphaRatio * outerStrength * (1. - curColor.a) * uAlpha;
|
||
|
float outerGlowStrength = min(1. - innerColor.a, outerGlowAlpha);
|
||
|
vec4 outerGlowColor = outerGlowStrength * glowColor.rgba;
|
||
|
|
||
|
if (knockout) {
|
||
|
float resultAlpha = outerGlowAlpha + innerGlowAlpha;
|
||
|
finalColor = vec4(glowColor.rgb * resultAlpha, resultAlpha);
|
||
|
}
|
||
|
else {
|
||
|
finalColor = innerColor + outerGlowColor;
|
||
|
}
|
||
|
}
|
||
|
`,cit=`struct GlowUniforms {
|
||
|
uDistance: f32,
|
||
|
uStrength: vec2<f32>,
|
||
|
uColor: vec3<f32>,
|
||
|
uAlpha: f32,
|
||
|
uQuality: f32,
|
||
|
uKnockout: f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> glowUniforms : GlowUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let quality = glowUniforms.uQuality;
|
||
|
let distance = glowUniforms.uDistance;
|
||
|
|
||
|
let dist: f32 = glowUniforms.uDistance;
|
||
|
let angleStepSize: f32 = min(1. / quality / distance, PI * 2.0);
|
||
|
let angleStepNum: f32 = ceil(PI * 2.0 / angleStepSize);
|
||
|
|
||
|
let px: vec2<f32> = vec2<f32>(1.0 / gfu.uInputSize.xy);
|
||
|
|
||
|
var totalAlpha: f32 = 0.0;
|
||
|
|
||
|
var direction: vec2<f32>;
|
||
|
var displaced: vec2<f32>;
|
||
|
var curColor: vec4<f32>;
|
||
|
|
||
|
for (var angle = 0.0; angle < PI * 2.0; angle += angleStepSize) {
|
||
|
direction = vec2<f32>(cos(angle), sin(angle)) * px;
|
||
|
for (var curDistance = 0.0; curDistance < dist; curDistance+=1) {
|
||
|
displaced = vec2<f32>(clamp(uv + direction * (curDistance + 1.0), gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
curColor = textureSample(uTexture, uSampler, displaced);
|
||
|
totalAlpha += (dist - curDistance) * curColor.a;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
curColor = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
let glowColorRGB = glowUniforms.uColor;
|
||
|
let glowAlpha = glowUniforms.uAlpha;
|
||
|
let glowColor = vec4<f32>(glowColorRGB, glowAlpha);
|
||
|
let knockout: bool = glowUniforms.uKnockout > 0.5;
|
||
|
let innerStrength = glowUniforms.uStrength[0];
|
||
|
let outerStrength = glowUniforms.uStrength[1];
|
||
|
|
||
|
let alphaRatio: f32 = (totalAlpha / (angleStepNum * dist * (dist + 1.0) / 2.0));
|
||
|
let innerGlowAlpha: f32 = (1.0 - alphaRatio) * innerStrength * curColor.a * glowAlpha;
|
||
|
let innerGlowStrength: f32 = min(1.0, innerGlowAlpha);
|
||
|
|
||
|
let innerColor: vec4<f32> = mix(curColor, glowColor, innerGlowStrength);
|
||
|
let outerGlowAlpha: f32 = alphaRatio * outerStrength * (1. - curColor.a) * glowAlpha;
|
||
|
let outerGlowStrength: f32 = min(1.0 - innerColor.a, outerGlowAlpha);
|
||
|
let outerGlowColor: vec4<f32> = outerGlowStrength * glowColor.rgba;
|
||
|
|
||
|
if (knockout) {
|
||
|
let resultAlpha: f32 = outerGlowAlpha + innerGlowAlpha;
|
||
|
return vec4<f32>(glowColor.rgb * resultAlpha, resultAlpha);
|
||
|
}
|
||
|
else {
|
||
|
return innerColor + outerGlowColor;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const PI: f32 = 3.14159265358979323846264;`,_it=Object.defineProperty,dit=(i,t,e)=>t in i?_it(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,lI=(i,t,e)=>(dit(i,typeof t!="symbol"?t+"":t,e),e);const fit=class SP extends xt{constructor(t){t={...SP.DEFAULT_OPTIONS,...t};const e=t.distance??10,s=t.quality??.1,r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:cit,entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:hit.replace(/__ANGLE_STEP_SIZE__/gi,`${(1/s/e).toFixed(7)}`).replace(/__DIST__/gi,`${e.toFixed(0)}.0`),name:"glow-filter"});super({gpuProgram:r,glProgram:n,resources:{glowUniforms:{uDistance:{value:e,type:"f32"},uStrength:{value:[t.innerStrength,t.outerStrength],type:"vec2<f32>"},uColor:{value:new Float32Array(3),type:"vec3<f32>"},uAlpha:{value:t.alpha,type:"f32"},uQuality:{value:s,type:"f32"},uKnockout:{value:(t==null?void 0:t.knockout)??!1?1:0,type:"f32"}}},padding:e}),lI(this,"uniforms"),lI(this,"_color"),this.uniforms=this.resources.glowUniforms.uniforms,this._color=new Mt,this.color=t.color??16777215}get distance(){return this.uniforms.uDistance}set distance(t){this.uniforms.uDistance=this.padding=t}get innerStrength(){return this.uniforms.uStrength[0]}set innerStrength(t){this.uniforms.uStrength[0]=t}get outerStrength(){return this.uniforms.uStrength[1]}set outerStrength(t){this.uniforms.uStrength[1]=t}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}get quality(){return this.uniforms.uQuality}set quality(t){this.uniforms.uQuality=t}get knockout(){return this.uniforms.uKnockout===1}set knockout(t){this.uniforms.uKnockout=t?1:0}};lI(fit,"DEFAULT_OPTIONS",{distance:10,outerStrength:4,innerStrength:0,color:16777215,alpha:1,quality:.1,knockout:!1});var git=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uDimensions;
|
||
|
uniform float uParallel;
|
||
|
uniform vec2 uLight;
|
||
|
uniform float uAspect;
|
||
|
uniform float uTime;
|
||
|
uniform vec3 uRay;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
\${PERLIN}
|
||
|
|
||
|
void main(void) {
|
||
|
vec2 uDimensions = uDimensions;
|
||
|
bool uParallel = uParallel > 0.5;
|
||
|
vec2 uLight = uLight;
|
||
|
float uAspect = uAspect;
|
||
|
|
||
|
vec2 coord = vTextureCoord * uInputSize.xy / uDimensions;
|
||
|
|
||
|
float d;
|
||
|
|
||
|
if (uParallel) {
|
||
|
float _cos = uLight.x;
|
||
|
float _sin = uLight.y;
|
||
|
d = (_cos * coord.x) + (_sin * coord.y * uAspect);
|
||
|
} else {
|
||
|
float dx = coord.x - uLight.x / uDimensions.x;
|
||
|
float dy = (coord.y - uLight.y / uDimensions.y) * uAspect;
|
||
|
float dis = sqrt(dx * dx + dy * dy) + 0.00001;
|
||
|
d = dy / dis;
|
||
|
}
|
||
|
|
||
|
float uTime = uTime;
|
||
|
vec3 uRay = uRay;
|
||
|
|
||
|
float gain = uRay[0];
|
||
|
float lacunarity = uRay[1];
|
||
|
float alpha = uRay[2];
|
||
|
|
||
|
vec3 dir = vec3(d, d, 0.0);
|
||
|
float noise = turb(dir + vec3(uTime, 0.0, 62.1 + uTime) * 0.05, vec3(480.0, 320.0, 480.0), lacunarity, gain);
|
||
|
noise = mix(noise, 0.0, 0.3);
|
||
|
//fade vertically.
|
||
|
vec4 mist = vec4(vec3(noise), 1.0) * (1.0 - coord.y);
|
||
|
mist.a = 1.0;
|
||
|
// apply user alpha
|
||
|
mist *= alpha;
|
||
|
|
||
|
finalColor = texture(uTexture, vTextureCoord) + mist;
|
||
|
}
|
||
|
`,pit=`struct GodrayUniforms {
|
||
|
uLight: vec2<f32>,
|
||
|
uParallel: f32,
|
||
|
uAspect: f32,
|
||
|
uTime: f32,
|
||
|
uRay: vec3<f32>,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> godrayUniforms : GodrayUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uDimensions: vec2<f32> = godrayUniforms.uDimensions;
|
||
|
let uParallel: bool = godrayUniforms.uParallel > 0.5;
|
||
|
let uLight: vec2<f32> = godrayUniforms.uLight;
|
||
|
let uAspect: f32 = godrayUniforms.uAspect;
|
||
|
|
||
|
let coord: vec2<f32> = uv * gfu.uInputSize.xy / uDimensions;
|
||
|
|
||
|
var d: f32;
|
||
|
|
||
|
if (uParallel) {
|
||
|
let _cos: f32 = uLight.x;
|
||
|
let _sin: f32 = uLight.y;
|
||
|
d = (_cos * coord.x) + (_sin * coord.y * uAspect);
|
||
|
} else {
|
||
|
let dx: f32 = coord.x - uLight.x / uDimensions.x;
|
||
|
let dy: f32 = (coord.y - uLight.y / uDimensions.y) * uAspect;
|
||
|
let dis: f32 = sqrt(dx * dx + dy * dy) + 0.00001;
|
||
|
d = dy / dis;
|
||
|
}
|
||
|
|
||
|
let uTime: f32 = godrayUniforms.uTime;
|
||
|
let uRay: vec3<f32> = godrayUniforms.uRay;
|
||
|
|
||
|
let gain = uRay[0];
|
||
|
let lacunarity = uRay[1];
|
||
|
let alpha = uRay[2];
|
||
|
|
||
|
let dir: vec3<f32> = vec3<f32>(d, d, 0.0);
|
||
|
var noise: f32 = turb(dir + vec3<f32>(uTime, 0.0, 62.1 + uTime) * 0.05, vec3<f32>(480.0, 320.0, 480.0), lacunarity, gain);
|
||
|
noise = mix(noise, 0.0, 0.3);
|
||
|
//fade vertically.
|
||
|
var mist: vec4<f32> = vec4<f32>(vec3<f32>(noise), 1.0) * (1.0 - coord.y);
|
||
|
mist.a = 1.0;
|
||
|
// apply user alpha
|
||
|
mist *= alpha;
|
||
|
return textureSample(uTexture, uSampler, uv) + mist;
|
||
|
}
|
||
|
|
||
|
\${PERLIN}`,mit=`vec3 mod289(vec3 x)
|
||
|
{
|
||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||
|
}
|
||
|
vec4 mod289(vec4 x)
|
||
|
{
|
||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||
|
}
|
||
|
vec4 permute(vec4 x)
|
||
|
{
|
||
|
return mod289(((x * 34.0) + 1.0) * x);
|
||
|
}
|
||
|
vec4 taylorInvSqrt(vec4 r)
|
||
|
{
|
||
|
return 1.79284291400159 - 0.85373472095314 * r;
|
||
|
}
|
||
|
vec3 fade(vec3 t)
|
||
|
{
|
||
|
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||
|
}
|
||
|
// Classic Perlin noise, periodic variant
|
||
|
float pnoise(vec3 P, vec3 rep)
|
||
|
{
|
||
|
vec3 Pi0 = mod(floor(P), rep); // Integer part, modulo period
|
||
|
vec3 Pi1 = mod(Pi0 + vec3(1.0), rep); // Integer part + 1, mod period
|
||
|
Pi0 = mod289(Pi0);
|
||
|
Pi1 = mod289(Pi1);
|
||
|
vec3 Pf0 = fract(P); // Fractional part for interpolation
|
||
|
vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
|
||
|
vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
|
||
|
vec4 iy = vec4(Pi0.yy, Pi1.yy);
|
||
|
vec4 iz0 = Pi0.zzzz;
|
||
|
vec4 iz1 = Pi1.zzzz;
|
||
|
vec4 ixy = permute(permute(ix) + iy);
|
||
|
vec4 ixy0 = permute(ixy + iz0);
|
||
|
vec4 ixy1 = permute(ixy + iz1);
|
||
|
vec4 gx0 = ixy0 * (1.0 / 7.0);
|
||
|
vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
|
||
|
gx0 = fract(gx0);
|
||
|
vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
|
||
|
vec4 sz0 = step(gz0, vec4(0.0));
|
||
|
gx0 -= sz0 * (step(0.0, gx0) - 0.5);
|
||
|
gy0 -= sz0 * (step(0.0, gy0) - 0.5);
|
||
|
vec4 gx1 = ixy1 * (1.0 / 7.0);
|
||
|
vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
|
||
|
gx1 = fract(gx1);
|
||
|
vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
|
||
|
vec4 sz1 = step(gz1, vec4(0.0));
|
||
|
gx1 -= sz1 * (step(0.0, gx1) - 0.5);
|
||
|
gy1 -= sz1 * (step(0.0, gy1) - 0.5);
|
||
|
vec3 g000 = vec3(gx0.x, gy0.x, gz0.x);
|
||
|
vec3 g100 = vec3(gx0.y, gy0.y, gz0.y);
|
||
|
vec3 g010 = vec3(gx0.z, gy0.z, gz0.z);
|
||
|
vec3 g110 = vec3(gx0.w, gy0.w, gz0.w);
|
||
|
vec3 g001 = vec3(gx1.x, gy1.x, gz1.x);
|
||
|
vec3 g101 = vec3(gx1.y, gy1.y, gz1.y);
|
||
|
vec3 g011 = vec3(gx1.z, gy1.z, gz1.z);
|
||
|
vec3 g111 = vec3(gx1.w, gy1.w, gz1.w);
|
||
|
vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
|
||
|
g000 *= norm0.x;
|
||
|
g010 *= norm0.y;
|
||
|
g100 *= norm0.z;
|
||
|
g110 *= norm0.w;
|
||
|
vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
|
||
|
g001 *= norm1.x;
|
||
|
g011 *= norm1.y;
|
||
|
g101 *= norm1.z;
|
||
|
g111 *= norm1.w;
|
||
|
float n000 = dot(g000, Pf0);
|
||
|
float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
|
||
|
float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
|
||
|
float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
|
||
|
float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
|
||
|
float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
|
||
|
float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
|
||
|
float n111 = dot(g111, Pf1);
|
||
|
vec3 fade_xyz = fade(Pf0);
|
||
|
vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
|
||
|
vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
|
||
|
float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x);
|
||
|
return 2.2 * n_xyz;
|
||
|
}
|
||
|
float turb(vec3 P, vec3 rep, float lacunarity, float gain)
|
||
|
{
|
||
|
float sum = 0.0;
|
||
|
float sc = 1.0;
|
||
|
float totalgain = 1.0;
|
||
|
for (float i = 0.0; i < 6.0; i++)
|
||
|
{
|
||
|
sum += totalgain * pnoise(P * sc, rep);
|
||
|
sc *= lacunarity;
|
||
|
totalgain *= gain;
|
||
|
}
|
||
|
return abs(sum);
|
||
|
}
|
||
|
`,Eit=`// Taken from https://gist.github.com/munrocket/236ed5ba7e409b8bdf1ff6eca5dcdc39
|
||
|
|
||
|
fn moduloVec3(x: vec3<f32>, y: vec3<f32>) -> vec3<f32>
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
fn mod289Vec3(x: vec3<f32>) -> vec3<f32>
|
||
|
{
|
||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||
|
}
|
||
|
fn mod289Vec4(x: vec4<f32>) -> vec4<f32>
|
||
|
{
|
||
|
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
||
|
}
|
||
|
fn permute4(x: vec4<f32>) -> vec4<f32>
|
||
|
{
|
||
|
return mod289Vec4(((x * 34.0) + 1.0) * x);
|
||
|
}
|
||
|
fn taylorInvSqrt(r: vec4<f32>) -> vec4<f32>
|
||
|
{
|
||
|
return 1.79284291400159 - 0.85373472095314 * r;
|
||
|
}
|
||
|
fn fade3(t: vec3<f32>) -> vec3<f32>
|
||
|
{
|
||
|
return t * t * t * (t * (t * 6.0 - 15.0) + 10.0);
|
||
|
}
|
||
|
fn fade2(t: vec2<f32>) -> vec2<f32> { return t * t * t * (t * (t * 6. - 15.) + 10.); }
|
||
|
|
||
|
fn perlinNoise2(P: vec2<f32>) -> f32 {
|
||
|
var Pi: vec4<f32> = floor(P.xyxy) + vec4<f32>(0., 0., 1., 1.);
|
||
|
let Pf = fract(P.xyxy) - vec4<f32>(0., 0., 1., 1.);
|
||
|
Pi = Pi % vec4<f32>(289.); // To avoid truncation effects in permutation
|
||
|
let ix = Pi.xzxz;
|
||
|
let iy = Pi.yyww;
|
||
|
let fx = Pf.xzxz;
|
||
|
let fy = Pf.yyww;
|
||
|
let i = permute4(permute4(ix) + iy);
|
||
|
var gx: vec4<f32> = 2. * fract(i * 0.0243902439) - 1.; // 1/41 = 0.024...
|
||
|
let gy = abs(gx) - 0.5;
|
||
|
let tx = floor(gx + 0.5);
|
||
|
gx = gx - tx;
|
||
|
var g00: vec2<f32> = vec2<f32>(gx.x, gy.x);
|
||
|
var g10: vec2<f32> = vec2<f32>(gx.y, gy.y);
|
||
|
var g01: vec2<f32> = vec2<f32>(gx.z, gy.z);
|
||
|
var g11: vec2<f32> = vec2<f32>(gx.w, gy.w);
|
||
|
let norm = 1.79284291400159 - 0.85373472095314 *
|
||
|
vec4<f32>(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11));
|
||
|
g00 = g00 * norm.x;
|
||
|
g01 = g01 * norm.y;
|
||
|
g10 = g10 * norm.z;
|
||
|
g11 = g11 * norm.w;
|
||
|
let n00 = dot(g00, vec2<f32>(fx.x, fy.x));
|
||
|
let n10 = dot(g10, vec2<f32>(fx.y, fy.y));
|
||
|
let n01 = dot(g01, vec2<f32>(fx.z, fy.z));
|
||
|
let n11 = dot(g11, vec2<f32>(fx.w, fy.w));
|
||
|
let fade_xy = fade2(Pf.xy);
|
||
|
let n_x = mix(vec2<f32>(n00, n01), vec2<f32>(n10, n11), vec2<f32>(fade_xy.x));
|
||
|
let n_xy = mix(n_x.x, n_x.y, fade_xy.y);
|
||
|
return 2.3 * n_xy;
|
||
|
}
|
||
|
|
||
|
// Classic Perlin noise, periodic variant
|
||
|
fn perlinNoise3(P: vec3<f32>, rep: vec3<f32>) -> f32
|
||
|
{
|
||
|
var Pi0: vec3<f32> = moduloVec3(floor(P), rep); // Integer part, modulo period
|
||
|
var Pi1: vec3<f32> = moduloVec3(Pi0 + vec3<f32>(1.0), rep); // Integer part + 1, mod period
|
||
|
Pi0 = mod289Vec3(Pi0);
|
||
|
Pi1 = mod289Vec3(Pi1);
|
||
|
let Pf0: vec3<f32> = fract(P); // Fractional part for interpolation
|
||
|
let Pf1: vec3<f32> = Pf0 - vec3<f32>(1.0); // Fractional part - 1.0
|
||
|
let ix: vec4<f32> = vec4<f32>(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
|
||
|
let iy: vec4<f32> = vec4<f32>(Pi0.yy, Pi1.yy);
|
||
|
let iz0: vec4<f32> = Pi0.zzzz;
|
||
|
let iz1: vec4<f32> = Pi1.zzzz;
|
||
|
let ixy: vec4<f32> = permute4(permute4(ix) + iy);
|
||
|
let ixy0: vec4<f32> = permute4(ixy + iz0);
|
||
|
let ixy1: vec4<f32> = permute4(ixy + iz1);
|
||
|
var gx0: vec4<f32> = ixy0 * (1.0 / 7.0);
|
||
|
var gy0: vec4<f32> = fract(floor(gx0) * (1.0 / 7.0)) - 0.5;
|
||
|
gx0 = fract(gx0);
|
||
|
let gz0: vec4<f32> = vec4<f32>(0.5) - abs(gx0) - abs(gy0);
|
||
|
let sz0: vec4<f32> = step(gz0, vec4<f32>(0.0));
|
||
|
gx0 -= sz0 * (step(vec4<f32>(0.0), gx0) - 0.5);
|
||
|
gy0 -= sz0 * (step(vec4<f32>(0.0), gy0) - 0.5);
|
||
|
var gx1: vec4<f32> = ixy1 * (1.0 / 7.0);
|
||
|
var gy1: vec4<f32> = fract(floor(gx1) * (1.0 / 7.0)) - 0.5;
|
||
|
gx1 = fract(gx1);
|
||
|
let gz1: vec4<f32> = vec4<f32>(0.5) - abs(gx1) - abs(gy1);
|
||
|
let sz1: vec4<f32> = step(gz1, vec4<f32>(0.0));
|
||
|
gx1 -= sz1 * (step(vec4<f32>(0.0), gx1) - 0.5);
|
||
|
gy1 -= sz1 * (step(vec4<f32>(0.0), gy1) - 0.5);
|
||
|
var g000: vec3<f32> = vec3<f32>(gx0.x, gy0.x, gz0.x);
|
||
|
var g100: vec3<f32> = vec3<f32>(gx0.y, gy0.y, gz0.y);
|
||
|
var g010: vec3<f32> = vec3<f32>(gx0.z, gy0.z, gz0.z);
|
||
|
var g110: vec3<f32> = vec3<f32>(gx0.w, gy0.w, gz0.w);
|
||
|
var g001: vec3<f32> = vec3<f32>(gx1.x, gy1.x, gz1.x);
|
||
|
var g101: vec3<f32> = vec3<f32>(gx1.y, gy1.y, gz1.y);
|
||
|
var g011: vec3<f32> = vec3<f32>(gx1.z, gy1.z, gz1.z);
|
||
|
var g111: vec3<f32> = vec3<f32>(gx1.w, gy1.w, gz1.w);
|
||
|
let norm0: vec4<f32> = taylorInvSqrt(vec4<f32>(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
|
||
|
g000 *= norm0.x;
|
||
|
g010 *= norm0.y;
|
||
|
g100 *= norm0.z;
|
||
|
g110 *= norm0.w;
|
||
|
let norm1: vec4<f32> = taylorInvSqrt(vec4<f32>(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
|
||
|
g001 *= norm1.x;
|
||
|
g011 *= norm1.y;
|
||
|
g101 *= norm1.z;
|
||
|
g111 *= norm1.w;
|
||
|
let n000: f32 = dot(g000, Pf0);
|
||
|
let n100: f32 = dot(g100, vec3<f32>(Pf1.x, Pf0.yz));
|
||
|
let n010: f32 = dot(g010, vec3<f32>(Pf0.x, Pf1.y, Pf0.z));
|
||
|
let n110: f32 = dot(g110, vec3<f32>(Pf1.xy, Pf0.z));
|
||
|
let n001: f32 = dot(g001, vec3<f32>(Pf0.xy, Pf1.z));
|
||
|
let n101: f32 = dot(g101, vec3<f32>(Pf1.x, Pf0.y, Pf1.z));
|
||
|
let n011: f32 = dot(g011, vec3<f32>(Pf0.x, Pf1.yz));
|
||
|
let n111: f32 = dot(g111, Pf1);
|
||
|
let fade_xyz: vec3<f32> = fade3(Pf0);
|
||
|
let n_z: vec4<f32> = mix(vec4<f32>(n000, n100, n010, n110), vec4<f32>(n001, n101, n011, n111), fade_xyz.z);
|
||
|
let n_yz: vec2<f32> = mix(n_z.xy, n_z.zw, fade_xyz.y);
|
||
|
let n_xyz: f32 = mix(n_yz.x, n_yz.y, fade_xyz.x);
|
||
|
return 2.2 * n_xyz;
|
||
|
}
|
||
|
fn turb(P: vec3<f32>, rep: vec3<f32>, lacunarity: f32, gain: f32) -> f32
|
||
|
{
|
||
|
var sum: f32 = 0.0;
|
||
|
var sc: f32 = 1.0;
|
||
|
var totalgain: f32 = 1.0;
|
||
|
for (var i = 0.0; i < 6.0; i += 1)
|
||
|
{
|
||
|
sum += totalgain * perlinNoise3(P * sc, rep);
|
||
|
sc *= lacunarity;
|
||
|
totalgain *= gain;
|
||
|
}
|
||
|
return abs(sum);
|
||
|
}`,Tit=Object.defineProperty,Iit=(i,t,e)=>t in i?Tit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,ho=(i,t,e)=>(Iit(i,typeof t!="symbol"?t+"":t,e),e);const Sit=class RP extends xt{constructor(t){t={...RP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:pit.replace("${PERLIN}",Eit),entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:git.replace("${PERLIN}",mit),name:"god-ray-filter"});super({gpuProgram:e,glProgram:s,resources:{godrayUniforms:{uLight:{value:new Float32Array(2),type:"vec2<f32>"},uParallel:{value:0,type:"f32"},uAspect:{value:0,type:"f32"},uTime:{value:t.time,type:"f32"},uRay:{value:new Float32Array(3),type:"vec3<f32>"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"}}}}),ho(this,"uniforms"),ho(this,"time",0),ho(this,"_angleLight",[0,0]),ho(this,"_angle",0),ho(this,"_center"),this.uniforms=this.resources.godrayUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){const n=e.frame.width,a=e.frame.height;this.uniforms.uLight[0]=this.parallel?this._angleLight[0]:this._center.x,this.uniforms.uLight[1]=this.parallel?this._angleLight[1]:this._center.y,this.uniforms.uDimensions[0]=n,this.uniforms.uDimensions[1]=a,this.uniforms.uAspect=a/n,this.uniforms.uTime=this.time,t.applyFilter(this,e,s,r)}get angle(){return this._angle}set angle(t){this._angle=t;const e=t*$o;this._angleLight[0]=Math.cos(e),this._angleLight[1]=Math.sin(e)}get parallel(){return this.uniforms.uParallel>.5}set parallel(t){this.uniforms.uParallel=t?1:0}get center(){return this._center}set center(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this._center=t}get centerX(){return this.center.x}set centerX(t){this.center.x=t}get centerY(){return this.center.y}set centerY(t){this.center.y=t}get gain(){return this.uniforms.uRay[0]}set gain(t){this.uniforms.uRay[0]=t}get lacunarity(){return this.uniforms.uRay[1]}set lacunarity(t){this.uniforms.uRay[1]=t}get alpha(){return this.uniforms.uRay[2]}set alpha(t){this.uniforms.uRay[2]=t}};ho(Sit,"DEFAULT_OPTIONS",{angle:30,gain:.5,lacunarity:2.5,parallel:!0,time:0,center:{x:0,y:0},alpha:1});var Rit=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec3 uHsl;
|
||
|
uniform float uAlpha;
|
||
|
uniform float uColorize;
|
||
|
|
||
|
// https://en.wikipedia.org/wiki/Luma_(video)
|
||
|
const vec3 weight = vec3(0.299, 0.587, 0.114);
|
||
|
|
||
|
float getWeightedAverage(vec3 rgb) {
|
||
|
return rgb.r * weight.r + rgb.g * weight.g + rgb.b * weight.b;
|
||
|
}
|
||
|
|
||
|
// https://gist.github.com/mairod/a75e7b44f68110e1576d77419d608786?permalink_comment_id=3195243#gistcomment-3195243
|
||
|
const vec3 k = vec3(0.57735, 0.57735, 0.57735);
|
||
|
|
||
|
vec3 hueShift(vec3 color, float angle) {
|
||
|
float cosAngle = cos(angle);
|
||
|
return vec3(
|
||
|
color * cosAngle +
|
||
|
cross(k, color) * sin(angle) +
|
||
|
k * dot(k, color) * (1.0 - cosAngle)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
vec3 resultRGB = color.rgb;
|
||
|
|
||
|
float hue = uHsl[0];
|
||
|
float saturation = uHsl[1];
|
||
|
float lightness = uHsl[2];
|
||
|
|
||
|
// colorize
|
||
|
if (uColorize > 0.5) {
|
||
|
resultRGB = vec3(getWeightedAverage(resultRGB), 0., 0.);
|
||
|
}
|
||
|
|
||
|
// hue
|
||
|
resultRGB = hueShift(resultRGB, hue);
|
||
|
|
||
|
// saturation
|
||
|
// https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/huesaturation.js
|
||
|
float average = (resultRGB.r + resultRGB.g + resultRGB.b) / 3.0;
|
||
|
|
||
|
if (saturation > 0.) {
|
||
|
resultRGB += (average - resultRGB) * (1. - 1. / (1.001 - saturation));
|
||
|
} else {
|
||
|
resultRGB -= (average - resultRGB) * saturation;
|
||
|
}
|
||
|
|
||
|
// lightness
|
||
|
resultRGB = mix(resultRGB, vec3(ceil(lightness)) * color.a, abs(lightness));
|
||
|
|
||
|
// alpha
|
||
|
finalColor = mix(color, vec4(resultRGB, color.a), uAlpha);
|
||
|
}
|
||
|
`,Ait=`struct HslUniforms {
|
||
|
uHsl:vec3<f32>,
|
||
|
uColorize:f32,
|
||
|
uAlpha:f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> hslUniforms : HslUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
var resultRGB: vec3<f32> = color.rgb;
|
||
|
|
||
|
let hue: f32 = hslUniforms.uHsl[0];
|
||
|
let saturation: f32 = hslUniforms.uHsl[1];
|
||
|
let lightness: f32 = hslUniforms.uHsl[2];
|
||
|
|
||
|
// colorize
|
||
|
if (hslUniforms.uColorize > 0.5) {
|
||
|
resultRGB = vec3<f32>(dot(color.rgb, vec3<f32>(0.299, 0.587, 0.114)), 0., 0.);
|
||
|
}
|
||
|
|
||
|
// hue
|
||
|
resultRGB = hueShift(resultRGB, hue);
|
||
|
|
||
|
// saturation
|
||
|
// https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/huesaturation.js
|
||
|
let average: f32 = (resultRGB.r + resultRGB.g + resultRGB.b) / 3.0;
|
||
|
|
||
|
if (saturation > 0.) {
|
||
|
resultRGB += (average - resultRGB) * (1. - 1. / (1.001 - saturation));
|
||
|
} else {
|
||
|
resultRGB -= (average - resultRGB) * saturation;
|
||
|
}
|
||
|
|
||
|
// lightness
|
||
|
resultRGB = mix(resultRGB, vec3<f32>(ceil(lightness)) * color.a, abs(lightness));
|
||
|
|
||
|
// alpha
|
||
|
return mix(color, vec4<f32>(resultRGB, color.a), hslUniforms.uAlpha);
|
||
|
}
|
||
|
|
||
|
// https://gist.github.com/mairod/a75e7b44f68110e1576d77419d608786?permalink_comment_id=3195243#gistcomment-3195243
|
||
|
const k: vec3<f32> = vec3(0.57735, 0.57735, 0.57735);
|
||
|
|
||
|
fn hueShift(color: vec3<f32>, angle: f32) -> vec3<f32>
|
||
|
{
|
||
|
let cosAngle: f32 = cos(angle);
|
||
|
return vec3<f32>(
|
||
|
color * cosAngle +
|
||
|
cross(k, color) * sin(angle) +
|
||
|
k * dot(k, color) * (1.0 - cosAngle)
|
||
|
);
|
||
|
}`,Oit=Object.defineProperty,yit=(i,t,e)=>t in i?Oit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,hI=(i,t,e)=>(yit(i,typeof t!="symbol"?t+"":t,e),e);const vit=class AP extends xt{constructor(t){t={...AP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Ait,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Rit,name:"hsl-adjustment-filter"});super({gpuProgram:e,glProgram:s,resources:{hslUniforms:{uHsl:{value:new Float32Array(3),type:"vec3<f32>"},uColorize:{value:t.colorize?1:0,type:"f32"},uAlpha:{value:t.alpha,type:"f32"}}}}),hI(this,"uniforms"),hI(this,"_hue"),this.uniforms=this.resources.hslUniforms.uniforms,Object.assign(this,t)}get hue(){return this._hue}set hue(t){this._hue=t,this.uniforms.uHsl[0]=t*(Math.PI/180)}get saturation(){return this.uniforms.uHsl[1]}set saturation(t){this.uniforms.uHsl[1]=t}get lightness(){return this.uniforms.uHsl[2]}set lightness(t){this.uniforms.uHsl[2]=t}get colorize(){return this.uniforms.uColorize===1}set colorize(t){this.uniforms.uColorize=t?1:0}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}};hI(vit,"DEFAULT_OPTIONS",{hue:0,saturation:0,lightness:0,colorize:!1,alpha:1});var Cit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uVelocity;
|
||
|
uniform int uKernelSize;
|
||
|
uniform float uOffset;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
const int MAX_KERNEL_SIZE = 2048;
|
||
|
|
||
|
// Notice:
|
||
|
// the perfect way:
|
||
|
// int kernelSize = min(uKernelSize, MAX_KERNELSIZE);
|
||
|
// BUT in real use-case , uKernelSize < MAX_KERNELSIZE almost always.
|
||
|
// So use uKernelSize directly.
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
if (uKernelSize == 0)
|
||
|
{
|
||
|
finalColor = color;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vec2 velocity = uVelocity / uInputSize.xy;
|
||
|
float offset = -uOffset / length(uVelocity) - 0.5;
|
||
|
int k = uKernelSize - 1;
|
||
|
|
||
|
for(int i = 0; i < MAX_KERNEL_SIZE - 1; i++) {
|
||
|
if (i == k) {
|
||
|
break;
|
||
|
}
|
||
|
vec2 bias = velocity * (float(i) / float(k) + offset);
|
||
|
color += texture(uTexture, vTextureCoord + bias);
|
||
|
}
|
||
|
finalColor = color / float(uKernelSize);
|
||
|
}
|
||
|
`,Mit=`struct MotionBlurUniforms {
|
||
|
uVelocity: vec2<f32>,
|
||
|
uKernelSize: f32,
|
||
|
uOffset: f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> motionBlurUniforms : MotionBlurUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uVelocity = motionBlurUniforms.uVelocity;
|
||
|
let uKernelSize = motionBlurUniforms.uKernelSize;
|
||
|
let uOffset = motionBlurUniforms.uOffset;
|
||
|
|
||
|
let velocity: vec2<f32> = uVelocity / gfu.uInputSize.xy;
|
||
|
let offset: f32 = -uOffset / length(uVelocity) - 0.5;
|
||
|
let k: i32 = i32(min(uKernelSize - 1, MAX_KERNEL_SIZE - 1));
|
||
|
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
for(var i: i32 = 0; i < k; i += 1) {
|
||
|
let bias: vec2<f32> = velocity * (f32(i) / f32(k) + offset);
|
||
|
color += textureSample(uTexture, uSampler, uv + bias);
|
||
|
}
|
||
|
|
||
|
return select(color / f32(uKernelSize), textureSample(uTexture, uSampler, uv), uKernelSize == 0);
|
||
|
}
|
||
|
|
||
|
const MAX_KERNEL_SIZE: f32 = 2048;`,xit=Object.defineProperty,Pit=(i,t,e)=>t in i?xit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,cI=(i,t,e)=>(Pit(i,typeof t!="symbol"?t+"":t,e),e);const bit=class OP extends xt{constructor(...t){let e=t[0]??{};if(Array.isArray(e)||"x"in e&&"y"in e||e instanceof Pe){ct("6.0.0","MotionBlurFilter constructor params are now options object. See params: { velocity, kernelSize, offset }");const n="x"in e?e.x:e[0],a="y"in e?e.y:e[1];e={velocity:{x:n,y:a}},t[1]!==void 0&&(e.kernelSize=t[1]),t[2]!==void 0&&(e.offset=t[2])}e={...OP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Mit,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:Cit,name:"motion-blur-filter"});super({gpuProgram:s,glProgram:r,resources:{motionBlurUniforms:{uVelocity:{value:e.velocity,type:"vec2<f32>"},uKernelSize:{value:Math.trunc(e.kernelSize??5),type:"i32"},uOffset:{value:e.offset,type:"f32"}}}}),cI(this,"uniforms"),cI(this,"_kernelSize"),this.uniforms=this.resources.motionBlurUniforms.uniforms,Object.assign(this,e)}get velocity(){return this.uniforms.uVelocity}set velocity(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uVelocity=t,this._updateDirty()}get velocityX(){return this.velocity.x}set velocityX(t){this.velocity.x=t,this._updateDirty()}get velocityY(){return this.velocity.y}set velocityY(t){this.velocity.y=t,this._updateDirty()}get kernelSize(){return this._kernelSize}set kernelSize(t){this._kernelSize=t,this._updateDirty()}get offset(){return this.uniforms.uOffset}set offset(t){this.uniforms.uOffset=t}_updateDirty(){this.padding=(Math.max(Math.abs(this.velocityX),Math.abs(this.velocityY))>>0)+1,this.uniforms.uKernelSize=this.velocityX!==0||this.velocityY!==0?this._kernelSize:0}};cI(bit,"DEFAULT_OPTIONS",{velocity:{x:0,y:0},kernelSize:5,offset:0});var Nit=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
const int MAX_COLORS = \${MAX_COLORS};
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec3 uOriginalColors[MAX_COLORS];
|
||
|
uniform vec3 uTargetColors[MAX_COLORS];
|
||
|
uniform float uTolerance;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
float alpha = finalColor.a;
|
||
|
if (alpha < 0.0001)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vec3 color = finalColor.rgb / alpha;
|
||
|
|
||
|
for(int i = 0; i < MAX_COLORS; i++)
|
||
|
{
|
||
|
vec3 origColor = uOriginalColors[i];
|
||
|
if (origColor.r < 0.0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
vec3 colorDiff = origColor - color;
|
||
|
if (length(colorDiff) < uTolerance)
|
||
|
{
|
||
|
vec3 targetColor = uTargetColors[i];
|
||
|
finalColor = vec4((targetColor + colorDiff) * alpha, alpha);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
`,Uit=`struct MultiColorReplaceUniforms {
|
||
|
uOriginalColors: array<vec3<f32>, MAX_COLORS>,
|
||
|
uTargetColors: array<vec3<f32>, MAX_COLORS>,
|
||
|
uTolerance:f32,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> multiColorReplaceUniforms : MultiColorReplaceUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uOriginalColors = multiColorReplaceUniforms.uOriginalColors;
|
||
|
let uTargetColors = multiColorReplaceUniforms.uTargetColors;
|
||
|
let uTolerance = multiColorReplaceUniforms.uTolerance;
|
||
|
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
let alpha: f32 = color.a;
|
||
|
|
||
|
if (alpha > 0.0001)
|
||
|
{
|
||
|
var modColor: vec3<f32> = vec3<f32>(color.rgb) / alpha;
|
||
|
|
||
|
for(var i: i32 = 0; i < MAX_COLORS; i += 1)
|
||
|
{
|
||
|
let origColor: vec3<f32> = uOriginalColors[i];
|
||
|
if (origColor.r < 0.0)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
let colorDiff: vec3<f32> = origColor - modColor;
|
||
|
|
||
|
if (length(colorDiff) < uTolerance)
|
||
|
{
|
||
|
let targetColor: vec3<f32> = uTargetColors[i];
|
||
|
color = vec4((targetColor + colorDiff) * alpha, alpha);
|
||
|
return color;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
const MAX_COLORS: i32 = \${MAX_COLORS};`,Dit=Object.defineProperty,Lit=(i,t,e)=>t in i?Dit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,kc=(i,t,e)=>(Lit(i,typeof t!="symbol"?t+"":t,e),e);const Fit=class yP extends xt{constructor(...t){let e=t[0]??{};Array.isArray(e)&&(ct("6.0.0","MultiColorReplaceFilter constructor params are now options object. See params: { replacements, tolerance, maxColors }"),e={replacements:e},t[1]&&(e.tolerance=t[1]),t[2]&&(e.maxColors=t[2])),e={...yP.DEFAULT_OPTIONS,...e};const s=e.maxColors??e.replacements.length,r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Uit.replace(/\$\{MAX_COLORS\}/g,s.toFixed(0)),entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:Nit.replace(/\$\{MAX_COLORS\}/g,s.toFixed(0)),name:"multi-color-replace-filter"});super({gpuProgram:r,glProgram:n,resources:{multiColorReplaceUniforms:{uOriginalColors:{value:new Float32Array(3*s),type:"vec3<f32>",size:s},uTargetColors:{value:new Float32Array(3*s),type:"vec3<f32>",size:s},uTolerance:{value:e.tolerance,type:"f32"}}}}),kc(this,"uniforms"),kc(this,"_replacements",[]),kc(this,"_maxColors"),this._maxColors=s,this.uniforms=this.resources.multiColorReplaceUniforms.uniforms,this.replacements=e.replacements}set replacements(t){const e=this.uniforms.uOriginalColors,s=this.uniforms.uTargetColors,r=t.length,n=new Mt;if(r>this._maxColors)throw new Error(`Length of replacements (${r}) exceeds the maximum colors length (${this._maxColors})`);e[r*3]=-1;let a,o,u;for(let l=0;l<r;l++){const c=t[l];n.setValue(c[0]),[a,o,u]=n.toArray(),e[l*3]=a,e[l*3+1]=o,e[l*3+2]=u,n.setValue(c[1]),[a,o,u]=n.toArray(),s[l*3]=a,s[l*3+1]=o,s[l*3+2]=u}this._replacements=t}get replacements(){return this._replacements}refresh(){this.replacements=this._replacements}get maxColors(){return this._maxColors}get tolerance(){return this.uniforms.uTolerance}set tolerance(t){this.uniforms.uTolerance=t}set epsilon(t){ct("6.0.0","MultiColorReplaceFilter.epsilon is deprecated, please use MultiColorReplaceFilter.tolerance instead"),this.tolerance=t}get epsilon(){return ct("6.0.0","MultiColorReplaceFilter.epsilon is deprecated, please use MultiColorReplaceFilter.tolerance instead"),this.tolerance}};kc(Fit,"DEFAULT_OPTIONS",{replacements:[[16711680,255]],tolerance:.05,maxColors:void 0});var wit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uSepia;
|
||
|
uniform vec2 uNoise;
|
||
|
uniform vec3 uScratch;
|
||
|
uniform vec3 uVignetting;
|
||
|
uniform float uSeed;
|
||
|
uniform vec2 uDimensions;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
const float SQRT_2 = 1.414213;
|
||
|
const vec3 SEPIA_RGB = vec3(112.0 / 255.0, 66.0 / 255.0, 20.0 / 255.0);
|
||
|
|
||
|
float rand(vec2 co) {
|
||
|
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
vec3 Overlay(vec3 src, vec3 dst)
|
||
|
{
|
||
|
// if (dst <= 0.5) then: 2 * src * dst
|
||
|
// if (dst > 0.5) then: 1 - 2 * (1 - dst) * (1 - src)
|
||
|
return vec3((dst.x <= 0.5) ? (2.0 * src.x * dst.x) : (1.0 - 2.0 * (1.0 - dst.x) * (1.0 - src.x)),
|
||
|
(dst.y <= 0.5) ? (2.0 * src.y * dst.y) : (1.0 - 2.0 * (1.0 - dst.y) * (1.0 - src.y)),
|
||
|
(dst.z <= 0.5) ? (2.0 * src.z * dst.z) : (1.0 - 2.0 * (1.0 - dst.z) * (1.0 - src.z)));
|
||
|
}
|
||
|
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
vec3 color = finalColor.rgb;
|
||
|
|
||
|
if (uSepia > 0.0)
|
||
|
{
|
||
|
float gray = (color.x + color.y + color.z) / 3.0;
|
||
|
vec3 grayscale = vec3(gray);
|
||
|
|
||
|
color = Overlay(SEPIA_RGB, grayscale);
|
||
|
|
||
|
color = grayscale + uSepia * (color - grayscale);
|
||
|
}
|
||
|
|
||
|
vec2 coord = vTextureCoord * uInputSize.xy / uDimensions.xy;
|
||
|
|
||
|
float vignette = uVignetting[0];
|
||
|
float vignetteAlpha = uVignetting[1];
|
||
|
float vignetteBlur = uVignetting[2];
|
||
|
|
||
|
if (vignette > 0.0)
|
||
|
{
|
||
|
float outter = SQRT_2 - vignette * SQRT_2;
|
||
|
vec2 dir = vec2(vec2(0.5, 0.5) - coord);
|
||
|
dir.y *= uDimensions.y / uDimensions.x;
|
||
|
float darker = clamp((outter - length(dir) * SQRT_2) / ( 0.00001 + vignetteBlur * SQRT_2), 0.0, 1.0);
|
||
|
color.rgb *= darker + (1.0 - darker) * (1.0 - vignetteAlpha);
|
||
|
}
|
||
|
|
||
|
float scratch = uScratch[0];
|
||
|
float scratchDensity = uScratch[1];
|
||
|
float scratchWidth = uScratch[2];
|
||
|
|
||
|
if (scratchDensity > uSeed && scratch != 0.0)
|
||
|
{
|
||
|
float phase = uSeed * 256.0;
|
||
|
float s = mod(floor(phase), 2.0);
|
||
|
float dist = 1.0 / scratchDensity;
|
||
|
float d = distance(coord, vec2(uSeed * dist, abs(s - uSeed * dist)));
|
||
|
if (d < uSeed * 0.6 + 0.4)
|
||
|
{
|
||
|
highp float period = scratchDensity * 10.0;
|
||
|
|
||
|
float xx = coord.x * period + phase;
|
||
|
float aa = abs(mod(xx, 0.5) * 4.0);
|
||
|
float bb = mod(floor(xx / 0.5), 2.0);
|
||
|
float yy = (1.0 - bb) * aa + bb * (2.0 - aa);
|
||
|
|
||
|
float kk = 2.0 * period;
|
||
|
float dw = scratchWidth / uDimensions.x * (0.75 + uSeed);
|
||
|
float dh = dw * kk;
|
||
|
|
||
|
float tine = (yy - (2.0 - dh));
|
||
|
|
||
|
if (tine > 0.0) {
|
||
|
float _sign = sign(scratch);
|
||
|
|
||
|
tine = s * tine / period + scratch + 0.1;
|
||
|
tine = clamp(tine + 1.0, 0.5 + _sign * 0.5, 1.5 + _sign * 0.5);
|
||
|
|
||
|
color.rgb *= tine;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
float noise = uNoise[0];
|
||
|
float noiseSize = uNoise[1];
|
||
|
|
||
|
if (noise > 0.0 && noiseSize > 0.0)
|
||
|
{
|
||
|
vec2 pixelCoord = vTextureCoord.xy * uInputSize.xy;
|
||
|
pixelCoord.x = floor(pixelCoord.x / noiseSize);
|
||
|
pixelCoord.y = floor(pixelCoord.y / noiseSize);
|
||
|
// vec2 d = pixelCoord * noiseSize * vec2(1024.0 + uSeed * 512.0, 1024.0 - uSeed * 512.0);
|
||
|
// float _noise = snoise(d) * 0.5;
|
||
|
float _noise = rand(pixelCoord * noiseSize * uSeed) - 0.5;
|
||
|
color += _noise * noise;
|
||
|
}
|
||
|
|
||
|
finalColor.rgb = color;
|
||
|
}`,Git=`struct OldFilmUniforms {
|
||
|
uSepia: f32,
|
||
|
uNoise: vec2<f32>,
|
||
|
uScratch: vec3<f32>,
|
||
|
uVignetting: vec3<f32>,
|
||
|
uSeed: f32,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> oldFilmUniforms : OldFilmUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
|
||
|
if (oldFilmUniforms.uSepia > 0.)
|
||
|
{
|
||
|
color = vec4<f32>(sepia(color.rgb), color.a);
|
||
|
}
|
||
|
|
||
|
let coord: vec2<f32> = uv * gfu.uInputSize.xy / oldFilmUniforms.uDimensions;
|
||
|
|
||
|
if (oldFilmUniforms.uVignetting[0] > 0.)
|
||
|
{
|
||
|
color *= vec4<f32>(vec3<f32>(vignette(color.rgb, coord)), color.a);
|
||
|
}
|
||
|
|
||
|
let uScratch = oldFilmUniforms.uScratch;
|
||
|
|
||
|
if (uScratch[1] > oldFilmUniforms.uSeed && uScratch[0] != 0.)
|
||
|
{
|
||
|
color = vec4<f32>(scratch(color.rgb, coord), color.a);
|
||
|
}
|
||
|
|
||
|
let uNoise = oldFilmUniforms.uNoise;
|
||
|
|
||
|
if (uNoise[0] > 0.0 && uNoise[1] > 0.0)
|
||
|
{
|
||
|
color += vec4<f32>(vec3<f32>(noise(uv)), color.a);
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
const SQRT_2: f32 = 1.414213;
|
||
|
const SEPIA_RGB: vec3<f32> = vec3<f32>(112.0 / 255.0, 66.0 / 255.0, 20.0 / 255.0);
|
||
|
|
||
|
fn modulo(x: f32, y: f32) -> f32
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
|
||
|
fn rand(co: vec2<f32>) -> f32
|
||
|
{
|
||
|
return fract(sin(dot(co, vec2<f32>(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
fn overlay(src: vec3<f32>, dst: vec3<f32>) -> vec3<f32>
|
||
|
{
|
||
|
// if (dst <= 0.5) then: 2 * src * dst
|
||
|
// if (dst > 0.5) then: 1 - 2 * (1 - dst) * (1 - src)
|
||
|
|
||
|
return vec3<f32>(
|
||
|
select((1.0 - 2.0 * (1.0 - dst.x) * (1.0 - src.x)), (2.0 * src.x * dst.x), (dst.x <= 0.5)),
|
||
|
select((1.0 - 2.0 * (1.0 - dst.y) * (1.0 - src.y)), (2.0 * src.y * dst.y), (dst.y <= 0.5)),
|
||
|
select((1.0 - 2.0 * (1.0 - dst.z) * (1.0 - src.z)), (2.0 * src.z * dst.z), (dst.z <= 0.5))
|
||
|
);
|
||
|
}
|
||
|
|
||
|
fn sepia(co: vec3<f32>) -> vec3<f32>
|
||
|
{
|
||
|
let gray: f32 = (co.x + co.y + co.z) / 3.0;
|
||
|
let grayscale: vec3<f32> = vec3<f32>(gray);
|
||
|
let color = overlay(SEPIA_RGB, grayscale);
|
||
|
return grayscale + oldFilmUniforms.uSepia * (color - grayscale);
|
||
|
}
|
||
|
|
||
|
fn vignette(co: vec3<f32>, coord: vec2<f32>) -> f32
|
||
|
{
|
||
|
let uVignetting = oldFilmUniforms.uVignetting;
|
||
|
let uDimensions = oldFilmUniforms.uDimensions;
|
||
|
|
||
|
let outter: f32 = SQRT_2 - uVignetting[0] * SQRT_2;
|
||
|
var dir: vec2<f32> = vec2<f32>(vec2<f32>(0.5) - coord);
|
||
|
dir.y *= uDimensions.y / uDimensions.x;
|
||
|
let darker: f32 = clamp((outter - length(dir) * SQRT_2) / ( 0.00001 + uVignetting[2] * SQRT_2), 0.0, 1.0);
|
||
|
return darker + (1.0 - darker) * (1.0 - uVignetting[1]);
|
||
|
}
|
||
|
|
||
|
fn scratch(co: vec3<f32>, coord: vec2<f32>) -> vec3<f32>
|
||
|
{
|
||
|
var color = co;
|
||
|
let uScratch = oldFilmUniforms.uScratch;
|
||
|
let uSeed = oldFilmUniforms.uSeed;
|
||
|
let uDimensions = oldFilmUniforms.uDimensions;
|
||
|
|
||
|
let phase: f32 = uSeed * 256.0;
|
||
|
let s: f32 = modulo(floor(phase), 2.0);
|
||
|
let dist: f32 = 1.0 / uScratch[1];
|
||
|
let d: f32 = distance(coord, vec2<f32>(uSeed * dist, abs(s - uSeed * dist)));
|
||
|
|
||
|
if (d < uSeed * 0.6 + 0.4)
|
||
|
{
|
||
|
let period: f32 = uScratch[1] * 10.0;
|
||
|
|
||
|
let xx: f32 = coord.x * period + phase;
|
||
|
let aa: f32 = abs(modulo(xx, 0.5) * 4.0);
|
||
|
let bb: f32 = modulo(floor(xx / 0.5), 2.0);
|
||
|
let yy: f32 = (1.0 - bb) * aa + bb * (2.0 - aa);
|
||
|
|
||
|
let kk: f32 = 2.0 * period;
|
||
|
let dw: f32 = uScratch[2] / uDimensions.x * (0.75 + uSeed);
|
||
|
let dh: f32 = dw * kk;
|
||
|
|
||
|
var tine: f32 = (yy - (2.0 - dh));
|
||
|
|
||
|
if (tine > 0.0) {
|
||
|
let _sign: f32 = sign(uScratch[0]);
|
||
|
|
||
|
tine = s * tine / period + uScratch[0] + 0.1;
|
||
|
tine = clamp(tine + 1.0, 0.5 + _sign * 0.5, 1.5 + _sign * 0.5);
|
||
|
|
||
|
color *= tine;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
fn noise(coord: vec2<f32>) -> f32
|
||
|
{
|
||
|
let uNoise = oldFilmUniforms.uNoise;
|
||
|
let uSeed = oldFilmUniforms.uSeed;
|
||
|
|
||
|
var pixelCoord: vec2<f32> = coord * gfu.uInputSize.xy;
|
||
|
pixelCoord.x = floor(pixelCoord.x / uNoise[1]);
|
||
|
pixelCoord.y = floor(pixelCoord.y / uNoise[1]);
|
||
|
return (rand(pixelCoord * uNoise[1] * uSeed) - 0.5) * uNoise[0];
|
||
|
}`,Bit=Object.defineProperty,kit=(i,t,e)=>t in i?Bit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,_I=(i,t,e)=>(kit(i,typeof t!="symbol"?t+"":t,e),e);const zit=class vP extends xt{constructor(t){t={...vP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Git,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:wit,name:"old-film-filter"});super({gpuProgram:e,glProgram:s,resources:{oldFilmUniforms:{uSepia:{value:t.sepia,type:"f32"},uNoise:{value:new Float32Array(2),type:"vec2<f32>"},uScratch:{value:new Float32Array(3),type:"vec3<f32>"},uVignetting:{value:new Float32Array(3),type:"vec3<f32>"},uSeed:{value:t.seed,type:"f32"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"}}}}),_I(this,"uniforms"),_I(this,"seed"),this.uniforms=this.resources.oldFilmUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){this.uniforms.uDimensions[0]=e.frame.width,this.uniforms.uDimensions[1]=e.frame.height,this.uniforms.uSeed=this.seed,t.applyFilter(this,e,s,r)}get sepia(){return this.uniforms.uSepia}set sepia(t){this.uniforms.uSepia=t}get noise(){return this.uniforms.uNoise[0]}set noise(t){this.uniforms.uNoise[0]=t}get noiseSize(){return this.uniforms.uNoise[1]}set noiseSize(t){this.uniforms.uNoise[1]=t}get scratch(){return this.uniforms.uScratch[0]}set scratch(t){this.uniforms.uScratch[0]=t}get scratchDensity(){return this.uniforms.uScratch[1]}set scratchDensity(t){this.uniforms.uScratch[1]=t}get scratchWidth(){return this.uniforms.uScratch[2]}set scratchWidth(t){this.uniforms.uScratch[2]=t}get vignetting(){return this.uniforms.uVignetting[0]}set vignetting(t){this.uniforms.uVignetting[0]=t}get vignettingAlpha(){return this.uniforms.uVignetting[1]}set vignettingAlpha(t){this.uniforms.uVignetting[1]=t}get vignettingBlur(){return this.uniforms.uVignetting[2]}set vignettingBlur(t){this.uniforms.uVignetting[2]=t}};_I(zit,"DEFAULT_OPTIONS",{sepia:.3,noise:.3,noiseSize:1,scratch:.5,scratchDensity:.3,scratchWidth:1,vignetting:.3,vignettingAlpha:1,vignettingBlur:.3,seed:0});var Vit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uThickness;
|
||
|
uniform vec3 uColor;
|
||
|
uniform float uAlpha;
|
||
|
uniform float uKnockout;
|
||
|
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
const float DOUBLE_PI = 2. * 3.14159265358979323846264;
|
||
|
const float ANGLE_STEP = \${ANGLE_STEP};
|
||
|
|
||
|
float outlineMaxAlphaAtPos(vec2 pos) {
|
||
|
if (uThickness.x == 0. || uThickness.y == 0.) {
|
||
|
return 0.;
|
||
|
}
|
||
|
|
||
|
vec4 displacedColor;
|
||
|
vec2 displacedPos;
|
||
|
float maxAlpha = 0.;
|
||
|
|
||
|
for (float angle = 0.; angle <= DOUBLE_PI; angle += ANGLE_STEP) {
|
||
|
displacedPos.x = vTextureCoord.x + uThickness.x * cos(angle);
|
||
|
displacedPos.y = vTextureCoord.y + uThickness.y * sin(angle);
|
||
|
displacedColor = texture(uTexture, clamp(displacedPos, uInputClamp.xy, uInputClamp.zw));
|
||
|
maxAlpha = max(maxAlpha, displacedColor.a);
|
||
|
}
|
||
|
|
||
|
return maxAlpha;
|
||
|
}
|
||
|
|
||
|
void main(void) {
|
||
|
vec4 sourceColor = texture(uTexture, vTextureCoord);
|
||
|
vec4 contentColor = sourceColor * float(uKnockout < 0.5);
|
||
|
float outlineAlpha = uAlpha * outlineMaxAlphaAtPos(vTextureCoord.xy) * (1.-sourceColor.a);
|
||
|
vec4 outlineColor = vec4(vec3(uColor) * outlineAlpha, outlineAlpha);
|
||
|
finalColor = contentColor + outlineColor;
|
||
|
}
|
||
|
`,Hit=`struct OutlineUniforms {
|
||
|
uThickness:vec2<f32>,
|
||
|
uColor:vec3<f32>,
|
||
|
uAlpha:f32,
|
||
|
uAngleStep:f32,
|
||
|
uKnockout:f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> outlineUniforms : OutlineUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let sourceColor: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let contentColor: vec4<f32> = sourceColor * (1. - outlineUniforms.uKnockout);
|
||
|
|
||
|
let outlineAlpha: f32 = outlineUniforms.uAlpha * outlineMaxAlphaAtPos(uv) * (1. - sourceColor.a);
|
||
|
let outlineColor: vec4<f32> = vec4<f32>(vec3<f32>(outlineUniforms.uColor) * outlineAlpha, outlineAlpha);
|
||
|
|
||
|
return contentColor + outlineColor;
|
||
|
}
|
||
|
|
||
|
fn outlineMaxAlphaAtPos(uv: vec2<f32>) -> f32 {
|
||
|
let thickness = outlineUniforms.uThickness;
|
||
|
|
||
|
if (thickness.x == 0. || thickness.y == 0.) {
|
||
|
return 0.;
|
||
|
}
|
||
|
|
||
|
let angleStep = outlineUniforms.uAngleStep;
|
||
|
|
||
|
var displacedColor: vec4<f32>;
|
||
|
var displacedPos: vec2<f32>;
|
||
|
|
||
|
var maxAlpha: f32 = 0.;
|
||
|
var displaced: vec2<f32>;
|
||
|
var curColor: vec4<f32>;
|
||
|
|
||
|
for (var angle = 0.; angle <= DOUBLE_PI; angle += angleStep)
|
||
|
{
|
||
|
displaced.x = uv.x + thickness.x * cos(angle);
|
||
|
displaced.y = uv.y + thickness.y * sin(angle);
|
||
|
curColor = textureSample(uTexture, uSampler, clamp(displaced, gfu.uInputClamp.xy, gfu.uInputClamp.zw));
|
||
|
maxAlpha = max(maxAlpha, curColor.a);
|
||
|
}
|
||
|
|
||
|
return maxAlpha;
|
||
|
}
|
||
|
|
||
|
const DOUBLE_PI: f32 = 3.14159265358979323846264 * 2.;`,Yit=Object.defineProperty,Wit=(i,t,e)=>t in i?Yit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Ca=(i,t,e)=>(Wit(i,typeof t!="symbol"?t+"":t,e),e);const TS=class jn extends xt{constructor(...t){let e=t[0]??{};typeof e=="number"&&(ct("6.0.0","OutlineFilter constructor params are now options object. See params: { thickness, color, quality, alpha, knockout }"),e={thickness:e},t[1]!==void 0&&(e.color=t[1]),t[2]!==void 0&&(e.quality=t[2]),t[3]!==void 0&&(e.alpha=t[3]),t[4]!==void 0&&(e.knockout=t[4])),e={...jn.DEFAULT_OPTIONS,...e};const s=e.quality??.1,r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Hit,entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:Vit.replace(/\$\{ANGLE_STEP\}/,jn.getAngleStep(s).toFixed(7)),name:"outline-filter"});super({gpuProgram:r,glProgram:n,resources:{outlineUniforms:{uThickness:{value:new Float32Array(2),type:"vec2<f32>"},uColor:{value:new Float32Array(3),type:"vec3<f32>"},uAlpha:{value:e.alpha,type:"f32"},uAngleStep:{value:0,type:"f32"},uKnockout:{value:e.knockout?1:0,type:"f32"}}}}),Ca(this,"uniforms"),Ca(this,"_thickness"),Ca(this,"_quality"),Ca(this,"_color"),this.uniforms=this.resources.outlineUniforms.uniforms,this.uniforms.uAngleStep=jn.getAngleStep(s),this._color=new Mt,this.color=e.color??0,Object.assign(this,e)}apply(t,e,s,r){this.uniforms.uThickness[0]=this.thickness/e.source.width,this.uniforms.uThickness[1]=this.thickness/e.source.height,t.applyFilter(this,e,s,r)}static getAngleStep(t){return parseFloat((Math.PI*2/Math.max(t*jn.MAX_SAMPLES,jn.MIN_SAMPLES)).toFixed(7))}get thickness(){return this._thickness}set thickness(t){this._thickness=this.padding=t}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}get quality(){return this._quality}set quality(t){this._quality=t,this.uniforms.uAngleStep=jn.getAngleStep(t)}get knockout(){return this.uniforms.uKnockout===1}set knockout(t){this.uniforms.uKnockout=t?1:0}};Ca(TS,"DEFAULT_OPTIONS",{thickness:1,color:0,alpha:1,quality:.1,knockout:!1});Ca(TS,"MIN_SAMPLES",1);Ca(TS,"MAX_SAMPLES",100);var jit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uRadian;
|
||
|
uniform vec2 uCenter;
|
||
|
uniform float uRadius;
|
||
|
uniform int uKernelSize;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
const int MAX_KERNEL_SIZE = 2048;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 color = texture(uTexture, vTextureCoord);
|
||
|
|
||
|
if (uKernelSize == 0)
|
||
|
{
|
||
|
finalColor = color;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float aspect = uInputSize.y / uInputSize.x;
|
||
|
vec2 center = uCenter.xy / uInputSize.xy;
|
||
|
float gradient = uRadius / uInputSize.x * 0.3;
|
||
|
float radius = uRadius / uInputSize.x - gradient * 0.5;
|
||
|
int k = uKernelSize - 1;
|
||
|
|
||
|
vec2 coord = vTextureCoord;
|
||
|
vec2 dir = vec2(center - coord);
|
||
|
float dist = length(vec2(dir.x, dir.y * aspect));
|
||
|
|
||
|
float radianStep = uRadian;
|
||
|
if (radius >= 0.0 && dist > radius) {
|
||
|
float delta = dist - radius;
|
||
|
float gap = gradient;
|
||
|
float scale = 1.0 - abs(delta / gap);
|
||
|
if (scale <= 0.0) {
|
||
|
finalColor = color;
|
||
|
return;
|
||
|
}
|
||
|
radianStep *= scale;
|
||
|
}
|
||
|
radianStep /= float(k);
|
||
|
|
||
|
float s = sin(radianStep);
|
||
|
float c = cos(radianStep);
|
||
|
mat2 rotationMatrix = mat2(vec2(c, -s), vec2(s, c));
|
||
|
|
||
|
for(int i = 0; i < MAX_KERNEL_SIZE - 1; i++) {
|
||
|
if (i == k) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
coord -= center;
|
||
|
coord.y *= aspect;
|
||
|
coord = rotationMatrix * coord;
|
||
|
coord.y /= aspect;
|
||
|
coord += center;
|
||
|
|
||
|
vec4 sample = texture(uTexture, coord);
|
||
|
|
||
|
// switch to pre-multiplied alpha to correctly blur transparent images
|
||
|
// sample.rgb *= sample.a;
|
||
|
|
||
|
color += sample;
|
||
|
}
|
||
|
|
||
|
finalColor = color / float(uKernelSize);
|
||
|
}
|
||
|
`,Kit=`struct RadialBlurUniforms {
|
||
|
uRadian: f32,
|
||
|
uCenter: vec2<f32>,
|
||
|
uKernelSize: f32,
|
||
|
uRadius: f32,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> radialBlurUniforms : RadialBlurUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uRadian = radialBlurUniforms.uRadian;
|
||
|
let uCenter = radialBlurUniforms.uCenter;
|
||
|
let uKernelSize = radialBlurUniforms.uKernelSize;
|
||
|
let uRadius = radialBlurUniforms.uRadius;
|
||
|
|
||
|
var returnColorOnly = false;
|
||
|
|
||
|
if (uKernelSize == 0)
|
||
|
{
|
||
|
returnColorOnly = true;
|
||
|
}
|
||
|
|
||
|
let aspect: f32 = gfu.uInputSize.y / gfu.uInputSize.x;
|
||
|
let center: vec2<f32> = uCenter.xy / gfu.uInputSize.xy;
|
||
|
let gradient: f32 = uRadius / gfu.uInputSize.x * 0.3;
|
||
|
let radius: f32 = uRadius / gfu.uInputSize.x - gradient * 0.5;
|
||
|
let k: i32 = i32(uKernelSize - 1);
|
||
|
|
||
|
var coord: vec2<f32> = uv;
|
||
|
let dir: vec2<f32> = vec2<f32>(center - coord);
|
||
|
let dist: f32 = length(vec2<f32>(dir.x, dir.y * aspect));
|
||
|
|
||
|
var radianStep: f32 = uRadian;
|
||
|
|
||
|
if (radius >= 0.0 && dist > radius)
|
||
|
{
|
||
|
let delta: f32 = dist - radius;
|
||
|
let gap: f32 = gradient;
|
||
|
let scale: f32 = 1.0 - abs(delta / gap);
|
||
|
if (scale <= 0.0) {
|
||
|
returnColorOnly = true;
|
||
|
}
|
||
|
radianStep *= scale;
|
||
|
}
|
||
|
|
||
|
radianStep /= f32(k);
|
||
|
|
||
|
let s: f32 = sin(radianStep);
|
||
|
let c: f32 = cos(radianStep);
|
||
|
let rotationMatrix: mat2x2<f32> = mat2x2<f32>(vec2<f32>(c, -s), vec2<f32>(s, c));
|
||
|
|
||
|
var color: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let baseColor = vec4<f32>(color);
|
||
|
|
||
|
let minK: i32 = min(i32(uKernelSize) - 1, MAX_KERNEL_SIZE - 1);
|
||
|
|
||
|
for(var i: i32 = 0; i < minK; i += 1)
|
||
|
{
|
||
|
coord -= center;
|
||
|
coord.y *= aspect;
|
||
|
coord = rotationMatrix * coord;
|
||
|
coord.y /= aspect;
|
||
|
coord += center;
|
||
|
let sample: vec4<f32> = textureSample(uTexture, uSampler, coord);
|
||
|
// switch to pre-multiplied alpha to correctly blur transparent images
|
||
|
// sample.rgb *= sample.a;
|
||
|
color += sample;
|
||
|
}
|
||
|
|
||
|
return select(color / f32(uKernelSize), baseColor, returnColorOnly);
|
||
|
}
|
||
|
|
||
|
const MAX_KERNEL_SIZE: i32 = 2048;`,Xit=Object.defineProperty,qit=(i,t,e)=>t in i?Xit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,zc=(i,t,e)=>(qit(i,typeof t!="symbol"?t+"":t,e),e);const $it=class CP extends xt{constructor(...t){let e=t[0]??{};if(typeof e=="number"){if(ct("6.0.0","RadialBlurFilter constructor params are now options object. See params: { angle, center, kernelSize, radius }"),e={angle:e},t[1]){const n="x"in t[1]?t[1].x:t[1][0],a="y"in t[1]?t[1].y:t[1][1];e.center={x:n,y:a}}t[2]&&(e.kernelSize=t[2]),t[3]&&(e.radius=t[3])}e={...CP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Kit,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:jit,name:"radial-blur-filter"});super({gpuProgram:s,glProgram:r,resources:{radialBlurUniforms:{uRadian:{value:0,type:"f32"},uCenter:{value:e.center,type:"vec2<f32>"},uKernelSize:{value:e.kernelSize,type:"i32"},uRadius:{value:e.radius,type:"f32"}}}}),zc(this,"uniforms"),zc(this,"_angle"),zc(this,"_kernelSize"),this.uniforms=this.resources.radialBlurUniforms.uniforms,Object.assign(this,e)}_updateKernelSize(){this.uniforms.uKernelSize=this._angle!==0?this.kernelSize:0}get angle(){return this._angle}set angle(t){this._angle=t,this.uniforms.uRadian=t*Math.PI/180,this._updateKernelSize()}get center(){return this.uniforms.uCenter}set center(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uCenter=t}get centerX(){return this.center.x}set centerX(t){this.center.x=t}get centerY(){return this.center.y}set centerY(t){this.center.y=t}get kernelSize(){return this._kernelSize}set kernelSize(t){this._kernelSize=t,this._updateKernelSize()}get radius(){return this.uniforms.uRadius}set radius(t){this.uniforms.uRadius=t<0||t===1/0?-1:t}};zc($it,"DEFAULT_OPTIONS",{angle:0,center:{x:0,y:0},kernelSize:5,radius:-1});var Qit=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uMirror;
|
||
|
uniform float uBoundary;
|
||
|
uniform vec2 uAmplitude;
|
||
|
uniform vec2 uWavelength;
|
||
|
uniform vec2 uAlpha;
|
||
|
uniform float uTime;
|
||
|
uniform vec2 uDimensions;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
float rand(vec2 co) {
|
||
|
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec2 pixelCoord = vTextureCoord.xy * uInputSize.xy;
|
||
|
vec2 coord = pixelCoord / uDimensions;
|
||
|
|
||
|
if (coord.y < uBoundary) {
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
float k = (coord.y - uBoundary) / (1. - uBoundary + 0.0001);
|
||
|
float areaY = uBoundary * uDimensions.y / uInputSize.y;
|
||
|
float v = areaY + areaY - vTextureCoord.y;
|
||
|
float y = uMirror > 0.5 ? v : vTextureCoord.y;
|
||
|
|
||
|
float _amplitude = ((uAmplitude.y - uAmplitude.x) * k + uAmplitude.x ) / uInputSize.x;
|
||
|
float _waveLength = ((uWavelength.y - uWavelength.x) * k + uWavelength.x) / uInputSize.y;
|
||
|
float _alpha = (uAlpha.y - uAlpha.x) * k + uAlpha.x;
|
||
|
|
||
|
float x = vTextureCoord.x + cos(v * 6.28 / _waveLength - uTime) * _amplitude;
|
||
|
x = clamp(x, uInputClamp.x, uInputClamp.z);
|
||
|
|
||
|
vec4 color = texture(uTexture, vec2(x, y));
|
||
|
|
||
|
finalColor = color * _alpha;
|
||
|
}
|
||
|
`,Zit=`struct ReflectionUniforms {
|
||
|
uMirror: f32,
|
||
|
uBoundary: f32,
|
||
|
uAmplitude: vec2<f32>,
|
||
|
uWavelength: vec2<f32>,
|
||
|
uAlpha: vec2<f32>,
|
||
|
uTime: f32,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> reflectionUniforms : ReflectionUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uDimensions: vec2<f32> = reflectionUniforms.uDimensions;
|
||
|
let uBoundary: f32 = reflectionUniforms.uBoundary;
|
||
|
let uMirror: bool = reflectionUniforms.uMirror > 0.5;
|
||
|
let uAmplitude: vec2<f32> = reflectionUniforms.uAmplitude;
|
||
|
let uWavelength: vec2<f32> = reflectionUniforms.uWavelength;
|
||
|
let uAlpha: vec2<f32> = reflectionUniforms.uAlpha;
|
||
|
let uTime: f32 = reflectionUniforms.uTime;
|
||
|
|
||
|
let pixelCoord: vec2<f32> = uv * gfu.uInputSize.xy;
|
||
|
let coord: vec2<f32> = pixelCoord /uDimensions;
|
||
|
var returnColorOnly: bool = false;
|
||
|
|
||
|
if (coord.y < uBoundary) {
|
||
|
returnColorOnly = true;
|
||
|
}
|
||
|
|
||
|
let k: f32 = (coord.y - uBoundary) / (1. - uBoundary + 0.0001);
|
||
|
let areaY: f32 = uBoundary * uDimensions.y / gfu.uInputSize.y;
|
||
|
let v: f32 = areaY + areaY - uv.y;
|
||
|
let y: f32 = select(uv.y, v, uMirror);
|
||
|
|
||
|
let amplitude: f32 = ((uAmplitude.y - uAmplitude.x) * k + uAmplitude.x ) / gfu.uInputSize.x;
|
||
|
let waveLength: f32 = ((uWavelength.y - uWavelength.x) * k + uWavelength.x) / gfu.uInputSize.y;
|
||
|
let alpha: f32 = select((uAlpha.y - uAlpha.x) * k + uAlpha.x, 1., returnColorOnly);
|
||
|
|
||
|
var x: f32 = uv.x + cos(v * 6.28 / waveLength - uTime) * amplitude;
|
||
|
x = clamp(x, gfu.uInputClamp.x, gfu.uInputClamp.z);
|
||
|
|
||
|
return textureSample(uTexture, uSampler, select(vec2<f32>(x, y), uv, returnColorOnly)) * alpha;
|
||
|
}
|
||
|
|
||
|
fn rand(co: vec2<f32>) -> f32
|
||
|
{
|
||
|
return fract(sin(dot(co.xy, vec2(12.9898, 78.233))) * 43758.5453);
|
||
|
}`,Jit=Object.defineProperty,trt=(i,t,e)=>t in i?Jit(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,dI=(i,t,e)=>(trt(i,typeof t!="symbol"?t+"":t,e),e);const ert=class MP extends xt{constructor(t){t={...MP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Zit,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Qit,name:"reflection-filter"});super({gpuProgram:e,glProgram:s,resources:{reflectionUniforms:{uMirror:{value:t.mirror?1:0,type:"f32"},uBoundary:{value:t.boundary,type:"f32"},uAmplitude:{value:t.amplitude,type:"vec2<f32>"},uWavelength:{value:t.waveLength,type:"vec2<f32>"},uAlpha:{value:t.alpha,type:"vec2<f32>"},uTime:{value:t.time,type:"f32"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"}}}}),dI(this,"uniforms"),dI(this,"time",0),this.uniforms=this.resources.reflectionUniforms.uniforms,Object.assign(this,t)}apply(t,e,s,r){this.uniforms.uDimensions[0]=e.frame.width,this.uniforms.uDimensions[1]=e.frame.height,this.uniforms.uTime=this.time,t.applyFilter(this,e,s,r)}get mirror(){return this.uniforms.uMirror>.5}set mirror(t){this.uniforms.uMirror=t?1:0}get boundary(){return this.uniforms.uBoundary}set boundary(t){this.uniforms.uBoundary=t}get amplitude(){return Array.from(this.uniforms.uAmplitude)}set amplitude(t){this.uniforms.uAmplitude[0]=t[0],this.uniforms.uAmplitude[1]=t[1]}get amplitudeStart(){return this.uniforms.uAmplitude[0]}set amplitudeStart(t){this.uniforms.uAmplitude[0]=t}get amplitudeEnd(){return this.uniforms.uAmplitude[1]}set amplitudeEnd(t){this.uniforms.uAmplitude[1]=t}get waveLength(){return Array.from(this.uniforms.uWavelength)}set waveLength(t){this.uniforms.uWavelength[0]=t[0],this.uniforms.uWavelength[1]=t[1]}get wavelengthStart(){return this.uniforms.uWavelength[0]}set wavelengthStart(t){this.uniforms.uWavelength[0]=t}get wavelengthEnd(){return this.uniforms.uWavelength[1]}set wavelengthEnd(t){this.uniforms.uWavelength[1]=t}get alpha(){return Array.from(this.uniforms.uAlpha)}set alpha(t){this.uniforms.uAlpha[0]=t[0],this.uniforms.uAlpha[1]=t[1]}get alphaStart(){return this.uniforms.uAlpha[0]}set alphaStart(t){this.uniforms.uAlpha[0]=t}get alphaEnd(){return this.uniforms.uAlpha[1]}set alphaEnd(t){this.uniforms.uAlpha[1]=t}};dI(ert,"DEFAULT_OPTIONS",{mirror:!0,boundary:.5,amplitude:[0,20],waveLength:[30,100],alpha:[1,1],time:0});var srt=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec2 uRed;
|
||
|
uniform vec2 uGreen;
|
||
|
uniform vec2 uBlue;
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
float r = texture(uTexture, vTextureCoord + uRed/uInputSize.xy).r;
|
||
|
float g = texture(uTexture, vTextureCoord + uGreen/uInputSize.xy).g;
|
||
|
float b = texture(uTexture, vTextureCoord + uBlue/uInputSize.xy).b;
|
||
|
float a = texture(uTexture, vTextureCoord).a;
|
||
|
finalColor = vec4(r, g, b, a);
|
||
|
}
|
||
|
`,irt=`struct RgbSplitUniforms {
|
||
|
uRed: vec2<f32>,
|
||
|
uGreen: vec2<f32>,
|
||
|
uBlue: vec3<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> rgbSplitUniforms : RgbSplitUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let r = textureSample(uTexture, uSampler, uv + vec2<f32>(rgbSplitUniforms.uRed.x / gfu.uInputSize.x, rgbSplitUniforms.uRed.y / gfu.uInputSize.y)).r;
|
||
|
let g = textureSample(uTexture, uSampler, uv + vec2<f32>(rgbSplitUniforms.uGreen.x / gfu.uInputSize.x, rgbSplitUniforms.uGreen.y / gfu.uInputSize.y)).g;
|
||
|
let b = textureSample(uTexture, uSampler, uv + vec2<f32>(rgbSplitUniforms.uBlue.x / gfu.uInputSize.x, rgbSplitUniforms.uBlue.y / gfu.uInputSize.y)).b;
|
||
|
let a = textureSample(uTexture, uSampler, uv).a;
|
||
|
return vec4<f32>(r, g, b, a);
|
||
|
}
|
||
|
`,rrt=Object.defineProperty,nrt=(i,t,e)=>t in i?rrt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,xP=(i,t,e)=>(nrt(i,typeof t!="symbol"?t+"":t,e),e);const art=class PP extends xt{constructor(...t){let e=t[0]??{};(Array.isArray(e)||"x"in e&&"y"in e)&&(ct("6.0.0","RGBSplitFilter constructor params are now options object. See params: { red, green, blue }"),e={red:e},t[1]!==void 0&&(e.green=t[1]),t[2]!==void 0&&(e.blue=t[2])),e={...PP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:irt,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:srt,name:"rgb-split-filter"});super({gpuProgram:s,glProgram:r,resources:{rgbSplitUniforms:{uRed:{value:e.red,type:"vec2<f32>"},uGreen:{value:e.green,type:"vec2<f32>"},uBlue:{value:e.blue,type:"vec2<f32>"}}}}),xP(this,"uniforms"),this.uniforms=this.resources.rgbSplitUniforms.uniforms,Object.assign(this,e)}get red(){return this.uniforms.uRed}set red(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uRed=t}get redX(){return this.red.x}set redX(t){this.red.x=t}get redY(){return this.red.y}set redY(t){this.red.y=t}get green(){return this.uniforms.uGreen}set green(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uGreen=t}get greenX(){return this.green.x}set greenX(t){this.green.x=t}get greenY(){return this.green.y}set greenY(t){this.green.y=t}get blue(){return this.uniforms.uBlue}set blue(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uBlue=t}get blueX(){return this.blue.x}set blueX(t){this.blue.x=t}get blueY(){return this.blue.y}set blueY(t){this.blue.y=t}};xP(art,"DEFAULT_OPTIONS",{red:{x:-10,y:0},green:{x:0,y:10},blue:{x:0,y:0}});var ort=`
|
||
|
precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uCenter;
|
||
|
uniform float uTime;
|
||
|
uniform float uSpeed;
|
||
|
uniform vec4 uWave;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
uniform vec4 uInputClamp;
|
||
|
|
||
|
const float PI = 3.14159;
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
float uAmplitude = uWave[0];
|
||
|
float uWavelength = uWave[1];
|
||
|
float uBrightness = uWave[2];
|
||
|
float uRadius = uWave[3];
|
||
|
|
||
|
float halfWavelength = uWavelength * 0.5 / uInputSize.x;
|
||
|
float maxRadius = uRadius / uInputSize.x;
|
||
|
float currentRadius = uTime * uSpeed / uInputSize.x;
|
||
|
|
||
|
float fade = 1.0;
|
||
|
|
||
|
if (maxRadius > 0.0) {
|
||
|
if (currentRadius > maxRadius) {
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
return;
|
||
|
}
|
||
|
fade = 1.0 - pow(currentRadius / maxRadius, 2.0);
|
||
|
}
|
||
|
|
||
|
vec2 dir = vec2(vTextureCoord - uCenter / uInputSize.xy);
|
||
|
dir.y *= uInputSize.y / uInputSize.x;
|
||
|
float dist = length(dir);
|
||
|
|
||
|
if (dist <= 0.0 || dist < currentRadius - halfWavelength || dist > currentRadius + halfWavelength) {
|
||
|
finalColor = texture(uTexture, vTextureCoord);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vec2 diffUV = normalize(dir);
|
||
|
|
||
|
float diff = (dist - currentRadius) / halfWavelength;
|
||
|
|
||
|
float p = 1.0 - pow(abs(diff), 2.0);
|
||
|
|
||
|
// float powDiff = diff * pow(p, 2.0) * ( amplitude * fade );
|
||
|
float powDiff = 1.25 * sin(diff * PI) * p * ( uAmplitude * fade );
|
||
|
|
||
|
vec2 offset = diffUV * powDiff / uInputSize.xy;
|
||
|
|
||
|
// Do clamp :
|
||
|
vec2 coord = vTextureCoord + offset;
|
||
|
vec2 clampedCoord = clamp(coord, uInputClamp.xy, uInputClamp.zw);
|
||
|
vec4 color = texture(uTexture, clampedCoord);
|
||
|
if (coord != clampedCoord) {
|
||
|
color *= max(0.0, 1.0 - length(coord - clampedCoord));
|
||
|
}
|
||
|
|
||
|
// No clamp :
|
||
|
// finalColor = texture(uTexture, vTextureCoord + offset);
|
||
|
|
||
|
color.rgb *= 1.0 + (uBrightness - 1.0) * p * fade;
|
||
|
|
||
|
finalColor = color;
|
||
|
}
|
||
|
`,urt=`
|
||
|
struct ShockWaveUniforms {
|
||
|
uTime: f32,
|
||
|
uOffset: vec2<f32>,
|
||
|
uSpeed: f32,
|
||
|
uWave: vec4<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> shockwaveUniforms : ShockWaveUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
|
||
|
let uTime = shockwaveUniforms.uTime;
|
||
|
let uOffset = shockwaveUniforms.uOffset;
|
||
|
let uSpeed = shockwaveUniforms.uSpeed;
|
||
|
let uAmplitude = shockwaveUniforms.uWave[0];
|
||
|
let uWavelength = shockwaveUniforms.uWave[1];
|
||
|
let uBrightness = shockwaveUniforms.uWave[2];
|
||
|
let uRadius = shockwaveUniforms.uWave[3];
|
||
|
let halfWavelength: f32 = uWavelength * 0.5 / gfu.uInputSize.x;
|
||
|
let maxRadius: f32 = uRadius / gfu.uInputSize.x;
|
||
|
let currentRadius: f32 = uTime * uSpeed / gfu.uInputSize.x;
|
||
|
var fade: f32 = 1.0;
|
||
|
var returnColorOnly: bool = false;
|
||
|
|
||
|
if (maxRadius > 0.0) {
|
||
|
if (currentRadius > maxRadius) {
|
||
|
returnColorOnly = true;
|
||
|
}
|
||
|
fade = 1.0 - pow(currentRadius / maxRadius, 2.0);
|
||
|
}
|
||
|
var dir: vec2<f32> = vec2<f32>(uv - uOffset / gfu.uInputSize.xy);
|
||
|
dir.y *= gfu.uInputSize.y / gfu.uInputSize.x;
|
||
|
|
||
|
let dist:f32 = length(dir);
|
||
|
|
||
|
if (dist <= 0.0 || dist < currentRadius - halfWavelength || dist > currentRadius + halfWavelength) {
|
||
|
returnColorOnly = true;
|
||
|
}
|
||
|
|
||
|
let diffUV: vec2<f32> = normalize(dir);
|
||
|
let diff: f32 = (dist - currentRadius) / halfWavelength;
|
||
|
let p: f32 = 1.0 - pow(abs(diff), 2.0);
|
||
|
let powDiff: f32 = 1.25 * sin(diff * PI) * p * ( uAmplitude * fade );
|
||
|
let offset: vec2<f32> = diffUV * powDiff / gfu.uInputSize.xy;
|
||
|
// Do clamp :
|
||
|
let coord: vec2<f32> = uv + offset;
|
||
|
let clampedCoord: vec2<f32> = clamp(coord, gfu.uInputClamp.xy, gfu.uInputClamp.zw);
|
||
|
|
||
|
var clampedColor: vec4<f32> = textureSample(uTexture, uSampler, clampedCoord);
|
||
|
|
||
|
if (boolVec2(coord, clampedCoord))
|
||
|
{
|
||
|
clampedColor *= max(0.0, 1.0 - length(coord - clampedCoord));
|
||
|
}
|
||
|
// No clamp :
|
||
|
var finalColor = clampedColor;
|
||
|
|
||
|
return select(finalColor, textureSample(uTexture, uSampler, uv), returnColorOnly);
|
||
|
}
|
||
|
|
||
|
fn boolVec2(x: vec2<f32>, y: vec2<f32>) -> bool
|
||
|
{
|
||
|
if (x.x == y.x && x.y == y.y)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const PI: f32 = 3.14159265358979323846264;
|
||
|
`,lrt=Object.defineProperty,hrt=(i,t,e)=>t in i?lrt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,fI=(i,t,e)=>(hrt(i,typeof t!="symbol"?t+"":t,e),e);const crt=class bP extends xt{constructor(...t){let e=t[0]??{};(Array.isArray(e)||"x"in e&&"y"in e)&&(ct("6.0.0","ShockwaveFilter constructor params are now options object. See params: { center, speed, amplitude, wavelength, brightness, radius, time }"),e={center:e,...t[1]},t[2]!==void 0&&(e.time=t[2])),e={...bP.DEFAULT_OPTIONS,...e};const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:urt,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:ort,name:"shockwave-filter"});super({gpuProgram:s,glProgram:r,resources:{shockwaveUniforms:{uTime:{value:e.time,type:"f32"},uCenter:{value:e.center,type:"vec2<f32>"},uSpeed:{value:e.speed,type:"f32"},uWave:{value:new Float32Array(4),type:"vec4<f32>"}}}}),fI(this,"uniforms"),fI(this,"time"),this.time=0,this.uniforms=this.resources.shockwaveUniforms.uniforms,Object.assign(this,e)}apply(t,e,s,r){this.uniforms.uTime=this.time,t.applyFilter(this,e,s,r)}get center(){return this.uniforms.uCenter}set center(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uCenter=t}get centerX(){return this.uniforms.uCenter.x}set centerX(t){this.uniforms.uCenter.x=t}get centerY(){return this.uniforms.uCenter.y}set centerY(t){this.uniforms.uCenter.y=t}get speed(){return this.uniforms.uSpeed}set speed(t){this.uniforms.uSpeed=t}get amplitude(){return this.uniforms.uWave[0]}set amplitude(t){this.uniforms.uWave[0]=t}get wavelength(){return this.uniforms.uWave[1]}set wavelength(t){this.uniforms.uWave[1]=t}get brightness(){return this.uniforms.uWave[2]}set brightness(t){this.uniforms.uWave[2]=t}get radius(){return this.uniforms.uWave[3]}set radius(t){this.uniforms.uWave[3]=t}};fI(crt,"DEFAULT_OPTIONS",{center:{x:0,y:0},speed:500,amplitude:30,wavelength:160,brightness:1,radius:-1});var _rt=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform sampler2D uMapTexture;
|
||
|
uniform vec3 uColor;
|
||
|
uniform float uAlpha;
|
||
|
uniform vec2 uDimensions;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
void main() {
|
||
|
vec4 diffuseColor = texture(uTexture, vTextureCoord);
|
||
|
vec2 lightCoord = (vTextureCoord * uInputSize.xy) / uDimensions;
|
||
|
vec4 light = texture(uMapTexture, lightCoord);
|
||
|
vec3 ambient = uColor.rgb * uAlpha;
|
||
|
vec3 intensity = ambient + light.rgb;
|
||
|
vec3 color = diffuseColor.rgb * intensity;
|
||
|
finalColor = vec4(color, diffuseColor.a);
|
||
|
}
|
||
|
`,drt=`struct SimpleLightmapUniforms {
|
||
|
uColor: vec3<f32>,
|
||
|
uAlpha: f32,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> simpleLightmapUniforms : SimpleLightmapUniforms;
|
||
|
@group(1) @binding(1) var uMapTexture: texture_2d<f32>;
|
||
|
@group(1) @binding(2) var uMapSampler: sampler;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>,
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uColor = simpleLightmapUniforms.uColor;
|
||
|
let uAlpha = simpleLightmapUniforms.uAlpha;
|
||
|
let uDimensions = simpleLightmapUniforms.uDimensions;
|
||
|
|
||
|
let diffuseColor: vec4<f32> = textureSample(uTexture, uSampler, uv);
|
||
|
let lightCoord: vec2<f32> = (uv * gfu.uInputSize.xy) / simpleLightmapUniforms.uDimensions;
|
||
|
let light: vec4<f32> = textureSample(uMapTexture, uMapSampler, lightCoord);
|
||
|
let ambient: vec3<f32> = uColor * uAlpha;
|
||
|
let intensity: vec3<f32> = ambient + light.rgb;
|
||
|
let finalColor: vec3<f32> = diffuseColor.rgb * intensity;
|
||
|
return vec4<f32>(finalColor, diffuseColor.a);
|
||
|
}`,frt=Object.defineProperty,grt=(i,t,e)=>t in i?frt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,Vc=(i,t,e)=>(grt(i,typeof t!="symbol"?t+"":t,e),e);const prt=class NP extends xt{constructor(...t){let e=t[0]??{};if(e instanceof W&&(ct("6.0.0","SimpleLightmapFilter constructor params are now options object. See params: { lightMap, color, alpha }"),e={lightMap:e},t[1]!==void 0&&(e.color=t[1]),t[2]!==void 0&&(e.alpha=t[2])),e={...NP.DEFAULT_OPTIONS,...e},!e.lightMap)throw Error("No light map texture source was provided to SimpleLightmapFilter");const s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:drt,entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:_rt,name:"simple-lightmap-filter"});super({gpuProgram:s,glProgram:r,resources:{simpleLightmapUniforms:{uColor:{value:new Float32Array(3),type:"vec3<f32>"},uAlpha:{value:e.alpha,type:"f32"},uDimensions:{value:new Float32Array(2),type:"vec2<f32>"}},uMapTexture:e.lightMap.source,uMapSampler:e.lightMap.source.style}}),Vc(this,"uniforms"),Vc(this,"_color"),Vc(this,"_lightMap"),this.uniforms=this.resources.simpleLightmapUniforms.uniforms,this._color=new Mt,this.color=e.color??0,Object.assign(this,e)}apply(t,e,s,r){this.uniforms.uDimensions[0]=e.frame.width,this.uniforms.uDimensions[1]=e.frame.height,t.applyFilter(this,e,s,r)}get lightMap(){return this._lightMap}set lightMap(t){this._lightMap=t,this.resources.uMapTexture=t.source,this.resources.uMapSampler=t.source.style}get color(){return this._color.value}set color(t){this._color.setValue(t);const[e,s,r]=this._color.toArray();this.uniforms.uColor[0]=e,this.uniforms.uColor[1]=s,this.uniforms.uColor[2]=r}get alpha(){return this.uniforms.uAlpha}set alpha(t){this.uniforms.uAlpha=t}};Vc(prt,"DEFAULT_OPTIONS",{lightMap:W.WHITE,color:0,alpha:1});var mrt=`in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uBlur;
|
||
|
uniform vec2 uStart;
|
||
|
uniform vec2 uEnd;
|
||
|
uniform vec2 uDelta;
|
||
|
uniform vec2 uDimensions;
|
||
|
|
||
|
float random(vec3 scale, float seed)
|
||
|
{
|
||
|
return fract(sin(dot(gl_FragCoord.xyz + seed, scale)) * 43758.5453 + seed);
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec4 color = vec4(0.0);
|
||
|
float total = 0.0;
|
||
|
|
||
|
float blur = uBlur[0];
|
||
|
float gradientBlur = uBlur[1];
|
||
|
|
||
|
float offset = random(vec3(12.9898, 78.233, 151.7182), 0.0);
|
||
|
vec2 normal = normalize(vec2(uStart.y - uEnd.y, uEnd.x - uStart.x));
|
||
|
float radius = smoothstep(0.0, 1.0, abs(dot(vTextureCoord * uDimensions - uStart, normal)) / gradientBlur) * blur;
|
||
|
|
||
|
for (float t = -30.0; t <= 30.0; t++)
|
||
|
{
|
||
|
float percent = (t + offset - 0.5) / 30.0;
|
||
|
float weight = 1.0 - abs(percent);
|
||
|
vec4 sample = texture(uTexture, vTextureCoord + uDelta / uDimensions * percent * radius);
|
||
|
sample.rgb *= sample.a;
|
||
|
color += sample * weight;
|
||
|
total += weight;
|
||
|
}
|
||
|
|
||
|
color /= total;
|
||
|
color.rgb /= color.a + 0.00001;
|
||
|
|
||
|
finalColor = color;
|
||
|
}
|
||
|
`,Ert=`struct TiltShiftUniforms {
|
||
|
uBlur: vec2<f32>,
|
||
|
uStart: vec2<f32>,
|
||
|
uEnd: vec2<f32>,
|
||
|
uDelta: vec2<f32>,
|
||
|
uDimensions: vec2<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> tiltShiftUniforms : TiltShiftUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uBlur = tiltShiftUniforms.uBlur[0];
|
||
|
let uBlurGradient = tiltShiftUniforms.uBlur[1];
|
||
|
let uStart = tiltShiftUniforms.uStart;
|
||
|
let uEnd = tiltShiftUniforms.uEnd;
|
||
|
let uDelta = tiltShiftUniforms.uDelta;
|
||
|
let uDimensions = tiltShiftUniforms.uDimensions;
|
||
|
|
||
|
var color: vec4<f32> = vec4<f32>(0.0);
|
||
|
var total: f32 = 0.0;
|
||
|
|
||
|
let offset: f32 = random(position, vec3<f32>(12.9898, 78.233, 151.7182), 0.0);
|
||
|
let normal: vec2<f32> = normalize(vec2<f32>(uStart.y - uEnd.y, uEnd.x - uStart.x));
|
||
|
let radius: f32 = smoothstep(0.0, 1.0, abs(dot(uv * uDimensions - uStart, normal)) / uBlurGradient) * uBlur;
|
||
|
|
||
|
for (var t: f32 = -30.0; t <= 30.0; t += 1.0)
|
||
|
{
|
||
|
var percent: f32 = (t + offset - 0.5) / 30.0;
|
||
|
var weight: f32 = 1.0 - abs(percent);
|
||
|
var sample: vec4<f32> = textureSample(uTexture, uSampler, uv + uDelta / uDimensions * percent * radius);
|
||
|
sample = vec4<f32>(sample.xyz * sample.a, sample.a); // multiply sample.rgb with sample.a
|
||
|
color += sample * weight;
|
||
|
total += weight;
|
||
|
}
|
||
|
|
||
|
color /= total;
|
||
|
color = vec4<f32>(color.xyz / (color.a + 0.00001), color.a); // divide color.rgb by color.a + 0.00001
|
||
|
|
||
|
return color;
|
||
|
}
|
||
|
|
||
|
|
||
|
fn random(position: vec4<f32>, scale: vec3<f32>, seed: f32) -> f32
|
||
|
{
|
||
|
return fract(sin(dot(position.xyz + seed, scale)) * 43758.5453 + seed);
|
||
|
}`,Trt=Object.defineProperty,Irt=(i,t,e)=>t in i?Trt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,gI=(i,t,e)=>(Irt(i,typeof t!="symbol"?t+"":t,e),e);const Srt=class UP extends xt{constructor(t){const{width:e,height:s}=mM.defaultOptions;t={...UP.DEFAULT_OPTIONS,start:{x:0,y:s/2},end:{x:e,y:s/2},...t};const r=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Ert,entryPoint:"mainFragment"}}),n=Tt.from({vertex:Qt,fragment:mrt,name:"tilt-shift-axis-filter"});super({gpuProgram:r,glProgram:n,resources:{tiltShiftUniforms:{uBlur:{value:new Float32Array([t.blur,t.gradientBlur]),type:"vec2<f32>"},uStart:{value:t.start,type:"vec2<f32>"},uEnd:{value:t.end,type:"vec2<f32>"},uDelta:{value:new Float32Array([0,0]),type:"vec2<f32>"},uDimensions:{value:new Float32Array([e,s]),type:"vec2<f32>"}}}}),gI(this,"uniforms"),gI(this,"_tiltAxis"),this.uniforms=this.resources.tiltShiftUniforms.uniforms,this._tiltAxis=t.axis}updateDimensions(t){const{uDimensions:e}=this.uniforms;e[0]=t.frame.width,e[1]=t.frame.height}updateDelta(){if(this.uniforms.uDelta[0]=0,this.uniforms.uDelta[1]=0,this._tiltAxis===void 0)return;const t=this.uniforms.uEnd,e=this.uniforms.uStart,s=t.x-e.x,r=t.y-e.y,n=Math.sqrt(s*s+r*r),a=this._tiltAxis==="vertical";this.uniforms.uDelta[0]=a?-r/n:s/n,this.uniforms.uDelta[1]=a?s/n:r/n}};gI(Srt,"DEFAULT_OPTIONS",{blur:100,gradientBlur:600});var Rrt=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform vec2 uTwist;
|
||
|
uniform vec2 uOffset;
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
vec2 mapCoord( vec2 coord )
|
||
|
{
|
||
|
coord *= uInputSize.xy;
|
||
|
coord += uInputSize.zw;
|
||
|
|
||
|
return coord;
|
||
|
}
|
||
|
|
||
|
vec2 unmapCoord( vec2 coord )
|
||
|
{
|
||
|
coord -= uInputSize.zw;
|
||
|
coord /= uInputSize.xy;
|
||
|
|
||
|
return coord;
|
||
|
}
|
||
|
|
||
|
vec2 twist(vec2 coord)
|
||
|
{
|
||
|
coord -= uOffset;
|
||
|
|
||
|
float dist = length(coord);
|
||
|
float uRadius = uTwist[0];
|
||
|
float uAngle = uTwist[1];
|
||
|
|
||
|
if (dist < uRadius)
|
||
|
{
|
||
|
float ratioDist = (uRadius - dist) / uRadius;
|
||
|
float angleMod = ratioDist * ratioDist * uAngle;
|
||
|
float s = sin(angleMod);
|
||
|
float c = cos(angleMod);
|
||
|
coord = vec2(coord.x * c - coord.y * s, coord.x * s + coord.y * c);
|
||
|
}
|
||
|
|
||
|
coord += uOffset;
|
||
|
|
||
|
return coord;
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
vec2 coord = mapCoord(vTextureCoord);
|
||
|
coord = twist(coord);
|
||
|
coord = unmapCoord(coord);
|
||
|
finalColor = texture(uTexture, coord);
|
||
|
}
|
||
|
`,Art=`struct TwistUniforms {
|
||
|
uTwist:vec2<f32>,
|
||
|
uOffset:vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> twistUniforms : TwistUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@location(0) uv: vec2<f32>,
|
||
|
@builtin(position) position: vec4<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
return textureSample(uTexture, uSampler, unmapCoord(twist(mapCoord(uv))));
|
||
|
}
|
||
|
|
||
|
fn mapCoord(coord: vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
var mappedCoord: vec2<f32> = coord;
|
||
|
mappedCoord *= gfu.uInputSize.xy;
|
||
|
mappedCoord += gfu.uOutputFrame.xy;
|
||
|
return mappedCoord;
|
||
|
}
|
||
|
|
||
|
fn unmapCoord(coord: vec2<f32> ) -> vec2<f32>
|
||
|
{
|
||
|
var mappedCoord: vec2<f32> = coord;
|
||
|
mappedCoord -= gfu.uOutputFrame.xy;
|
||
|
mappedCoord /= gfu.uInputSize.xy;
|
||
|
return mappedCoord;
|
||
|
}
|
||
|
|
||
|
fn twist(coord: vec2<f32>) -> vec2<f32>
|
||
|
{
|
||
|
var twistedCoord: vec2<f32> = coord;
|
||
|
let uRadius = twistUniforms.uTwist[0];
|
||
|
let uAngle = twistUniforms.uTwist[1];
|
||
|
let uOffset = twistUniforms.uOffset;
|
||
|
|
||
|
twistedCoord -= uOffset;
|
||
|
|
||
|
let dist = length(twistedCoord);
|
||
|
|
||
|
if (dist < uRadius)
|
||
|
{
|
||
|
let ratioDist: f32 = (uRadius - dist) / uRadius;
|
||
|
let angleMod: f32 = ratioDist * ratioDist * uAngle;
|
||
|
let s: f32 = sin(angleMod);
|
||
|
let c: f32 = cos(angleMod);
|
||
|
twistedCoord = vec2<f32>(twistedCoord.x * c - twistedCoord.y * s, twistedCoord.x * s + twistedCoord.y * c);
|
||
|
}
|
||
|
|
||
|
twistedCoord += uOffset;
|
||
|
return twistedCoord;
|
||
|
}
|
||
|
`,Ort=Object.defineProperty,yrt=(i,t,e)=>t in i?Ort(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,DP=(i,t,e)=>(yrt(i,typeof t!="symbol"?t+"":t,e),e);const vrt=class LP extends xt{constructor(t){t={...LP.DEFAULT_OPTIONS,...t};const e=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Art,entryPoint:"mainFragment"}}),s=Tt.from({vertex:Qt,fragment:Rrt,name:"twist-filter"});super({gpuProgram:e,glProgram:s,resources:{twistUniforms:{uTwist:{value:[t.radius??0,t.angle??0],type:"vec2<f32>"},uOffset:{value:t.offset,type:"vec2<f32>"}}},...t}),DP(this,"uniforms"),this.uniforms=this.resources.twistUniforms.uniforms}get radius(){return this.uniforms.uTwist[0]}set radius(t){this.uniforms.uTwist[0]=t}get angle(){return this.uniforms.uTwist[1]}set angle(t){this.uniforms.uTwist[1]=t}get offset(){return this.uniforms.uOffset}set offset(t){this.uniforms.uOffset=t}get offsetX(){return this.offset.x}set offsetX(t){this.offset.x=t}get offsetY(){return this.offset.y}set offsetY(t){this.offset.y=t}};DP(vrt,"DEFAULT_OPTIONS",{padding:20,radius:200,angle:4,offset:{x:0,y:0}});var Crt=`precision highp float;
|
||
|
in vec2 vTextureCoord;
|
||
|
out vec4 finalColor;
|
||
|
|
||
|
uniform sampler2D uTexture;
|
||
|
uniform float uStrength;
|
||
|
uniform vec2 uCenter;
|
||
|
uniform vec2 uRadii;
|
||
|
|
||
|
uniform vec4 uInputSize;
|
||
|
|
||
|
const float MAX_KERNEL_SIZE = \${MAX_KERNEL_SIZE};
|
||
|
|
||
|
// author: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
|
||
|
highp float rand(vec2 co, float seed) {
|
||
|
const highp float a = 12.9898, b = 78.233, c = 43758.5453;
|
||
|
highp float dt = dot(co + seed, vec2(a, b)), sn = mod(dt, 3.14159);
|
||
|
return fract(sin(sn) * c + seed);
|
||
|
}
|
||
|
|
||
|
void main() {
|
||
|
float minGradient = uRadii[0] * 0.3;
|
||
|
float innerRadius = (uRadii[0] + minGradient * 0.5) / uInputSize.x;
|
||
|
|
||
|
float gradient = uRadii[1] * 0.3;
|
||
|
float radius = (uRadii[1] - gradient * 0.5) / uInputSize.x;
|
||
|
|
||
|
float countLimit = MAX_KERNEL_SIZE;
|
||
|
|
||
|
vec2 dir = vec2(uCenter.xy / uInputSize.xy - vTextureCoord);
|
||
|
float dist = length(vec2(dir.x, dir.y * uInputSize.y / uInputSize.x));
|
||
|
|
||
|
float strength = uStrength;
|
||
|
|
||
|
float delta = 0.0;
|
||
|
float gap;
|
||
|
if (dist < innerRadius) {
|
||
|
delta = innerRadius - dist;
|
||
|
gap = minGradient;
|
||
|
} else if (radius >= 0.0 && dist > radius) { // radius < 0 means it's infinity
|
||
|
delta = dist - radius;
|
||
|
gap = gradient;
|
||
|
}
|
||
|
|
||
|
if (delta > 0.0) {
|
||
|
float normalCount = gap / uInputSize.x;
|
||
|
delta = (normalCount - delta) / normalCount;
|
||
|
countLimit *= delta;
|
||
|
strength *= delta;
|
||
|
if (countLimit < 1.0)
|
||
|
{
|
||
|
gl_FragColor = texture(uTexture, vTextureCoord);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// randomize the lookup values to hide the fixed number of samples
|
||
|
float offset = rand(vTextureCoord, 0.0);
|
||
|
|
||
|
float total = 0.0;
|
||
|
vec4 color = vec4(0.0);
|
||
|
|
||
|
dir *= strength;
|
||
|
|
||
|
for (float t = 0.0; t < MAX_KERNEL_SIZE; t++) {
|
||
|
float percent = (t + offset) / MAX_KERNEL_SIZE;
|
||
|
float weight = 4.0 * (percent - percent * percent);
|
||
|
vec2 p = vTextureCoord + dir * percent;
|
||
|
vec4 sample = texture(uTexture, p);
|
||
|
|
||
|
// switch to pre-multiplied alpha to correctly blur transparent images
|
||
|
// sample.rgb *= sample.a;
|
||
|
|
||
|
color += sample * weight;
|
||
|
total += weight;
|
||
|
|
||
|
if (t > countLimit){
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
color /= total;
|
||
|
// switch back from pre-multiplied alpha
|
||
|
// color.rgb /= color.a + 0.00001;
|
||
|
|
||
|
gl_FragColor = color;
|
||
|
}
|
||
|
`,Mrt=`struct ZoomBlurUniforms {
|
||
|
uStrength:f32,
|
||
|
uCenter:vec2<f32>,
|
||
|
uRadii:vec2<f32>,
|
||
|
};
|
||
|
|
||
|
struct GlobalFilterUniforms {
|
||
|
uInputSize:vec4<f32>,
|
||
|
uInputPixel:vec4<f32>,
|
||
|
uInputClamp:vec4<f32>,
|
||
|
uOutputFrame:vec4<f32>,
|
||
|
uGlobalFrame:vec4<f32>,
|
||
|
uOutputTexture:vec4<f32>,
|
||
|
};
|
||
|
|
||
|
@group(0) @binding(0) var<uniform> gfu: GlobalFilterUniforms;
|
||
|
|
||
|
@group(0) @binding(1) var uTexture: texture_2d<f32>;
|
||
|
@group(0) @binding(2) var uSampler: sampler;
|
||
|
@group(1) @binding(0) var<uniform> zoomBlurUniforms : ZoomBlurUniforms;
|
||
|
|
||
|
@fragment
|
||
|
fn mainFragment(
|
||
|
@builtin(position) position: vec4<f32>,
|
||
|
@location(0) uv : vec2<f32>
|
||
|
) -> @location(0) vec4<f32> {
|
||
|
let uStrength = zoomBlurUniforms.uStrength;
|
||
|
let uCenter = zoomBlurUniforms.uCenter;
|
||
|
let uRadii = zoomBlurUniforms.uRadii;
|
||
|
|
||
|
let minGradient: f32 = uRadii[0] * 0.3;
|
||
|
let innerRadius: f32 = (uRadii[0] + minGradient * 0.5) / gfu.uInputSize.x;
|
||
|
|
||
|
let gradient: f32 = uRadii[1] * 0.3;
|
||
|
let radius: f32 = (uRadii[1] - gradient * 0.5) / gfu.uInputSize.x;
|
||
|
|
||
|
let MAX_KERNEL_SIZE: f32 = \${MAX_KERNEL_SIZE};
|
||
|
|
||
|
var countLimit: f32 = MAX_KERNEL_SIZE;
|
||
|
|
||
|
var dir: vec2<f32> = vec2<f32>(uCenter / gfu.uInputSize.xy - uv);
|
||
|
let dist: f32 = length(vec2<f32>(dir.x, dir.y * gfu.uInputSize.y / gfu.uInputSize.x));
|
||
|
|
||
|
var strength: f32 = uStrength;
|
||
|
|
||
|
var delta: f32 = 0.0;
|
||
|
var gap: f32;
|
||
|
|
||
|
if (dist < innerRadius) {
|
||
|
delta = innerRadius - dist;
|
||
|
gap = minGradient;
|
||
|
} else if (radius >= 0.0 && dist > radius) { // radius < 0 means it's infinity
|
||
|
delta = dist - radius;
|
||
|
gap = gradient;
|
||
|
}
|
||
|
|
||
|
var returnColorOnly: bool = false;
|
||
|
|
||
|
if (delta > 0.0) {
|
||
|
let normalCount: f32 = gap / gfu.uInputSize.x;
|
||
|
delta = (normalCount - delta) / normalCount;
|
||
|
countLimit *= delta;
|
||
|
strength *= delta;
|
||
|
|
||
|
if (countLimit < 1.0)
|
||
|
{
|
||
|
returnColorOnly = true;;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// randomize the lookup values to hide the fixed number of samples
|
||
|
let offset: f32 = rand(uv, 0.0);
|
||
|
|
||
|
var total: f32 = 0.0;
|
||
|
var color: vec4<f32> = vec4<f32>(0.);
|
||
|
|
||
|
dir *= strength;
|
||
|
|
||
|
for (var t = 0.0; t < MAX_KERNEL_SIZE; t += 1.0) {
|
||
|
let percent: f32 = (t + offset) / MAX_KERNEL_SIZE;
|
||
|
let weight: f32 = 4.0 * (percent - percent * percent);
|
||
|
let p: vec2<f32> = uv + dir * percent;
|
||
|
let sample: vec4<f32> = textureSample(uTexture, uSampler, p);
|
||
|
|
||
|
if (t < countLimit)
|
||
|
{
|
||
|
color += sample * weight;
|
||
|
total += weight;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
color /= total;
|
||
|
|
||
|
return select(color, textureSample(uTexture, uSampler, uv), returnColorOnly);
|
||
|
}
|
||
|
|
||
|
fn modulo(x: f32, y: f32) -> f32
|
||
|
{
|
||
|
return x - y * floor(x/y);
|
||
|
}
|
||
|
|
||
|
// author: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
|
||
|
fn rand(co: vec2<f32>, seed: f32) -> f32
|
||
|
{
|
||
|
let a: f32 = 12.9898;
|
||
|
let b: f32 = 78.233;
|
||
|
let c: f32 = 43758.5453;
|
||
|
let dt: f32 = dot(co + seed, vec2<f32>(a, b));
|
||
|
let sn: f32 = modulo(dt, 3.14159);
|
||
|
return fract(sin(sn) * c + seed);
|
||
|
}`,xrt=Object.defineProperty,Prt=(i,t,e)=>t in i?xrt(i,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):i[t]=e,FP=(i,t,e)=>(Prt(i,typeof t!="symbol"?t+"":t,e),e);const brt=class wP extends xt{constructor(t){t={...wP.DEFAULT_OPTIONS,...t};const e=t.maxKernelSize??32,s=At.from({vertex:{source:Zt,entryPoint:"mainVertex"},fragment:{source:Mrt.replace("${MAX_KERNEL_SIZE}",e.toFixed(1)),entryPoint:"mainFragment"}}),r=Tt.from({vertex:Qt,fragment:Crt.replace("${MAX_KERNEL_SIZE}",e.toFixed(1)),name:"zoom-blur-filter"});super({gpuProgram:s,glProgram:r,resources:{zoomBlurUniforms:{uStrength:{value:t.strength,type:"f32"},uCenter:{value:t.center,type:"vec2<f32>"},uRadii:{value:new Float32Array(2),type:"vec2<f32>"}}}}),FP(this,"uniforms"),this.uniforms=this.resources.zoomBlurUniforms.uniforms,Object.assign(this,t)}get strength(){return this.uniforms.uStrength}set strength(t){this.uniforms.uStrength=t}get center(){return this.uniforms.uCenter}set center(t){Array.isArray(t)&&(t={x:t[0],y:t[1]}),this.uniforms.uCenter=t}get centerX(){return this.uniforms.uCenter.x}set centerX(t){this.uniforms.uCenter.x=t}get centerY(){return this.uniforms.uCenter.y}set centerY(t){this.uniforms.uCenter.y=t}get innerRadius(){return this.uniforms.uRadii[0]}set innerRadius(t){this.uniforms.uRadii[0]=t}get radius(){return this.uniforms.uRadii[1]}set radius(t){this.uniforms.uRadii[1]=t<0||t===1/0?-1:t}};FP(brt,"DEFAULT_OPTIONS",{strength:.1,center:{x:0,y:0},innerRadius:0,radius:-1,maxKernelSize:32});class GP{constructor(t){this._ink=t.ink;let e=t.foreground,s=t.background;e=e.replace("#",""),s=s.replace("#",""),this._foreGround=parseInt(e,16),this._backGround=parseInt(s,16),this._colorTransform=null,this._rgb=parseInt(e,16),this._r=this._rgb>>16&255,this._g=this._rgb>>8&255,this._b=this._rgb>>0&255,this._redMultiplier=this._r/255*1,this._greenMultiplier=this._g/255*1,this._blueMultiplier=this._b/255*1,this._alphaMultiplier=1,this._paletteIsGrayscale=!0,this._ink===37&&(this._alphaMultiplier=.5,this._paletteIsGrayscale=!1),this._colorTransform=new Jx({red:this._r/255,green:this._g/255,blue:this._b/255,alpha:this._alphaMultiplier}),this._colorMap=this.generatePaletteMapForGrayscale(this._backGround,this._foreGround)}get ink(){return this._ink}get colorTransform(){return this._colorTransform}get reds(){return this._colorMap.get("reds")}get greens(){return this._colorMap.get("greens")}get blues(){return this._colorMap.get("blues")}get alphas(){return this._colorMap.get("alphas")}get paletteIsGrayscale(){return this._paletteIsGrayscale}generatePaletteMapForGrayscale(t,e){const s=t>>24&255,r=t>>16&255,n=t>>8&255,a=t&255,o=e>>24&255,u=e>>16&255,l=e>>8&255,c=e&255,h=(o-s)/255,_=(u-r)/255,d=(l-n)/255,f=(c-a)/255,p=new Map,g=[];let m=s,O=r,y=n,C=a;for(let P=0;P<256;P++){m+=h,O+=_,y+=d,C+=f;const L=Math.max(0,Math.min(255,Math.round(m))),N=Math.max(0,Math.min(255,Math.round(O))),F=Math.max(0,Math.min(255,Math.round(y))),x=Math.max(0,Math.min(255,Math.round(C))),U=L<<24|N<<16|F<<8|x;g.push(U)}return p.set("alphas",g),p.set("reds",g),p.set("greens",g),p.set("blues",g),p}}class BP{constructor(t){this._offset=t.offset}get offset(){return this._offset}}class kP{constructor(t,e){this._animation=t,this._id=e.id,this._ink=e.ink,this._member=e.member,this._hasStaticY=!!e.staticY,this._hasDirections=!!e.directions,this._dx=[],this._dy=[],this._dz=[];const s=e.directionList;if(s&&s.length)for(const r of s){const n=r.id;n!==void 0&&(this._dx[n]=r.dx||0,this._dy[n]=r.dy||0,this._dz[n]=r.dz||0)}}getDirectionOffsetX(t){return t<this._dx.length?this._dx[t]:0}getDirectionOffsetY(t){return t<this._dy.length?this._dy[t]:0}getDirectionOffsetZ(t){return t<this._dz.length?this._dz[t]:0}get animation(){return this._animation}get id(){return this._id}get ink(){return this._ink}get member(){return this._member}get hasDirections(){return this._hasDirections}get hasStaticY(){return this._hasStaticY}}const yo=class yo{constructor(t,e){if(this._id=e.name,this._description=this._id,this._frames=[],this._spriteData=null,this._avatarData=null,this._directionData=null,this._removeData=null,this._a
|
||
|
* howler.js v2.2.4
|
||
|
* howlerjs.com
|
||
|
*
|
||
|
* (c) 2013-2020, James Simpson of GoldFire Studios
|
||
|
* goldfirestudios.com
|
||
|
*
|
||
|
* MIT License
|
||
|
*/(function(i){(function(){var t=function(){this.init()};t.prototype={init:function(){var h=this||e;return h._counter=1e3,h._html5AudioPool=[],h.html5PoolSize=10,h._codecs={},h._howls=[],h._muted=!1,h._volume=1,h._canPlayEvent="canplaythrough",h._navigator=typeof window<"u"&&window.navigator?window.navigator:null,h.masterGain=null,h.noAudio=!1,h.usingWebAudio=!0,h.autoSuspend=!0,h.ctx=null,h.autoUnlock=!0,h._setup(),h},volume:function(h){var _=this||e;if(h=parseFloat(h),_.ctx||c(),typeof h<"u"&&h>=0&&h<=1){if(_._volume=h,_._muted)return _;_.usingWebAudio&&_.masterGain.gain.setValueAtTime(h,e.ctx.currentTime);for(var d=0;d<_._howls.length;d++)if(!_._howls[d]._webAudio)for(var f=_._howls[d]._getSoundIds(),p=0;p<f.length;p++){var g=_._howls[d]._soundById(f[p]);g&&g._node&&(g._node.volume=g._volume*h)}return _}return _._volume},mute:function(h){var _=this||e;_.ctx||c(),_._muted=h,_.usingWebAudio&&_.masterGain.gain.setValueAtTime(h?0:_._volume,e.ctx.currentTime);for(var d=0;d<_._howls.length;d++)if(!_._howls[d]._webAudio)for(var f=_._howls[d]._getSoundIds(),p=0;p<f.length;p++){var g=_._howls[d]._soundById(f[p]);g&&g._node&&(g._node.muted=h?!0:g._muted)}return _},stop:function(){for(var h=this||e,_=0;_<h._howls.length;_++)h._howls[_].stop();return h},unload:function(){for(var h=this||e,_=h._howls.length-1;_>=0;_--)h._howls[_].unload();return h.usingWebAudio&&h.ctx&&typeof h.ctx.close<"u"&&(h.ctx.close(),h.ctx=null,c()),h},codecs:function(h){return(this||e)._codecs[h.replace(/^x-/,"")]},_setup:function(){var h=this||e;if(h.state=h.ctx&&h.ctx.state||"suspended",h._autoSuspend(),!h.usingWebAudio)if(typeof Audio<"u")try{var _=new Audio;typeof _.oncanplaythrough>"u"&&(h._canPlayEvent="canplay")}catch{h.noAudio=!0}else h.noAudio=!0;try{var _=new Audio;_.muted&&(h.noAudio=!0)}catch{}return h.noAudio||h._setupCodecs(),h},_setupCodecs:function(){var h=this||e,_=null;try{_=typeof Audio<"u"?new Audio:null}catch{return h}if(!_||typeof _.canPlayType!="function")return h;var d=_.canPlayType("audio/mpeg;").replace(/^no$/,""),f=h._navigator?h._navigator.userAgent:"",p=f.match(/OPR\/(\d+)/g),g=p&&parseInt(p[0].split("/")[1],10)<33,m=f.indexOf("Safari")!==-1&&f.indexOf("Chrome")===-1,O=f.match(/Version\/(.*?) /),y=m&&O&&parseInt(O[1],10)<15;return h._codecs={mp3:!!(!g&&(d||_.canPlayType("audio/mp3;").replace(/^no$/,""))),mpeg:!!d,opus:!!_.canPlayType('audio/ogg; codecs="opus"').replace(/^no$/,""),ogg:!!_.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),oga:!!_.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,""),wav:!!(_.canPlayType('audio/wav; codecs="1"')||_.canPlayType("audio/wav")).replace(/^no$/,""),aac:!!_.canPlayType("audio/aac;").replace(/^no$/,""),caf:!!_.canPlayType("audio/x-caf;").replace(/^no$/,""),m4a:!!(_.canPlayType("audio/x-m4a;")||_.canPlayType("audio/m4a;")||_.canPlayType("audio/aac;")).replace(/^no$/,""),m4b:!!(_.canPlayType("audio/x-m4b;")||_.canPlayType("audio/m4b;")||_.canPlayType("audio/aac;")).replace(/^no$/,""),mp4:!!(_.canPlayType("audio/x-mp4;")||_.canPlayType("audio/mp4;")||_.canPlayType("audio/aac;")).replace(/^no$/,""),weba:!!(!y&&_.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),webm:!!(!y&&_.canPlayType('audio/webm; codecs="vorbis"').replace(/^no$/,"")),dolby:!!_.canPlayType('audio/mp4; codecs="ec-3"').replace(/^no$/,""),flac:!!(_.canPlayType("audio/x-flac;")||_.canPlayType("audio/flac;")).replace(/^no$/,"")},h},_unlockAudio:function(){var h=this||e;if(!(h._audioUnlocked||!h.ctx)){h._audioUnlocked=!1,h.autoUnlock=!1,!h._mobileUnloaded&&h.ctx.sampleRate!==44100&&(h._mobileUnloaded=!0,h.unload()),h._scratchBuffer=h.ctx.createBuffer(1,1,22050);var _=function(d){for(;h._html5AudioPool.length<h.html5PoolSize;)try{var f=new Audio;f._unlocked=!0,h._releaseHtml5Audio(f)}catch{h.noAudio=!0;break}for(var p=0;p<h._howls.length;p++)if(!h._howls[p]._webAudio)for(var g=h._howls[p]._getSoundIds(),m=0;m<g.length;m++){var O=h._howls[p]._soundById(g[m]);O&&O._node&&!O._node._unlocked&&(O._node._unlocked=!0,O._node.load())}h._autoResume();var y=h.ctx.createBufferSource();y.buffer=h._scratchBuffe
|
||
|
* Spatial Plugin - Adds support for stereo and 3D audio where Web Audio is supported.
|
||
|
*
|
||
|
* howler.js v2.2.4
|
||
|
* howlerjs.com
|
||
|
*
|
||
|
* (c) 2013-2020, James Simpson of GoldFire Studios
|
||
|
* goldfirestudios.com
|
||
|
*
|
||
|
* MIT License
|
||
|
*/(function(){HowlerGlobal.prototype._pos=[0,0,0],HowlerGlobal.prototype._orientation=[0,0,-1,0,1,0],HowlerGlobal.prototype.stereo=function(e){var s=this;if(!s.ctx||!s.ctx.listener)return s;for(var r=s._howls.length-1;r>=0;r--)s._howls[r].stereo(e);return s},HowlerGlobal.prototype.pos=function(e,s,r){var n=this;if(!n.ctx||!n.ctx.listener)return n;if(s=typeof s!="number"?n._pos[1]:s,r=typeof r!="number"?n._pos[2]:r,typeof e=="number")n._pos=[e,s,r],typeof n.ctx.listener.positionX<"u"?(n.ctx.listener.positionX.setTargetAtTime(n._pos[0],Howler.ctx.currentTime,.1),n.ctx.listener.positionY.setTargetAtTime(n._pos[1],Howler.ctx.currentTime,.1),n.ctx.listener.positionZ.setTargetAtTime(n._pos[2],Howler.ctx.currentTime,.1)):n.ctx.listener.setPosition(n._pos[0],n._pos[1],n._pos[2]);else return n._pos;return n},HowlerGlobal.prototype.orientation=function(e,s,r,n,a,o){var u=this;if(!u.ctx||!u.ctx.listener)return u;var l=u._orientation;if(s=typeof s!="number"?l[1]:s,r=typeof r!="number"?l[2]:r,n=typeof n!="number"?l[3]:n,a=typeof a!="number"?l[4]:a,o=typeof o!="number"?l[5]:o,typeof e=="number")u._orientation=[e,s,r,n,a,o],typeof u.ctx.listener.forwardX<"u"?(u.ctx.listener.forwardX.setTargetAtTime(e,Howler.ctx.currentTime,.1),u.ctx.listener.forwardY.setTargetAtTime(s,Howler.ctx.currentTime,.1),u.ctx.listener.forwardZ.setTargetAtTime(r,Howler.ctx.currentTime,.1),u.ctx.listener.upX.setTargetAtTime(n,Howler.ctx.currentTime,.1),u.ctx.listener.upY.setTargetAtTime(a,Howler.ctx.currentTime,.1),u.ctx.listener.upZ.setTargetAtTime(o,Howler.ctx.currentTime,.1)):u.ctx.listener.setOrientation(e,s,r,n,a,o);else return l;return u},Howl.prototype.init=function(e){return function(s){var r=this;return r._orientation=s.orientation||[1,0,0],r._stereo=s.stereo||null,r._pos=s.pos||null,r._pannerAttr={coneInnerAngle:typeof s.coneInnerAngle<"u"?s.coneInnerAngle:360,coneOuterAngle:typeof s.coneOuterAngle<"u"?s.coneOuterAngle:360,coneOuterGain:typeof s.coneOuterGain<"u"?s.coneOuterGain:0,distanceModel:typeof s.distanceModel<"u"?s.distanceModel:"inverse",maxDistance:typeof s.maxDistance<"u"?s.maxDistance:1e4,panningModel:typeof s.panningModel<"u"?s.panningModel:"HRTF",refDistance:typeof s.refDistance<"u"?s.refDistance:1,rolloffFactor:typeof s.rolloffFactor<"u"?s.rolloffFactor:1},r._onstereo=s.onstereo?[{fn:s.onstereo}]:[],r._onpos=s.onpos?[{fn:s.onpos}]:[],r._onorientation=s.onorientation?[{fn:s.onorientation}]:[],e.call(this,s)}}(Howl.prototype.init),Howl.prototype.stereo=function(e,s){var r=this;if(!r._webAudio)return r;if(r._state!=="loaded")return r._queue.push({event:"stereo",action:function(){r.stereo(e,s)}}),r;var n=typeof Howler.ctx.createStereoPanner>"u"?"spatial":"stereo";if(typeof s>"u")if(typeof e=="number")r._stereo=e,r._pos=[e,0,0];else return r._stereo;for(var a=r._getSoundIds(s),o=0;o<a.length;o++){var u=r._soundById(a[o]);if(u)if(typeof e=="number")u._stereo=e,u._pos=[e,0,0],u._node&&(u._pannerAttr.panningModel="equalpower",(!u._panner||!u._panner.pan)&&t(u,n),n==="spatial"?typeof u._panner.positionX<"u"?(u._panner.positionX.setValueAtTime(e,Howler.ctx.currentTime),u._panner.positionY.setValueAtTime(0,Howler.ctx.currentTime),u._panner.positionZ.setValueAtTime(0,Howler.ctx.currentTime)):u._panner.setPosition(e,0,0):u._panner.pan.setValueAtTime(e,Howler.ctx.currentTime)),r._emit("stereo",u._id);else return u._stereo}return r},Howl.prototype.pos=function(e,s,r,n){var a=this;if(!a._webAudio)return a;if(a._state!=="loaded")return a._queue.push({event:"pos",action:function(){a.pos(e,s,r,n)}}),a;if(s=typeof s!="number"?0:s,r=typeof r!="number"?-.5:r,typeof n>"u")if(typeof e=="number")a._pos=[e,s,r];else return a._pos;for(var o=a._getSoundIds(n),u=0;u<o.length;u++){var l=a._soundById(o[u]);if(l)if(typeof e=="number")l._pos=[e,s,r],l._node&&((!l._panner||l._panner.pan)&&t(l,"spatial"),typeof l._panner.positionX<"u"?(l._panner.positionX.setValueAtTime(e,Howler.ctx.currentTime),l._panner.positionY.setValueAtTime(s,Howler.ctx.currentTime),l._panner.positionZ.setValueAtTime(r,Howler.ctx.currentTime)):l._panner.setPosition(e,s,r)),a._emit("pos",l._id);else
|