Fix #106706: fireflies with Nishita sky sun sampling at certain angles

Due to floating point differences between importance sampling and
texture evaluation, disagreeing on whether or not a ray lies within
the sun disc.

* Use the same input values for geographical_to_direction() in
  sky_radiance_nishita() and kernel_data.background.sun.
* The mathematical operations in pdf_uniform_cone() were adjusted to
  match sky_radiance_nishita().

Pull Request: https://projects.blender.org/blender/blender/pulls/106764
This commit is contained in:
Alaska
2023-04-17 17:29:27 +02:00
committed by Brecht Van Lommel
parent a8feb20e1c
commit cff94a808e
7 changed files with 45 additions and 31 deletions

View File

@@ -981,22 +981,8 @@ static ShaderNode *add_node(Scene *scene,
sky->set_sun_disc(b_sky_node.sun_disc());
sky->set_sun_size(b_sky_node.sun_size());
sky->set_sun_intensity(b_sky_node.sun_intensity());
/* Patch sun position to be able to animate daylight cycle while keeping the shading code
* simple. */
float sun_rotation = b_sky_node.sun_rotation();
/* Wrap into [-2PI..2PI] range. */
float sun_elevation = fmodf(b_sky_node.sun_elevation(), M_2PI_F);
/* Wrap into [-PI..PI] range. */
if (fabsf(sun_elevation) >= M_PI_F) {
sun_elevation -= copysignf(2.0f, sun_elevation) * M_PI_F;
}
/* Wrap into [-PI/2..PI/2] range while keeping the same absolute position. */
if (sun_elevation >= M_PI_2_F || sun_elevation <= -M_PI_2_F) {
sun_elevation = copysignf(M_PI_F, sun_elevation) - sun_elevation;
sun_rotation += M_PI_F;
}
sky->set_sun_elevation(sun_elevation);
sky->set_sun_rotation(sun_rotation);
sky->set_sun_elevation(b_sky_node.sun_elevation());
sky->set_sun_rotation(b_sky_node.sun_rotation());
sky->set_altitude(b_sky_node.altitude());
sky->set_air_density(b_sky_node.air_density());
sky->set_dust_density(b_sky_node.dust_density());

View File

@@ -132,11 +132,11 @@ color sky_radiance_nishita(vector dir, float nishita_data[10], string filename)
/* definitions */
vector sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2);
float sun_dir_angle = precise_angle(dir, sun_dir);
float half_angular = angular_diameter / 2.0;
float half_angular = angular_diameter * 0.5f;
float dir_elevation = M_PI_2 - direction[0];
/* if ray inside sun disc render it, otherwise render 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_dir_angle < half_angular && sun_disc == 1 && raytype("importance_bake") != 1) {
/* get 2 pixels data */
color pixel_bottom = color(nishita_data[0], nishita_data[1], nishita_data[2]);

View File

@@ -84,8 +84,8 @@ ccl_device_inline void sample_uniform_cone(const float3 N,
ccl_device_inline float pdf_uniform_cone(const float3 N, float3 D, float angle)
{
float zMin = cosf(angle);
float z = dot(N, D);
if (z > zMin) {
float z = precise_angle(N, D);
if (z < angle) {
return M_1_2PI_F / (1.0f - zMin);
}
return 0.0f;

View File

@@ -138,11 +138,11 @@ ccl_device float3 sky_radiance_nishita(KernelGlobals kg,
/* definitions */
float3 sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2_F);
float sun_dir_angle = precise_angle(dir, sun_dir);
float half_angular = angular_diameter / 2.0f;
float half_angular = angular_diameter * 0.5f;
float dir_elevation = M_PI_2_F - direction.x;
/* if ray inside sun disc render it, otherwise render 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 && !(path_flag & PATH_RAY_IMPORTANCE_BAKE)) {
/* get 2 pixels data */
float y;

View File

@@ -730,7 +730,7 @@ void LightManager::device_update_background(Device *device,
/* Determine sun direction from lat/long and texture mapping. */
float latitude = sky->get_sun_elevation();
float longitude = M_2PI_F - sky->get_sun_rotation() + M_PI_2_F;
float longitude = sky->get_sun_rotation() + M_PI_2_F;
float3 sun_direction = make_float3(
cosf(latitude) * cosf(longitude), cosf(latitude) * sinf(longitude), sinf(latitude));
Transform sky_transform = transform_inverse(sky->tex_mapping.compute_transform());

View File

@@ -758,12 +758,7 @@ static void sky_texture_precompute_nishita(SunSky *sunsky,
float pixel_top[3];
SKY_nishita_skymodel_precompute_sun(
sun_elevation, sun_size, altitude, air_density, dust_density, pixel_bottom, pixel_top);
/* limit sun rotation between 0 and 360 degrees */
sun_rotation = fmodf(sun_rotation, M_2PI_F);
if (sun_rotation < 0.0f) {
sun_rotation += M_2PI_F;
}
sun_rotation = M_2PI_F - sun_rotation;
/* send data to svm_sky */
sunsky->nishita_data[0] = pixel_bottom[0];
sunsky->nishita_data[1] = pixel_bottom[1];
@@ -873,6 +868,37 @@ NODE_DEFINE(SkyTextureNode)
SkyTextureNode::SkyTextureNode() : TextureNode(get_node_type()) {}
void SkyTextureNode::simplify_settings(Scene * /* scene */)
{
/* Patch sun position so users are able to animate the daylight cycle while keeping the shading
* code simple. */
float new_sun_elevation = sun_elevation;
float new_sun_rotation = sun_rotation;
/* Wrap `new_sun_elevation` into [-2PI..2PI] range. */
new_sun_elevation = fmodf(new_sun_elevation, M_2PI_F);
/* Wrap `new_sun_elevation` into [-PI..PI] range. */
if (fabsf(new_sun_elevation) >= M_PI_F) {
new_sun_elevation -= copysignf(2.0f, new_sun_elevation) * M_PI_F;
}
/* Wrap `new_sun_elevation` into [-PI/2..PI/2] range while keeping the same absolute position. */
if (new_sun_elevation >= M_PI_2_F || new_sun_elevation <= -M_PI_2_F) {
new_sun_elevation = copysignf(M_PI_F, new_sun_elevation) - new_sun_elevation;
new_sun_rotation += M_PI_F;
}
/* Wrap `new_sun_rotation` into [-2PI..2PI] range. */
new_sun_rotation = fmodf(new_sun_rotation, M_2PI_F);
/* Wrap `new_sun_rotation` into [0..2PI] range. */
if (new_sun_rotation < 0.0f) {
new_sun_rotation += M_2PI_F;
}
new_sun_rotation = M_2PI_F - new_sun_rotation;
sun_elevation = new_sun_elevation;
sun_rotation = new_sun_rotation;
}
void SkyTextureNode::compile(SVMCompiler &compiler)
{
ShaderInput *vector_in = input("Vector");

View File

@@ -167,6 +167,8 @@ class SkyTextureNode : public TextureNode {
NODE_SOCKET_API(float3, vector)
ImageHandle handle;
void simplify_settings(Scene *scene);
float get_sun_size()
{
/* Clamping for numerical precision. */