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

Add Properties Conditionally to an Object or an Array

Learn: Hamming Distance in Javascript

Node.js(CommonJS module specification) and require.js(AMD- asynchronous module definition)

Getting Started with Web Accessibility in React

//platform.twitter.com/widgets.js from Twitter https://twitter.com/thehikeexperts

Vst Plugin Error Reason

Implementing Eureka and Zuul for Service Discovery and Dynamic Routing in JavaScript Microservices…

you should learning Ant — Design — Mobile when you use React.js

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

Ready, set, Babylon.js!

Getting started with React Three Fiber.

ThreeJS — The most simple local developing environment with Vite

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