useTexture loads a PNG or JPEG and returns a three.js texture, or null while it loads. Images are decoded natively from their bytes (Hermes has no image decoder of its own), shared between components, and freed when the last user unmounts.
import { Box, Scene } from "@apricot/react";
import { useTexture } from "@apricot/react/model";
export function CerealBox() {
const front = useTexture(require("./assets/cereal-front.png"));
return (
<Scene style={{ flex: 1 }} look="studio">
<Box size={[1.6, 2.2, 0.5]} material={{ preset: "standard", color: "#ffffff", map: front }} />
</Scene>
);
}- Import it from
@apricot/react/model. srcis a bundled image (require(...)) or a URL.- Use
color: "#ffffff"with amap: the image is multiplied by the material's colour, and most presets are not white. - A
<Box>shows the image on each of its six faces. For one face, use a<Plane>or a model with UVs.
Options#
useTexture(src, options):
| Option | Default | Use |
|---|---|---|
colorSpace |
sRGB | Colour images. Pass NoColorSpace (from three) for data such as masks and normal maps. |
flipY |
true |
Image rows map top to bottom, as three.js expects. |
repeat |
false |
Tile the image instead of stretching the edge pixels. |
premultiplyAlpha |
true |
Keep colours premultiplied by alpha (what phone decoders produce). Preset materials handle it. Pass false only for three.js materials of your own that expect straight colour. |
Errors#
useTexture logs failures and returns null. To show what went wrong, use useTextureState, which returns { texture, error }:
import { Plane } from "@apricot/react";
import { useTextureState } from "@apricot/react/model";
export function Photo({ url }: { url: string }) {
const { texture, error } = useTextureState(url);
return <Plane size={[3, 2]} material={{ preset: "standard", color: error ? "#ff4d4f" : "#ffffff", map: texture }} />;
}Engraving and printing#
A mask image (opaque = engraved) passed as engrave changes the colour, roughness and metalness where the mask is set. This is how the metal card's art is engraved:
import { Box, Scene } from "@apricot/react";
import { useTexture } from "@apricot/react/model";
export function Engraved() {
const mask = useTexture(require("./assets/logo-mask.png"));
return (
<Scene style={{ flex: 1 }} look="none" environment="studio" background="#0e0f12">
<Box
size={[3, 2, 0.05]}
radius={0.02}
material={{
preset: "brushed-metal",
engrave: mask ? { mask, color: "#6f737a", roughness: 0.62, metalness: 1 } : null,
}}
/>
</Scene>
);
}For payment cards, <Card art> from @apricot/assets does this for every finish: see the card-tilt recipe.
Related#
- Shapes and materials.
- Model reference:
useTexture,useTextureState.