Glossy spheres in Three.js

A simple trick to improve the quality of your Three.js scenes

3 min readNov 29, 2016

--

Recently I’ve been on mr.doob’s website and I’ve been amazed by all his experiments.
I hadn’t (and for the most part, still haven’t) idea how to achieve such a level of quality with Three.js, therefore I decided to dive into his code and try to learn one cool thing at a time.

I haven’t found any clear explanation about this topic on the internet, so here it is! Hopefully this will save a couple hours to someone :)

(here you can find part 2 on animations with alpha textures and here another post on real-time reflections)

Glossy effect

Among the cool things from mr.doob’s screne was the photo realistic glossy effect of his materials, I decided to exploring the code from there.

What I want to achieve:

from mrdoob.com

(I’m going to talk about the material, not lights and background).

First of all, set this options in your WebGLRenderer

renderer.gammaInput = true;
renderer.gammaOutput = true;

To achieve that nice glossiness we have to use a THREE.MeshStandardMaterial, the new physically accurate material in Three.js.

var material = new THREE.MeshStandardMaterial({color: “#000”, roughness: 0});

At this point we have this:

We’re not quite there yet.

In order to have a believable glossy effect we need a reflex of something. The fastest way to create a reflex is to fake it with a texture. (an heavier solution would be to use real-time reflections)

Here’s the texture:

Let’s add it to our material as an environment map. (You can read more about the topic here)

var envMap = new THREE.TextureLoader().load('envMap.png');
envMap.mapping = THREE.SphericalReflectionMapping;
material.envMap = envMap;

And that’s what we’ve got now:

Here’s our glossy ball! Pretty cool, I’d say :)

Now if you feel fancy it’s possible to add some nice roughness to the material simply by using another texture. First of all let’s change the material’s roughness from 0 to 1, and then add the new texture.

Here’s the texture:

16x16 px black and white texture
var material = new THREE.MeshStandardMaterial({color: “#000”, roughness: 1});var roughnessMap = new THREE.TextureLoader().load('roughnessMap.png');
roughnessMap.magFilter = THREE.NearestFilter;
material.roughnessMap = roughnessMap;

Et voilà! that’s pretty close to what mr.doob has on his website, not considering light and background.

Complete example:

var geometry = new THREE.SphereGeometry(30, 64, 64); 
var material = new THREE.MeshStandardMaterial({ color: “#000”, roughness: 1 });

var envMap = new THREE.TextureLoader().load(‘envMap.png’);
envMap.mapping = THREE.SphericalReflectionMapping;
material.envMap = envMap;
var roughnessMap = new THREE.TextureLoader().load(‘roughnessMap.png’);
roughnessMap.magFilter = THREE.NearestFilter;
material.roughnessMap = roughnessMap;
roughnessMap.magFilter = THREE.NearestFilter;
material.roughnessMap = roughnessMap;
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);

Here’s a codepen for you to play around with (the textures are loaded as data uri, to avoid references external to the codepen).

Note: it won’t be so easy to achieve this effect in something other than a sphere. But probably mapping a different environment map with a different technique could help.

If you want real reflections from the environment of your mesh, take a look at CubeCamera.

Where can you find me?

Follow me on Twitter: https://twitter.com/psoffritti
My website/portfolio: pierfrancescosoffritti.com
My GitHub account: https://github.com/PierfrancescoSoffritti
My LinkedIn account: linkedin.com/in/pierfrancescosoffritti/en

--

--

Responses (1)