LuxCoreRender / LuxCore

LuxCore source repository
Apache License 2.0
1.15k stars 144 forks source link

Red fringe when using dispersion on a sphere #47

Closed Theverat closed 6 years ago

Theverat commented 6 years ago

I noticed a red fringe on a sphere with dispersion enabled (cauchyc 0.05).

red_fringe1

Higher cauchy c value (0.2) makes it stronger: red_fringe2

I went back to 765fb611bef8bf3cadf037b4cf8e1daed1559c50 and it shows the same red fringe. So I do not think it was introduced in the latest glass sampling changes. 765fb611bef8bf3cadf037b4cf8e1daed1559c50

Classic API does not show this kind of fringe. classic

Testscene: 00019.zip

Dade916 commented 6 years ago

Side note: the attached test scene has ".visibility.indirect.*" set false for the sky, it can be very confusing.

They posted rendered images have a normal sky. It may be a bug in FILESAVER or BlendLuxCore.

Theverat commented 6 years ago

Side note: the attached test scene has ".visibility.indirect.*" set false for the sky, it can be very confusing.

Sorry, a leftover from an old test. The images were rendered with BIDIR which does not use this setting as far as I know.

Dade916 commented 6 years ago

The difference is due to a different formula used for B term of the Cauchy's equation. Our was suggested by Neo here: https://github.com/LuxCoreRender/BlendLuxCore/commit/d3fed046ab62e18226e410b42a16ca1bccefb530#commitcomment-26617643

While old LuxRender uses B=IOR.

This is the code:

static float WaveLength2IOR(const float waveLength, const float IOR, const float C) {
    // Cauchy's equation for relationship between the refractive index and wavelength
    // note: Cauchy's lambda is expressed in micrometers while waveLength is in nanometers

    // This is the formula suggested by Neo here:
    // https://github.com/LuxCoreRender/BlendLuxCore/commit/d3fed046ab62e18226e410b42a16ca1bccefb530#commitcomment-26617643
    // Compute IOR at 589 nm (natrium D line)
    //const float B = IOR - C / Sqr(589.f / 1000.f);

    // The B used by old LuxRender
    const float B = IOR;

    // Cauchy's equation
    const float cauchyEq = B + C / Sqr(waveLength / 1000.f);

    return cauchyEq;
}

I switched to the same B and I'm obtaining the same results:

rgb_imagepipeline

For the moment, I committed the LuxRender's formula, may be @neo2068 can further investigate/explain how B should be computed.

P.S. this stuff doesn't stop to amaze me, it is mind blowing to do in 50 in lines of code the same work LuxRender was doing with his arsenal of spectral rendering. LuxCore really render the same stuff. Someone should write a paper on this stuff.

Dade916 commented 6 years ago

I mean the dispersion of the sun highlight on the sphere is better in LuxCore version, ahaha !

Theverat commented 6 years ago

1450748043062

neo2068 commented 6 years ago

I think a value of 0.05 or 0.2 for the dispersion parameter, i.e. cauchy C coefficient is way to big. A normal range should be about 0.002 - 0.015. I briefly explained the formula here https://github.com/LuxCoreRender/BlendLuxCore/commit/d3fed046ab62e18226e410b42a16ca1bccefb530#commitcomment-26617643

The IOR in the literature is measured at a fixed wavelength, i.e. 589nm (Natrium D line) @ 20°C. To model the dispersion of white light into the different colors you need the IORs for each wavelength of the visible spectrum. Therefor Cauchy proposed to fit a curve onto the measured IORs at different wavelength and describe the dispersion with the coefficients of this fitting curve.

IOR(lambda) = B + C/lambda^2

If you have the IOR at 589 nm and the C coefficient (which we expose as the dispersion parameter) you could calculate the B coefficient with the above formula (the wavelength has to be in µm!)

IOR(0.589) = B + C/0.589^2 <=> B = IOR(0.589) - C/0.589^2

Which is the formula in the code. For example the IOR for borosilicate crown glass BK7 is 1.5168. The cauchy coefficients are B = 1.5046 and C = 0.0042. With the above formula you get

B = IOR(0.589) - C/0.589^2 = 1.5168 - 0.0042/0.589^2 = 1.5046

I think that the formula should be physically correct. If you use the IOR directly as the B coefficient you get a too high IOR. grafik

Theverat commented 6 years ago

I think a value of 0.05 or 0.2 for the dispersion parameter, i.e. cauchy C coefficient is way to big. A normal range should be about 0.002 - 0.015.

I'm aware, I wanted to exaggerate the effect so it is easier to see.

I think that the formula should be physically correct. If you use the IOR directly as the B coefficient you get a too high IOR.

Does that mean that LuxRender did it wrong all these years? And how do we remove the red fringe if we switch back to the other formula?

neo2068 commented 6 years ago

While old LuxRender uses B=IOR.

In the cauchytexture code of old LuxRender is a conversion formula https://bitbucket.org/luxrender/lux/src/f56582df55f42928ca409f5dba909b2019ca9e8e/textures/cauchytexture.cpp?at=default&fileviewer=file-view-default#cauchytexture.cpp-37 which divides with WAVELENGTH_START*WAVELENGTH_END instead of WAVELENGTH_D*WAVELENGTH_D. When I add the cauchytexture conversion to the chart above I get the yellow line. In the fresnelcauchy code there is B=IOR which is wrong in my opinion. We have to check which calculation is correct.

grafik