mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Merge branch 'blender-v5.2-release'
This commit is contained in:
commit
9516867296
16 changed files with 244 additions and 76 deletions
|
|
@ -60,10 +60,22 @@ ccl_device_inline float bsdf_get_roughness_pass_squared(const ccl_private Shader
|
|||
/* Widen the compact ray differential dD after a non-specular bounce so that
|
||||
* texture mip selection on subsequent hits reflects the BSDF lobe's angular
|
||||
* spread. This significantly save memory, and is needed to make image cache
|
||||
* memory usage scale with render tile size rather than overall resolution. */
|
||||
ccl_device_forceinline float bsdf_widen_dD(const float prev_dD, const float2 sampled_roughness)
|
||||
* memory usage scale with render tile size rather than overall resolution.
|
||||
*
|
||||
* This must be done consistently between next event estimation and forward
|
||||
* sampling for both to converge to the same result for MIS. This is not just
|
||||
* a theoretical concern, but can otherwise lead to seams.
|
||||
*
|
||||
* To achieve that, the sampled roughness is computed as a MIS weighted
|
||||
* average. This makes it so directions with high contribution from sharp
|
||||
* BSDFs have a lower roughness, as they will have a high MIS weight. */
|
||||
ccl_device_forceinline float bsdf_widen_dD(const float prev_dD, const float avg_roughness_squared)
|
||||
{
|
||||
return max(prev_dD, min(sampled_roughness.x, sampled_roughness.y));
|
||||
if (!(avg_roughness_squared > 0.0f)) {
|
||||
return prev_dD;
|
||||
}
|
||||
|
||||
return max(prev_dD, sqrtf(avg_roughness_squared));
|
||||
}
|
||||
|
||||
/* An additional term to smooth illumination on grazing angles when using bump mapping
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@ KERNEL_STRUCT_MEMBER(background, float, map_weight)
|
|||
KERNEL_STRUCT_MEMBER(background, float, portal_weight)
|
||||
KERNEL_STRUCT_MEMBER(background, int, map_res_x)
|
||||
KERNEL_STRUCT_MEMBER(background, int, map_res_y)
|
||||
/* Ray differential used for generating the importance map. */
|
||||
KERNEL_STRUCT_MEMBER(background, float, map_dD)
|
||||
/* Multiple importance sampling. */
|
||||
KERNEL_STRUCT_MEMBER(background, int, use_mis)
|
||||
/* Light-group. */
|
||||
|
|
@ -42,7 +44,6 @@ KERNEL_STRUCT_MEMBER(background, int, lightgroup)
|
|||
KERNEL_STRUCT_MEMBER(background, int, object_index)
|
||||
/* Padding. */
|
||||
KERNEL_STRUCT_MEMBER(background, int, pad1)
|
||||
KERNEL_STRUCT_MEMBER(background, int, pad2)
|
||||
KERNEL_STRUCT_END(KernelBackground)
|
||||
|
||||
/* BVH: own BVH2 if no native device acceleration struct used. */
|
||||
|
|
|
|||
|
|
@ -66,12 +66,19 @@ ccl_device Spectrum integrator_eval_background_shader(KernelGlobals kg,
|
|||
ShaderDataTinyStorage emission_sd_storage;
|
||||
ccl_private ShaderData *emission_sd = AS_SHADER_DATA(&emission_sd_storage);
|
||||
|
||||
/* Clamp indirect evaluations to the importance map. Camera rays are not affected
|
||||
* by the importance map and don't involve NEE, so don't need this. */
|
||||
float ray_dD = INTEGRATOR_STATE(state, ray, dD);
|
||||
if (!(path_visibility & PATH_RAY_VISIBILITY_CAMERA)) {
|
||||
ray_dD = background_light_clamp_dD(kg, ray_dD);
|
||||
}
|
||||
|
||||
PROFILING_INIT_FOR_SHADER(kg, PROFILING_SHADE_LIGHT_SETUP);
|
||||
shader_setup_from_background(kg,
|
||||
emission_sd,
|
||||
INTEGRATOR_STATE(state, ray, P),
|
||||
INTEGRATOR_STATE(state, ray, D),
|
||||
INTEGRATOR_STATE(state, ray, dD),
|
||||
ray_dD,
|
||||
INTEGRATOR_STATE(state, ray, time));
|
||||
|
||||
PROFILING_SHADER(emission_sd->object, emission_sd->shader);
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ ccl_device ShaderEvalResult integrate_light_nee(KernelGlobals kg, IntegratorShad
|
|||
if (light_type == LIGHT_BACKGROUND) {
|
||||
/* Background light. */
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
const float ray_dD = ray.dD;
|
||||
const float ray_dD = background_light_clamp_dD(kg, ray.dD);
|
||||
#else
|
||||
const float ray_dD = 0.0f;
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -391,7 +391,9 @@ ccl_device
|
|||
|
||||
/* Evaluate BSDF. */
|
||||
BsdfEval bsdf_eval ccl_optional_struct_init;
|
||||
const float bsdf_pdf = surface_shader_bsdf_eval(kg, state, sd, ls.D, &bsdf_eval, ls.shader);
|
||||
float avg_roughness_squared = 0.0f;
|
||||
const float bsdf_pdf = surface_shader_bsdf_eval(
|
||||
kg, state, sd, ls.D, &bsdf_eval, ls.shader, avg_roughness_squared);
|
||||
|
||||
Ray ray ccl_optional_struct_init;
|
||||
|
||||
|
|
@ -427,6 +429,12 @@ ccl_device
|
|||
|
||||
/* Create shadow ray. */
|
||||
light_sample_to_surface_shadow_ray(kg, sd, &ls, &ray);
|
||||
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
/* Widen ray differences, with same logic as forward sampling to ensure
|
||||
* both MIS strategies converge to the same result. */
|
||||
ray.dD = bsdf_widen_dD(INTEGRATOR_STATE(state, ray, dD), avg_roughness_squared);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ray.self.object != OBJECT_NONE) {
|
||||
|
|
@ -514,6 +522,8 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
|||
float bsdf_eta = 1.0f;
|
||||
float mis_pdf = 1.0f;
|
||||
|
||||
float bsdf_avg_roughness_squared = 0.0f;
|
||||
|
||||
#if defined(__PATH_GUIDING__) && PATH_GUIDING_LEVEL >= 4
|
||||
if (kernel_data.integrator.use_surface_guiding &&
|
||||
(kernel_data.kernel_features & KERNEL_FEATURE_PATH_GUIDING))
|
||||
|
|
@ -530,7 +540,8 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
|||
&unguided_bsdf_pdf,
|
||||
&bsdf_sampled_roughness,
|
||||
&bsdf_eta,
|
||||
rng_state);
|
||||
rng_state,
|
||||
bsdf_avg_roughness_squared);
|
||||
|
||||
if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) {
|
||||
return LABEL_NONE;
|
||||
|
|
@ -549,7 +560,8 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
|||
&bsdf_wo,
|
||||
&bsdf_pdf,
|
||||
&bsdf_sampled_roughness,
|
||||
&bsdf_eta);
|
||||
&bsdf_eta,
|
||||
bsdf_avg_roughness_squared);
|
||||
|
||||
if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) {
|
||||
return LABEL_NONE;
|
||||
|
|
@ -571,8 +583,11 @@ ccl_device_forceinline int integrate_surface_bsdf_bssrdf_bounce(
|
|||
INTEGRATOR_STATE_WRITE(state, ray, tmax) = FLT_MAX;
|
||||
#ifdef __RAY_DIFFERENTIALS__
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dP) = differential_make_compact(sd->dP);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dD) = bsdf_widen_dD(INTEGRATOR_STATE(state, ray, dD),
|
||||
bsdf_sampled_roughness);
|
||||
|
||||
/* Widen ray differences, with same logic as NEE sampling to ensure
|
||||
* both MIS strategies converge to the same result. */
|
||||
const float dD = bsdf_widen_dD(INTEGRATOR_STATE(state, ray, dD), bsdf_avg_roughness_squared);
|
||||
INTEGRATOR_STATE_WRITE(state, ray, dD) = dD;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,7 @@ KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, float, tmin, KERNEL_FEATURE_PATH_TRACING
|
|||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, float, tmax, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, float, time, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, float, dP, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, float, dD, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, int, self_light_object, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_MEMBER_PACKED(shadow_ray, int, self_light_prim, KERNEL_FEATURE_PATH_TRACING)
|
||||
KERNEL_STRUCT_END(shadow_ray)
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ ccl_device_forceinline void integrator_state_write_shadow_ray(
|
|||
INTEGRATOR_STATE_WRITE(state, shadow_ray, tmax) = ray->tmax;
|
||||
INTEGRATOR_STATE_WRITE(state, shadow_ray, time) = ray->time;
|
||||
INTEGRATOR_STATE_WRITE(state, shadow_ray, dP) = ray->dP;
|
||||
INTEGRATOR_STATE_WRITE(state, shadow_ray, dD) = ray->dD;
|
||||
}
|
||||
|
||||
ccl_device_forceinline void integrator_state_read_shadow_ray(ConstIntegratorShadowState state,
|
||||
|
|
@ -100,7 +101,7 @@ ccl_device_forceinline void integrator_state_read_shadow_ray(ConstIntegratorShad
|
|||
ray->tmax = INTEGRATOR_STATE(state, shadow_ray, tmax);
|
||||
ray->time = INTEGRATOR_STATE(state, shadow_ray, time);
|
||||
ray->dP = INTEGRATOR_STATE(state, shadow_ray, dP);
|
||||
ray->dD = differential_zero_compact();
|
||||
ray->dD = INTEGRATOR_STATE(state, shadow_ray, dD);
|
||||
}
|
||||
|
||||
ccl_device_forceinline void integrator_state_write_shadow_ray_self(
|
||||
|
|
@ -389,6 +390,7 @@ ccl_device_forceinline void integrator_state_write_mnee(IntegratorState state,
|
|||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_ray, D) = ls->D;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_ray, P) = ray->P;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_ray, dP) = ray->dP;
|
||||
INTEGRATOR_STATE_WRITE(shadow_state, shadow_ray, dD) = ray->dD;
|
||||
INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, object) = ray->self.object;
|
||||
INTEGRATOR_STATE_ARRAY_WRITE(shadow_state, shadow_isect, 1, type) = ray->self.prim;
|
||||
|
||||
|
|
@ -445,7 +447,7 @@ ccl_device_forceinline void integrator_state_read_mnee_ray(ConstIntegratorState
|
|||
ray->tmin = ((ls->shader & SHADER_CAST_SHADOW) == 0) ? FLT_MAX : 0.0f;
|
||||
ray->time = INTEGRATOR_STATE(state, ray, time);
|
||||
ray->dP = INTEGRATOR_STATE(shadow_state, shadow_ray, dP);
|
||||
ray->dD = differential_zero_compact();
|
||||
ray->dD = INTEGRATOR_STATE(shadow_state, shadow_ray, dD);
|
||||
ray->self.object = INTEGRATOR_STATE_ARRAY(shadow_state, shadow_isect, 1, object);
|
||||
ray->self.prim = INTEGRATOR_STATE_ARRAY(shadow_state, shadow_isect, 1, type);
|
||||
ray->self.light_object = ls->object;
|
||||
|
|
|
|||
|
|
@ -275,7 +275,9 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
|
|||
ccl_private BsdfEval *result_eval,
|
||||
float sum_pdf,
|
||||
float sum_sample_weight,
|
||||
const uint light_shader_flags)
|
||||
const uint light_shader_flags,
|
||||
float sum_pdf_roughness_squared,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
/* This is the veach one-sample model with balance heuristic,
|
||||
* some PDF factors drop out when using balance heuristic weighting. */
|
||||
|
|
@ -295,7 +297,12 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
|
|||
if (!_surface_shader_exclude(sc->type, light_shader_flags)) {
|
||||
bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight);
|
||||
}
|
||||
sum_pdf += bsdf_pdf * sc->sample_weight;
|
||||
|
||||
const float weight = bsdf_pdf * sc->sample_weight;
|
||||
sum_pdf += weight;
|
||||
|
||||
/* See #bsdf_widen_dD for the motivation for this weighted average roughness. */
|
||||
sum_pdf_roughness_squared += weight * bsdf_get_specular_roughness_squared(sc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +310,8 @@ ccl_device_inline float _surface_shader_bsdf_eval_mis(KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
r_avg_roughness_squared = (sum_pdf > 0.0f) ? sum_pdf_roughness_squared / sum_pdf : 0.0f;
|
||||
|
||||
return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
|
||||
}
|
||||
|
||||
|
|
@ -311,12 +320,14 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg,
|
|||
const float3 wo,
|
||||
ccl_private BsdfEval *result_eval,
|
||||
ccl_private float *pdfs,
|
||||
const uint light_shader_flags)
|
||||
const uint light_shader_flags,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
/* This is the veach one-sample model with balance heuristic, some pdf
|
||||
* factors drop out when using balance heuristic weighting. */
|
||||
float sum_pdf = 0.0f;
|
||||
float sum_sample_weight = 0.0f;
|
||||
float sum_pdf_roughness_squared = 0.0f;
|
||||
bsdf_eval_init(result_eval, zero_spectrum());
|
||||
for (int i = 0; i < sd->num_closure; i++) {
|
||||
const ccl_private ShaderClosure *sc = &sd->closure[i];
|
||||
|
|
@ -330,9 +341,14 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg,
|
|||
if (!_surface_shader_exclude(sc->type, light_shader_flags)) {
|
||||
bsdf_eval_accum(result_eval, sc, wo, eval * sc->weight);
|
||||
}
|
||||
sum_pdf += bsdf_pdf * sc->sample_weight;
|
||||
kernel_assert(bsdf_pdf * sc->sample_weight >= 0.0f);
|
||||
pdfs[i] = bsdf_pdf * sc->sample_weight;
|
||||
|
||||
const float weight = bsdf_pdf * sc->sample_weight;
|
||||
sum_pdf += weight;
|
||||
kernel_assert(weight >= 0.0f);
|
||||
pdfs[i] = weight;
|
||||
|
||||
/* See #bsdf_widen_dD for the motivation for this weighted average roughness. */
|
||||
sum_pdf_roughness_squared += weight * bsdf_get_specular_roughness_squared(sc);
|
||||
}
|
||||
else {
|
||||
pdfs[i] = 0.0f;
|
||||
|
|
@ -354,6 +370,8 @@ ccl_device_inline float surface_shader_bsdf_eval_pdfs(const KernelGlobals kg,
|
|||
}
|
||||
}
|
||||
|
||||
r_avg_roughness_squared = (sum_pdf > 0.0f) ? sum_pdf_roughness_squared / sum_pdf : 0.0f;
|
||||
|
||||
return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
|
||||
}
|
||||
|
||||
|
|
@ -368,12 +386,21 @@ ccl_device_inline
|
|||
ccl_private ShaderData *sd,
|
||||
const float3 wo,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
const uint light_shader_flags)
|
||||
const uint light_shader_flags,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
bsdf_eval_init(bsdf_eval, zero_spectrum());
|
||||
|
||||
float pdf = _surface_shader_bsdf_eval_mis(
|
||||
kg, sd, wo, nullptr, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
|
||||
float pdf = _surface_shader_bsdf_eval_mis(kg,
|
||||
sd,
|
||||
wo,
|
||||
nullptr,
|
||||
bsdf_eval,
|
||||
0.0f,
|
||||
0.0f,
|
||||
light_shader_flags,
|
||||
0.0f,
|
||||
r_avg_roughness_squared);
|
||||
|
||||
/* If the light does not use MIS, then it is only sampled via NEE, so the probability of hitting
|
||||
* the light using BSDF sampling is zero. */
|
||||
|
|
@ -474,21 +501,25 @@ surface_shader_bssrdf_sample_weight(const ccl_private ShaderData *ccl_restrict s
|
|||
/* Sample direction for picked BSDF, and return evaluation and pdf for all
|
||||
* BSDFs combined using MIS. */
|
||||
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure_mis(
|
||||
KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
/* BSSRDF should already have been handled elsewhere. */
|
||||
kernel_assert(CLOSURE_IS_BSDF(sc->type));
|
||||
|
||||
r_avg_roughness_squared = 0.0f;
|
||||
|
||||
const bool use_surface_guiding = INTEGRATOR_STATE(state, guiding, use_surface_guiding);
|
||||
const float guiding_sampling_prob = INTEGRATOR_STATE(
|
||||
state, guiding, surface_guiding_sampling_prob);
|
||||
|
|
@ -524,7 +555,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
float unguided_bsdf_pdfs[MAX_CLOSURE];
|
||||
|
||||
*unguided_bsdf_pdf = surface_shader_bsdf_eval_pdfs(
|
||||
kg, sd, *wo, bsdf_eval, unguided_bsdf_pdfs, 0);
|
||||
kg, sd, *wo, bsdf_eval, unguided_bsdf_pdfs, 0, r_avg_roughness_squared);
|
||||
*bsdf_pdf = (guiding_sampling_prob * guide_pdf * (1.0f - bssrdf_sampling_prob)) +
|
||||
((1.0f - guiding_sampling_prob) * (*unguided_bsdf_pdf));
|
||||
float sum_pdfs = 0.0f;
|
||||
|
|
@ -577,12 +608,25 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
|
||||
|
||||
const float roughness_squared = bsdf_get_specular_roughness_squared(sc);
|
||||
if (sd->num_closure > 1) {
|
||||
const float sweight = sc->sample_weight;
|
||||
*unguided_bsdf_pdf = _surface_shader_bsdf_eval_mis(
|
||||
kg, sd, *wo, sc, bsdf_eval, (*unguided_bsdf_pdf) * sweight, sweight, 0);
|
||||
const float weight = (*unguided_bsdf_pdf) * sweight;
|
||||
*unguided_bsdf_pdf = _surface_shader_bsdf_eval_mis(kg,
|
||||
sd,
|
||||
*wo,
|
||||
sc,
|
||||
bsdf_eval,
|
||||
weight,
|
||||
sweight,
|
||||
0,
|
||||
weight * roughness_squared,
|
||||
r_avg_roughness_squared);
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
|
||||
}
|
||||
else {
|
||||
r_avg_roughness_squared = roughness_squared;
|
||||
}
|
||||
*bsdf_pdf = *unguided_bsdf_pdf;
|
||||
|
||||
if (use_surface_guiding) {
|
||||
|
|
@ -598,23 +642,27 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_mis(KernelGlobals kg,
|
|||
return label;
|
||||
}
|
||||
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
const ccl_private RNGState *rng_state,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *mis_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure_ris(
|
||||
KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
const ccl_private RNGState *rng_state,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *mis_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
/* BSSRDF should already have been handled elsewhere. */
|
||||
kernel_assert(CLOSURE_IS_BSDF(sc->type));
|
||||
|
||||
r_avg_roughness_squared = 0.0f;
|
||||
|
||||
const bool use_surface_guiding = INTEGRATOR_STATE(state, guiding, use_surface_guiding);
|
||||
const float guiding_sampling_prob = INTEGRATOR_STATE(
|
||||
state, guiding, surface_guiding_sampling_prob);
|
||||
|
|
@ -637,6 +685,9 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
// selected RIS candidate
|
||||
int ris_idx = 0;
|
||||
|
||||
// directional roughness for each of the two RIS candidates
|
||||
float ris_avg_roughness_squared[2] = {0.0f, 0.0f};
|
||||
|
||||
// meta data for the two RIS candidates
|
||||
GuidingRISSample ris_samples[2];
|
||||
ris_samples[0].rand = rand_bsdf;
|
||||
|
|
@ -658,19 +709,25 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
bsdf_eval_init(
|
||||
&ris_samples[0].bsdf_eval, sc, ris_samples[0].wo, ris_samples[0].eval * sc->weight);
|
||||
if (ris_samples[0].bsdf_pdf > 0.0f) {
|
||||
const float roughness_squared = bsdf_get_specular_roughness_squared(sc);
|
||||
if (sd->num_closure > 1) {
|
||||
const float sweight = sc->sample_weight;
|
||||
const float weight = ris_samples[0].bsdf_pdf * sweight;
|
||||
ris_samples[0].bsdf_pdf = _surface_shader_bsdf_eval_mis(kg,
|
||||
sd,
|
||||
ris_samples[0].wo,
|
||||
sc,
|
||||
&ris_samples[0].bsdf_eval,
|
||||
(ris_samples[0].bsdf_pdf) *
|
||||
sweight,
|
||||
weight,
|
||||
sweight,
|
||||
0);
|
||||
0,
|
||||
weight * roughness_squared,
|
||||
ris_avg_roughness_squared[0]);
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(&ris_samples[0].bsdf_eval)) >= 0.0f);
|
||||
}
|
||||
else {
|
||||
ris_avg_roughness_squared[0] = roughness_squared;
|
||||
}
|
||||
ris_samples[0].avg_bsdf_eval = average(ris_samples[0].bsdf_eval.sum);
|
||||
ris_samples[0].guide_pdf = guiding_bsdf_pdf(kg, ris_samples[0].wo);
|
||||
ris_samples[0].guide_pdf *= (1.0f - bssrdf_sampling_prob);
|
||||
|
|
@ -689,8 +746,13 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
ris_samples[1].guide_pdf *= (1.0f - bssrdf_sampling_prob);
|
||||
ris_samples[1].incoming_radiance_pdf = guiding_surface_incoming_radiance_pdf(
|
||||
kg, ris_samples[1].wo);
|
||||
ris_samples[1].bsdf_pdf = surface_shader_bsdf_eval_pdfs(
|
||||
kg, sd, ris_samples[1].wo, &ris_samples[1].bsdf_eval, unguided_bsdf_pdfs, 0);
|
||||
ris_samples[1].bsdf_pdf = surface_shader_bsdf_eval_pdfs(kg,
|
||||
sd,
|
||||
ris_samples[1].wo,
|
||||
&ris_samples[1].bsdf_eval,
|
||||
unguided_bsdf_pdfs,
|
||||
0,
|
||||
ris_avg_roughness_squared[1]);
|
||||
ris_samples[1].label = ris_samples[0].label;
|
||||
ris_samples[1].avg_bsdf_eval = average(ris_samples[1].bsdf_eval.sum);
|
||||
ris_samples[1].bsdf_pdf = max(0.0f, ris_samples[1].bsdf_pdf);
|
||||
|
|
@ -751,6 +813,7 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
*sampled_roughness = ris_samples[ris_idx].sampled_roughness;
|
||||
*eta = ris_samples[ris_idx].eta;
|
||||
*bsdf_eval = ris_samples[ris_idx].bsdf_eval;
|
||||
r_avg_roughness_squared = ris_avg_roughness_squared[ris_idx];
|
||||
|
||||
kernel_assert(isfinite_safe(guide_pdf));
|
||||
kernel_assert(isfinite_safe(*bsdf_pdf));
|
||||
|
|
@ -812,12 +875,25 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
|
||||
|
||||
const float roughness_squared = bsdf_get_specular_roughness_squared(sc);
|
||||
if (sd->num_closure > 1) {
|
||||
const float sweight = sc->sample_weight;
|
||||
*unguided_bsdf_pdf = _surface_shader_bsdf_eval_mis(
|
||||
kg, sd, *wo, sc, bsdf_eval, (*unguided_bsdf_pdf) * sweight, sweight, 0);
|
||||
const float weight = (*unguided_bsdf_pdf) * sweight;
|
||||
*unguided_bsdf_pdf = _surface_shader_bsdf_eval_mis(kg,
|
||||
sd,
|
||||
*wo,
|
||||
sc,
|
||||
bsdf_eval,
|
||||
weight,
|
||||
sweight,
|
||||
0,
|
||||
weight * roughness_squared,
|
||||
r_avg_roughness_squared);
|
||||
kernel_assert(reduce_min(bsdf_eval_sum(bsdf_eval)) >= 0.0f);
|
||||
}
|
||||
else {
|
||||
r_avg_roughness_squared = roughness_squared;
|
||||
}
|
||||
*bsdf_pdf = *unguided_bsdf_pdf;
|
||||
*mis_pdf = *bsdf_pdf;
|
||||
}
|
||||
|
|
@ -828,21 +904,24 @@ ccl_device int surface_shader_bsdf_guided_sample_closure_ris(KernelGlobals kg,
|
|||
return label;
|
||||
}
|
||||
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *mis_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta,
|
||||
const ccl_private RNGState *rng_state)
|
||||
ccl_device int surface_shader_bsdf_guided_sample_closure(
|
||||
KernelGlobals kg,
|
||||
IntegratorState state,
|
||||
ccl_private ShaderData *sd,
|
||||
const ccl_private ShaderClosure *sc,
|
||||
const float3 rand_bsdf,
|
||||
ccl_private BsdfEval *bsdf_eval,
|
||||
ccl_private float3 *wo,
|
||||
ccl_private float *bsdf_pdf,
|
||||
ccl_private float *mis_pdf,
|
||||
ccl_private float *unguided_bsdf_pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta,
|
||||
const ccl_private RNGState *rng_state,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
int label = LABEL_NONE;
|
||||
r_avg_roughness_squared = 0.0f;
|
||||
if (kernel_data.integrator.guiding_directional_sampling_type ==
|
||||
GUIDING_DIRECTIONAL_SAMPLING_TYPE_PRODUCT_MIS ||
|
||||
kernel_data.integrator.guiding_directional_sampling_type ==
|
||||
|
|
@ -858,7 +937,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
|
|||
bsdf_pdf,
|
||||
unguided_bsdf_pdf,
|
||||
sampled_roughness,
|
||||
eta);
|
||||
eta,
|
||||
r_avg_roughness_squared);
|
||||
*mis_pdf = (*unguided_bsdf_pdf > 0.0f) ? *bsdf_pdf : 0.0f;
|
||||
}
|
||||
else if (kernel_data.integrator.guiding_directional_sampling_type ==
|
||||
|
|
@ -876,7 +956,8 @@ ccl_device int surface_shader_bsdf_guided_sample_closure(KernelGlobals kg,
|
|||
mis_pdf,
|
||||
unguided_bsdf_pdf,
|
||||
sampled_roughness,
|
||||
eta);
|
||||
eta,
|
||||
r_avg_roughness_squared);
|
||||
}
|
||||
if (!(*unguided_bsdf_pdf > 0.0f)) {
|
||||
*bsdf_pdf = 0.0f;
|
||||
|
|
@ -897,7 +978,8 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
|
|||
ccl_private float3 *wo,
|
||||
ccl_private float *pdf,
|
||||
ccl_private float2 *sampled_roughness,
|
||||
ccl_private float *eta)
|
||||
ccl_private float *eta,
|
||||
ccl_private float &r_avg_roughness_squared)
|
||||
{
|
||||
/* BSSRDF should already have been handled elsewhere. */
|
||||
kernel_assert(CLOSURE_IS_BSDF(sc->type));
|
||||
|
|
@ -911,13 +993,29 @@ ccl_device int surface_shader_bsdf_sample_closure(KernelGlobals kg,
|
|||
if (*pdf != 0.0f) {
|
||||
bsdf_eval_init(bsdf_eval, sc, *wo, eval * sc->weight);
|
||||
|
||||
const float sweight = sc->sample_weight;
|
||||
const float roughness_squared = bsdf_get_specular_roughness_squared(sc);
|
||||
|
||||
if (sd->num_closure > 1) {
|
||||
const float sweight = sc->sample_weight;
|
||||
*pdf = _surface_shader_bsdf_eval_mis(kg, sd, *wo, sc, bsdf_eval, *pdf * sweight, sweight, 0);
|
||||
const float weight = *pdf * sweight;
|
||||
*pdf = _surface_shader_bsdf_eval_mis(kg,
|
||||
sd,
|
||||
*wo,
|
||||
sc,
|
||||
bsdf_eval,
|
||||
weight,
|
||||
sweight,
|
||||
0,
|
||||
weight * roughness_squared,
|
||||
r_avg_roughness_squared);
|
||||
}
|
||||
else {
|
||||
r_avg_roughness_squared = roughness_squared;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bsdf_eval_init(bsdf_eval, zero_spectrum());
|
||||
r_avg_roughness_squared = 0.0f;
|
||||
}
|
||||
|
||||
return label;
|
||||
|
|
|
|||
|
|
@ -17,6 +17,15 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
/* Background Light */
|
||||
|
||||
/* Clamp the ray differential so the background is not evaluated coarser than the importance map.
|
||||
* At lower mip levels a sharp feature like the sun becomes bigger and blurred. This is not
|
||||
* accounted for in the higher resolution importance map where the sun remains smaller, leading
|
||||
* to noise. The blurring may also make shadows too soft and clamping reduces that bias. */
|
||||
ccl_device_forceinline float background_light_clamp_dD(KernelGlobals kg, const float dD)
|
||||
{
|
||||
return min(dD, kernel_data.background.map_dD);
|
||||
}
|
||||
|
||||
ccl_device float3 background_map_sample(KernelGlobals kg,
|
||||
const float2 rand,
|
||||
ccl_private float *pdf)
|
||||
|
|
|
|||
|
|
@ -1229,6 +1229,7 @@ void LightManager::device_update_background(Device *device,
|
|||
if (!background_light || !background_light->is_enabled) {
|
||||
kbackground->map_res_x = 0;
|
||||
kbackground->map_res_y = 0;
|
||||
kbackground->map_dD = FLT_MAX;
|
||||
kbackground->use_mis = (kbackground->portal_weight > 0.0f);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1318,6 +1319,13 @@ void LightManager::device_update_background(Device *device,
|
|||
kbackground->map_res_x = res.x;
|
||||
kbackground->map_res_y = res.y;
|
||||
|
||||
/* Minimum ray differential for one importance map pixels, using the minimum of both
|
||||
* dimensions to account for non-square maps.
|
||||
* See #background_light_clamp_dD for motivation. */
|
||||
kbackground->map_dD = (kbackground->map_weight > 0.0f && res.x > 0 && res.y > 0) ?
|
||||
min(M_PI_F / res.y, M_2PI_F / res.x) :
|
||||
FLT_MAX;
|
||||
|
||||
vector<float3> pixels;
|
||||
shade_background_pixels(device, dscene, res.x, res.y, pixels, progress);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:bf53462f60517c84f67d45e825c395aba326062dc34cd46e1b03f76d6887db64
|
||||
size 28510
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ece45f07116794f4cb145c053b5f06917063bcac891545466774b3a2c1f6987a
|
||||
size 31931
|
||||
oid sha256:4e0cd7dbf059e58ff3c117e6c07a38bc9663f36f2e86860ec2cf7fbfdfe55e7c
|
||||
size 31526
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ea63325c6d539c03e268fff978db3884bd66fb8a8bb94c7375679c0b2d0949e9
|
||||
size 25376
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:ecc4864325f8bb2855959eb373c086c7ccbbc09586ab1fea6369db0007d6df8a
|
||||
size 1023452
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:48805dd7802f14fb9fc3e10c06a6a20a7c7a32a7a4317246a4a01669d07e29aa
|
||||
size 126706
|
||||
3
tests/files/render/image_mipmap/textures/world_sun.tx
Normal file
3
tests/files/render/image_mipmap/textures/world_sun.tx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:45d2d7645d4e49b0afa0f211ceccd5a856fd5c707876179e34e20ad80f7da04b
|
||||
size 29885
|
||||
Loading…
Add table
Add a link
Reference in a new issue