// photo in shape
Photo in shape
Any image (a photo, a logo, a map) can be wrapped onto a 3D shape. You give flutter_fiber the image bytes, it decodes them into a Fiber3DTexture, and you assign that texture to the map of a Fiber3DStandardMaterial. The shape's surface then shows the image, lit like any other surface.
There is no image-loading dependency. The package takes raw bytes from wherever you get them (app assets, a file, the network) and decodes them with Flutter's own image codec.
// demo
Demo
A world image wrapped around a Fiber3DSphere.
A logo on a Fiber3DBox. The same image appears on every face.
// how to use it
How to use it
Replace your_image.png with your own file. The three steps are the same for every shape.
1. Add the image to your app and declare it under flutter: assets: in your pubspec.yaml:
flutter:
assets:
- assets/images/your_image.png2. Load and decode it. Decoding is asynchronous, so wait for ensureDecoded() before using the texture. In a State class:
import 'package:flutter/services.dart' show rootBundle;
import 'package:flutter_fiber/flutter_fiber.dart';
Fiber3DTexture? _texture;
@override
void initState() {
super.initState();
_loadTexture();
}
Future<void> _loadTexture() async {
final data = await rootBundle.load('assets/images/your_image.png');
final bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
final texture = Fiber3DTexture(bytes);
await texture.ensureDecoded(); // texture.isReady is now true
if (!mounted) return;
setState(() => _texture = texture);
}3. Use it as the material's map on any shape. Here it is on a sphere. The surrounding canvas, camera and lights are set up as in Install & Quick Start:
// In build(): wait until the texture is ready.
final texture = _texture;
if (texture == null) {
return const Center(child: CircularProgressIndicator());
}
// Then, inside your Fiber3DCanvas children:
Fiber3DMesh(
geometry: Fiber3DSphere(radius: 1.8, widthSegments: 64, heightSegments: 48),
material: Fiber3DStandardMaterial(
color: 0xffffff, // white = show the image untinted
roughness: 0.85,
map: texture,
),
showEdges: false,
onFrame: (elapsed, delta, transform) {
transform.rotation.y = elapsed.inMicroseconds / 1e6 * 0.25; // slow spin
},
)// choosing a shape
Choosing a shape
Sphere (a globe or ball). The sphere wraps the image around itself, so use a wide image with a 2:1 ratio, like a flat world map (an equirectangular image). Raise widthSegments and heightSegments for a smoother surface.
Box (a logo, a label). Each of the six faces shows the whole image. Swap the geometry in step 3:
Fiber3DMesh(
geometry: Fiber3DBox(width: 1.0, height: 1.0, depth: 1.0),
material: Fiber3DStandardMaterial(
color: 0xffffff,
roughness: 0.6,
map: texture,
),
showEdges: false,
)A flat picture. Use a Fiber3DPlane with the same width-to-height ratio as the image, so it isn't stretched.
A different image on each face. One mesh holds one material, and so one image. To show a different image on each face, build the shape from separate planes, one per face, each with its own texture. The Text in shape page shows this with a six-sided die. It works the same way for images.
// tips & limits
Tips & limits
- Use
color: 0xffffffto show the image untinted. The material color multiplies the image, so any other color tints it. - With color management on (the default), the image is treated as sRGB, so its colors match the original file.
- The image is lit like any surface, so a dark image stays dark. If it looks too dim, raise the ambient light intensity or use a brighter image.
- Only
Fiber3DStandardMaterialaccepts textures. Images use the geometry's first UV set, linear filtering and clamp-to-edge wrapping, with no mipmaps. An image shown much smaller than its pixel size can look noisy, so resize large sources to roughly the size they will appear. - The decoded image is uploaded to the GPU once and is released when the canvas is disposed.