6eb28ffcac
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
243 lines
7.6 KiB
Markdown
243 lines
7.6 KiB
Markdown
# wolf_3d_flutter
|
|
|
|
Flutter integration package for the shared Wolfenstein 3D runtime.
|
|
|
|
## What This Package Provides
|
|
|
|
`wolf_3d_flutter` layers Flutter-specific host concerns on top of `wolf_3d_dart`:
|
|
|
|
- high-level engine facade (`Wolf3dFlutterEngine`),
|
|
- Flutter input adapter,
|
|
- platform audio integration,
|
|
- renderer host widgets and runtime mode helpers,
|
|
- app/session managers and persistence adapters,
|
|
- shader-enabled rendering support.
|
|
|
|
Primary entrypoint: `lib/wolf_3d_flutter.dart`
|
|
|
|
## Prerequisites
|
|
|
|
- Flutter SDK
|
|
- Dart SDK `^3.11.1`
|
|
- Workspace dependency on `wolf_3d_dart`
|
|
|
|
## Setup
|
|
|
|
From this directory:
|
|
|
|
```bash
|
|
flutter pub get
|
|
```
|
|
|
|
## Usage
|
|
|
|
Typical host initialization pattern:
|
|
|
|
```dart
|
|
final Wolf3dFlutterEngine engine = await Wolf3dFlutterEngine(
|
|
debug: kDebugMode,
|
|
).init();
|
|
```
|
|
|
|
`init()` handles platform setup, audio init, configured external discovery, and
|
|
optional seeded game injection.
|
|
|
|
To load packaged game data from `wolf_3d_assets`, use
|
|
`Wolf3dFlutterEngine.loadGameDataFromAssets(...)` and pass the result via
|
|
`seededGames`:
|
|
|
|
```dart
|
|
final retail = await Wolf3dFlutterEngine.loadGameDataFromAssets(
|
|
version: GameVersion.retail,
|
|
packageName: 'wolf_3d_assets',
|
|
assetDirectory: 'assets/retail',
|
|
);
|
|
|
|
final shareware = await Wolf3dFlutterEngine.loadGameDataFromAssets(
|
|
version: GameVersion.shareware,
|
|
packageName: 'wolf_3d_assets',
|
|
assetDirectory: 'assets/shareware',
|
|
);
|
|
|
|
final Wolf3dFlutterEngine engine = await Wolf3dFlutterEngine(
|
|
debug: kDebugMode,
|
|
).init(seededGames: [retail, shareware]);
|
|
```
|
|
|
|
The facade itself lives in `lib/engine/wolf3d_flutter_engine.dart` and is re-exported
|
|
through the package barrel at `lib/wolf_3d_flutter.dart`. External consumers
|
|
should keep importing the barrel unless they have a specific reason to target
|
|
the engine library directly.
|
|
|
|
The same pattern applies to the Flutter input adapter and the desktop
|
|
persistence adapters: they now live in focused subdirectories and are
|
|
re-exported through `lib/wolf_3d_flutter.dart`.
|
|
|
|
For full host wiring examples, see:
|
|
|
|
- `apps/wolf_3d_gui/lib/main.dart`
|
|
|
|
## Package Structure
|
|
|
|
- `lib/wolf_3d_flutter.dart` — barrel export for the public Flutter package surface.
|
|
- `lib/engine/wolf3d_flutter_engine.dart` — high-level engine facade and discovery bootstrap.
|
|
- `lib/input/` — Flutter-specific input adapters.
|
|
- `lib/persistence/` — desktop persistence adapters for saves and renderer settings.
|
|
- `lib/renderer/` — renderer host widgets.
|
|
- `lib/managers/` — runtime/session/display/persistence managers.
|
|
- `lib/audio/` — platform-aware audio backends.
|
|
- `shaders/wolf_world.frag` — base fragment shader included in package configuration.
|
|
- `shaders/wolf_world_bloom.frag` — bloom-enabled fragment shader variant.
|
|
|
|
## Integration Notes
|
|
|
|
- Keep UI/platform concerns in this package or app hosts, not in `wolf_3d_dart`.
|
|
- Use exported APIs from `lib/wolf_3d_flutter.dart` rather than importing private internals from `lib/src` in dependencies.
|
|
- Shader paths are declared in this package `pubspec.yaml` and must stay synchronized with renderer usage.
|
|
|
|
## Shader Architecture And Performance Notes
|
|
|
|
This package ships two shader variants:
|
|
|
|
- `shaders/wolf_world.frag` (base pass, no bloom taps)
|
|
- `shaders/wolf_world_bloom.frag` (bloom-enabled variant)
|
|
|
|
The renderer selects one variant in Dart based on runtime settings. This is a
|
|
performance decision: when bloom is disabled, we do not run bloom sampling code
|
|
at all.
|
|
|
|
### No-Branch Shader Policy
|
|
|
|
For package-owned shader sources, do not use `if` statements. Use branchless
|
|
selection patterns (`mix`, `step`, `smoothstep`, mask algebra) instead.
|
|
|
|
Static check:
|
|
|
|
```bash
|
|
rg "\bif\s*\(" packages/wolf_3d_flutter/shaders
|
|
```
|
|
|
|
Expected result: no matches in source shader files.
|
|
|
|
### Why This Is Different From Dart
|
|
|
|
If you are primarily a Dart developer, this is the key mindset shift:
|
|
|
|
- Dart code runs on CPU cores with branch prediction and comparatively cheap
|
|
control flow.
|
|
- Fragment shaders run across many pixels in parallel on GPU SIMD/SIMT lanes.
|
|
- If neighboring pixels take different branches, the GPU can serialize branch
|
|
paths (divergence), reducing throughput.
|
|
- Texture reads are usually more expensive than scalar ALU math. Removing bloom
|
|
work entirely when disabled is often better than trying to gate it inside one
|
|
shader.
|
|
|
|
In short: in Dart, `if` can be good structure. In fragment shaders, branchless
|
|
math and pass selection are often better for frame time.
|
|
|
|
### Dart-Style Thinking vs Shader-Style Thinking
|
|
|
|
CPU/Dart style:
|
|
|
|
```dart
|
|
if (effectsEnabled) {
|
|
uv = warp(uv);
|
|
}
|
|
if (outsideScreen(uv)) {
|
|
return bezelColor;
|
|
}
|
|
```
|
|
|
|
Shader style used here:
|
|
|
|
```glsl
|
|
vec2 effectiveUv = mix(uv, warpedUv, effectsMask);
|
|
float bezelMask = (1.0 - insideMask) * effectsMask;
|
|
vec3 outColor = mix(screenColor, bezelColor, bezelMask);
|
|
```
|
|
|
|
Both produce feature-equivalent behavior, but the second keeps execution paths
|
|
uniform across fragments.
|
|
|
|
### Shader Block Guide (What / Why)
|
|
|
|
1. UV normalization:
|
|
Convert fragment coordinates to 0..1 UV so all sampling math is resolution
|
|
agnostic.
|
|
|
|
2. Barrel warp:
|
|
Simulates curved CRT glass by pushing UVs outward as radius increases.
|
|
|
|
3. Inside/outside mask:
|
|
Computes whether warped UV remains on the emissive screen rectangle. This
|
|
replaces branch-based bezel routing.
|
|
|
|
4. Edge-aware AA:
|
|
Computes local luma span from N/S/E/W neighbors and blends toward neighborhood
|
|
average only where contrast indicates potential aliasing.
|
|
|
|
5. CRT modulation:
|
|
Applies scanlines, moving sweep, center lift, and vignette to mimic phosphor
|
|
and lens behavior.
|
|
|
|
6. Bezel shading:
|
|
Uses overflow distance and edge bleed sampling to build depth, inner lip, and
|
|
scene-tinted glow on bezel regions.
|
|
|
|
7. Bloom variant only:
|
|
Adds three-ring cross taps, brightness gating, and tone mapping. This code is
|
|
in a separate shader so bloom-off mode avoids paying this cost.
|
|
|
|
### Constant Tuning Reference
|
|
|
|
- Warp factor: `0.045`
|
|
Higher = stronger curvature.
|
|
|
|
- AA blend ceiling: `0.45`
|
|
Higher = softer edges, more blur risk.
|
|
|
|
- Scanline band: `0.88 + 0.12 * sin(...)`
|
|
Lower floor or higher amplitude increases CRT stripe intensity.
|
|
|
|
- Sweep speed: `uTime * 0.08`
|
|
Higher = faster sweep line travel.
|
|
|
|
- Bloom ring radii: `3`, `7`, `13` texels
|
|
Larger radii spread glow farther but increase halo size.
|
|
|
|
- Bloom gain: `0.42`
|
|
Higher = brighter bloom before tone map.
|
|
|
|
- Tone map: `color / (color + 0.75) * 1.75`
|
|
Controls highlight rolloff and midtone lift.
|
|
|
|
### Glossary
|
|
|
|
- UV: normalized texture coordinates in [0, 1].
|
|
- Luma: perceived brightness estimate from RGB.
|
|
- Mask: scalar 0..1 value used to blend between alternatives.
|
|
- Vignette: edge darkening effect.
|
|
- Tone map: compresses highlights into displayable range.
|
|
- Tap: one texture sample read.
|
|
- Divergence: parallel shader lanes taking different branches.
|
|
|
|
### Profiling Expectations
|
|
|
|
- Bloom disabled: base shader variant runs, no bloom taps.
|
|
- Bloom enabled: bloom shader variant runs, additional texture sampling cost.
|
|
- Effects disabled: both shaders still remain branchless; effect contribution is
|
|
blended out by mask values.
|
|
|
|
## Troubleshooting
|
|
|
|
- **No discovered game data**: confirm configured/persisted data directory paths are valid.
|
|
- **Desktop behavior mismatch**: verify desktop windowing and audio dependencies are available on the target OS.
|
|
- **Render issues after shader changes**: confirm shader path and package config are still aligned.
|
|
|
|
## Related Modules
|
|
|
|
- Core runtime package: [`../wolf_3d_dart/README.md`](../wolf_3d_dart/README.md)
|
|
- GUI host app: [`../../apps/wolf_3d_gui/README.md`](../../apps/wolf_3d_gui/README.md)
|
|
- Shared assets package: [`../wolf_3d_assets/README.md`](../wolf_3d_assets/README.md)
|
|
- Workspace overview: [`../../README.md`](../../README.md)
|