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

Hi,
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!

Three.js

Blender

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.

4 Likes

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

Blender

Three.js

Blender

Three.js

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.

4 Likes

Would you mind sharing your Tonemapping function? I’m running into similar problems with ACES at the moment.

follow the advice in that thread, it contains everything you need to set up

Thanks, that helps. I already have the outputencoding and tonemapping set up, its just that using a HDRI in Blender and using that some one in Three give wildly different results, mostly relating to highlight and shadow clipping.
Since Three supports custom tonemapping I’m sure the default Blender Film tonemapping can be achieved somehow :slight_smile:

acesfilmic and blender filmic seem near identical, but the again i haven’t studied details. i believe @donmccurdy was working on a different filmic curve.

Yes, you can find it here:

It depends on the postprocessing package to run, and is currently more expensive than other tone-mapping options, requiring two LUT samples. Perhaps there are cheaper ways to approximate this, I haven’t had much time to improve it lately.

1 Like

Thanks for sharing. I was hoping it would be as simple as adding a custom Tonemapping; I’m not sure if the extra passes justify the difference in output.
Especially since @drcmda is saying ACES and Blender filmic are near identical… something I’m not experiencing at all.

I’ll get some screenshots going.

ACES Filmic and Blender Filmic have similar goals, but it wouldn’t shock me at all if for some scenes they give fairly different visual output. Neither is designed to match the other, they are simply “mostly similar” because good tonemapping approaches for PBR rendering must do certain things.

If you have some familiarity with color grading (I do not) then it’s also possible to create a LUT or write a custom effect pass and define your own tone mapping.