This article is part of a series of articles about three.js. The first article is three.js fundamentals. If you haven't read that yet and you're new to three.js you might want to consider starting there.
Three.js provides several types of materials. They define how objects will appear in the scene. Which materials you use really depends on what you're trying to accomplish.
There are 2 ways to set most material properties. One at creation time which we've seen before.
const material = new THREE.MeshPhongMaterial({ color: 0xFF0000, // red (can also use a CSS color string here) flatShading: true, });
The other is after creation
const material = new THREE.MeshPhongMaterial(); material.color.setHSL(0, 1, .5); // red material.flatShading = true;
note that properties of type THREE.Color
have multiple ways to be set.
material.color.set(0x00FFFF); // same as CSS's #RRGGBB style material.color.set(cssString); // any CSS color, eg 'purple', '#F32', // 'rgb(255, 127, 64)', // 'hsl(180, 50%, 25%)' material.color.set(someColor) // some other THREE.Color material.color.setHSL(h, s, l) // where h, s, and l are 0 to 1 material.color.setRGB(r, g, b) // where r, g, and b are 0 to 1
And at creation time you can pass either a hex number or a CSS string
const m1 = new THREE.MeshBasicMaterial({color: 0xFF0000}); // red const m2 = new THREE.MeshBasicMaterial({color: 'red'}); // red const m3 = new THREE.MeshBasicMaterial({color: '#F00'}); // red const m4 = new THREE.MeshBasicMaterial({color: 'rgb(255,0,0)'}); // red const m5 = new THREE.MeshBasicMaterial({color: 'hsl(0,100%,50%)'}); // red
So let's go over three.js's set of materials.
The MeshBasicMaterial
is not affected by lights.
The MeshLambertMaterial
computes lighting only at the vertices vs the MeshPhongMaterial
which computes lighting at every pixel. The MeshPhongMaterial
also supports specular highlights.
The shininess
setting of the MeshPhongMaterial
determines the shininess of the specular highlight. It defaults to 30.
Note that setting the emissive
property to a color on either a
MeshLambertMaterial
or a MeshPhongMaterial
and setting the color
to black
(and shininess
to 0 for phong) ends up looking just like the MeshBasicMaterial
.
Why have all 3 when MeshPhongMaterial
can do the same things as MeshBasicMaterial
and MeshLambertMaterial
? The reason is the more sophisticated material
takes more GPU power to draw. On a slower GPU like say a mobile phone
you might want to reduce the GPU power needed to draw your scene by
using one of the less complex materials. It also follows that if you
don't need the extra features then use the simplest material. If you don't
need the lighting and the specular highlight then use the MeshBasicMaterial
.
The MeshToonMaterial
is similar to the MeshPhongMaterial
with one big difference. Rather than shading smoothly it uses a gradient map
(an X by 1 texture) to decide how to shade. The default uses a gradient map
that is 70% brightness for the first 70% and 100% after but you can supply your
own gradient map. This ends up giving a 2 tone look that looks like a cartoon.
Next up there are 2 physically based rendering materials. Physically Based Rendering is often abbreviated PBR.
The materials above use simple math to make materials that look 3D but they aren't what actually happens in real world. The 2 PBR materials use much more complex math to come close to what actually happens in the real world.
The first one is MeshStandardMaterial
. The biggest difference between
MeshPhongMaterial
and MeshStandardMaterial
is it uses different parameters.
MeshPhongMaterial
had a shininess
setting. MeshStandardMaterial
has 2
settings roughness
and metalness
.
At a basic level roughness
is the opposite
of shininess
. Something that has a high roughness, like a baseball doesn't
have hard reflections whereas something that's not rough, like a billiard ball,
is very shiny. Roughness goes from 0 to 1.
The other setting, metalness
, says
how metal the material is. Metals behave differently than non-metals. 0
for non-metal and 1 for metal.
Here's a quick sample of MeshStandardMaterial
with roughness
from 0 to 1
across and metalness
from 0 to 1 down.
The MeshPhysicalMaterial
is same as the MeshStandardMaterial
but it
adds a clearcoat
parameter that goes from 0 to 1 for how much to
apply a clearcoat gloss layer and a clearCoatRoughness
parameter
that specifies how rough the gloss layer is.
Here's the same grid of roughness
by metalness
as above but with
clearcoat
and clearCoatRoughness
settings.
The various standard materials progress from fastest to slowest
MeshBasicMaterial
➡ MeshLambertMaterial
➡ MeshPhongMaterial
➡
MeshStandardMaterial
➡ MeshPhysicalMaterial
. The slower materials
can make more realistic looking scenes but you might need to design
your code to use the faster materials on low powered or mobile machines.
There are 3 materials that have special uses. ShadowMaterial
is used to get the data created from shadows. We haven't
covered shadows yet. When we do we'll use this material
to take a peek at what's happening behind the scenes.
The MeshDepthMaterial
renders the depth of each pixel where
pixels at negative near
of the camera are 0 and negative far
are 1. Certain special effects can use this data which we'll
get into at another time.
The MeshNormalMaterial
will show you the normals of geometry.
Normals are the direction a particular triangle or pixel faces.
MeshNormalMaterial
draws the view space normals (the normals relative to the camera).
x is red,
y is green, and
z is blue so things facing
to the right will be pink,
to the left will be aqua,
up will be light green,
down will be purple,
and toward the screen will be lavender.
ShaderMaterial
is for making custom materials using the three.js shader
system. RawShaderMaterial
is for making entirely custom shaders with
no help from three.js. Both of these topics are large and will be
covered later.
Most materials share a bunch of settings all defined by Material
.
See the docs
for all of them but let's go over two of the most commonly used
properties.
flatShading
:
whether or not the object looks faceted or smooth. default = false
.
side
: which sides of triangles to show. The default is THREE.FrontSide
.
Other options are THREE.BackSide
and THREE.DoubleSide
(both sides).
Most 3D objects drawn in three are probably opaque solids so the back sides
(the sides facing inside the solid) do not need to be drawn. The most common
reason to set side
is for planes or other non-solid objects where it is
common to see the back sides of triangles.
Here are 6 planes drawn with THREE.FrontSide
and THREE.DoubleSide
.
There's really a lot to consider with materials and we actually still have a bunch more to go. In particular we've mostly ignored textures which open up a whole slew of options. Before we cover textures though we need to take a break and cover setting up your development environment