Fix value range in Nishita LUT
This commit is contained in:
parent
34f6e0fc7c
commit
d610cc6a2f
|
@ -44,17 +44,12 @@ uniform vec2 nishitaDensity;
|
||||||
#define nishita_mie_dir 0.76 // Aerosols anisotropy ("direction")
|
#define nishita_mie_dir 0.76 // Aerosols anisotropy ("direction")
|
||||||
#define nishita_mie_dir_sq 0.5776 // Squared aerosols anisotropy
|
#define nishita_mie_dir_sq 0.5776 // Squared aerosols anisotropy
|
||||||
|
|
||||||
// The ozone absorption coefficients are taken from Cycles code.
|
|
||||||
// Because Cycles calculates 21 wavelengths, we use the coefficients
|
|
||||||
// which are closest to the RGB wavelengths (645nm, 510nm, 440nm).
|
|
||||||
// Precalculating values by simulating Blender's spec_to_xyz() function
|
|
||||||
// to include all 21 wavelengths gave unrealistic results
|
|
||||||
#define nishita_ozone_coeff vec3(1.59051840791988e-6, 0.00000096707041180970, 0.00000007309568762914)
|
|
||||||
|
|
||||||
// Values from [Hill: 60]
|
// Values from [Hill: 60]
|
||||||
#define sun_limb_darkening_col vec3(0.397, 0.503, 0.652)
|
#define sun_limb_darkening_col vec3(0.397, 0.503, 0.652)
|
||||||
|
|
||||||
float random(vec2 coords) {
|
float random(vec2 coords) {
|
||||||
|
// Returned value is in [0, 1]
|
||||||
return fract(sin(dot(coords.xy, vec2(12.9898,78.233))) * 43758.5453);
|
return fract(sin(dot(coords.xy, vec2(12.9898,78.233))) * 43758.5453);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,17 +120,18 @@ vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const floa
|
||||||
// Idea behind this: "Rotate" everything by iPos (-> iPos is the new zenith) and then all calculations for the
|
// Idea behind this: "Rotate" everything by iPos (-> iPos is the new zenith) and then all calculations for the
|
||||||
// inner integral only depend on the sample height (iHeight) and sunTheta (angle between sun and new zenith).
|
// inner integral only depend on the sample height (iHeight) and sunTheta (angle between sun and new zenith).
|
||||||
float sunTheta = acos(dot(normalize(iPos), normalize(pSun)));
|
float sunTheta = acos(dot(normalize(iPos), normalize(pSun)));
|
||||||
vec3 jODepth = nishita_lookupLUT(iHeight, sunTheta);
|
vec3 jAttn = nishita_lookupLUT(iHeight, sunTheta);
|
||||||
|
|
||||||
// Apply dithering to reduce visible banding
|
|
||||||
jODepth += mix(-1000, 1000, random(r.xy));
|
|
||||||
|
|
||||||
// Calculate attenuation
|
// Calculate attenuation
|
||||||
vec3 attn = exp(-(
|
vec3 iAttn = exp(-(
|
||||||
nishita_mie_coeff * (iOdMie + jODepth.y)
|
nishita_mie_coeff * iOdMie
|
||||||
+ (nishita_rayleigh_coeff) * (iOdRlh + jODepth.x)
|
+ nishita_rayleigh_coeff * iOdRlh
|
||||||
+ nishita_ozone_coeff * jODepth.z
|
// + 0 for ozone
|
||||||
));
|
));
|
||||||
|
vec3 attn = iAttn * jAttn;
|
||||||
|
|
||||||
|
// Apply dithering to reduce visible banding
|
||||||
|
attn *= 0.98 + random(r.xy) * 0.04;
|
||||||
|
|
||||||
// Accumulate scattering
|
// Accumulate scattering
|
||||||
totalRlh += odStepRlh * attn;
|
totalRlh += odStepRlh * attn;
|
||||||
|
|
|
@ -80,11 +80,24 @@ class NishitaData {
|
||||||
**/
|
**/
|
||||||
public static var radiusPlanet = 6360000;
|
public static var radiusPlanet = 6360000;
|
||||||
|
|
||||||
|
/** Rayleigh scattering coefficient. **/
|
||||||
|
public static var rayleighCoeff = new Vec3(5.5e-6, 13.0e-6, 22.4e-6);
|
||||||
/** Rayleigh scattering scale parameter. **/
|
/** Rayleigh scattering scale parameter. **/
|
||||||
public static var rayleighScale = 8e3;
|
public static var rayleighScale = 8e3;
|
||||||
|
|
||||||
|
/** Mie scattering coefficient. **/
|
||||||
|
public static var mieCoeff = 2e-5;
|
||||||
/** Mie scattering scale parameter. **/
|
/** Mie scattering scale parameter. **/
|
||||||
public static var mieScale = 1.2e3;
|
public static var mieScale = 1.2e3;
|
||||||
|
|
||||||
|
/** Ozone scattering coefficient. **/
|
||||||
|
// The ozone absorption coefficients are taken from Cycles code.
|
||||||
|
// Because Cycles calculates 21 wavelengths, we use the coefficients
|
||||||
|
// which are closest to the RGB wavelengths (645nm, 510nm, 440nm).
|
||||||
|
// Precalculating values by simulating Blender's spec_to_xyz() function
|
||||||
|
// to include all 21 wavelengths gave unrealistic results.
|
||||||
|
public static var ozoneCoeff = new Vec3(1.59051840791988e-6, 0.00000096707041180970, 0.00000007309568762914);
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
/** Approximates the density of ozone for a given sample height. **/
|
/** Approximates the density of ozone for a given sample height. **/
|
||||||
|
@ -185,6 +198,29 @@ class NishitaData {
|
||||||
jTime += jStepSize;
|
jTime += jStepSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return jODepth.mult(jStepSize);
|
jODepth.mult(jStepSize);
|
||||||
|
|
||||||
|
// Precalculate a part of the secondary attenuation.
|
||||||
|
// For one variable (e.g. x) in the vector, the formula is as follows:
|
||||||
|
//
|
||||||
|
// attn.x = exp(-(coeffX * (firstOpticalDepth.x + secondOpticalDepth.x)))
|
||||||
|
//
|
||||||
|
// We can split that up via:
|
||||||
|
//
|
||||||
|
// attn.x = exp(-(coeffX * firstOpticalDepth.x + coeffX * secondOpticalDepth.x))
|
||||||
|
// = exp(-(coeffX * firstOpticalDepth.x)) * exp(-(coeffX * secondOpticalDepth.x))
|
||||||
|
//
|
||||||
|
// The first factor of the resulting multiplication is calculated in the
|
||||||
|
// shader, but we can already precalculate the second one. As a side
|
||||||
|
// effect this keeps the range of the LUT values small because we don't
|
||||||
|
// store the optical depth but the attenuation.
|
||||||
|
var jAttenuation = new Vec3();
|
||||||
|
var mie = mieCoeff * jODepth.y;
|
||||||
|
jAttenuation.addf(mie, mie, mie);
|
||||||
|
jAttenuation.add(rayleighCoeff.clone().mult(jODepth.x));
|
||||||
|
jAttenuation.add(ozoneCoeff.clone().mult(jODepth.z));
|
||||||
|
jAttenuation.exp(jAttenuation.mult(-1));
|
||||||
|
|
||||||
|
return jAttenuation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue