Refactor Shiny widget and shader code to remove unused time variable; optimize shader functions by eliminating time dependency for improved performance
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
+11
-28
@@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:ui' as ui;
|
import 'dart:ui' as ui;
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
|
||||||
|
|
||||||
import 'shiny_controller.dart';
|
import 'shiny_controller.dart';
|
||||||
|
|
||||||
@@ -244,30 +243,19 @@ class Shiny extends StatefulWidget {
|
|||||||
State<Shiny> createState() => _ShinyState();
|
State<Shiny> createState() => _ShinyState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
|
class _ShinyState extends State<Shiny> {
|
||||||
static Future<ui.FragmentProgram>? _programFuture;
|
static Future<ui.FragmentProgram>? _programFuture;
|
||||||
|
|
||||||
ui.FragmentShader? _shader;
|
ui.FragmentShader? _shader;
|
||||||
StreamSubscription<Offset>? _tiltSub;
|
StreamSubscription<Offset>? _tiltSub;
|
||||||
late final Ticker _ticker;
|
|
||||||
|
|
||||||
double _time = 0.0;
|
|
||||||
Offset _tilt = Offset.zero;
|
Offset _tilt = Offset.zero;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_ticker = createTicker((Duration elapsed) {
|
|
||||||
if (!mounted || _shader == null) return;
|
|
||||||
setState(() {
|
|
||||||
_time = elapsed.inMicroseconds / 1000000.0;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
_attachController();
|
_attachController();
|
||||||
if (widget.enableShader) {
|
if (widget.enableShader) {
|
||||||
_loadShader();
|
_loadShader();
|
||||||
_ticker.start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,9 +270,6 @@ class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
|
|||||||
if (oldWidget.enableShader != widget.enableShader) {
|
if (oldWidget.enableShader != widget.enableShader) {
|
||||||
if (widget.enableShader) {
|
if (widget.enableShader) {
|
||||||
if (_shader == null) _loadShader();
|
if (_shader == null) _loadShader();
|
||||||
_ticker.start();
|
|
||||||
} else {
|
|
||||||
_ticker.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,7 +314,6 @@ class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_ticker.dispose();
|
|
||||||
_tiltSub?.cancel();
|
_tiltSub?.cancel();
|
||||||
_shader?.dispose();
|
_shader?.dispose();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
@@ -343,17 +327,16 @@ class _ShinyState extends State<Shiny> with TickerProviderStateMixin {
|
|||||||
..setFloat(1, bounds.height)
|
..setFloat(1, bounds.height)
|
||||||
..setFloat(2, effectiveTilt.dx)
|
..setFloat(2, effectiveTilt.dx)
|
||||||
..setFloat(3, effectiveTilt.dy)
|
..setFloat(3, effectiveTilt.dy)
|
||||||
..setFloat(4, _time)
|
..setFloat(4, widget.prismatic)
|
||||||
..setFloat(5, widget.prismatic)
|
..setFloat(5, widget.sparkle)
|
||||||
..setFloat(6, widget.sparkle)
|
..setFloat(6, widget.specular)
|
||||||
..setFloat(7, widget.specular)
|
..setFloat(7, widget.diffraction)
|
||||||
..setFloat(8, widget.diffraction)
|
..setFloat(8, widget.style.index.toDouble())
|
||||||
..setFloat(9, widget.style.index.toDouble())
|
..setFloat(9, widget.sparkleShape.kind.index.toDouble())
|
||||||
..setFloat(10, widget.sparkleShape.kind.index.toDouble())
|
..setFloat(10, widget.sparkleShape.primary)
|
||||||
..setFloat(11, widget.sparkleShape.primary)
|
..setFloat(11, widget.sparkleShape.secondary)
|
||||||
..setFloat(12, widget.sparkleShape.secondary)
|
..setFloat(12, widget.sparkleShape.tertiary)
|
||||||
..setFloat(13, widget.sparkleShape.tertiary)
|
..setFloat(13, widget.opacity);
|
||||||
..setFloat(14, widget.opacity);
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+27
-24
@@ -5,7 +5,6 @@ out vec4 fragColor;
|
|||||||
|
|
||||||
uniform vec2 uSize;
|
uniform vec2 uSize;
|
||||||
uniform vec2 uTilt;
|
uniform vec2 uTilt;
|
||||||
uniform float uTime;
|
|
||||||
uniform float uPrismatic;
|
uniform float uPrismatic;
|
||||||
uniform float uSparkle;
|
uniform float uSparkle;
|
||||||
uniform float uSpecular;
|
uniform float uSpecular;
|
||||||
@@ -120,14 +119,15 @@ float sparkleShapeMask(vec2 p, vec2 id) {
|
|||||||
return sparkleRectangleMask(p, uSparklePrimary, uSparkleSecondary, randomRotation * uSparkleTertiary);
|
return sparkleRectangleMask(p, uSparklePrimary, uSparkleSecondary, randomRotation * uSparkleTertiary);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 styleHolographicSilver(vec2 uv, vec2 tilt, float time) {
|
vec3 styleHolographicSilver(vec2 uv, vec2 tilt) {
|
||||||
vec2 p = uv * 2.0 - 1.0;
|
vec2 p = uv * 2.0 - 1.0;
|
||||||
float flowA = noise(uv * 3.5 + vec2(time * 0.03, -time * 0.02));
|
vec2 tiltWarp = tilt * 0.18;
|
||||||
float flowB = noise(uv * 7.0 + vec2(-time * 0.02, time * 0.03));
|
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);
|
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 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 + time * 0.2);
|
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 + time * 0.03;
|
float phase = flowA * 1.8 + ribbon * 0.28 + plume * 0.22;
|
||||||
|
|
||||||
vec3 holo = rainbow(phase, 0.72, 1.0);
|
vec3 holo = rainbow(phase, 0.72, 1.0);
|
||||||
float blend = smoothstep(-0.65, 0.95, ribbon + plume * 0.55);
|
float blend = smoothstep(-0.65, 0.95, ribbon + plume * 0.55);
|
||||||
@@ -136,7 +136,7 @@ vec3 styleHolographicSilver(vec2 uv, vec2 tilt, float time) {
|
|||||||
return mix(silver, holo, 0.65 * blend);
|
return mix(silver, holo, 0.65 * blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 styleCrackedIce(vec2 uv, vec2 tilt, float time) {
|
vec3 styleCrackedIce(vec2 uv, vec2 tilt) {
|
||||||
float maxZ = -999.0;
|
float maxZ = -999.0;
|
||||||
vec2 bestSlope = vec2(0.0);
|
vec2 bestSlope = vec2(0.0);
|
||||||
float bestHash = 0.0;
|
float bestHash = 0.0;
|
||||||
@@ -187,11 +187,11 @@ vec3 styleCrackedIce(vec2 uv, vec2 tilt, float time) {
|
|||||||
|
|
||||||
// --- VIBRANT COLOR OPTICS ---
|
// --- VIBRANT COLOR OPTICS ---
|
||||||
float alignment = dot(tilt, normalize(bestSlope + vec2(0.001)));
|
float alignment = dot(tilt, normalize(bestSlope + vec2(0.001)));
|
||||||
float phase = dot(uv, vec2(0.6, -0.4)) + time * 0.05 + bestHash * 0.6 + alignment * 0.5;
|
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));
|
float saturation = 0.7 + 0.3 * hash(vec2(bestHash, 6.1));
|
||||||
vec3 baseColor = rainbow(phase, saturation, 1.0);
|
vec3 baseColor = rainbow(phase, saturation, 1.0);
|
||||||
|
|
||||||
float lightCycle = sin(alignment * 4.0 + bestHash * TWO_PI + time * 0.15);
|
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 ambient = 0.15 + 0.25 * max(0.0, lightCycle);
|
||||||
vec3 finalColor = baseColor * ambient;
|
vec3 finalColor = baseColor * ambient;
|
||||||
float flash = pow(max(0.0, lightCycle), 5.0);
|
float flash = pow(max(0.0, lightCycle), 5.0);
|
||||||
@@ -201,7 +201,7 @@ vec3 styleCrackedIce(vec2 uv, vec2 tilt, float time) {
|
|||||||
return finalColor;
|
return finalColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 styleSilverMosaic(vec2 uv, vec2 tilt, float time) {
|
vec3 styleSilverMosaic(vec2 uv, vec2 tilt) {
|
||||||
// Mosaic tile grid.
|
// Mosaic tile grid.
|
||||||
vec2 g = uv * 6.0;
|
vec2 g = uv * 6.0;
|
||||||
vec2 id = floor(g);
|
vec2 id = floor(g);
|
||||||
@@ -228,7 +228,7 @@ vec3 styleSilverMosaic(vec2 uv, vec2 tilt, float time) {
|
|||||||
// 2D cross product sign decides which side of the highlight receives hue shift.
|
// 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 side = sign(radialDir.x * lightDir.y - radialDir.y * lightDir.x);
|
||||||
|
|
||||||
float basePhase = length(tilt) * 2.5 + time * 0.1;
|
float basePhase = length(tilt) * 2.5 + dot(uv, vec2(0.9, -0.7));
|
||||||
|
|
||||||
float phase = basePhase + side * angleDiff * 1.8;
|
float phase = basePhase + side * angleDiff * 1.8;
|
||||||
vec3 holoColor = rainbow(phase, 0.85, 1.0);
|
vec3 holoColor = rainbow(phase, 0.85, 1.0);
|
||||||
@@ -252,7 +252,7 @@ vec3 styleSilverMosaic(vec2 uv, vec2 tilt, float time) {
|
|||||||
return clamp(finalColor * border, 0.0, 1.0);
|
return clamp(finalColor * border, 0.0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3 styleSuperGoldVinyl(vec2 uv, vec2 tilt, float time) {
|
vec3 styleSuperGoldVinyl(vec2 uv, vec2 tilt) {
|
||||||
vec2 g = uv * 60.0;
|
vec2 g = uv * 60.0;
|
||||||
vec2 staggered = vec2(g.x + 0.5 * mod(floor(g.y), 2.0), g.y);
|
vec2 staggered = vec2(g.x + 0.5 * mod(floor(g.y), 2.0), g.y);
|
||||||
vec2 f = fract(staggered) - 0.5;
|
vec2 f = fract(staggered) - 0.5;
|
||||||
@@ -262,7 +262,7 @@ vec3 styleSuperGoldVinyl(vec2 uv, vec2 tilt, float time) {
|
|||||||
float dotMask = smoothstep(0.1764, 0.01, d2);
|
float dotMask = smoothstep(0.1764, 0.01, d2);
|
||||||
float emboss = smoothstep(0.2025, 0.0324, 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 + time * 0.2);
|
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 gold = vec3(0.84, 0.70, 0.24);
|
||||||
vec3 warm = vec3(1.0, 0.88, 0.42);
|
vec3 warm = vec3(1.0, 0.88, 0.42);
|
||||||
vec3 shadow = vec3(0.18, 0.14, 0.05);
|
vec3 shadow = vec3(0.18, 0.14, 0.05);
|
||||||
@@ -286,15 +286,18 @@ void main() {
|
|||||||
|
|
||||||
// Highlight uses stretched UVs so glare spans the full widget area.
|
// Highlight uses stretched UVs so glare spans the full widget area.
|
||||||
float highlightDistance = length(uv - (center + (uTilt * 0.35)));
|
float highlightDistance = length(uv - (center + (uTilt * 0.35)));
|
||||||
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), 3.2);
|
|
||||||
|
|
||||||
bool isHolographicSilver = uStyle < 0.5;
|
bool isHolographicSilver = uStyle < 0.5;
|
||||||
bool isCrackedIce = uStyle >= 0.5 && uStyle < 1.5;
|
bool isCrackedIce = uStyle >= 0.5 && uStyle < 1.5;
|
||||||
bool isSilverMosaic = uStyle >= 1.5 && uStyle < 2.5;
|
bool isSilverMosaic = uStyle >= 1.5 && uStyle < 2.5;
|
||||||
|
|
||||||
float prismaticGain = isHolographicSilver ? 1.10 : (isCrackedIce ? 1.00 : (isSilverMosaic ? 1.30 : 1.55));
|
float specularSharpness = isHolographicSilver ? 3.0 : (isCrackedIce ? 4.0 : (isSilverMosaic ? 3.4 : 3.6));
|
||||||
float sparkleGain = isHolographicSilver ? 1.00 : (isCrackedIce ? 0.55 : (isSilverMosaic ? 0.80 : 0.70));
|
float specularMask = pow(max(0.0, 1.0 - highlightDistance * 2.6), specularSharpness);
|
||||||
float specularGain = isHolographicSilver ? 1.00 : (isCrackedIce ? 1.35 : (isSilverMosaic ? 1.15 : 1.50));
|
|
||||||
|
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);
|
float sparkleGridScale = isCrackedIce ? 7.0 : (isSilverMosaic ? 14.0 : 18.0);
|
||||||
|
|
||||||
@@ -313,7 +316,7 @@ void main() {
|
|||||||
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
float alignment = max(0.0, dot(tiltDir, sparkleNormal));
|
||||||
|
|
||||||
if (alignment > 0.0) {
|
if (alignment > 0.0) {
|
||||||
float twinkle = 0.5 + 0.5 * sin(uTime * 5.5 + sparkleHash * TWO_PI);
|
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;
|
float shapeMask = 0.0;
|
||||||
|
|
||||||
if (isCrackedIce) {
|
if (isCrackedIce) {
|
||||||
@@ -336,13 +339,13 @@ void main() {
|
|||||||
vec3 styleBase;
|
vec3 styleBase;
|
||||||
// Style bases sample aspect-corrected UVs for stable pattern geometry.
|
// Style bases sample aspect-corrected UVs for stable pattern geometry.
|
||||||
if (uStyle < 0.5) {
|
if (uStyle < 0.5) {
|
||||||
styleBase = styleHolographicSilver(aspectUV, uTilt, uTime);
|
styleBase = styleHolographicSilver(aspectUV, uTilt);
|
||||||
} else if (uStyle < 1.5) {
|
} else if (uStyle < 1.5) {
|
||||||
styleBase = styleCrackedIce(aspectUV, uTilt, uTime);
|
styleBase = styleCrackedIce(aspectUV, uTilt);
|
||||||
} else if (uStyle < 2.5) {
|
} else if (uStyle < 2.5) {
|
||||||
styleBase = styleSilverMosaic(aspectUV, uTilt, uTime);
|
styleBase = styleSilverMosaic(aspectUV, uTilt);
|
||||||
} else {
|
} else {
|
||||||
styleBase = styleSuperGoldVinyl(aspectUV, uTilt, uTime);
|
styleBase = styleSuperGoldVinyl(aspectUV, uTilt);
|
||||||
}
|
}
|
||||||
|
|
||||||
float styleLuma = dot(styleBase, vec3(0.299, 0.587, 0.114));
|
float styleLuma = dot(styleBase, vec3(0.299, 0.587, 0.114));
|
||||||
@@ -357,8 +360,8 @@ void main() {
|
|||||||
float edgeSpec = pow(1.0 - directional, 2.2);
|
float edgeSpec = pow(1.0 - directional, 2.2);
|
||||||
vec3 specular = vec3(specularMask) * (0.3 + 0.7 * edgeSpec) * uSpecular * (0.35 + 0.65 * tiltMag) * specularGain;
|
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)) + uTime * 0.04;
|
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 * (0.08 + 0.14 * edgeSpec);
|
vec3 prismaticTint = rainbow(prismaticPhase, 0.72, 1.0) * uPrismatic * prismaticGain * prismaticTintGain * (0.08 + 0.14 * edgeSpec);
|
||||||
|
|
||||||
float microStrength = isCrackedIce ? 0.08 : 0.18;
|
float microStrength = isCrackedIce ? 0.08 : 0.18;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user