This commit is contained in:
Moritz Brückner 2021-03-31 20:33:52 +02:00
parent ffcc5fcceb
commit c5be90d0b0
3 changed files with 17 additions and 31 deletions

View file

@ -66,25 +66,15 @@ vec3 nishita_lookupLUT(const float height, const float sunTheta) {
return textureLod(nishitaLUT, coords, 0.0).rgb;
}
/* Approximates the density of ozone for a given sample height. Values taken from Cycles code. */
float nishita_density_ozone(const float height) {
return (height < 10000.0 || height >= 40000.0) ? 0.0 : (height < 25000.0 ? (height - 10000.0) / 15000.0 : -((height - 40000.0) / 15000.0));
}
/* ray-sphere intersection that assumes
* the sphere is centered at the origin.
* No intersection when result.x > result.y */
/* See raySphereIntersection() in armory/Sources/renderpath/Nishita.hx */
vec2 nishita_rsi(const vec3 r0, const vec3 rd, const float sr) {
float a = dot(rd, rd);
float b = 2.0 * dot(rd, r0);
float c = dot(r0, r0) - (sr * sr);
float d = (b*b) - 4.0*a*c;
if (d < 0.0) return vec2(1e5,-1e5);
return vec2(
(-b - sqrt(d))/(2.0*a),
(-b + sqrt(d))/(2.0*a)
);
// If d < 0.0 the ray does not intersect the sphere
return (d < 0.0) ? vec2(1e5,-1e5) : vec2((-b - sqrt(d))/(2.0*a), (-b + sqrt(d))/(2.0*a));
}
/*
@ -94,43 +84,41 @@ vec2 nishita_rsi(const vec3 r0, const vec3 rd, const float sr) {
* rPlanet: planet radius
*/
vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const float rPlanet) {
// Calculate the step size of the primary ray.
// Calculate the step size of the primary ray
vec2 p = nishita_rsi(r0, r, nishita_atmo_radius);
if (p.x > p.y) return vec3(0,0,0);
if (p.x > p.y) return vec3(0.0);
p.y = min(p.y, nishita_rsi(r0, r, rPlanet).x);
float iStepSize = (p.y - p.x) / float(nishita_iSteps);
// Initialize the primary ray time.
// Primary ray time
float iTime = 0.0;
// Initialize accumulators for Rayleigh and Mie scattering.
// Accumulators for Rayleigh and Mie scattering.
vec3 totalRlh = vec3(0,0,0);
vec3 totalMie = vec3(0,0,0);
// Initialize optical depth accumulators for the primary ray.
// Optical depth accumulators for the primary ray
float iOdRlh = 0.0;
float iOdMie = 0.0;
// Calculate the Rayleigh and Mie phases.
// Calculate the Rayleigh and Mie phases
float mu = dot(r, pSun);
float mumu = mu * mu;
float pRlh = 3.0 / (16.0 * PI) * (1.0 + mumu);
float pMie = 3.0 / (8.0 * PI) * ((1.0 - nishita_mie_dir_sq) * (mumu + 1.0)) / (pow(1.0 + nishita_mie_dir_sq - 2.0 * mu * nishita_mie_dir, 1.5) * (2.0 + nishita_mie_dir_sq));
// Sample the primary ray.
// Sample the primary ray
for (int i = 0; i < nishita_iSteps; i++) {
// Calculate the primary ray sample position.
// Calculate the primary ray sample position and height
vec3 iPos = r0 + r * (iTime + iStepSize * 0.5);
// Calculate the height of the sample.
float iHeight = length(iPos) - rPlanet;
// Calculate the optical depth of the Rayleigh and Mie scattering for this step
float odStepRlh = exp(-iHeight / nishita_rayleigh_scale) * nishitaDensity.x * iStepSize;
float odStepMie = exp(-iHeight / nishita_mie_scale) * nishitaDensity.y * iStepSize;
// Accumulate optical depth.
// Accumulate optical depth
iOdRlh += odStepRlh;
iOdMie += odStepMie;
@ -142,22 +130,20 @@ vec3 nishita_atmosphere(const vec3 r, const vec3 r0, const vec3 pSun, const floa
// Apply dithering to reduce visible banding
jODepth += mix(-1000, 1000, random(r.xy));
// Calculate attenuation.
// Calculate attenuation
vec3 attn = exp(-(
nishita_mie_coeff * (iOdMie + jODepth.y)
+ (nishita_rayleigh_coeff) * (iOdRlh + jODepth.x)
+ nishita_ozone_coeff * jODepth.z
));
// Accumulate scattering.
// Accumulate scattering
totalRlh += odStepRlh * attn;
totalMie += odStepMie * attn;
// Increment the primary ray time.
iTime += iStepSize;
}
// Calculate and return the final color.
return nishita_sun_intensity * (pRlh * nishita_rayleigh_coeff * totalRlh + pMie * nishita_mie_coeff * totalMie);
}
@ -166,7 +152,7 @@ vec3 sun_disk(const vec3 n, const vec3 light_dir, const float disk_size, const f
float dist = distance(n, light_dir) / disk_size;
// Darken the edges of the sun
// [Hill: 28, 60] (code from [Nec96])
// [Hill: 28, 60] (according to [Nec96])
float invDist = 1.0 - dist;
float mu = sqrt(invDist * invDist);
vec3 limb_darkening = 1.0 - (1.0 - pow(vec3(mu), sun_limb_darkening_col));

View file

@ -177,9 +177,9 @@ class Uniforms {
var v: Vec4 = null;
switch (link) {
case "_nishitaDensity": {
v = iron.object.Uniforms.helpVec;
var w = Scene.active.world;
if (w != null) {
v = iron.object.Uniforms.helpVec;
// We only need Rayleigh and Mie density in the sky shader -> Vec2
v.x = w.raw.nishita_density[0];
v.y = w.raw.nishita_density[1];

View file

@ -296,7 +296,7 @@ def parse_tex_sky(node: bpy.types.ShaderNodeTexSky, out_socket: bpy.types.NodeSo
if node.sky_type == 'PREETHAM' or node.sky_type == 'HOSEK_WILKIE':
if node.sky_type == 'PREETHAM':
log.warn('Preetham sky model is not supported, using Hosek Wilkie sky model instead')
log.info('Info: Preetham sky model is not supported, using Hosek Wilkie sky model instead')
return parse_sky_hosekwilkie(node, state)