Skip to content

Commit 0549eb0

Browse files
authored
feat: better specular on all platforms for FakeGlass (whynotmake-it#83)
1 parent 2102c69 commit 0549eb0

File tree

4 files changed

+50
-38
lines changed

4 files changed

+50
-38
lines changed

packages/liquid_glass_renderer/example/lib/basic_app.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ class BasicApp extends HookWidget {
3030
Widget build(BuildContext context) {
3131
final tab = useState(0);
3232

33+
final light = useRotatingAnimationController();
34+
3335
return GestureDetector(
3436
onTap: () {
3537
SettingsSheet(
3638
settingsNotifier: settingsNotifier,
37-
lightAngleAnimation: AlwaysStoppedAnimation(0),
39+
lightAngleAnimation: light,
3840
).show(context);
3941
},
4042
child: CupertinoPageScaffold(
@@ -56,9 +58,10 @@ class BasicApp extends HookWidget {
5658
),
5759
Center(
5860
child: ListenableBuilder(
59-
listenable: Listenable.merge([settingsNotifier]),
61+
listenable: Listenable.merge([settingsNotifier, light]),
6062
builder: (context, child) {
6163
final settings = settingsNotifier.value.copyWith(
64+
lightAngle: light.value,
6265
glassColor: CupertinoTheme.of(
6366
context,
6467
).barBackgroundColor.withValues(alpha: 0.4),

packages/liquid_glass_renderer/lib/liquid_glass_renderer.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
library liquid_glass_renderer;
33

44
export 'src/fake_glass.dart' show FakeGlass;
5-
export 'src/stretch.dart' show LiquidStretch;
65
export 'src/glass_glow.dart' show GlassGlow, GlassGlowLayer;
76
export 'src/glass_link.dart' show GlassLink;
87
export 'src/glassify.dart' show Glassify;
98
export 'src/liquid_glass.dart' show LiquidGlass;
109
export 'src/liquid_glass_layer.dart' show LiquidGlassLayer;
1110
export 'src/liquid_glass_settings.dart' show LiquidGlassSettings;
1211
export 'src/liquid_shape.dart';
12+
export 'src/stretch.dart' show LiquidStretch;

packages/liquid_glass_renderer/lib/src/fake_glass.dart

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// ignore_for_file: require_trailing_commas
22

33
import 'dart:math' as math;
4-
import 'dart:ui';
4+
import 'dart:ui' as ui;
55

66
import 'package:flutter/foundation.dart';
77
import 'package:flutter/material.dart';
@@ -111,18 +111,18 @@ class _RenderFakeGlass extends RenderProxyBox {
111111
@override
112112
void paint(PaintingContext context, Offset offset) {
113113
// Create saturation filter if needed
114-
final ImageFilter? saturationFilter = settings.saturation != 1.0
115-
? ColorFilter.matrix(_createSaturationMatrix(settings.saturation))
114+
final ui.ImageFilter? saturationFilter = settings.saturation != 1.0
115+
? ui.ColorFilter.matrix(_createSaturationMatrix(settings.saturation))
116116
: null;
117117

118-
final blurFilter = ImageFilter.blur(
118+
final blurFilter = ui.ImageFilter.blur(
119119
sigmaX: settings.blur,
120120
sigmaY: settings.blur,
121121
);
122122

123123
// Combine blur and saturation filters
124124
final combinedFilter = saturationFilter != null
125-
? ImageFilter.compose(
125+
? ui.ImageFilter.compose(
126126
inner: saturationFilter,
127127
outer: blurFilter,
128128
)
@@ -136,7 +136,7 @@ class _RenderFakeGlass extends RenderProxyBox {
136136
(context, offset) {
137137
final path = shape.getOuterPath(offset & size);
138138
_paintColor(context.canvas, path);
139-
_paintSpecular(context.canvas, path);
139+
_paintSpecular(context.canvas, path, offset & size);
140140
super.paint(context, offset);
141141
},
142142
offset,
@@ -179,51 +179,64 @@ class _RenderFakeGlass extends RenderProxyBox {
179179
canvas.drawPath(path, paint);
180180
}
181181

182-
void _paintSpecular(Canvas canvas, Path path) {
183-
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
184-
// Compute alignments from light angle
182+
void _paintSpecular(Canvas canvas, Path path, Rect bounds) {
183+
final squareBounds = Rect.fromCenter(
184+
center: bounds.center,
185+
width: bounds.longestSide,
186+
height: bounds.longestSide,
187+
);
185188
final radians = settings.lightAngle;
186189

187-
final x = -1 * math.cos(radians);
188-
final y = -1 * math.sin(radians);
190+
final x = math.cos(radians);
191+
final y = math.sin(radians);
192+
193+
final alignmentWithShortestSide = size.aspectRatio < 1 ? x : y;
189194

190195
final color = Colors.white.withValues(
191-
alpha: switch (defaultTargetPlatform) {
192-
TargetPlatform.iOS => settings.lightIntensity.clamp(0, 1) * 2,
193-
_ => settings.lightIntensity.clamp(0, 1),
194-
},
196+
alpha: (settings.lightIntensity * 2).clamp(0, 1),
195197
);
198+
199+
final adjustment = 1 - 1 / size.aspectRatio;
200+
final inset = ui.lerpDouble(
201+
0,
202+
.4,
203+
adjustment * alignmentWithShortestSide.abs(),
204+
)!;
205+
206+
final secondInset = ui.lerpDouble(
207+
.15,
208+
.5,
209+
adjustment * alignmentWithShortestSide.abs(),
210+
)!;
211+
196212
final shader = LinearGradient(
197213
colors: [
198214
color,
199215
color.withValues(alpha: settings.ambientStrength.clamp(0, 1)),
200216
color.withValues(alpha: settings.ambientStrength.clamp(0, 1)),
201217
color,
202218
],
219+
stops: [
220+
inset,
221+
secondInset,
222+
1 - secondInset,
223+
1 - inset,
224+
],
203225
begin: Alignment(x, y),
204226
end: Alignment(-x, -y),
205-
).createShader(path.getBounds());
206-
207-
// Paint sharp outline
227+
).createShader(squareBounds);
208228

209229
final paint = Paint()
210230
..shader = shader
211231
..blendMode = BlendMode.softLight
212232
..style = PaintingStyle.stroke
213-
..strokeWidth = 1;
214-
215-
if (defaultTargetPlatform != TargetPlatform.iOS) {
216-
paint.maskFilter = const MaskFilter.blur(BlurStyle.normal, .7);
217-
} else {
218-
paint.strokeWidth = 3;
219-
}
220-
233+
..strokeWidth = 3;
221234
canvas.drawPath(path, paint);
222235

223-
// Paint a second, slightly blurred outline
224-
if (defaultTargetPlatform != TargetPlatform.iOS) {
225-
paint.maskFilter = const MaskFilter.blur(BlurStyle.normal, 2);
226-
canvas.drawPath(path, paint);
227-
}
236+
paint
237+
..strokeWidth = 1
238+
..color = color.withValues(alpha: color.a * 0.5)
239+
..blendMode = BlendMode.hardLight;
240+
canvas.drawPath(path, paint);
228241
}
229242
}

packages/liquid_glass_renderer/lib/src/glass_glow.dart

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,6 @@ class GlassGlowLayerState extends State<GlassGlowLayer>
171171
_radiusController,
172172
]),
173173
builder: (context, child) {
174-
print(_alphaController.value);
175-
print(_radiusController.value);
176-
print(_offsetController.value);
177-
178174
return _RenderGlassGlowLayerWidget(
179175
glowRadius: _baseRadius * _radiusController.value,
180176
glowColor: _baseColor.withValues(

0 commit comments

Comments
 (0)