Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
@@ -1,382 +0,0 @@
|
||||
#version 460 core
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uTilt;
|
||||
uniform float uPrismatic;
|
||||
uniform float uSparkle;
|
||||
uniform float uSpecular;
|
||||
uniform float uDiffraction;
|
||||
uniform float uStyle;
|
||||
uniform float uSparkleShapeKind;
|
||||
uniform float uSparklePrimary;
|
||||
uniform float uSparkleSecondary;
|
||||
uniform float uSparkleTertiary;
|
||||
uniform float uOpacity;
|
||||
|
||||
#define TWO_PI 6.28318530718
|
||||
|
||||
// Precomputed rotation matrices reduce repeated sin/cos work in tiled layers.
|
||||
#define ROT_0_78 mat2( 0.71091, 0.70328, -0.70328, 0.71091)
|
||||
#define ROT_M0_5 mat2( 0.87758, -0.47943, 0.47943, 0.87758)
|
||||
#define ROT_1_2 mat2( 0.36236, 0.93204, -0.93204, 0.36236)
|
||||
|
||||
float hash(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
|
||||
float a = hash(i);
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(float h, float s, float v) {
|
||||
vec3 k = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
|
||||
vec3 p = abs(fract(vec3(h) + k) * 6.0 - 3.0);
|
||||
return v * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), s);
|
||||
}
|
||||
|
||||
vec3 rainbow(float phase, float saturation, float value) {
|
||||
return hsv2rgb(fract(phase), saturation, value);
|
||||
}
|
||||
|
||||
float sdBox(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
float sdRegularPolygon(vec2 p, float sides, float radius) {
|
||||
float angle = atan(p.y, p.x);
|
||||
float sector = TWO_PI / sides;
|
||||
return cos(floor(0.5 + angle / sector) * sector - angle) * length(p) - radius;
|
||||
}
|
||||
|
||||
float sparkleStarMask(vec2 p, float points, float innerRatio) {
|
||||
float angle = atan(p.y, p.x);
|
||||
float radius = dot(p, p);
|
||||
float spikes = 0.5 + 0.5 * cos(angle * points);
|
||||
float starRadius = mix(0.34 * innerRatio, 0.34, pow(spikes, 1.4));
|
||||
return smoothstep(0.0009, -0.0009, radius - (starRadius * starRadius));
|
||||
}
|
||||
|
||||
vec2 rotatePoint(vec2 p, float rotation) {
|
||||
float c = cos(rotation);
|
||||
float s = sin(rotation);
|
||||
return vec2(c * p.x - s * p.y, s * p.x + c * p.y);
|
||||
}
|
||||
|
||||
float sparkleRectangleMask(vec2 p, float halfWidth, float halfHeight, float rotation) {
|
||||
vec2 q = rotatePoint(p, rotation);
|
||||
float body = sdBox(q, vec2(halfWidth, halfHeight));
|
||||
float bevel = sdBox(q, vec2(halfWidth * 0.78, halfHeight * 0.78));
|
||||
float bodyMask = smoothstep(0.03, -0.03, body);
|
||||
|
||||
float centerLine = 1.0 - smoothstep(0.0, halfHeight * 1.25, abs(q.y));
|
||||
float endFade = 1.0 - smoothstep(halfWidth * 0.55, halfWidth * 1.05, abs(q.x));
|
||||
float streak = centerLine * endFade;
|
||||
float bevelRing = smoothstep(0.025, -0.025, body) - smoothstep(0.025, -0.025, bevel);
|
||||
return clamp(bodyMask * (0.58 + 0.42 * streak) + bevelRing * 0.25, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float sparklePolygonMask(vec2 p, float sides, float aspectRatio, float rotation) {
|
||||
vec2 q = rotatePoint(p, rotation);
|
||||
q.x /= aspectRatio;
|
||||
float poly = sdRegularPolygon(q, sides, 0.26);
|
||||
return smoothstep(0.03, -0.03, poly);
|
||||
}
|
||||
|
||||
float sparkleShapeMask(vec2 p, vec2 id) {
|
||||
float randomRotation = hash(id + 5.1) * TWO_PI;
|
||||
if (uSparkleShapeKind < 0.5) {
|
||||
return 0.0;
|
||||
}
|
||||
if (uSparkleShapeKind < 1.5) {
|
||||
return sparkleStarMask(p, uSparklePrimary, uSparkleSecondary);
|
||||
}
|
||||
if (uSparkleShapeKind < 2.5) {
|
||||
return sparkleRectangleMask(p, uSparklePrimary, uSparkleSecondary, randomRotation * uSparkleTertiary);
|
||||
}
|
||||
if (uSparkleShapeKind < 3.5) {
|
||||
return sparklePolygonMask(p, uSparklePrimary, uSparkleSecondary, uSparkleTertiary);
|
||||
}
|
||||
if (uSparkleShapeKind < 4.5) {
|
||||
float sides = 5.0 + floor(hash(id + 9.4) * 4.0);
|
||||
float aspect = 0.7 + hash(id + 13.1) * 0.7;
|
||||
return sparklePolygonMask(p, sides, aspect, randomRotation);
|
||||
}
|
||||
return sparkleRectangleMask(p, uSparklePrimary, uSparkleSecondary, randomRotation * uSparkleTertiary);
|
||||
}
|
||||
|
||||
vec3 styleHolographicSilver(vec2 uv, vec2 tilt) {
|
||||
vec2 p = uv * 2.0 - 1.0;
|
||||
vec2 tiltWarp = tilt * 0.18;
|
||||
float flowA = noise(uv * 3.5 + tiltWarp + vec2(dot(uv, vec2(0.25, -0.22))));
|
||||
float flowB = noise(uv * 7.0 - tiltWarp + vec2(dot(uv, vec2(-0.18, 0.21))));
|
||||
vec2 warp = p + 0.25 * vec2(flowA - 0.5, flowB - 0.5);
|
||||
float ribbon = sin(dot(warp, vec2(6.5, 2.8)) + flowA * 5.0 + dot(tilt, vec2(2.2, -1.7)));
|
||||
float plume = sin(length(warp + vec2(flowB - 0.5, flowA - 0.5)) * 9.0 - tilt.x * 3.0 + dot(uv, vec2(1.5, -1.2)));
|
||||
float phase = flowA * 1.8 + ribbon * 0.28 + plume * 0.22;
|
||||
|
||||
vec3 holo = rainbow(phase, 0.72, 1.0);
|
||||
float blend = smoothstep(-0.65, 0.95, ribbon + plume * 0.55);
|
||||
vec3 silver = vec3(0.62, 0.65, 0.70) * (0.85 + 0.15 * flowB);
|
||||
|
||||
return mix(silver, holo, 0.65 * blend);
|
||||
}
|
||||
|
||||
vec3 styleCrackedIce(vec2 uv, vec2 tilt) {
|
||||
float maxZ = -999.0;
|
||||
vec2 bestSlope = vec2(0.0);
|
||||
float bestHash = 0.0;
|
||||
float bestEdge = 1.0;
|
||||
|
||||
vec2 warp = vec2(sin(uv.y * 10.0), cos(uv.x * 10.0)) * 0.05;
|
||||
vec2 baseUV = uv + warp;
|
||||
|
||||
// --- LAYER 1 ---
|
||||
vec2 p1 = baseUV * 12.0;
|
||||
vec2 id1 = floor(p1);
|
||||
vec2 f1 = fract(p1) - 0.5;
|
||||
vec2 slope1 = vec2(hash(id1 + 1.2), hash(id1 + 1.3)) * 2.0 - 1.0;
|
||||
float z1 = dot(f1, slope1) * 3.5;
|
||||
if (z1 > maxZ) {
|
||||
maxZ = z1; bestSlope = slope1; bestHash = hash(id1 + 1.1); bestEdge = min(0.5 - abs(f1.x), 0.5 - abs(f1.y));
|
||||
}
|
||||
|
||||
// --- LAYER 2 (Optimized Rotation) ---
|
||||
vec2 p2 = (ROT_0_78 * baseUV) * 15.0;
|
||||
vec2 id2 = floor(p2);
|
||||
vec2 f2 = fract(p2) - 0.5;
|
||||
vec2 slope2 = vec2(hash(id2 + 2.2), hash(id2 + 2.3)) * 2.0 - 1.0;
|
||||
float z2 = 0.8 + dot(f2, slope2) * 3.5;
|
||||
if (z2 > maxZ) {
|
||||
maxZ = z2; bestSlope = slope2; bestHash = hash(id2 + 2.1); bestEdge = min(0.5 - abs(f2.x), 0.5 - abs(f2.y));
|
||||
}
|
||||
|
||||
// --- LAYER 3 (Optimized Rotation) ---
|
||||
vec2 p3 = (ROT_M0_5 * baseUV) * 18.0;
|
||||
vec2 id3 = floor(p3);
|
||||
vec2 f3 = fract(p3) - 0.5;
|
||||
vec2 slope3 = vec2(hash(id3 + 3.2), hash(id3 + 3.3)) * 2.0 - 1.0;
|
||||
float z3 = 1.6 + dot(f3, slope3) * 3.5;
|
||||
if (z3 > maxZ) {
|
||||
maxZ = z3; bestSlope = slope3; bestHash = hash(id3 + 3.1); bestEdge = min(0.5 - abs(f3.x), 0.5 - abs(f3.y));
|
||||
}
|
||||
|
||||
// --- LAYER 4 (Optimized Rotation) ---
|
||||
vec2 p4 = (ROT_1_2 * baseUV) * 21.0;
|
||||
vec2 id4 = floor(p4);
|
||||
vec2 f4 = fract(p4) - 0.5;
|
||||
vec2 slope4 = vec2(hash(id4 + 4.2), hash(id4 + 4.3)) * 2.0 - 1.0;
|
||||
float z4 = 2.4 + dot(f4, slope4) * 3.5;
|
||||
if (z4 > maxZ) {
|
||||
maxZ = z4; bestSlope = slope4; bestHash = hash(id4 + 4.1); bestEdge = min(0.5 - abs(f4.x), 0.5 - abs(f4.y));
|
||||
}
|
||||
|
||||
// --- VIBRANT COLOR OPTICS ---
|
||||
float alignment = dot(tilt, normalize(bestSlope + vec2(0.001)));
|
||||
float phase = dot(uv, vec2(0.6, -0.4)) + bestHash * 0.6 + alignment * 0.5;
|
||||
float saturation = 0.7 + 0.3 * hash(vec2(bestHash, 6.1));
|
||||
vec3 baseColor = rainbow(phase, saturation, 1.0);
|
||||
|
||||
float lightCycle = sin(alignment * 4.0 + bestHash * TWO_PI + dot(uv, vec2(2.1, -1.7)));
|
||||
float ambient = 0.15 + 0.25 * max(0.0, lightCycle);
|
||||
vec3 finalColor = baseColor * ambient;
|
||||
float flash = pow(max(0.0, lightCycle), 5.0);
|
||||
finalColor += mix(baseColor, vec3(1.0, 0.95, 0.85), 0.6) * flash * 0.55;
|
||||
finalColor += baseColor * smoothstep(0.05, 0.0, bestEdge) * flash * 0.4;
|
||||
|
||||
return finalColor;
|
||||
}
|
||||
|
||||
vec3 styleSilverMosaic(vec2 uv, vec2 tilt) {
|
||||
// Mosaic tile grid.
|
||||
vec2 g = uv * 6.0;
|
||||
vec2 id = floor(g);
|
||||
|
||||
// Center local tile coordinates for radial optics.
|
||||
vec2 f = fract(g) - 0.5;
|
||||
|
||||
// Real foil sheets often alternate the grain of the squares to catch light from all angles.
|
||||
if (mod(id.x + id.y, 2.0) > 0.5) {
|
||||
f = vec2(-f.y, f.x);
|
||||
}
|
||||
|
||||
vec2 radialDir = normalize(f + vec2(0.0001));
|
||||
|
||||
vec2 lightDir = normalize(tilt + vec2(0.001));
|
||||
|
||||
// Radial highlight where tile direction aligns with light direction.
|
||||
float alignment = abs(dot(radialDir, lightDir));
|
||||
|
||||
float highlight = pow(alignment, 12.0);
|
||||
|
||||
float angleDiff = acos(alignment);
|
||||
|
||||
// 2D cross product sign decides which side of the highlight receives hue shift.
|
||||
float side = sign(radialDir.x * lightDir.y - radialDir.y * lightDir.x);
|
||||
|
||||
float basePhase = length(tilt) * 2.5 + dot(uv, vec2(0.9, -0.7));
|
||||
|
||||
float phase = basePhase + side * angleDiff * 1.8;
|
||||
vec3 holoColor = rainbow(phase, 0.85, 1.0);
|
||||
|
||||
// White specular core appears when alignment is nearly perfect.
|
||||
vec3 core = vec3(1.0) * smoothstep(0.98, 1.0, alignment);
|
||||
|
||||
vec3 foilBase = vec3(0.25, 0.27, 0.30);
|
||||
|
||||
vec3 finalColor = foilBase + (holoColor * highlight * 1.5) + (core * 0.8);
|
||||
|
||||
// Tile borders and edge darkening add perceived depth.
|
||||
float edgeX = 0.5 - abs(f.x);
|
||||
float edgeY = 0.5 - abs(f.y);
|
||||
|
||||
float border = smoothstep(0.0, 0.015, min(edgeX, edgeY));
|
||||
|
||||
float dist = length(f);
|
||||
finalColor *= mix(0.7, 1.0, 1.0 - smoothstep(0.0, 0.5, dist) * 0.3);
|
||||
|
||||
return clamp(finalColor * border, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 styleSuperGoldVinyl(vec2 uv, vec2 tilt) {
|
||||
vec2 g = uv * 60.0;
|
||||
vec2 staggered = vec2(g.x + 0.5 * mod(floor(g.y), 2.0), g.y);
|
||||
vec2 f = fract(staggered) - 0.5;
|
||||
|
||||
// Distance-squared masks avoid square roots and preserve circular dots.
|
||||
float d2 = dot(f, f);
|
||||
float dotMask = smoothstep(0.1764, 0.01, d2);
|
||||
float emboss = smoothstep(0.2025, 0.0324, d2);
|
||||
|
||||
float sheen = 0.5 + 0.5 * sin(dot(uv, vec2(18.0, -6.0)) + noise(uv * 6.0) * 2.5 + dot(tilt, vec2(2.4, 1.8)) * 2.0);
|
||||
vec3 gold = vec3(0.84, 0.70, 0.24);
|
||||
vec3 warm = vec3(1.0, 0.88, 0.42);
|
||||
vec3 shadow = vec3(0.18, 0.14, 0.05);
|
||||
|
||||
return gold * (0.75 + 0.25 * sheen) + warm * dotMask * 0.28 + shadow * emboss * 0.08;
|
||||
}
|
||||
|
||||
void main() {
|
||||
// UVs in [0, 1] for global lighting and center-based effects.
|
||||
vec2 uv = FlutterFragCoord().xy / uSize;
|
||||
vec2 center = vec2(0.5, 0.5);
|
||||
vec2 fromCenter = uv - center;
|
||||
|
||||
// Aspect-corrected UVs keep grids and sparkles physically proportional.
|
||||
float maxDim = max(uSize.x, uSize.y);
|
||||
vec2 aspectUV = FlutterFragCoord().xy / maxDim;
|
||||
|
||||
float tiltMag = length(uTilt);
|
||||
float safeTiltMag = max(tiltMag, 0.001);
|
||||
vec2 tiltDir = uTilt / safeTiltMag;
|
||||
|
||||
// Highlight uses stretched UVs so glare spans the full widget area.
|
||||
float highlightDistance = length(uv - (center + (uTilt * 0.35)));
|
||||
|
||||
bool isHolographicSilver = uStyle < 0.5;
|
||||
bool isCrackedIce = uStyle >= 0.5 && uStyle < 1.5;
|
||||
bool isSilverMosaic = uStyle >= 1.5 && uStyle < 2.5;
|
||||
|
||||
float specularSharpness = isHolographicSilver ? 3.0 : (isCrackedIce ? 4.0 : (isSilverMosaic ? 3.4 : 3.6));
|
||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), specularSharpness);
|
||||
|
||||
float prismaticGain = isHolographicSilver ? 1.10 : (isCrackedIce ? 1.00 : (isSilverMosaic ? 1.30 : 1.18));
|
||||
float sparkleGain = isHolographicSilver ? 1.00 : (isCrackedIce ? 0.70 : (isSilverMosaic ? 0.80 : 0.70));
|
||||
float specularGain = isHolographicSilver ? 1.00 : (isCrackedIce ? 1.65 : (isSilverMosaic ? 1.15 : 1.50));
|
||||
float prismaticTintGain = isHolographicSilver ? 1.00 : (isCrackedIce ? 0.90 : (isSilverMosaic ? 1.15 : 0.65));
|
||||
|
||||
float sparkleGridScale = isCrackedIce ? 7.0 : (isSilverMosaic ? 14.0 : 18.0);
|
||||
|
||||
// Sparkle grid uses aspect-corrected coordinates to avoid stretching.
|
||||
vec2 sparkleGrid = aspectUV * sparkleGridScale;
|
||||
vec2 grid = floor(sparkleGrid);
|
||||
|
||||
float rarityThreshold = isCrackedIce ? 0.965 : (isSilverMosaic ? 0.88 : 0.83);
|
||||
float rarity = step(rarityThreshold, hash(grid + 0.31));
|
||||
|
||||
vec3 sparkle = vec3(0.0);
|
||||
if (rarity > 0.0) {
|
||||
vec2 cell = fract(sparkleGrid) - 0.5;
|
||||
float sparkleHash = hash(grid);
|
||||
vec2 sparkleNormal = normalize(vec2(sparkleHash * 2.0 - 1.0, hash(grid + 19.7) * 2.0 - 1.0));
|
||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||
|
||||
if (alignment > 0.0) {
|
||||
float twinkle = 0.45 + 0.55 * sin(dot(cell, vec2(21.0, -17.0)) + dot(uTilt, vec2(5.3, -4.1)) + sparkleHash * TWO_PI);
|
||||
float shapeMask = 0.0;
|
||||
|
||||
if (isCrackedIce) {
|
||||
float sides = 5.0 + floor(hash(grid + 9.4) * 4.0);
|
||||
float aspect = 0.75 + hash(grid + 13.1) * 0.55;
|
||||
shapeMask = sparklePolygonMask(cell, sides, aspect, hash(grid + 5.1) * TWO_PI);
|
||||
} else {
|
||||
shapeMask = sparkleShapeMask(cell, grid);
|
||||
}
|
||||
|
||||
float sparklePower = isCrackedIce ? 4.8 : (isSilverMosaic ? 3.8 : 3.2);
|
||||
float sparkleIntensity = isCrackedIce ? 0.25 : (isSilverMosaic ? 0.55 : 1.0);
|
||||
float sparkleChroma = isCrackedIce ? 0.20 : 0.35;
|
||||
float sparkleMask = pow(alignment, sparklePower) * twinkle * rarity * shapeMask;
|
||||
vec3 sparkleColor = mix(vec3(1.0), rainbow(sparkleHash + dot(uTilt, vec2(0.2, -0.15)), 0.55, 1.0), sparkleChroma);
|
||||
sparkle = sparkleColor * sparkleMask * uSparkle * sparkleIntensity * sparkleGain;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 styleBase;
|
||||
// Style bases sample aspect-corrected UVs for stable pattern geometry.
|
||||
if (uStyle < 0.5) {
|
||||
styleBase = styleHolographicSilver(aspectUV, uTilt);
|
||||
} else if (uStyle < 1.5) {
|
||||
styleBase = styleCrackedIce(aspectUV, uTilt);
|
||||
} else if (uStyle < 2.5) {
|
||||
styleBase = styleSilverMosaic(aspectUV, uTilt);
|
||||
} else {
|
||||
styleBase = styleSuperGoldVinyl(aspectUV, uTilt);
|
||||
}
|
||||
|
||||
float styleLuma = dot(styleBase, vec3(0.299, 0.587, 0.114));
|
||||
vec3 chromaAdjusted = mix(vec3(styleLuma), styleBase, 0.2 + 0.8 * uPrismatic);
|
||||
|
||||
// Directional lighting uses center-relative UVs for broad foil gradients.
|
||||
vec2 normal2d = normalize(fromCenter + vec2(0.001));
|
||||
float directional = 0.5 + 0.5 * dot(normal2d, tiltDir);
|
||||
float tiltLighting = mix(0.86, 1.20, pow(directional, 1.2));
|
||||
chromaAdjusted *= tiltLighting;
|
||||
|
||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag) * specularGain;
|
||||
|
||||
float prismaticPhase = dot(aspectUV, vec2(3.6, -2.1)) + dot(uTilt, vec2(0.9, -0.7));
|
||||
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * prismaticGain * prismaticTintGain * (0.08 + 0.14 * edgeSpec);
|
||||
|
||||
float microStrength = isCrackedIce ? 0.08 : 0.18;
|
||||
|
||||
// Micro diffraction uses aspect-corrected UVs to keep grain isotropic.
|
||||
float microMask = 0.5 + 0.5 * sin(dot(aspectUV, vec2(137.0, 57.0)) + noise(aspectUV * 14.0) * 4.0 + dot(uTilt, vec2(9.0, 4.0)) * 2.0);
|
||||
vec3 microShimmer = rainbow(noise(aspectUV * 10.0) + dot(uTilt, vec2(0.4, -0.3)) * 0.3, 0.65, 1.0) * microMask * uDiffraction * microStrength;
|
||||
|
||||
vec3 styleColor = chromaAdjusted + microShimmer + prismaticTint + (specular * 0.22) + sparkle;
|
||||
vec3 mappedColor = styleColor / (1.0 + styleColor * 0.3);
|
||||
float luma = dot(mappedColor, vec3(0.299, 0.587, 0.114));
|
||||
vec3 vibrantColor = mix(vec3(luma), mappedColor, 1.4);
|
||||
|
||||
float foilBrightness = dot(vibrantColor, vec3(0.333));
|
||||
float alpha = clamp(foilBrightness * 0.5, 0.0, 0.35) * clamp(uOpacity, 0.0, 1.0);
|
||||
vec3 finalColor = clamp(vibrantColor, 0.0, 1.0);
|
||||
|
||||
fragColor = vec4(finalColor * alpha, alpha);
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
#version 460 core
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uTilt;
|
||||
uniform float uPrismatic;
|
||||
uniform float uSparkle;
|
||||
uniform float uSpecular;
|
||||
uniform float uDiffraction;
|
||||
uniform float uOpacity;
|
||||
|
||||
#define TWO_PI 6.28318530718
|
||||
#define ROT_0_78 mat2(0.71091, 0.70328, -0.70328, 0.71091)
|
||||
#define ROT_M0_5 mat2(0.87758, -0.47943, 0.47943, 0.87758)
|
||||
#define ROT_1_2 mat2(0.36236, 0.93204, -0.93204, 0.36236)
|
||||
|
||||
float hash(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
float a = hash(i);
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(float h, float s, float v) {
|
||||
vec3 k = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
|
||||
vec3 p = abs(fract(vec3(h) + k) * 6.0 - 3.0);
|
||||
return v * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), s);
|
||||
}
|
||||
|
||||
vec3 rainbow(float phase, float saturation, float value) {
|
||||
return hsv2rgb(fract(phase), saturation, value);
|
||||
}
|
||||
|
||||
vec2 safeNormalize(vec2 p) {
|
||||
return p * inversesqrt(max(dot(p, p), 0.000001));
|
||||
}
|
||||
|
||||
float sdRegularPolygon(vec2 p, float sides, float radius) {
|
||||
float angle = atan(p.y, p.x);
|
||||
float sector = TWO_PI / sides;
|
||||
return cos(floor(0.5 + angle / sector) * sector - angle) * length(p) - radius;
|
||||
}
|
||||
|
||||
float sparklePolygonMask(vec2 p, float sides, float aspectRatio, float rotation) {
|
||||
float c = cos(rotation);
|
||||
float s = sin(rotation);
|
||||
vec2 q = vec2(c * p.x - s * p.y, s * p.x + c * p.y);
|
||||
q.x /= aspectRatio;
|
||||
float poly = sdRegularPolygon(q, sides, 0.26);
|
||||
return smoothstep(0.03, -0.03, poly);
|
||||
}
|
||||
|
||||
vec3 styleBase(vec2 uv, vec2 tilt) {
|
||||
float maxZ = -999.0;
|
||||
vec2 bestSlope = vec2(0.0);
|
||||
float bestHash = 0.0;
|
||||
float bestEdge = 1.0;
|
||||
|
||||
vec2 warp = vec2(sin(uv.y * 10.0), cos(uv.x * 10.0)) * 0.05;
|
||||
vec2 baseUV = uv + warp;
|
||||
|
||||
vec2 p1 = baseUV * 12.0;
|
||||
vec2 id1 = floor(p1);
|
||||
vec2 f1 = fract(p1) - 0.5;
|
||||
vec2 slope1 = vec2(hash(id1 + 1.2), hash(id1 + 1.3)) * 2.0 - 1.0;
|
||||
float z1 = dot(f1, slope1) * 3.5;
|
||||
float edge1 = min(0.5 - abs(f1.x), 0.5 - abs(f1.y));
|
||||
float hash1 = hash(id1 + 1.1);
|
||||
float use1 = step(maxZ, z1);
|
||||
maxZ = mix(maxZ, z1, use1);
|
||||
bestSlope = mix(bestSlope, slope1, use1);
|
||||
bestHash = mix(bestHash, hash1, use1);
|
||||
bestEdge = mix(bestEdge, edge1, use1);
|
||||
|
||||
vec2 p2 = (ROT_0_78 * baseUV) * 15.0;
|
||||
vec2 id2 = floor(p2);
|
||||
vec2 f2 = fract(p2) - 0.5;
|
||||
vec2 slope2 = vec2(hash(id2 + 2.2), hash(id2 + 2.3)) * 2.0 - 1.0;
|
||||
float z2 = 0.8 + dot(f2, slope2) * 3.5;
|
||||
float edge2 = min(0.5 - abs(f2.x), 0.5 - abs(f2.y));
|
||||
float hash2 = hash(id2 + 2.1);
|
||||
float use2 = step(maxZ, z2);
|
||||
maxZ = mix(maxZ, z2, use2);
|
||||
bestSlope = mix(bestSlope, slope2, use2);
|
||||
bestHash = mix(bestHash, hash2, use2);
|
||||
bestEdge = mix(bestEdge, edge2, use2);
|
||||
|
||||
vec2 p3 = (ROT_M0_5 * baseUV) * 18.0;
|
||||
vec2 id3 = floor(p3);
|
||||
vec2 f3 = fract(p3) - 0.5;
|
||||
vec2 slope3 = vec2(hash(id3 + 3.2), hash(id3 + 3.3)) * 2.0 - 1.0;
|
||||
float z3 = 1.6 + dot(f3, slope3) * 3.5;
|
||||
float edge3 = min(0.5 - abs(f3.x), 0.5 - abs(f3.y));
|
||||
float hash3 = hash(id3 + 3.1);
|
||||
float use3 = step(maxZ, z3);
|
||||
maxZ = mix(maxZ, z3, use3);
|
||||
bestSlope = mix(bestSlope, slope3, use3);
|
||||
bestHash = mix(bestHash, hash3, use3);
|
||||
bestEdge = mix(bestEdge, edge3, use3);
|
||||
|
||||
vec2 p4 = (ROT_1_2 * baseUV) * 21.0;
|
||||
vec2 id4 = floor(p4);
|
||||
vec2 f4 = fract(p4) - 0.5;
|
||||
vec2 slope4 = vec2(hash(id4 + 4.2), hash(id4 + 4.3)) * 2.0 - 1.0;
|
||||
float z4 = 2.4 + dot(f4, slope4) * 3.5;
|
||||
float edge4 = min(0.5 - abs(f4.x), 0.5 - abs(f4.y));
|
||||
float hash4 = hash(id4 + 4.1);
|
||||
float use4 = step(maxZ, z4);
|
||||
maxZ = mix(maxZ, z4, use4);
|
||||
bestSlope = mix(bestSlope, slope4, use4);
|
||||
bestHash = mix(bestHash, hash4, use4);
|
||||
bestEdge = mix(bestEdge, edge4, use4);
|
||||
|
||||
float alignment = dot(tilt, safeNormalize(bestSlope + vec2(0.001)));
|
||||
float phase = dot(uv, vec2(0.6, -0.4)) + bestHash * 0.6 + alignment * 0.5;
|
||||
float saturation = 0.7 + 0.3 * hash(vec2(bestHash, 6.1));
|
||||
vec3 baseColor = rainbow(phase, saturation, 1.0);
|
||||
float lightCycle = sin(alignment * 4.0 + bestHash * TWO_PI + dot(uv, vec2(2.1, -1.7)));
|
||||
float ambient = 0.15 + 0.25 * max(0.0, lightCycle);
|
||||
float flash = pow(max(0.0, lightCycle), 5.0);
|
||||
vec3 finalColor = baseColor * ambient;
|
||||
finalColor += mix(baseColor, vec3(1.0, 0.95, 0.85), 0.6) * flash * 0.55;
|
||||
finalColor += baseColor * smoothstep(0.05, 0.0, bestEdge) * flash * 0.4;
|
||||
return finalColor;
|
||||
}
|
||||
|
||||
vec3 sparkleLayer(vec2 aspectUV, vec2 tilt, vec2 tiltDir) {
|
||||
vec2 sparkleGrid = aspectUV * 7.0;
|
||||
vec2 grid = floor(sparkleGrid);
|
||||
vec2 cell = fract(sparkleGrid) - 0.5;
|
||||
float sparkleHash = hash(grid);
|
||||
vec2 sparkleNormal = safeNormalize(vec2(sparkleHash * 2.0 - 1.0, hash(grid + 19.7) * 2.0 - 1.0));
|
||||
float rarity = step(0.965, hash(grid + 0.31));
|
||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||
float twinkle = 0.45 + 0.55 * sin(dot(cell, vec2(21.0, -17.0)) + dot(tilt, vec2(5.3, -4.1)) + sparkleHash * TWO_PI);
|
||||
float sides = 5.0 + floor(hash(grid + 9.4) * 4.0);
|
||||
float aspect = 0.75 + hash(grid + 13.1) * 0.55;
|
||||
float shapeMask = sparklePolygonMask(cell, sides, aspect, hash(grid + 5.1) * TWO_PI);
|
||||
float sparkleMask = pow(alignment, 4.8) * twinkle * rarity * shapeMask;
|
||||
vec3 sparkleColor = mix(vec3(1.0), rainbow(sparkleHash + dot(tilt, vec2(0.2, -0.15)), 0.55, 1.0), 0.20);
|
||||
return sparkleColor * sparkleMask * uSparkle * 0.25 * 0.70;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 frag = FlutterFragCoord().xy;
|
||||
vec2 uv = frag / uSize;
|
||||
vec2 fromCenter = uv - vec2(0.5);
|
||||
float maxDim = max(uSize.x, uSize.y);
|
||||
vec2 aspectUV = frag / maxDim;
|
||||
float tiltMag = length(uTilt);
|
||||
vec2 tiltDir = safeNormalize(uTilt + vec2(0.001));
|
||||
float highlightDistance = length(uv - (vec2(0.5) + (uTilt * 0.35)));
|
||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), 4.0);
|
||||
|
||||
vec3 base = styleBase(aspectUV, uTilt);
|
||||
vec3 sparkle = sparkleLayer(aspectUV, uTilt, tiltDir);
|
||||
float baseLuma = dot(base, vec3(0.299, 0.587, 0.114));
|
||||
vec3 chromaAdjusted = mix(vec3(baseLuma), base, 0.2 + 0.8 * uPrismatic);
|
||||
|
||||
vec2 normal2d = safeNormalize(fromCenter + vec2(0.001));
|
||||
float directional = 0.5 + 0.5 * dot(normal2d, tiltDir);
|
||||
float tiltLighting = mix(0.86, 1.20, pow(directional, 1.2));
|
||||
chromaAdjusted *= tiltLighting;
|
||||
|
||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag) * 1.65;
|
||||
float prismaticPhase = dot(aspectUV, vec2(3.6, -2.1)) + dot(uTilt, vec2(0.9, -0.7));
|
||||
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * 0.90 * (0.08 + 0.14 * edgeSpec);
|
||||
float microMask = 0.5 + 0.5 * sin(dot(aspectUV, vec2(137.0, 57.0)) + noise(aspectUV * 14.0) * 4.0 + dot(uTilt, vec2(9.0, 4.0)) * 2.0);
|
||||
vec3 microShimmer = rainbow(noise(aspectUV * 10.0) + dot(uTilt, vec2(0.4, -0.3)) * 0.3, 0.65, 1.0) * microMask * uDiffraction * 0.08;
|
||||
|
||||
vec3 styleColor = chromaAdjusted + microShimmer + prismaticTint + (specular * 0.22) + sparkle;
|
||||
vec3 mappedColor = styleColor / (1.0 + styleColor * 0.3);
|
||||
float luma = dot(mappedColor, vec3(0.299, 0.587, 0.114));
|
||||
vec3 vibrantColor = mix(vec3(luma), mappedColor, 1.4);
|
||||
float foilBrightness = dot(vibrantColor, vec3(0.333));
|
||||
float alpha = clamp(foilBrightness * 0.5, 0.0, 0.35) * clamp(uOpacity, 0.0, 1.0);
|
||||
vec3 finalColor = clamp(vibrantColor, 0.0, 1.0);
|
||||
fragColor = vec4(finalColor * alpha, alpha);
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
#version 460 core
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uTilt;
|
||||
uniform float uPrismatic;
|
||||
uniform float uSparkle;
|
||||
uniform float uSpecular;
|
||||
uniform float uDiffraction;
|
||||
uniform float uOpacity;
|
||||
|
||||
#define TWO_PI 6.28318530718
|
||||
|
||||
float hash(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
float a = hash(i);
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(float h, float s, float v) {
|
||||
vec3 k = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
|
||||
vec3 p = abs(fract(vec3(h) + k) * 6.0 - 3.0);
|
||||
return v * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), s);
|
||||
}
|
||||
|
||||
vec3 rainbow(float phase, float saturation, float value) {
|
||||
return hsv2rgb(fract(phase), saturation, value);
|
||||
}
|
||||
|
||||
vec2 safeNormalize(vec2 p) {
|
||||
return p * inversesqrt(max(dot(p, p), 0.000001));
|
||||
}
|
||||
|
||||
float sparkleStarMask(vec2 p, float points, float innerRatio) {
|
||||
float angle = atan(p.y, p.x);
|
||||
float radius = dot(p, p);
|
||||
float spikes = 0.5 + 0.5 * cos(angle * points);
|
||||
float starRadius = mix(0.34 * innerRatio, 0.34, pow(spikes, 1.4));
|
||||
return smoothstep(0.0009, -0.0009, radius - (starRadius * starRadius));
|
||||
}
|
||||
|
||||
vec3 styleBase(vec2 uv, vec2 tilt) {
|
||||
vec2 p = uv * 2.0 - 1.0;
|
||||
vec2 tiltWarp = tilt * 0.18;
|
||||
float flowA = noise(uv * 3.5 + tiltWarp + vec2(dot(uv, vec2(0.25, -0.22))));
|
||||
float flowB = noise(uv * 7.0 - tiltWarp + vec2(dot(uv, vec2(-0.18, 0.21))));
|
||||
vec2 warp = p + 0.25 * vec2(flowA - 0.5, flowB - 0.5);
|
||||
float ribbon = sin(dot(warp, vec2(6.5, 2.8)) + flowA * 5.0 + dot(tilt, vec2(2.2, -1.7)));
|
||||
float plume = sin(length(warp + vec2(flowB - 0.5, flowA - 0.5)) * 9.0 - tilt.x * 3.0 + dot(uv, vec2(1.5, -1.2)));
|
||||
float phase = flowA * 1.8 + ribbon * 0.28 + plume * 0.22;
|
||||
vec3 holo = rainbow(phase, 0.72, 1.0);
|
||||
float blend = smoothstep(-0.65, 0.95, ribbon + plume * 0.55);
|
||||
vec3 silver = vec3(0.62, 0.65, 0.70) * (0.85 + 0.15 * flowB);
|
||||
return mix(silver, holo, 0.65 * blend);
|
||||
}
|
||||
|
||||
vec3 sparkleLayer(vec2 aspectUV, vec2 tilt, vec2 tiltDir) {
|
||||
vec2 sparkleGrid = aspectUV * 18.0;
|
||||
vec2 grid = floor(sparkleGrid);
|
||||
vec2 cell = fract(sparkleGrid) - 0.5;
|
||||
float sparkleHash = hash(grid);
|
||||
vec2 sparkleNormal = safeNormalize(vec2(sparkleHash * 2.0 - 1.0, hash(grid + 19.7) * 2.0 - 1.0));
|
||||
float rarity = step(0.83, hash(grid + 0.31));
|
||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||
float twinkle = 0.45 + 0.55 * sin(dot(cell, vec2(21.0, -17.0)) + dot(tilt, vec2(5.3, -4.1)) + sparkleHash * TWO_PI);
|
||||
float shapeMask = sparkleStarMask(cell, 8.0, 0.42);
|
||||
float sparkleMask = pow(alignment, 3.2) * twinkle * rarity * shapeMask;
|
||||
vec3 sparkleColor = mix(vec3(1.0), rainbow(sparkleHash + dot(tilt, vec2(0.2, -0.15)), 0.55, 1.0), 0.35);
|
||||
return sparkleColor * sparkleMask * uSparkle;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 frag = FlutterFragCoord().xy;
|
||||
vec2 uv = frag / uSize;
|
||||
vec2 fromCenter = uv - vec2(0.5);
|
||||
float maxDim = max(uSize.x, uSize.y);
|
||||
vec2 aspectUV = frag / maxDim;
|
||||
float tiltMag = length(uTilt);
|
||||
vec2 tiltDir = safeNormalize(uTilt + vec2(0.001));
|
||||
float highlightDistance = length(uv - (vec2(0.5) + (uTilt * 0.35)));
|
||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), 3.0);
|
||||
|
||||
vec3 base = styleBase(aspectUV, uTilt);
|
||||
vec3 sparkle = sparkleLayer(aspectUV, uTilt, tiltDir);
|
||||
float baseLuma = dot(base, vec3(0.299, 0.587, 0.114));
|
||||
vec3 chromaAdjusted = mix(vec3(baseLuma), base, 0.2 + 0.8 * uPrismatic);
|
||||
|
||||
vec2 normal2d = safeNormalize(fromCenter + vec2(0.001));
|
||||
float directional = 0.5 + 0.5 * dot(normal2d, tiltDir);
|
||||
float tiltLighting = mix(0.86, 1.20, pow(directional, 1.2));
|
||||
chromaAdjusted *= tiltLighting;
|
||||
|
||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag);
|
||||
float prismaticPhase = dot(aspectUV, vec2(3.6, -2.1)) + dot(uTilt, vec2(0.9, -0.7));
|
||||
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * 1.10 * (0.08 + 0.14 * edgeSpec);
|
||||
float microMask = 0.5 + 0.5 * sin(dot(aspectUV, vec2(137.0, 57.0)) + noise(aspectUV * 14.0) * 4.0 + dot(uTilt, vec2(9.0, 4.0)) * 2.0);
|
||||
vec3 microShimmer = rainbow(noise(aspectUV * 10.0) + dot(uTilt, vec2(0.4, -0.3)) * 0.3, 0.65, 1.0) * microMask * uDiffraction * 0.18;
|
||||
|
||||
vec3 styleColor = chromaAdjusted + microShimmer + prismaticTint + (specular * 0.22) + sparkle;
|
||||
vec3 mappedColor = styleColor / (1.0 + styleColor * 0.3);
|
||||
float luma = dot(mappedColor, vec3(0.299, 0.587, 0.114));
|
||||
vec3 vibrantColor = mix(vec3(luma), mappedColor, 1.4);
|
||||
float foilBrightness = dot(vibrantColor, vec3(0.333));
|
||||
float alpha = clamp(foilBrightness * 0.5, 0.0, 0.35) * clamp(uOpacity, 0.0, 1.0);
|
||||
vec3 finalColor = clamp(vibrantColor, 0.0, 1.0);
|
||||
fragColor = vec4(finalColor * alpha, alpha);
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
#version 460 core
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uTilt;
|
||||
uniform float uPrismatic;
|
||||
uniform float uSparkle;
|
||||
uniform float uSpecular;
|
||||
uniform float uDiffraction;
|
||||
uniform float uOpacity;
|
||||
|
||||
#define TWO_PI 6.28318530718
|
||||
|
||||
float hash(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
float a = hash(i);
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(float h, float s, float v) {
|
||||
vec3 k = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
|
||||
vec3 p = abs(fract(vec3(h) + k) * 6.0 - 3.0);
|
||||
return v * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), s);
|
||||
}
|
||||
|
||||
vec3 rainbow(float phase, float saturation, float value) {
|
||||
return hsv2rgb(fract(phase), saturation, value);
|
||||
}
|
||||
|
||||
vec2 safeNormalize(vec2 p) {
|
||||
return p * inversesqrt(max(dot(p, p), 0.000001));
|
||||
}
|
||||
|
||||
float sdRegularPolygon(vec2 p, float sides, float radius) {
|
||||
float angle = atan(p.y, p.x);
|
||||
float sector = TWO_PI / sides;
|
||||
return cos(floor(0.5 + angle / sector) * sector - angle) * length(p) - radius;
|
||||
}
|
||||
|
||||
float sparklePolygonMask(vec2 p, float sides, float aspectRatio, float rotation) {
|
||||
float c = cos(rotation);
|
||||
float s = sin(rotation);
|
||||
vec2 q = vec2(c * p.x - s * p.y, s * p.x + c * p.y);
|
||||
q.x /= aspectRatio;
|
||||
float poly = sdRegularPolygon(q, sides, 0.26);
|
||||
return smoothstep(0.03, -0.03, poly);
|
||||
}
|
||||
|
||||
vec3 styleBase(vec2 uv, vec2 tilt) {
|
||||
vec2 g = uv * 6.0;
|
||||
vec2 id = floor(g);
|
||||
vec2 f = fract(g) - 0.5;
|
||||
vec2 rotatedF = vec2(-f.y, f.x);
|
||||
f = mix(f, rotatedF, step(0.5, mod(id.x + id.y, 2.0)));
|
||||
vec2 radialDir = safeNormalize(f + vec2(0.0001));
|
||||
vec2 lightDir = safeNormalize(tilt + vec2(0.001));
|
||||
float alignment = abs(dot(radialDir, lightDir));
|
||||
float highlight = pow(alignment, 12.0);
|
||||
float angleDiff = acos(clamp(alignment, 0.0, 1.0));
|
||||
float side = sign(radialDir.x * lightDir.y - radialDir.y * lightDir.x);
|
||||
float basePhase = length(tilt) * 2.5 + dot(uv, vec2(0.9, -0.7));
|
||||
float phase = basePhase + side * angleDiff * 1.8;
|
||||
vec3 holoColor = rainbow(phase, 0.85, 1.0);
|
||||
vec3 core = vec3(1.0) * smoothstep(0.98, 1.0, alignment);
|
||||
vec3 foilBase = vec3(0.25, 0.27, 0.30);
|
||||
vec3 finalColor = foilBase + (holoColor * highlight * 1.5) + (core * 0.8);
|
||||
float edgeX = 0.5 - abs(f.x);
|
||||
float edgeY = 0.5 - abs(f.y);
|
||||
float border = smoothstep(0.0, 0.015, min(edgeX, edgeY));
|
||||
float dist = length(f);
|
||||
finalColor *= mix(0.7, 1.0, 1.0 - smoothstep(0.0, 0.5, dist) * 0.3);
|
||||
return clamp(finalColor * border, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 sparkleLayer(vec2 aspectUV, vec2 tilt, vec2 tiltDir) {
|
||||
vec2 sparkleGrid = aspectUV * 14.0;
|
||||
vec2 grid = floor(sparkleGrid);
|
||||
vec2 cell = fract(sparkleGrid) - 0.5;
|
||||
float sparkleHash = hash(grid);
|
||||
vec2 sparkleNormal = safeNormalize(vec2(sparkleHash * 2.0 - 1.0, hash(grid + 19.7) * 2.0 - 1.0));
|
||||
float rarity = step(0.88, hash(grid + 0.31));
|
||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||
float twinkle = 0.45 + 0.55 * sin(dot(cell, vec2(21.0, -17.0)) + dot(tilt, vec2(5.3, -4.1)) + sparkleHash * TWO_PI);
|
||||
float shapeMask = sparklePolygonMask(cell, 6.0, 1.0, 0.0);
|
||||
float sparkleMask = pow(alignment, 3.8) * twinkle * rarity * shapeMask;
|
||||
vec3 sparkleColor = mix(vec3(1.0), rainbow(sparkleHash + dot(tilt, vec2(0.2, -0.15)), 0.55, 1.0), 0.35);
|
||||
return sparkleColor * sparkleMask * uSparkle * 0.55 * 0.80;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 frag = FlutterFragCoord().xy;
|
||||
vec2 uv = frag / uSize;
|
||||
vec2 fromCenter = uv - vec2(0.5);
|
||||
float maxDim = max(uSize.x, uSize.y);
|
||||
vec2 aspectUV = frag / maxDim;
|
||||
float tiltMag = length(uTilt);
|
||||
vec2 tiltDir = safeNormalize(uTilt + vec2(0.001));
|
||||
float highlightDistance = length(uv - (vec2(0.5) + (uTilt * 0.35)));
|
||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), 3.4);
|
||||
|
||||
vec3 base = styleBase(aspectUV, uTilt);
|
||||
vec3 sparkle = sparkleLayer(aspectUV, uTilt, tiltDir);
|
||||
float baseLuma = dot(base, vec3(0.299, 0.587, 0.114));
|
||||
vec3 chromaAdjusted = mix(vec3(baseLuma), base, 0.2 + 0.8 * uPrismatic);
|
||||
|
||||
vec2 normal2d = safeNormalize(fromCenter + vec2(0.001));
|
||||
float directional = 0.5 + 0.5 * dot(normal2d, tiltDir);
|
||||
float tiltLighting = mix(0.86, 1.20, pow(directional, 1.2));
|
||||
chromaAdjusted *= tiltLighting;
|
||||
|
||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag) * 1.15;
|
||||
float prismaticPhase = dot(aspectUV, vec2(3.6, -2.1)) + dot(uTilt, vec2(0.9, -0.7));
|
||||
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * 1.30 * 1.15 * (0.08 + 0.14 * edgeSpec);
|
||||
float microMask = 0.5 + 0.5 * sin(dot(aspectUV, vec2(137.0, 57.0)) + noise(aspectUV * 14.0) * 4.0 + dot(uTilt, vec2(9.0, 4.0)) * 2.0);
|
||||
vec3 microShimmer = rainbow(noise(aspectUV * 10.0) + dot(uTilt, vec2(0.4, -0.3)) * 0.3, 0.65, 1.0) * microMask * uDiffraction * 0.18;
|
||||
|
||||
vec3 styleColor = chromaAdjusted + microShimmer + prismaticTint + (specular * 0.22) + sparkle;
|
||||
vec3 mappedColor = styleColor / (1.0 + styleColor * 0.3);
|
||||
float luma = dot(mappedColor, vec3(0.299, 0.587, 0.114));
|
||||
vec3 vibrantColor = mix(vec3(luma), mappedColor, 1.4);
|
||||
float foilBrightness = dot(vibrantColor, vec3(0.333));
|
||||
float alpha = clamp(foilBrightness * 0.5, 0.0, 0.35) * clamp(uOpacity, 0.0, 1.0);
|
||||
vec3 finalColor = clamp(vibrantColor, 0.0, 1.0);
|
||||
fragColor = vec4(finalColor * alpha, alpha);
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
#version 460 core
|
||||
#include <flutter/runtime_effect.glsl>
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uTilt;
|
||||
uniform float uPrismatic;
|
||||
uniform float uSparkle;
|
||||
uniform float uSpecular;
|
||||
uniform float uDiffraction;
|
||||
uniform float uOpacity;
|
||||
|
||||
#define TWO_PI 6.28318530718
|
||||
|
||||
float hash(vec2 p) {
|
||||
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
||||
p3 += dot(p3, p3.yzx + 33.33);
|
||||
return fract((p3.x + p3.y) * p3.z);
|
||||
}
|
||||
|
||||
float noise(vec2 p) {
|
||||
vec2 i = floor(p);
|
||||
vec2 f = fract(p);
|
||||
vec2 u = f * f * (3.0 - 2.0 * f);
|
||||
float a = hash(i);
|
||||
float b = hash(i + vec2(1.0, 0.0));
|
||||
float c = hash(i + vec2(0.0, 1.0));
|
||||
float d = hash(i + vec2(1.0, 1.0));
|
||||
return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
|
||||
}
|
||||
|
||||
vec3 hsv2rgb(float h, float s, float v) {
|
||||
vec3 k = vec3(1.0, 2.0 / 3.0, 1.0 / 3.0);
|
||||
vec3 p = abs(fract(vec3(h) + k) * 6.0 - 3.0);
|
||||
return v * mix(vec3(1.0), clamp(p - 1.0, 0.0, 1.0), s);
|
||||
}
|
||||
|
||||
vec3 rainbow(float phase, float saturation, float value) {
|
||||
return hsv2rgb(fract(phase), saturation, value);
|
||||
}
|
||||
|
||||
vec2 safeNormalize(vec2 p) {
|
||||
return p * inversesqrt(max(dot(p, p), 0.000001));
|
||||
}
|
||||
|
||||
float sdBox(vec2 p, vec2 b) {
|
||||
vec2 d = abs(p) - b;
|
||||
return length(max(d, 0.0)) + min(max(d.x, d.y), 0.0);
|
||||
}
|
||||
|
||||
float sparkleRectangleMask(vec2 p, float halfWidth, float halfHeight, float rotation) {
|
||||
float c = cos(rotation);
|
||||
float s = sin(rotation);
|
||||
vec2 q = vec2(c * p.x - s * p.y, s * p.x + c * p.y);
|
||||
float body = sdBox(q, vec2(halfWidth, halfHeight));
|
||||
float bevel = sdBox(q, vec2(halfWidth * 0.78, halfHeight * 0.78));
|
||||
float bodyMask = smoothstep(0.03, -0.03, body);
|
||||
float centerLine = 1.0 - smoothstep(0.0, halfHeight * 1.25, abs(q.y));
|
||||
float endFade = 1.0 - smoothstep(halfWidth * 0.55, halfWidth * 1.05, abs(q.x));
|
||||
float streak = centerLine * endFade;
|
||||
float bevelRing = smoothstep(0.025, -0.025, body) - smoothstep(0.025, -0.025, bevel);
|
||||
return clamp(bodyMask * (0.58 + 0.42 * streak) + bevelRing * 0.25, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec3 styleBase(vec2 uv, vec2 tilt) {
|
||||
vec2 g = uv * 60.0;
|
||||
vec2 staggered = vec2(g.x + 0.5 * mod(floor(g.y), 2.0), g.y);
|
||||
vec2 f = fract(staggered) - 0.5;
|
||||
float d2 = dot(f, f);
|
||||
float dotMask = smoothstep(0.1764, 0.01, d2);
|
||||
float emboss = smoothstep(0.2025, 0.0324, d2);
|
||||
float sheen = 0.5 + 0.5 * sin(dot(uv, vec2(18.0, -6.0)) + noise(uv * 6.0) * 2.5 + dot(tilt, vec2(2.4, 1.8)) * 2.0);
|
||||
vec3 gold = vec3(0.84, 0.70, 0.24);
|
||||
vec3 warm = vec3(1.0, 0.88, 0.42);
|
||||
vec3 shadow = vec3(0.18, 0.14, 0.05);
|
||||
return gold * (0.75 + 0.25 * sheen) + warm * dotMask * 0.28 + shadow * emboss * 0.08;
|
||||
}
|
||||
|
||||
vec3 sparkleLayer(vec2 aspectUV, vec2 tilt, vec2 tiltDir) {
|
||||
vec2 sparkleGrid = aspectUV * 18.0;
|
||||
vec2 grid = floor(sparkleGrid);
|
||||
vec2 cell = fract(sparkleGrid) - 0.5;
|
||||
float sparkleHash = hash(grid);
|
||||
vec2 sparkleNormal = safeNormalize(vec2(sparkleHash * 2.0 - 1.0, hash(grid + 19.7) * 2.0 - 1.0));
|
||||
float rarity = step(0.83, hash(grid + 0.31));
|
||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||
float twinkle = 0.45 + 0.55 * sin(dot(cell, vec2(21.0, -17.0)) + dot(tilt, vec2(5.3, -4.1)) + sparkleHash * TWO_PI);
|
||||
float shapeMask = sparkleRectangleMask(cell, 0.34, 0.045, hash(grid + 5.1) * TWO_PI);
|
||||
float sparkleMask = pow(alignment, 3.2) * twinkle * rarity * shapeMask;
|
||||
vec3 sparkleColor = mix(vec3(1.0), rainbow(sparkleHash + dot(tilt, vec2(0.2, -0.15)), 0.55, 1.0), 0.35);
|
||||
return sparkleColor * sparkleMask * uSparkle * 0.70;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec2 frag = FlutterFragCoord().xy;
|
||||
vec2 uv = frag / uSize;
|
||||
vec2 fromCenter = uv - vec2(0.5);
|
||||
float maxDim = max(uSize.x, uSize.y);
|
||||
vec2 aspectUV = frag / maxDim;
|
||||
float tiltMag = length(uTilt);
|
||||
vec2 tiltDir = safeNormalize(uTilt + vec2(0.001));
|
||||
float highlightDistance = length(uv - (vec2(0.5) + (uTilt * 0.35)));
|
||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), 3.6);
|
||||
|
||||
vec3 base = styleBase(aspectUV, uTilt);
|
||||
vec3 sparkle = sparkleLayer(aspectUV, uTilt, tiltDir);
|
||||
float baseLuma = dot(base, vec3(0.299, 0.587, 0.114));
|
||||
vec3 chromaAdjusted = mix(vec3(baseLuma), base, 0.2 + 0.8 * uPrismatic);
|
||||
|
||||
vec2 normal2d = safeNormalize(fromCenter + vec2(0.001));
|
||||
float directional = 0.5 + 0.5 * dot(normal2d, tiltDir);
|
||||
float tiltLighting = mix(0.86, 1.20, pow(directional, 1.2));
|
||||
chromaAdjusted *= tiltLighting;
|
||||
|
||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag) * 1.50;
|
||||
float prismaticPhase = dot(aspectUV, vec2(3.6, -2.1)) + dot(uTilt, vec2(0.9, -0.7));
|
||||
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * 1.18 * 0.65 * (0.08 + 0.14 * edgeSpec);
|
||||
float microMask = 0.5 + 0.5 * sin(dot(aspectUV, vec2(137.0, 57.0)) + noise(aspectUV * 14.0) * 4.0 + dot(uTilt, vec2(9.0, 4.0)) * 2.0);
|
||||
vec3 microShimmer = rainbow(noise(aspectUV * 10.0) + dot(uTilt, vec2(0.4, -0.3)) * 0.3, 0.65, 1.0) * microMask * uDiffraction * 0.18;
|
||||
|
||||
vec3 styleColor = chromaAdjusted + microShimmer + prismaticTint + (specular * 0.22) + sparkle;
|
||||
vec3 mappedColor = styleColor / (1.0 + styleColor * 0.3);
|
||||
float luma = dot(mappedColor, vec3(0.299, 0.587, 0.114));
|
||||
vec3 vibrantColor = mix(vec3(luma), mappedColor, 1.4);
|
||||
float foilBrightness = dot(vibrantColor, vec3(0.333));
|
||||
float alpha = clamp(foilBrightness * 0.5, 0.0, 0.35) * clamp(uOpacity, 0.0, 1.0);
|
||||
vec3 finalColor = clamp(vibrantColor, 0.0, 1.0);
|
||||
fragColor = vec4(finalColor * alpha, alpha);
|
||||
}
|
||||
Reference in New Issue
Block a user