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_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]
|
||||
#define sun_limb_darkening_col vec3(0.397, 0.503, 0.652)
|
||||
|
||||
float random(vec2 coords) {
|
||||
// Returned value is in [0, 1]
|
||||
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
|
||||
// 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)));
|
||||
vec3 jODepth = nishita_lookupLUT(iHeight, sunTheta);
|
||||
|
||||
// Apply dithering to reduce visible banding
|
||||
jODepth += mix(-1000, 1000, random(r.xy));
|
||||
vec3 jAttn = nishita_lookupLUT(iHeight, sunTheta);
|
||||
|
||||
// Calculate attenuation
|
||||
vec3 attn = exp(-(
|
||||
nishita_mie_coeff * (iOdMie + jODepth.y)
|
||||
+ (nishita_rayleigh_coeff) * (iOdRlh + jODepth.x)
|
||||
+ nishita_ozone_coeff * jODepth.z
|
||||
vec3 iAttn = exp(-(
|
||||
nishita_mie_coeff * iOdMie
|
||||
+ nishita_rayleigh_coeff * iOdRlh
|
||||
// + 0 for ozone
|
||||
));
|
||||
vec3 attn = iAttn * jAttn;
|
||||
|
||||
// Apply dithering to reduce visible banding
|
||||
attn *= 0.98 + random(r.xy) * 0.04;
|
||||
|
||||
// Accumulate scattering
|
||||
totalRlh += odStepRlh * attn;
|
||||
|
|
|
@ -80,11 +80,24 @@ class NishitaData {
|
|||
**/
|
||||
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. **/
|
||||
public static var rayleighScale = 8e3;
|
||||
|
||||
/** Mie scattering coefficient. **/
|
||||
public static var mieCoeff = 2e-5;
|
||||
/** Mie scattering scale parameter. **/
|
||||
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() {}
|
||||
|
||||
/** Approximates the density of ozone for a given sample height. **/
|
||||
|
@ -185,6 +198,29 @@ class NishitaData {
|
|||
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 New Issue