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:
committed by
Brecht Van Lommel
parent
a8feb20e1c
commit
cff94a808e
@@ -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());
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user