Custom Materials

How to use custom materials in uikit.

uikit allows to provide custom material classes for the background and border on the Text, Container, and Image components. This allows to change the appearance and use more complex (and computationally expensive) materials such as a MeshPhysicalMaterial.

In the following example, we are creating a text element with a material based on the phong material with high specular and shininess. Using the border properties, we can create a border that creates the illusion of a 3D Mesh. Specifically, the borderBend property allows bending the normals on the border to create this effect efficiently.

import { Canvas } from '@react-three/fiber'
import { OrbitControls } from '@react-three/drei'
import { Root, Text } from '@react-three/uikit'
import { MeshPhongMaterial } from 'three'

class FancyMaterial extends MeshPhongMaterial {
constructor() {
  super({
    specular: 0x111111,
    shininess: 100,
  })
}
}

export default function App() {
return (
  <Canvas style={{ position: "absolute", inset: "0", touchAction: "none" }} gl={{ localClippingEnabled: true }}>
    <OrbitControls />
    <directionalLight position={[1,0,1]} intensity={10} />
    <Root>
      <Text
        backgroundColor="black"
        color="white"
        padding={24}
        borderRadius={32}
        fontSize={32}
        borderColor="black"
        borderBend={0.3}
        borderWidth={8}
        panelMaterialClass={FancyMaterial}
      >
        I look fancy
      </Text>
    </Root>
  </Canvas>
)
}

Let's go through the above example step by step. First, we are importing the necessary dependencies.

import { Canvas } from '@react-three/fiber'
import { OrbitControls } from '@react-three/drei'
import { Root, Text } from '@react-three/uikit'
import { MeshPhongMaterial } from 'three'

Then, we create a class for the material we want to adapt by changingthe default values.

class FancyMaterial extends MeshPhongMaterial {
  constructor() {
    super({
      specular: 0x111111,
      shininess: 100,
    })
  }
}

Lastly, the UI can be defined using a Root and Text component.

export default function App() {
  return (
    <Canvas>
      <OrbitControls />
      <Root>
        <Text
          backgroundColor="black"
          color="white"
          padding={24}
          borderRadius={32}
          fontSize={32}
          borderColor="black"
          borderBend={0.3}
          borderWidth={8}
          panelMaterialClass={FancyMaterial}
        >
          I look fancy
        </Text>
      </Root>
    </Canvas>
  )
}