Geek Culture
Published in

Geek Culture

Simulating Refraction in Three.js

Four magic orbs of refractive powers!

Last time, I made a simple wine glass in Blender and rendered it using Three.js. It mostly demonstrated the transmission property of the MeshPhysicalMaterial. This time I’m gonna show you how to simulate the refractive effects of the MeshPhysicalMaterial.

How refraction works in Three.js

It is actually much simpler than you think.

All you need for simulating refraction in Three.js is having these three properties set:

const material1 = new THREE.MeshPhysicalMaterial({
roughness: 0,
transmission: 1,
thickness: 2
});

First of all, setting transmission to 1 makes it transmissive. Then, set roughness to 0 or a very low value such that the material surface is smooth enough for us to clearly see through it. The final magic: giving your material a thickness so that it has the effect of a magnifying glass. The higher the thickness, the higher the magnifying property of your material.

Try my codesandbox embed below and tweak the settings to see how it affects the outcome:

There is one caveat though. Although the effects look real enough, it is not actually how real-life refraction works!

In real-life scenarios, if the refracted scenery or object is far enough from the glass orb, you should actually see an upside-down refraction. But in Three.js, this upside-down effect cannot be achieved from setting thickness in the PBR material.

real-life orb refraction

Iterations with normalMap and clearcoatNormalMap

I also made this other example that has 4 different glass orbs to show how other map properties affect the final refractive outcome in different interesting ways.

Firstly, I loaded an equirectangular texture on the envMap of all these orbs such that they have more realistic reflections.

For the first(top-left) orb, it has the most basic settings.

For the second(top-right) orb, I turned clearcoat to max and set a clearcoatNormalMap which is basically a normal map of scratched lines. You should be able to spot out some of those scratches at the brightest areas on the orb’s reflection. Clearcoat simulates the effect of another layer of reflective coating being applied on surfaces. Real-life examples are car paint, polished floor and wet surfaces. I also made it rougher and thicker so as to act as a clearer comparison to the first orb.

const material2 = new THREE.MeshPhysicalMaterial({
envMap: hdrEquirect,
roughness: 0.15,
clearcoat: 1,
clearcoatNormalMap: clearcoatNormal,
transmission: 1,
thickness: 4
});

For the third(bottom-left) orb, I applied a golf ball normal map for the normalMap property, resulting in this beautiful glass golf ball. We apply normal maps on materials to instruct Three.js to calculate reflections/refractions on each pixel according to the normal values provided by the normal map. The result is that reflections/refractions will look as if the material surface is uneven and bumpy, but in fact the material surface is still smoothly rendered according to the geometry.

For the refractions on the golf ball pattern to be more evident, I have to add in a little roughness.

const material3 = new THREE.MeshPhysicalMaterial({
envMap: hdrEquirect,
normalMap: golfNormal,
roughness: 0.15,
transmission: 1,
thickness: 2
});
the normal map jpg file of a golf ball

For the last orb, I applied the scratched clearcoatNormalMap and a different normalMap to contrast with the golf orb.

const material4 = new THREE.MeshPhysicalMaterial({
envMap: hdrEquirect,
normalMap: roughNormal,
clearcoat: 1,
clearcoatNormalMap: clearcoatNormal,
roughness: 0.15,
transmission: 1,
thickness: 2
});
the normal map jpg file of a rugged surface

And that’s it for this tutorial! Feel free to fork my codesandbox projects and mess around.

Shout out to https://tympanus.net/codrops/2021/10/27/creating-the-effect-of-transparent-glass-and-plastic-in-three-js/ which is a great tutorial and inspiration for me on this demo.

--

--

--

A new tech publication by Start it up (https://medium.com/swlh).

Recommended from Medium

How to center div or text horizontally and vertically

Ok, this is pretty fun for me so I hope you enjoy it.

Dynamically creating input fields in the Angular form

Tic-tac-toe game in React and Redux

A Blend Of JavaScript With Mendix Components to Enhance Our Mendix Application

Send SMS using Twilio Api in Node.js — Tutorial 2021

React-Slick in React.js Web Applications

Phaser a gaming library for Robot navigation.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Franky Hung

Franky Hung

Founder of Arkon Digital. I’m not a code fanatic, but I’m always amazed by what code can do. The endless possibilities in coding is what fascinates me everyday.

More from Medium

Creating Tony Stark’s “Badassium” in Three.js

Capturing Motion

ThreeJS objects reacting on audio

Internationalization Support: Spanish (and Beyond) Localization for the Processing Website