Reflections and Refractions in three JS

I have been attempting to further advance my webgl skills by attempting to replicate various webgl projects I have seen online like this one (KUBOTA FUTURE CUBE | Kubota Global Site), it seemed simple at first, a cube with a textured sphere inside of it but the devil is in the detail.
I have been able to replicate everything except for the reflection effect seen inside the glass cube.
If you look closely, you will notice that internal faces of the cube are reflecting the globe and that the cube itself has a PBR material attached creating this nice refraction effect when the cube is rotated.
I have been unable to copy this effect and I was wondering if someone could help me by just pointing in me in the right direction.
I understand how to make a mesh reflect objects (using the reflector class) within the scene but I dont know how to make this plane also have a glass like effect with proper refraction when looked at from different angles.

This would be a good walkthrough for the effect, using THREE.MeshPhysicalMaterial

The demo “Kubota Future Cube” is likely doing something more customized here, rather than a stock material.

This would be a good walkthrough for the effect, using THREE.MeshPhysicalMaterial

I am already closely familiar with PBR materials, I have no issue recreating a glass cube, just achieving the proper reflections and retractions.

The demo “Kubota Future Cube” is likely doing something more customized here, rather than a stock material.

Sounds about right, what I am curious about is how they went about achieving that.
I just wish someone more familiar with computer graphics could just point me in the right direction, as I do not have the time to jump into all the rabbit holes necessary to achieve this.

You can get very nearly the same effect (including refraction!) using only PBR materials like THREE.MeshPhysicalMaterial. I think you’ll find what you need in this tutorial.

1 Like

you can use meshtransmissionmaterial instead, it “sees” backfaces, but also has anisotropic blur and chroma. it looks imo a lot better than mpm.

some examples

it is also available for vanilla three GitHub - pmndrs/drei-vanilla: 🍦 drei-inspired helpers for threejs

ps, there’s also another one in drei just for realistic refraction alone, meshrefractionmaterial, but you would normally only use this for glass and diamonds, though in this case it could maybe work as well

1 Like

I already tried the mesh physical material before asking this questions and I got the nice refraction effect but no internal reflection.

My main issue is getting the backfaces of the cube to reflect the globe whilst also getting the refraction effect, I havent tested Drei’s mesh transmission material yet, I will give it a try see if I can get it to work.

imo thats just negative thickness, the kubota thing is probably not physically accurate but if that’s what you’re going for … HTML Markers (forked) - CodeSandbox

i don’t think this will be possible with meshphyiscalmaterial because it can’t look through itself.

1 Like

Indeed it is, that’s what makes it so hard to replicate.

Yep, tried it with MSM didnt work.
My idea was to create a bunch of reflective mirror planes inside the cube itself using the three JS reflector class.
It didnt work at all.

Since r151, the transmission feature of MeshPhysicalMaterial supports this as well.

1 Like

you would have to control the thickness for backfaces separately to get the kubota cube. the sandbox that i posted yesterday HTML Markers (forked) - CodeSandbox can you try with mpm if it does that? i wasn’t able to configure it, and even if it makes the backfaces reflect the inner contents it then wouldn’t refract on the front faces.
mtm looks in my opinion better in the end due to chroma and anisotropic blur, i think anything that refracts is probably better off with that, and it can have backface thickness. vanilla version is here GitHub - pmndrs/drei-vanilla: 🍦 drei-inspired helpers for threejs

I have tried to do the same on vanilla three.js, but for some reason, backsideThickness is not working


backside requires an additional renderpass. this can’t be properly packed into a class, you need to look into the useFrame of the react component where it’s doing that and copy that code as well. it’s the material and the webglrendertarget stuff.

It’s deeply unfortunate that the excellent developers behind react three fiber refuse to properly support vanilla three JS, I understand why they do this as they are probably being paid to expand the react ecosystem but still it goes against the spirit of the FOSS community.

nobody is paid to expand react. react is a tool that enables re-use. but re-use requires groundwork. if threejs had the requirements to form an interoprable eco system it would have done so long time ago, but it doesn’t, because a class can not substitute a component. people have to understand the differences between low level (webgl), mid level (threejs, globbing gl calls into primitives like cameras, meshes etc) and high level (components and functional composition, which does not exist in the oop realm). think about this, your argument can be 1:1 applied to poor webgl programmers that can’t benefit from three primitives — because their paradigm forbids it, low level is not mid level.

we are sharing everything that can be shared, everything is open source, we put all the agnostic stuff into vanilla libraries, we maintain the libraries that the vanilla community has neglected, we even bend over backwards to curate GitHub - pmndrs/drei-vanilla: 🍦 drei-inspired helpers for threejs but all this is constrained by classes.

anything that exceeds simple behaviour and requires lifecycles, awareness of the environment, context, suspense etc is not possible to express with classes, it requires a higher paradigm: interop is the result of functional composition between components that do not know one another.

look at three/examples — this is what happens when complicated things are shared in the vanilla space. very little of this is readily re-usable, they are basically applications. the time you spend untangling them is probably more than porting the react component because at least it is orderly.

2 Likes