Photorealistic render comparison, why does three.js look so bad?

I’m trying to setup the most realistic renderer in Three.js as you could get. I put together this comparison with Blender (real time evee, no raytracing or else) on one side and Three.js on the other. Both have The same HDRI lighting with the same orientation. They both use Filmic Tonemapping (ACES for three.js) and sRGB as output encoding. The materials are the same (PBR) and the maps are 8k in both. What can I tweak, what shader can I create, what tricks should I use to get the Three.js as good looking as blenders ? I hope I haven’t reached a glass ceiling here. Would love to get some insightful input from you guys!



If you take a scene optimized for Three.js, then import it in Blender, it will look awful too. The same will happen between expensive 3D graphics software, they are different engines, handling things differently.
So you have to do exactly that: optimize your scene for Three.js, play with lights, shaders, material parameters, until you get it right.

At first glance, you might have to lower glossiness, also the bumb map appears reversed for some reason, these are easy fixes.


Nice catch on the bump map, that made it look much better! Thanks! I know I need to setup lights and stuff, that’s what I usually do but I wanted to have the same scene in both softwares so I could compare other stuff easily like tone mapping, exposure, maybe color correction.

1 Like

Could you post another comparison after your corrections, please ?

Here are the updated comparisons





I might need to lower the roughness a bit but other than that there still are some big differences.

  • Hue shift : the blue is a bit leaning toward cyan
  • Burnt highlights and crushed shadows : This is due to the ACESFilmicTonemapping. Maybe I should remove some contrast/brightness before Tonemapping happens that way I wouldn’t loose that much info. The highlight fallof in Blender is miles better.
  • Blender might look a bit underexposed but that’s how it should be, I used a pretty dark HDRI. Three.js is overexposing the highlights here, but lowering the render Exposure in Three.js is making it look dirty and too contrasted.
  • The specular highlight on the blue part in Blender look more sharp, more defined, more real.

What do you guys think ?

There is an extra light in three js looks like.

How/where do you put a bump map on a MeshPhysicalMaterial? or you r talking about a NormalMap?

There actually is no extra light in Three.js, it just looks like it adds more contrast and brightness to the final. But the downside of it is that when I do add more lights, highlight fall off gets clipped and doesn’t look as real as blenders.

Yes I meant normal map sorry

Other comparison that shows how much contrast is added in three.js. It feels a bit fake with those clipped highlights and shadows

i think its just harsh light placement with too little ambience that throws it off. if you want i could have a look, given that you are at liberty to publish the gltf.

I know I could get a matching result regarding exposure and contrast but I could never get the same accurate highlight roll off that blender has. I would always get clipping highlights or shadows. Seems like the Dynamic range is clamped in Three.js.

you can get similar results with good environment maps, ambient light, light placement, fog, lut’s - there are a lot of tools to shape the outcome. i was digging through some examples i’ve made and here’s one that more or less fits the description: Shoe configurator - CodeSandbox there’s no way that harsh looking result you got there is all threejs can do, it most definitively could get blenders flat look with a bit of tweaking.

Hi all. Figured out one of the reasons why my result looked bad. I had to add
.encoding = THREE.sRGBEncoding;
to the diffuse texture. I read that GlTFLoader does it on its own but actually it doesn’t. Now my shoe looks almost as it does in Blender. I still coded my own tone mapping function because ACES looks too contrasted but other than that, the only things I needed to do were flipping the normal map and encoding the diffuse texture in sRGB.