Materials in react-three-fiber

Materials in react-three-fiber

In a 3D application things look a bit nicer if they have a material. A material is a set of parameters that instruct the renderer how to draw the surface of the geometry. That's not the same as a texture - a material might have a texture image, but it doesn't have to.

In Three.JS there are lots of different types of material, but for the purpose of this post we're only going to look at five;

  • meshBasicMaterial - the simplest material type
  • meshLambertMaterial - material that uses Lambert shading
  • meshPhongMaterial - material that uses Phong shading
  • meshStandardMaterial - material that uses Metallic-Roughness PBR shading
  • meshPhysicalMaterial - an extended version of meshStandardMaterial

Which type of material we should use really depends on what we want an object in the scene to look like. There are factors to balance. meshBasicMaterial, meshLambertMaterial, and meshPhongMaterial are all reasonably simple to define and fast to render. meshStandardMaterial and meshPhysicalMaterial are a bit more complicated and take longer to render but they look much better.

Materials versus Textures

Something to note is that materials are not textures. A texture is a part of a material. There are several texture options in most of the material options here - Three.JS can handle diffuse, bump, normal, specular and environment maps on the basic materials and even more on the Physically Based Rendering materials. Those will all be covered in later posts.

A big red ball

For the examples in this post we're going to use one of basic geometries in Three.JS - sphereGeometry. This generates a sphere that gives us a geometry that shows off the lighting and shading of each material rather well.

From left to right the materials in this example are meshBasicMaterial, meshLambertMaterial, meshPhongMaterial, meshStandardMaterial (with metalness and roughness) and meshPhysicalMaterial (with metalness, roughness and clearcoat).

Choosing a material depends on the level of control you need over how it looks, and how that balances with the speed of rendering. On that note though it is worthwhile noting that all of the materials are very fast to render once they've been loaded on to the GPU. Unless you have a lot going on in a scene, with material attributes changing in each frame, it's very unlikely to be worthwhile optimizing your materials before looking at other aspects of a page. However, it's wrong to waste the user's battery power or processing time unnecessarily, so it's still worth considering a 'lesser' material if that's all you really need.

meshBasicMaterial on the left of the example balls is by far the simplest and most basic material available. It literally just applies a color to your geometry. Lighting and shading are ignored. That's quite handy if you just need to see something in the scene, but rarely what you actually want in the application.

The next two examples, meshLambertMaterial and meshPhongMaterial, use approximate lighting and shading models to give a geometry highlights and shadows using the Lambert and Phong algorithms. They're excellent for developing fast small applications like games and visualisations. Plus they're really easy to define as they can be used with nothing more than a color attribute.

The final two materials are meshStandardMaterial and it's more complicated cousin meshPhysicalMaterial. These two materials take a Three.JS scene up a level by providing a physical rendering algorithm to shade a geometry. They can give a huge boost to how realistic something looks.

meshShaderMaterial

meshShaderMaterial is the most flexible material in Three.JS as it gives complete control over the rendering of something, but at the same time that control comes with a lot of complexity (including needing to learn a new programming language to use it.) It's a bit beyond the scope of this post.