{"layers":[{"breakpoints":[],"visible":true,"aspectRatio":1,"userDownsample":1,"layerType":"effect","type":"gradient","usesPingPong":false,"texture":false,"animating":false,"mouseMomentum":0,"mouseSpring":0,"isMask":0,"compiledFragmentShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec2 vTextureCoord;uniform vec2 uMousePos;const float PI = 3.14159265359;vec2 rotate(vec2 coord, float angle) {\nfloat s = sin(angle);\nfloat c = cos(angle);\nreturn vec2(\ncoord.x * c - coord.y * s,\ncoord.x * s + coord.y * c\n);\n}out vec4 fragColor;vec3 getBgColor(vec2 uv) {return vec3(0, 0, 0);\n}void main() {vec2 uv = vTextureCoord;\nvec2 pos = vec2(0.5, 0.5) + mix(vec2(0), (uMousePos-0.5), 0.0000);\nuv -= pos;\nuv /= max(0.5000*2., 1e-5);\nuv = rotate(uv, (0.0000 - 0.5) * 2. * PI);\nvec4 color = vec4(getBgColor(uv), 1.0) * 1.0000;\nfragColor = color;\n}"],"compiledVertexShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision mediump float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvTextureCoord = aTextureCoord;\n}"],"speed":0.25,"trackMouse":0,"trackAxes":"xy","data":{"downSample":0.5,"depth":false,"uniforms":{},"isBackground":true},"id":"570613b7-ad5a-4cef-85a4-982288a9bd3b","publicId":"gradient"},{"breakpoints":[{"max":null,"name":"Desktop","min":992,"props":{"fitToCanvas":0}},{"props":{"fitToCanvas":1},"min":576,"name":"Tablet","max":991},{"max":575,"name":"Mobile","min":0,"props":{"fitToCanvas":1}}],"aspectRatio":1.5796897038081805,"userDownsample":1,"states":{"appear":[{"local":{"pendingChanges":{},"changeDebouncer":null,"dragSession":null},"type":"appear","id":"6e3e26a9-b86c-49ca-984f-64a9f64b4b76","prop":"opacity","transition":{"ease":"easeInOutQuad","duration":1000,"delay":0},"complete":false,"progress":0,"value":0,"endValue":1,"initialized":false,"breakpoints":[],"loop":"none","loopDelay":0,"uniformData":{"type":"1f","name":"uOpacity","value":1}}],"scroll":[],"hover":[],"mousemove":[]},"opacity":1,"effects":["ce7fc62f-3c16-4f28-b397-0268992df679","3d651fdf-38ca-4b9e-813d-8efab46729c9","db9de959-e6a8-41e9-b206-bdee0967b73a"],"anchorPoint":8,"mask":0,"maskInvert":0,"maskDepth":0,"maskDepthLayer":0,"layerType":"image","width":2822.9055007052184,"widthMode":1,"height":1786.9999999999998,"heightMode":2,"left":0.5,"top":0.5,"src":"/assets/unicorn/hero-art.webp","imageNaturalSize":{"type":"Vec2","_x":3360,"_y":2127},"compiledFragmentShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec2 vTextureCoord;\nin vec3 vVertexPosition;uniform sampler2D uSourceImage;\nuniform int uFitToCanvas;uniform vec2 uArtboardResolution;\nuniform vec2 uMousePos;const float TAU = 6.28318530718;\nconst float PI = 3.14159265359;out vec4 fragColor;vec2 rotate2D(vec2 p, float angle) {\nfloat s = sin(angle);\nfloat c = cos(angle);\nreturn vec2(p.x * c - p.y * s, p.x * s + p.y * c);\n}vec2 getAnchorOffsets() {\nreturn vec2(0.5, 0.5);\n}vec4 sampleImage(vec2 canvasUV, vec2 mouseOffset, vec2 mouseRotOffset) {\nvec2 canvasPos = vec2(canvasUV.x * uArtboardResolution.x, (1.0 - canvasUV.y) * uArtboardResolution.y);\nvec2 imageUV;\nif (uFitToCanvas == 1) {\nfloat imageAspect = vec2(3360, 2127).x / vec2(3360, 2127).y;\nfloat canvasAspect = uArtboardResolution.x / uArtboardResolution.y;\nvec2 fitSize = vec2(\n(canvasAspect < imageAspect) ? uArtboardResolution.y * imageAspect : uArtboardResolution.x,\n(canvasAspect < imageAspect) ? uArtboardResolution.y : uArtboardResolution.x / imageAspect\n);\nvec2 offset = (uArtboardResolution - fitSize) * 0.5;\nvec2 adjustedPos = canvasPos + mouseOffset;\nimageUV = (adjustedPos - offset) / fitSize;\n} else {\nfloat absWidth = 2822.9055;\nfloat absHeight = 1787.0000 * uArtboardResolution.y;\nabsWidth = absWidth;\nabsHeight = (1 != 2 && 2 == 2) ? absWidth / 1.5797 : absHeight;vec2 elementSizePx = vec2(absWidth, absHeight);\nvec2 elementPosPx = vec2(0.5000, 0.5000) * uArtboardResolution - getAnchorOffsets() * elementSizePx;vec2 centerPos = elementPosPx + (elementSizePx * 0.5);\nvec2 relPos = canvasPos - centerPos + mouseOffset;\nvec2 unrotatedRelPos = rotate2D(relPos, 0.0000 * -TAU);\nvec2 elementPos = unrotatedRelPos + (elementSizePx * 0.5);\nimageUV = elementPos / elementSizePx;\n}\nvec2 flippedUV = vec2(imageUV.x, 1.0 - imageUV.y);\nvec4 color = textureLod(uSourceImage, flippedUV, 0.0);\nif (imageUV.x >= 0.0 && imageUV.x <= 1.0 && imageUV.y >= 0.0 && imageUV.y <= 1.0) {\nreturn color;\n} else {\nreturn vec4(0.0);\n}\n}vec4 applyImageAdjustments(vec4 color) {color.rgb = clamp(color.rgb, 0.0, 1.0);\ncolor.rgb *= color.a;\nreturn color;\n}vec4 getSourceOutput(vec2 uv, vec2 mouseOffsetPx, vec2 mouseRotOffset) {\nvec4 color = sampleImage(uv, mouseOffsetPx, mouseRotOffset);\nreturn applyImageAdjustments(color);\n}void main() {\nvec2 uv = vTextureCoord;\nvec2 mouseOffsetUV = (uMousePos - 0.5) * 0.0000;\nvec2 mouseOffsetPx = mouseOffsetUV;\nvec2 mouseRotOffset = (uMousePos - 0.5) * 0.0000 * PI * 0.5;\nuv -= mouseOffsetUV;\nfragColor = getSourceOutput(uv, mouseOffsetPx, mouseRotOffset);\n}"],"compiledVertexShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;\nuniform vec2 uMousePos;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\nfloat angleX = uMousePos.y * 0.5 - 0.25;\nfloat angleY = (1.-uMousePos.x) * 0.5 - 0.25;mat4 rotateX = mat4(1.0, 0.0, 0.0, 0.0,\n0.0, cos(angleX), -sin(angleX), 0.0,\n0.0, sin(angleX), cos(angleX), 0.0,\n0.0, 0.0, 0.0, 1.0);\nmat4 rotateY = mat4(cos(angleY), 0.0, sin(angleY), 0.0,\n0.0, 1.0, 0.0, 0.0,\n-sin(angleY), 0.0, cos(angleY), 0.0,\n0.0, 0.0, 0.0, 1.0);mat4 rotationMatrix = rotateX * rotateY;\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvVertexPosition = (rotationMatrix * vec4(aVertexPosition, 1.0)).xyz;\nvTextureCoord = (vec4(aTextureCoord, 0.0, 1.0)).xy;\n}"],"data":{"uniforms":{"artboardResolution":{"name":"uArtboardResolution","type":"2f","value":{"type":"Vec2","_x":1440,"_y":900}},"aspectRatio":{"name":"uAspectRatio","type":"1f","value":1.5796897038081805},"fitToCanvas":{"name":"uFitToCanvas","type":"1i","value":0}},"elementOpacity":1,"compositeShader":{"fragmentShader":"#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;\nin vec2 vTextureCoord;\nin vec3 vVertexPosition;uniform sampler2D uBgTexture;\nuniform sampler2D uTexture;\nuniform float uOpacity;const float PI = 3.14159265359;out vec4 fragColor;vec4 getNormalOutput(vec4 color, vec4 background) {\nreturn mix(background, color + background * (1.0 - color.a), uOpacity);\n}vec4 getOutputByMode(vec4 color, vec4 background) {\nreturn getNormalOutput(color, background);\n}void main() {\nvec2 uv = vTextureCoord;\nvec2 pos = vec2(0);uv -= pos;vec4 background = vec4(0);background = texture(uBgTexture, vTextureCoord);\nvec4 color = texture(uTexture, uv);vec4 col = getOutputByMode(color, background);fragColor = col;\n}","vertexShader":"#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;\nuniform mat4 uTextureMatrix;\nuniform vec2 uMousePos;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\nfloat angleX = uMousePos.y * 0.5 - 0.25;\nfloat angleY = (1.-uMousePos.x) * 0.5 - 0.25;mat4 rotateX = mat4(1.0, 0.0, 0.0, 0.0,\n0.0, cos(angleX), -sin(angleX), 0.0,\n0.0, sin(angleX), cos(angleX), 0.0,\n0.0, 0.0, 0.0, 1.0);\nmat4 rotateY = mat4(cos(angleY), 0.0, sin(angleY), 0.0,\n0.0, 1.0, 0.0, 0.0,\n-sin(angleY), 0.0, cos(angleY), 0.0,\n0.0, 0.0, 0.0, 1.0);mat4 rotationMatrix = rotateX * rotateY;\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvVertexPosition = (rotationMatrix * vec4(aVertexPosition, 1.0)).xyz;\nvTextureCoord = (uTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;\n}"},"compositeUniforms":{"resolution":{"name":"uResolution","type":"2f","value":{"type":"Vec2","_x":1080,"_y":1080}},"opacity":{"name":"uOpacity","type":"1f","value":1},"mousePos":{"name":"uMousePos","type":"2f","value":{"type":"Vec2","_x":0.5,"_y":0.5}}}},"id":"4cf0c4e1-8be4-431e-8c5a-15b90aa1c6f5","publicId":"image"},{"breakpoints":[],"visible":true,"aspectRatio":1,"userDownsample":1,"layerType":"effect","type":"glyphDither","usesPingPong":false,"texture":{"src":"https://assets.unicorn.studio/media/glyphs/porthole.png","sampler":"uSprite"},"parentLayer":"db9de959-e6a8-41e9-b206-bdee0967b73a","animating":false,"mouseMomentum":0,"mouseSpring":0,"isMask":0,"compiledFragmentShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec3 vVertexPosition;\nin vec2 vTextureCoord;\nuniform sampler2D uTexture;\nuniform sampler2D uSprite;uniform vec2 uMousePos;\nuniform vec2 uResolution;vec4 applyLayerMixAlpha(vec4 color, vec4 bg, float amount) {\nreturn mix(bg, color, amount);\n}out vec4 fragColor;const vec3 LUMA = vec3(0.2126, 0.7152, 0.0722);float getLuminance(vec3 color) {\nreturn dot(color, LUMA);\n}float getGridSize() {\nreturn mix(0.05, 0.005, 1.0000);\n}vec2 getCellSize(float gridSize, float aspectRatio, float aspectCorrection) {\nfloat baseGrid = 1.0 / gridSize;\nreturn vec2(1.0 / (baseGrid * aspectRatio), 1.0 / baseGrid) * aspectCorrection;\n}vec2 getPixelatedCoord(vec2 uv, vec2 pos, vec2 cellSize) {\nvec2 offsetUv = uv - pos;\nvec2 cell = floor(offsetUv / cellSize);\nvec2 cellCenter = (cell + 0.5) * cellSize;\nreturn cellCenter + pos;\n}ivec2 getGlyphTextureSize() {\nivec2 glyphTextureSize = textureSize(uSprite, 0);return glyphTextureSize;\n}float getGlyphHeight(ivec2 glyphTextureSize) {\nreturn float(glyphTextureSize.y);\n}float getGlyphCount(ivec2 glyphTextureSize) {\nfloat glyphHeight = getGlyphHeight(glyphTextureSize);\nreturn max(1.0, float(glyphTextureSize.x) / glyphHeight);\n}float getGlyphSelection(float luminance, float glyphCount) {\nreturn clamp(floor(luminance * glyphCount), 0.0, glyphCount - 1.0);\n}float getPhasedGlyphSelection(float luminance, float glyphCount, float gamma) {\nfloat glyphSelection = clamp(floor(luminance * glyphCount * gamma), 0.0, glyphCount - 1.0);\nfloat phaseOffset = floor(0.0000 * glyphCount + 0.5);\nreturn mod(glyphSelection + phaseOffset, glyphCount);\n}vec2 getGlyphSheetUv(vec2 uv, vec2 pos, float aspectRatio, float aspectCorrection, float gridSize, float glyphHeight, float glyphSelection, float glyphCount) {\nfloat normalizedSpriteSizeX = 1.0 / glyphCount;\nfloat normalizedSpriteSizeY = 1.0;\nvec2 spriteSize = vec2(glyphHeight / aspectRatio, glyphHeight) * (gridSize / glyphHeight) * aspectCorrection;\nvec2 localOffset = mod(uv - pos, spriteSize) / spriteSize;\nfloat inset = 0.5 / glyphHeight;\nlocalOffset = clamp(localOffset, inset, 1.0 - inset);return vec2(\nglyphSelection * normalizedSpriteSizeX + localOffset.x * normalizedSpriteSizeX,\nlocalOffset.y * normalizedSpriteSizeY\n);\n}vec4 sampleGlyphColor(vec2 glyphUv) {\nvec4 glyphColor = vec4(0.0);glyphColor = texture(uSprite, glyphUv);return glyphColor;\n}void main() {\nvec2 uv = vTextureCoord;\nvec2 pos = vec2(0.5, 0.5) + mix(vec2(0), (uMousePos-0.5), 0.0000);\nfloat aspectRatio = uResolution.x / uResolution.y;\nfloat aspectCorrection = mix(aspectRatio, 1./aspectRatio, 0.5);\nfloat gridSize = getGridSize();\nvec2 cellSize = getCellSize(gridSize, aspectRatio, aspectCorrection);\nvec2 pixelatedCoord = getPixelatedCoord(uv, pos, cellSize);\nvec4 bg = texture(uTexture, vTextureCoord);\nvec4 color = texture(uTexture, pixelatedCoord);float luminance = getLuminance(color.rgb);\nluminance = mix(luminance, 1.0 - luminance, float(0));\nfloat gamma = pow(mix(0.2, 2.2, 0.5300), 2.2);\nivec2 glyphTextureSize = getGlyphTextureSize();\nfloat glyphHeight = getGlyphHeight(glyphTextureSize);\nfloat glyphCount = getGlyphCount(glyphTextureSize);\nfloat glyphSelection = getGlyphSelection(luminance, glyphCount);\nfloat phasedGlyphSelection = getPhasedGlyphSelection(luminance, glyphCount, gamma);\nvec2 spriteSheetUV = getGlyphSheetUv(uv, pos, aspectRatio, aspectCorrection, gridSize, glyphHeight, phasedGlyphSelection, glyphCount);\nvec4 spriteColor = sampleGlyphColor(spriteSheetUV);\nfloat alpha = smoothstep(0.0, 1.0, spriteColor.r);vec3 cc = (color.rgb - glyphSelection * 0.04) * 1.4;\nvec3 col = cc;vec3 result = mix(mix(vec3(0.0), vec3(1.0), float(0)), col, alpha);\ncolor.rgb = result;\ncolor = applyLayerMixAlpha(color, bg, 1.0000);\nfragColor = color;}"],"compiledVertexShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision mediump float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;\nuniform mat4 uTextureMatrix;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvTextureCoord = (uTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;\n}"],"trackMouse":0,"trackAxes":"xy","data":{"depth":false,"uniforms":{},"isBackground":false,"texture":{"name":"Preset glyphs","src":"https://assets.unicorn.studio/media/glyphs/porthole.png","sampler":"uSprite"}},"id":"eda520a3-d5d5-4e3a-805a-977c9cb4362f","publicId":"glyph_dither"},{"breakpoints":[],"visible":true,"aspectRatio":1,"userDownsample":1,"layerType":"effect","type":"mouse","usesPingPong":true,"texture":false,"parentLayer":"ce7fc62f-3c16-4f28-b397-0268992df679","animating":false,"mouseMomentum":0,"mouseSpring":0,"isMask":0,"compiledFragmentShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec2 vTextureCoord;\nin vec3 vVertexPosition;uniform sampler2D uTexture;\nuniform sampler2D uPingPongTexture;\nuniform vec2 uResolution;const float PI = 3.14159265359;\nconst float ITERATIONS = 24.0;float getGaussianWeight(int index) {\nswitch(index) {\ncase 0: return 0.7978845608028654;\ncase 1: return 0.795118932516684;\ncase 2: return 0.7868794322038799;\ncase 3: return 0.7733362336056986;\ncase 4: return 0.7547664553859864;\ncase 5: return 0.7315447328280048;\ncase 6: return 0.704130653528599;\ncase 7: return 0.6730536454899063;\ncase 8: return 0.6388960110447045;\ncase 9: return 0.6022748643096089;\ncase 10: return 0.5638237508206051;\ncase 11: return 0.5241747061566029;\ncase 12: return 0.48394144903828673;\ncase 13: return 0.443704309411472;\ncase 14: return 0.40399737110811773;\ncase 15: return 0.36529817077804383;\ncase 16: return 0.3280201493519873;\ncase 17: return 0.29250790855907144;\ncase 18: return 0.2590351913317835;\ncase 19: return 0.2278053882403838;\ncase 20: return 0.19895427758549736;\ncase 21: return 0.17255463765302306;\ncase 22: return 0.1486223271179862;\ncase 23: return 0.12712341303392466;\ndefault: return 0.0;\n}\n}out vec4 fragColor;vec3 decodeTrailField(vec4 color) {\nfloat density = color.b;\nif (density <= 0.0001) {\nreturn vec3(0.0);\n}\nreturn vec3(color.rg * 2.0 - 1.0, density);\n}vec3 chromatic_aberration(vec3 color, vec2 uv, vec2 offset) {\nvec4 left = texture(uTexture, uv - offset);\nvec4 right = texture(uTexture, uv + offset);color.r = left.r;\ncolor.b = right.b;return color;\n}vec4 blurTrail(vec2 uv, vec2 mouseDir) {\nif (dot(mouseDir, mouseDir) <= 1e-8) {\nreturn texture(uTexture, uv);\n}\nvec2 distorted = mouseDir * 0.4;\nfloat total_weight = 0.0;\nvec4 color = vec4(0);\nfloat scale = 0.0001 + 0.4900 * 0.5;for (int i = 0; i <= 9; i++) {\nfloat weight = getGaussianWeight(i);\nvec2 offset = distorted * (1.5 + scale) * mix(1.0, float(i) / ITERATIONS, scale);\nvec2 st = uv - offset;\nvec4 samp = texture(uTexture, st);\nsamp.rgb = chromatic_aberration(samp.rgb, st, offset * 0.2500 * 0.12);\ncolor += weight * samp;\ntotal_weight += weight;\n}return color / total_weight;\n}vec4 getTrailColor(vec2 uv, vec2 mouseDir, float strength, float aspectRatio) {\nvec4 color = vec4(0);return blurTrail(uv, mouseDir);\n}void main() {\nvec2 uv = vTextureCoord;\nvec2 pingpongUv = uv;\nfloat aspectRatio = uResolution.x / uResolution.y;vec3 mouseTrail = decodeTrailField(texture(uPingPongTexture, pingpongUv));\nfloat strength = mouseTrail.z * (0.0100 * 1.5);\nvec2 direction = length(mouseTrail.xy) > 0.0001 ? normalize(mouseTrail.xy) : vec2(0.0);\nvec2 mouseDir = direction * strength;vec4 color = getTrailColor(uv, mouseDir, strength, aspectRatio);\nfragColor = color;\n}","#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;in vec3 vVertexPosition;\nin vec2 vTextureCoord;uniform sampler2D uPingPongTexture;\nuniform vec2 uPreviousMousePos;uniform vec2 uMousePos;\nuniform vec2 uResolution;const float PI = 3.14159265359;out vec4 fragColor;vec3 decodeTrailField(vec4 color) {\nfloat density = color.b;\nif (density <= 0.0001) {\nreturn vec3(0.0);\n}\nreturn vec3(color.rg * 2.0 - 1.0, density);\n}vec4 encodeTrailField(vec2 vector, float density) {\ndensity = clamp(density, 0.0, 1.0);\nif (density <= 0.0001) {\nreturn vec4(0.5, 0.5, 0.0, 1.0);\n}\nvec2 packedVector = clamp(vector, vec2(-1.0), vec2(1.0)) * 0.5 + 0.5;\nreturn vec4(packedVector, density, 1.0);\n}vec3 crossBlurTrailField(sampler2D tex, vec2 uv, float radius) {\nvec3 field = decodeTrailField(texture(tex, uv)) * 0.4;\nfield += decodeTrailField(texture(tex, uv + vec2(radius, 0.0))) * 0.15;\nfield += decodeTrailField(texture(tex, uv + vec2(-radius, 0.0))) * 0.15;\nfield += decodeTrailField(texture(tex, uv + vec2(0.0, radius))) * 0.15;\nfield += decodeTrailField(texture(tex, uv + vec2(0.0, -radius))) * 0.15;\nreturn field;\n}void main() {\nfloat aspectRatio = uResolution.x / uResolution.y;\nvec2 aspectVec = vec2(aspectRatio, 1.0);\nvec2 uv = vTextureCoord;\nvec2 correctedUv = uv * aspectVec;vec2 dir = (uMousePos - uPreviousMousePos) * aspectVec;\nfloat dist = length(dir);\nif (dist > 0.0) {\ndir = dir / dist;\n} else {\ndir = vec2(1.0, 0.0);\n}float rad = 0.2500 * 0.6 * mix(aspectRatio, 1.0, 0.5);\nvec3 lastField = vec3(0.0);float t = dist > 0.0 ? clamp(dot(correctedUv - uPreviousMousePos * aspectVec, dir) / dist, 0.0, 1.0) : 0.0;\nvec2 closestPoint = mix(uPreviousMousePos, uMousePos, t) * aspectVec;\nfloat distanceToLine = distance(correctedUv, closestPoint);float shrink = mix(0.5, 1.0, clamp(dist * 20.0, 0.0, 1.0));\nrad *= shrink;float s = 1.0 - smoothstep(rad * 0.0000, rad, distanceToLine);s = s * s;vec2 sampleUv = mix(uv, uv / (1.0 + 0.0000 * 0.03) + 0.0000 * 0.015, 0.0000);lastField = crossBlurTrailField(uPingPongTexture, sampleUv, 0.003);\nfloat decay = pow(0.2300, 0.1);\nvec2 decayedVector = lastField.xy * decay;\nfloat decayedDensity = lastField.z * decay;\nfloat currentDensity = clamp(min(1.0, dist * 10.0) * s, 0.0, 1.0);\nvec2 currentVector = dir * currentDensity;vec2 drawVector = decayedVector + currentVector;\nfloat drawDensity = max(decayedDensity, currentDensity);fragColor = encodeTrailField(drawVector, drawDensity);\n}"],"compiledVertexShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision mediump float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;\nuniform mat4 uTextureMatrix;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvTextureCoord = (uTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;\n}","#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision mediump float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvTextureCoord = aTextureCoord;\n}"],"data":{"depth":false,"uniforms":{},"isBackground":false},"id":"31583dca-4169-4463-a438-8a84653b774b","publicId":"mouse_trail"},{"breakpoints":[],"visible":true,"aspectRatio":1,"userDownsample":1,"layerType":"effect","type":"dither","usesPingPong":false,"texture":false,"parentLayer":"3d651fdf-38ca-4b9e-813d-8efab46729c9","animating":false,"mouseMomentum":0,"mouseSpring":0,"isMask":0,"compiledFragmentShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision highp float;\nprecision highp int;in vec3 vVertexPosition;\nin vec2 vTextureCoord;uniform sampler2D uTexture;\nuniform sampler2D uBlueNoise;uniform float uTime;uniform vec2 uResolution;uvec2 pcg2d(uvec2 v) {\nv = v * 1664525u + 1013904223u;\nv.x += v.y * v.y * 1664525u + 1013904223u;\nv.y += v.x * v.x * 1664525u + 1013904223u;\nv ^= v >> 16;\nv.x += v.y * v.y * 1664525u + 1013904223u;\nv.y += v.x * v.x * 1664525u + 1013904223u;\nreturn v;\n}float randFibo(vec2 p) {\nuvec2 v = floatBitsToUint(p);\nv = pcg2d(v);\nuint r = v.x ^ v.y;\nreturn float(r) / float(0xffffffffu);\n}const int MAX_LEVEL = 4;\nconst float TAU = 6.28318530718;float getBlueNoise(vec2 st, float delta, float size) {\nivec2 texSize = textureSize(uBlueNoise, 0);\nvec4 blueNoise = texelFetch(uBlueNoise, ivec2(fract(st * (uResolution/size)/vec2(texSize) * vec2(texSize.x/texSize.y, 1.0)) * vec2(texSize)) % texSize, 0);\nreturn mod((blueNoise.r - 0.5) * TAU + (delta * (1.0 / TAU)), TAU) / TAU - 0.005;\n}vec3 dither(vec3 color, vec2 st) {\nfloat delta = floor(uTime);\nvec2 offset = vec2(randFibo(vec2(123,16) + delta), randFibo(vec2(56,96) + delta));\nfloat noise = 0.0;\nnoise = getBlueNoise(st, delta, 2.);\nfloat dither_threshold = max(0.0001, 0.1200);\nfloat num_levels = 1.0 / dither_threshold;\nreturn floor(color * num_levels + noise) / num_levels;\n}out vec4 fragColor;void main() {\nvec2 uv = vTextureCoord;\nfloat delta = floor(uTime);\nvec4 color = texture(uTexture, uv);\ncolor.rgb = mix(color.rgb, dither(color.rgb, vTextureCoord), 0.1400);\nfragColor = color;}"],"compiledVertexShaders":["#version 300 es\n// Copyright (c) Unicorn Studio. Licensed under the Unicorn Studio Commercial License.\n// Unauthorized copying, redistribution, or use in competing products is prohibited.\nprecision mediump float;in vec3 aVertexPosition;\nin vec2 aTextureCoord;uniform mat4 uMVMatrix;\nuniform mat4 uPMatrix;\nuniform mat4 uTextureMatrix;out vec2 vTextureCoord;\nout vec3 vVertexPosition;void main() {\ngl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\nvTextureCoord = (uTextureMatrix * vec4(aTextureCoord, 0.0, 1.0)).xy;\n}"],"speed":0.25,"data":{"depth":false,"uniforms":{},"isBackground":false,"texture":{"src":"https://assets.unicorn.studio/media/blue_noise_med.png","sampler":"uBlueNoise"}},"id":"796fe96f-1daa-433c-9e1a-fb094378b3ad","publicId":"dither"}],"options":{"name":"Copy of Castle hero","fps":60,"dpi":1.5,"scale":1,"includeLogo":false,"isProduction":false,"flatten":false,"freePlan":false,"width":1440,"height":900},"version":"2.2.1","id":"IXwh9ZLHmf9R8zNQHQ27","designName":"Copy of Castle hero","designId":"i2zQGxbKxsPfYXFXAxYd","canvasId":"caeba151-f6e1-4fca-842b-165ce07ae39c","projectName":"Copy of Castle hero","sceneName":"Scene"}