I was looking at a three.js example where the writer draws numbers on each of the faces of an icosahedron using a canvas and a Three.CanvasTexture:
https://hofk.de/main/discourse.threejs/2021/NumberedIcosahedron/NumberedIcosahedron.html
I wondered if it was possible to extend the example to have more complex drawings on each face, or even animations. I discovered the RenderTexture component in drei and the example shown there:
https://drei.docs.pmnd.rs/portals/render-texture
It shows how to use RenderTexture to draw a complex animation on the faces of a cube.
I am attempting to combine the two examples to use RenderTexture to draw on an Icosahedron. I imagine I need to use RenderTexture to create a similar 1024×64 texture, just like in the first example. Then adopt the same uv mapping. I imagine that will produce the same result as the first example, but with the power of whatever RenderTexture can render. I got to the following point:
import { Canvas } from '@react-three/fiber'
import {
RenderTexture,
OrbitControls,
Text,
OrthographicCamera
} from '@react-three/drei'
import { suspend } from 'suspend-react'
const inter = import('@pmndrs/assets/fonts/inter_regular.woff')
export default function App() {
return (
<Canvas camera={{ position: [5, 5, 5], fov: 25 }}>
<ambientLight intensity={0.5} />
<directionalLight position={[10, 10, 5]} />
<Icosahedron />
<OrbitControls />
</Canvas>
)
}
const numbers = [
...Array(20)
.keys()
.map((n) => n + 1)
]
const step = 1024 / 20
const start = step * 0.5
const uvs = new Float32Array(120)
for (let i = 0; i < 20; i++) {
uvs[i * 6] = (0.067 + i) / 20
uvs[i * 6 + 1] = 0.25
uvs[i * 6 + 2] = (0.933 + i) / 20
uvs[i * 6 + 3] = 0.25
uvs[i * 6 + 4] = (0.5 + i) / 20
uvs[i * 6 + 5] = 1
}
function Icosahedron() {
return (
<mesh>
<icosahedronGeometry args={[1, 0]}>
<bufferAttribute
attach="attributes-uv"
count={60}
array={uvs}
itemSize={2}
/>
</icosahedronGeometry>
<meshStandardMaterial>
<RenderTexture attach="map" width={1024} height={64}>
<OrthographicCamera
makeDefault
args={[0, 1024, 0, 64, 1, 10]}
position={[0, 0, 5]}
/>
<color attach="background" args={['#111']} />
<ambientLight intensity={0.5} />
<directionalLight position={[10, 10, 5]} />
{numbers.map((n, i) => (
<Text
key={`text_${i}`}
position={[start + step * i, 0, 0]}
color="#FFF"
anchorX="center"
anchorY="middle"
font={suspend(inter).default}
fontSize={20}>
{`${n}`}
</Text>
))}
</RenderTexture>
</meshStandardMaterial>
</mesh>
)
}
However, the numbers draw are distorted and not in the correct positions. Am I approaching the problem in the correct way? Is RenderTexture even the right thing to use here? With the goal of drawing complex, animating faces on an icosahedron or similar shape.


