Fix #146630: Single Scattering Sky has darker pixels near horizon
Store the ground fading of Single Scattering sky directly in the LUT. Co-authored-by: Lukas Stockner <lukas@lukasstockner.de> Pull Request: https://projects.blender.org/blender/blender/pulls/146659
This commit is contained in:
committed by
Lukas Stockner
parent
0f3c6da272
commit
390f053e32
@@ -163,28 +163,11 @@ color sky_radiance_nishita(vector dir, float sky_data[11], string filename, stri
|
||||
if (x > 1.0) {
|
||||
x = x - 1.0;
|
||||
}
|
||||
color rgb_sky;
|
||||
if (sky_type == "single_scattering" && dir[2] < 0.0) {
|
||||
/* Fade ground to black for Single Scattering model and disable Sun disc below horizon */
|
||||
rgb_sun = color(0.0, 0.0, 0.0);
|
||||
if (dir[2] < -0.4) {
|
||||
rgb_sky = color(0.0, 0.0, 0.0);
|
||||
}
|
||||
else {
|
||||
float fade = pow(1.0 + dir[2] * 2.5, 3.0);
|
||||
color xyz = (color)texture(
|
||||
filename, x, 0.492, "wrap", "periodic", "interp", "linear", "alpha", alpha);
|
||||
rgb_sky = xyz_to_rgb(xyz[0], xyz[1], xyz[2]) * fade;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* Undo the non-linear transformation from the sky LUT */
|
||||
float dir_elevation_abs = (dir_elevation < 0.0) ? -dir_elevation : dir_elevation;
|
||||
float y = 1.0 - (sqrt(dir_elevation_abs / M_PI_2) * signx(dir_elevation) * 0.5 + 0.5);
|
||||
color xyz = (color)texture(
|
||||
filename, x, y, "wrap", "clamp", "interp", "linear", "alpha", alpha);
|
||||
rgb_sky = xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
|
||||
}
|
||||
/* Undo the non-linear transformation from the sky LUT */
|
||||
float dir_elevation_abs = (dir_elevation < 0.0) ? -dir_elevation : dir_elevation;
|
||||
float y = 1.0 - (sqrt(dir_elevation_abs / M_PI_2) * signx(dir_elevation) * 0.5 + 0.5);
|
||||
color xyz = (color)texture(filename, x, y, "wrap", "clamp", "interp", "linear", "alpha", alpha);
|
||||
color rgb_sky = xyz_to_rgb(xyz[0], xyz[1], xyz[2]);
|
||||
|
||||
return rgb_sun * sun_intensity + rgb_sky;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,6 @@ ccl_device float3 geographical_to_direction(const float lat, const float lon)
|
||||
}
|
||||
|
||||
ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
|
||||
const NodeSkyType type,
|
||||
const float3 dir,
|
||||
const uint32_t path_flag,
|
||||
const float3 pixel_bottom,
|
||||
@@ -142,7 +141,7 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
|
||||
const ccl_private float *sky_data,
|
||||
const uint texture_id)
|
||||
{
|
||||
/* definitions */
|
||||
/* Definitions */
|
||||
const float sun_elevation = sky_data[0];
|
||||
const float sun_rotation = sky_data[1];
|
||||
const float angular_diameter = sky_data[2];
|
||||
@@ -150,49 +149,32 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
|
||||
const float earth_intersection_angle = sky_data[4];
|
||||
const bool sun_disc = (angular_diameter >= 0.0f);
|
||||
float3 xyz = zero_float3();
|
||||
/* convert dir to spherical coordinates */
|
||||
const float2 direction = direction_to_spherical(dir);
|
||||
/* definitions */
|
||||
const float3 sun_dir = spherical_to_direction(sun_elevation - M_PI_2_F, sun_rotation - M_PI_2_F);
|
||||
const float sun_dir_angle = precise_angle(dir, sun_dir);
|
||||
const float half_angular = angular_diameter * 0.5f;
|
||||
const float dir_elevation = M_PI_2_F - direction.x;
|
||||
|
||||
/* If the ray is inside the sun disc, render it, otherwise render the sky.
|
||||
* Alternatively, ignore the sun if we're evaluating the background texture. */
|
||||
/* If the ray is inside the Sun disc, render it, otherwise render the sky.
|
||||
* Alternatively, ignore the Sun if we're evaluating the background texture. */
|
||||
if (sun_disc && sun_dir_angle < half_angular && dir_elevation > earth_intersection_angle &&
|
||||
!((path_flag & PATH_RAY_IMPORTANCE_BAKE) && kernel_data.background.use_sun_guiding))
|
||||
{
|
||||
/* sun interpolation */
|
||||
/* Sun interpolation */
|
||||
const float y = ((dir_elevation - sun_elevation) / angular_diameter) + 0.5f;
|
||||
/* limb darkening, coefficient is 0.6f */
|
||||
/* Limb darkening, coefficient is 0.6f */
|
||||
const float limb_darkening = (1.0f -
|
||||
0.6f * (1.0f - sqrtf(1.0f - sqr(sun_dir_angle / half_angular))));
|
||||
xyz = mix(pixel_bottom, pixel_top, y) * sun_intensity * limb_darkening;
|
||||
}
|
||||
|
||||
/* sky */
|
||||
/* Sky */
|
||||
const float x = fractf((-direction.y - M_PI_2_F + sun_rotation) * M_1_2PI_F);
|
||||
if (dir.z > 0.0f) {
|
||||
/* sky interpolation */
|
||||
/* more pixels toward horizon compensation */
|
||||
const float y = safe_sqrtf(dir_elevation * M_2_PI_F) * 0.5f + 0.5f;
|
||||
xyz += make_float3(kernel_tex_image_interp(kg, texture_id, x, y));
|
||||
}
|
||||
/* ground */
|
||||
else if (type == NODE_SKY_MULTIPLE_SCATTERING) {
|
||||
const float y = -safe_sqrtf(-dir_elevation * M_2_PI_F) * 0.5f + 0.5f;
|
||||
xyz += make_float3(kernel_tex_image_interp(kg, texture_id, x, y));
|
||||
}
|
||||
else if (dir.z >= -0.4f) {
|
||||
/* black ground fade */
|
||||
float fade = 1.0f + dir.z * 2.5f;
|
||||
fade = sqr(fade) * fade;
|
||||
/* interpolation */
|
||||
xyz += make_float3(kernel_tex_image_interp(kg, texture_id, x, 0.508f)) * fade;
|
||||
}
|
||||
/* Undo the non-linear transformation from the sky LUT */
|
||||
const float y = copysignf(sqrtf(fabsf(dir_elevation) * M_2_PI_F), dir_elevation) * 0.5f + 0.5f;
|
||||
xyz += make_float3(kernel_tex_image_interp(kg, texture_id, x, y));
|
||||
|
||||
/* convert to RGB */
|
||||
/* Convert to RGB */
|
||||
return xyz_to_rgb_clamped(kg, xyz);
|
||||
}
|
||||
|
||||
@@ -317,8 +299,7 @@ ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg,
|
||||
const uint texture_id = __float_as_uint(data.w);
|
||||
|
||||
/* Compute Sky */
|
||||
rgb = sky_radiance_nishita(
|
||||
kg, sky_type, dir, path_flag, pixel_bottom, pixel_top, sky_data, texture_id);
|
||||
rgb = sky_radiance_nishita(kg, dir, path_flag, pixel_bottom, pixel_top, sky_data, texture_id);
|
||||
}
|
||||
|
||||
stack_store_float3(stack, out_offset, rgb);
|
||||
|
||||
@@ -308,25 +308,20 @@ void SKY_single_scattering_precompute_texture(float *pixels,
|
||||
const float longitude_step = M_2PI_F / width;
|
||||
const int rows_per_task = std::max(1024 / width, 1);
|
||||
|
||||
SKY_parallel_for(0, height, rows_per_task, [=](const size_t begin, const size_t end) {
|
||||
/* Compute Sky in the upper hemisphere. */
|
||||
SKY_parallel_for(half_height, height, rows_per_task, [=](const size_t begin, const size_t end) {
|
||||
for (int y = begin; y < end; y++) {
|
||||
/* Sample more pixels toward the horizon. */
|
||||
float latitude = M_PI_2_F * sqr(float(y) / half_height - 1.0f);
|
||||
float *pixel_row = pixels + (y * width * stride);
|
||||
|
||||
for (int x = 0; x < half_width; x++) {
|
||||
float3 xyz;
|
||||
if (y > half_height) {
|
||||
float longitude = longitude_step * x - M_PI_F;
|
||||
float3 dir = geographical_to_direction(latitude, longitude);
|
||||
float spectrum[NUM_WAVELENGTHS];
|
||||
single_scattering(
|
||||
dir, sun_dir, cam_pos, air_density, aerosol_density, ozone_density, spectrum);
|
||||
xyz = spec_to_xyz(spectrum);
|
||||
}
|
||||
else {
|
||||
xyz = make_float3(0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
float longitude = longitude_step * x - M_PI_F;
|
||||
float3 dir = geographical_to_direction(latitude, longitude);
|
||||
float spectrum[NUM_WAVELENGTHS];
|
||||
single_scattering(
|
||||
dir, sun_dir, cam_pos, air_density, aerosol_density, ozone_density, spectrum);
|
||||
const float3 xyz = spec_to_xyz(spectrum);
|
||||
|
||||
/* Store pixels. */
|
||||
int pos_x = x * stride;
|
||||
@@ -341,6 +336,26 @@ void SKY_single_scattering_precompute_texture(float *pixels,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/* Fill in the lower hemisphere by fading out the horizon. */
|
||||
for (int y = 0; y < half_height; y++) {
|
||||
/* Sample more pixels toward the horizon. */
|
||||
float latitude = M_PI_2_F * sqr(float(y) / half_height - 1.0f);
|
||||
float3 dir = geographical_to_direction(latitude, 0.0f);
|
||||
float fade = 0.0f;
|
||||
if (dir.z < 0.4f) {
|
||||
fade = 1.0f - dir.z * 2.5f;
|
||||
fade = sqr(fade) * fade;
|
||||
}
|
||||
float *pixel_row = pixels + (y * width * stride);
|
||||
float *horizon_row = pixels + (half_height * width * stride);
|
||||
|
||||
for (int x = 0, offset = 0; x < width; x++, offset += stride) {
|
||||
pixel_row[offset + 0] = horizon_row[offset + 0] * fade;
|
||||
pixel_row[offset + 1] = horizon_row[offset + 1] * fade;
|
||||
pixel_row[offset + 2] = horizon_row[offset + 2] * fade;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********** Sun ***********/
|
||||
|
||||
@@ -165,21 +165,10 @@ void node_tex_sky_nishita(float3 co,
|
||||
float fade = 1.0f;
|
||||
float y;
|
||||
|
||||
if (sky_type == 0.0f && co.z < -0.4f) {
|
||||
/* Black ground if Single Scattering model */
|
||||
color = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
return;
|
||||
}
|
||||
if (sky_type == 0.0f && co.z < 0.0f) {
|
||||
/* Ground fade */
|
||||
fade = pow(1.0f + co.z * 2.5f, 3.0f);
|
||||
y = 0.508f;
|
||||
}
|
||||
else {
|
||||
/* Undo the non-linear transformation from the sky LUT. */
|
||||
float dir_elevation_abs = (dir_elevation < 0.0f) ? -dir_elevation : dir_elevation;
|
||||
y = sqrt(dir_elevation_abs / M_PI_2) * sign(dir_elevation) * 0.5f + 0.5f;
|
||||
}
|
||||
/* Undo the non-linear transformation from the sky LUT. */
|
||||
float dir_elevation_abs = (dir_elevation < 0.0f) ? -dir_elevation : dir_elevation;
|
||||
y = sqrt(dir_elevation_abs / M_PI_2) * sign(dir_elevation) * 0.5f + 0.5f;
|
||||
|
||||
/* Look up color in the precomputed map and convert to RGB. */
|
||||
xyz = fade * texture(ima, float3(x, y, layer)).rgb;
|
||||
color = float4(dot(xyz_to_r, xyz), dot(xyz_to_g, xyz), dot(xyz_to_b, xyz), 1.0f);
|
||||
|
||||
BIN
tests/files/render/texture/cycles_renders/sky_single_no_disc_high_altitude.png
(Stored with Git LFS)
BIN
tests/files/render/texture/cycles_renders/sky_single_no_disc_high_altitude.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/render/volume/cycles_ray_marching_renders/implicit_volume.png
(Stored with Git LFS)
BIN
tests/files/render/volume/cycles_ray_marching_renders/implicit_volume.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/render/volume/eevee_renders/implicit_volume.png
(Stored with Git LFS)
BIN
tests/files/render/volume/eevee_renders/implicit_volume.png
(Stored with Git LFS)
Binary file not shown.
BIN
tests/files/render/volume/eevee_renders/volume_scatter_fournier-forand.png
(Stored with Git LFS)
BIN
tests/files/render/volume/eevee_renders/volume_scatter_fournier-forand.png
(Stored with Git LFS)
Binary file not shown.
Reference in New Issue
Block a user