Page 1 of 1

Cycles: Fresnel term is incorrect - changes are needed.

Posted: Thu May 30, 2013 1:26 pm
by andcoder
I was doing some 3D scanning and rendering recently, trying to match real photographs as closely as possible. But in a lot of cases Cycles would produce very strange and highly unrealistic results while other engines like YafaRay and Mitsuba don't have those problems.
Cycles is great, its node system is really powerful, it's easy to prototype and tune stuff in, especially on my nVidia Titan.

So I reduced it to a single sphere surrounded with uniform red background and two spherical light sources. No diffuse + glossy BSDF with GGX normal distribution and a standard Fresnel node.

This is what you get (4 spheres with roughness 0.01, 0.1, 0.3 and 1.0) :

This is what shader looks like. Pretty standard. Here I use Mix Shader node but you can also plug it directly into Color and connect BSDF directly to Surface. That would be the same:

You can see what happens there with edges as roughness increases. You get this very unnatural outline around the edge.

Then I synced the code and looked at that Fresnel node (in fact, Layer Weight is also messed up) and discovered that it uses average normal instead of microfacet normal for both GGX and Beckmann roughness models. In fact, all the comments and references to equations are correct in actual BSDF nodes except that they don't compute Fresnel and leave it for Fresnel node.
That's a fundamental issue there. For microfacet models one has to compute Fresnel term based on microfacet normal since that's what the light really bounces off but not the average normal (whether it is geometry or pixel normal).

When Fresnel term is computed based on microfacet normal this is what you should get:

All direct highlights are fixed up and background fresnel effect is preserved.

With current shader system the best I could do is to do pre-integrated (kind of) Fresnel curve (should be really roughness dependent there):

Then you get something like this:

It helps with the outline but at the same time it removes the background (environment) reflection which is really bad since the object is no longer "married" to the environment.


The reason for this post is to raise awareness of the issue and start a discussion. Changes that I made locally are not committable yet - a hack in a sense that IOR is fixed to 1.5 dielectric, it's only for Glossy, it doesn't handle layering properly, etc... It would be nice to figure out, especially from people who know Cycles internals well, how to implement/integrate those things correctly inside the kernel and SVM.

- Dmitry

Posted: Mon Jun 03, 2013 9:42 pm
by canaldin
Nice study :D

I'm also quite dubious about the fresnel node especially when mixing nodes i.e. difuse-glossy or transparent-glossy

Try to contact Brecht Van Lomel, he's the creator and maintainer of cycles engine. Probably it's too much of a technical issue to discuss broadly on forums.

If you have troubles contacting him try to file a bug report, as this may be considered a bug, technically speaking.

Good luck and hope we get a better fresnel :)

Posted: Mon Jun 03, 2013 9:46 pm
by canaldin
P.S. if you can provide visual reference for real world samples of materials to back up your thesis that would be awesome as it may go into the official wiki article.

Posted: Tue Jun 04, 2013 11:35 am
by andcoder
There were a lot of studies by people who came up with those lighting models and distribution functions a long time ago. We just apply and rely on results of those studies. I can't argue with that but I can show some of test and results that I got. So far they are consistent.

Here is a paper bag, for instance, that I did a while a go and where I saw this strange problem with edges. I did a lot more tests and not just in Cycles.
(don't pay attention to the ground or translucency, those were not tuned there. It's just about the spec.)

The original bag was photographed with polarized light and specular component was extracted. Then roughness map was tuned to get the same specular characteristics at normal incidence. IOR is set to 1.5 which is common for dielectrics. Since the surface is mostly smooth (no macro bumps), GGX distribution fits it better. But it's possible to improve it by blending multiple distributions together.

On the left side is a real photograph, in the center a custom Blender build where Fresnel is computed based on microfacet normals, and on the right side is what you currently get with geometry/pixel normal as I described in the original post.


This problem is more apparent if you make a video, but it always looks like edges are glowing and there is nothing you can do there. They show up in all kinds of "random" places which makes animation rendering very unreliable. You could tune one specific shot let's say, but that's really animation unfriendly. And in motion it looks a lot worse.

- Dmitry

Posted: Tue Jun 04, 2013 12:24 pm
by canaldin
WOW, really awesome, прекрасно

You should submit those images to the wiki people.

As for the code try to do a bug report, your observations will surely get more attention in the bug-tracker.

As I said I'm not a coder. Once I was encoding video, and at the time blender was limiting the bitrate to 15 Mbits for no particular reason other than prevent children filling up their hard drives with exported animations at ginormous bitrates. So I got the code and searched for the keywords and chnged the two parameters, compiled and could export DNxHD like a boss. DNxHD by standard requires up to 220 Mbits. After that I submitted my observation as a bug and in 3 hours time it was in svn, it was a pre-release period. So now Me and my friends and pretty much everyone can export intermediate footage out of blender.

If you are unsure and would like to have some discussion with people more skilled than me post your observations on which is the de facto official blender forum.

Good luck

Posted: Thu Jul 11, 2013 3:29 pm
by famouswolf
Hi guys

Has this issue be resolved?
I ask because I am trying to replicate this issue
in 2.68 rc1, but it seems to be rendering correctly.

I set up the same sort of scene with the red BG,
same node setup (no diffuse, mix), but I don't get that horrible glow
around my sphere.


Posted: Mon Jul 15, 2013 1:19 am
by andcoder
There we no changes made as far as I can see.

Here is the .blend file I used to render those pictures above: ...

2.68 rc1 still has that issue :/

I spent quite some time digging into the internals of cycles but it looks like there is fundamental design issue that prevents one from fixing it easily.

The easiest thing seems to be to implement special combined/uber BSDFs. For example something like "Shiny Diffuse" that would handle both Diffuse and Specular components internally. Or something like "Dielectric" BSDF that would takes care of Glass - handle reflection and refraction correctly.

btw. Standard Glass BSDF is also busted in at least 2 ways. One, its fresnel is not microfacet based (doesn't work properly with both GGX and Beckmann distributions). Two, its specular is colored - that's not true for glass. There is a work around for coloring issues - just do it with nodes and mix colored refraction with uncolored reflection.

- Dmitry

fresnel problem

Posted: Mon Jul 15, 2013 9:07 am
by famouswolf
Hi Dmitry

Thanks for the blend file. The problem was that my lights were not
bright enough. Had them at 300.

Brecht is (I think) still working on an uber-shader for cycles.
Maybe he will sort this out in that shader.
That would be the easiest solution as far as I can see.
Don't really know the inner workings of blender.


Posted: Sun Sep 29, 2013 3:49 pm
by Bao
To the left is the Dmitry original setup exposing the bug in GGX.
To the right is a setup that can be used as a workaround, and also showing the correct way of using fresnel node.
I agree with Dmitry GGX must not give such light on the edges, but probably this will not be fixed and so this workaround works to avoid such lighting on the edges.