[Bf-blender-cvs] [e8e0669785c] gsoc-2018-many-light-sampling: Cycles: Picking position and normal fix for MIS
Erik Englesson
noreply at git.blender.org
Fri Aug 3 17:32:07 CEST 2018
Commit: e8e0669785cdd3b88f431e560a7323ae45958142
Author: Erik Englesson
Date: Wed Aug 1 09:40:14 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rBe8e0669785cdd3b88f431e560a7323ae45958142
Cycles: Picking position and normal fix for MIS
The picking position and normal has been changed to
use the position and normal from the last
non-transparent bounce.
===================================================================
M intern/cycles/kernel/kernel_bake.h
M intern/cycles/kernel/kernel_emission.h
M intern/cycles/kernel/kernel_light.h
M intern/cycles/kernel/kernel_path.h
M intern/cycles/kernel/kernel_path_branched.h
M intern/cycles/kernel/kernel_types.h
M intern/cycles/kernel/kernel_volume.h
M intern/cycles/kernel/split/kernel_do_volume.h
===================================================================
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index b6d01fe0987..75e1963a402 100644
--- a/intern/cycles/kernel/kernel_bake.h
+++ b/intern/cycles/kernel/kernel_bake.h
@@ -69,7 +69,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
bool is_volume_boundary = (state.volume_bounce > 0) || (state.volume_bounds_bounce > 0);
- float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf, is_volume_boundary);
+ float3 emission = indirect_primitive_emission(kg, sd, 0.0f, sd->P_pick, sd->N_pick, state.flag, state.ray_pdf, is_volume_boundary);
path_radiance_accum_emission(&L_sample, &state, throughput, emission);
}
@@ -143,7 +143,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
bool is_volume_boundary = (state.volume_bounce > 0) || (state.volume_bounds_bounce > 0);
- float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf, is_volume_boundary);
+ float3 emission = indirect_primitive_emission(kg, sd, 0.0f, sd->P_pick, sd->N_pick, state.flag, state.ray_pdf, is_volume_boundary);
path_radiance_accum_emission(&L_sample, &state, throughput, emission);
}
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 0f54ea66205..8fe773f5a4b 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -198,7 +198,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
/* Indirect Primitive Emission */
-ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf, bool is_volume_boundary)
+ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, float3 P, float3 N, int path_flag, float bsdf_pdf, bool is_volume_boundary)
{
/* evaluate emissive closure */
float3 L = shader_emissive_eval(kg, sd);
@@ -212,7 +212,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
/* multiple importance sampling, get triangle light pdf,
* and compute weight with respect to BSDF pdf */
float pdf = triangle_light_pdf(kg, sd, t);
- pdf *= light_distribution_pdf(kg, sd->P_pick, sd->N_pick, sd->prim, sd->object, is_volume_boundary);
+ pdf *= light_distribution_pdf(kg, P, N, sd->prim, sd->object, is_volume_boundary);
float mis_weight = power_heuristic(bsdf_pdf, pdf);
return L*mis_weight;
@@ -226,6 +226,7 @@ ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, Shader
ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
ShaderData *emission_sd,
ccl_addr_space PathState *state,
+ float3 N,
Ray *ray,
float3 *emission)
{
@@ -280,7 +281,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
* and compute weight with respect to BSDF pdf */
/* multiply with light picking probablity to pdf */
- ls.pdf *= light_distribution_pdf(kg, ray->P, emission_sd->N_pick, ~ls.lamp, -1, is_inside_volume);
+ ls.pdf *= light_distribution_pdf(kg, ray->P, N, ~ls.lamp, -1, is_inside_volume);
float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
L *= mis_weight;
}
@@ -328,6 +329,17 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
#ifdef __BACKGROUND_MIS__
+ /* consider shading point at previous non-transparent bounce */
+ float3 P_pick;
+ float3 N_pick;
+ if(state->ray_t == 0.0f){ // Non-transparent bounce
+ P_pick = emission_sd->P_pick;
+ N_pick = emission_sd->N_pick;
+ } else { // Transparent bounce
+ P_pick = ray->P - state->ray_t*ray->D;
+ N_pick = state->ray_N;
+ }
+
/* todo: looks like this only happens for volume boundaries and not inside.
* is this expected? */
bool is_on_volume_boundary = false;
@@ -343,9 +355,9 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
if(!(state->flag & PATH_RAY_MIS_SKIP) && res_x) {
/* multiple importance sampling, get background light pdf for ray
* direction, and compute weight with respect to BSDF pdf */
- float pdf = background_light_pdf(kg, ray->P, ray->D);
+ float pdf = background_light_pdf(kg, P_pick, ray->D);
int background_index = kernel_data.integrator.background_light_index;
- pdf *= light_distribution_pdf(kg, ray->P, N, ~background_index, -1, is_on_volume_boundary);
+ pdf *= light_distribution_pdf(kg, P_pick, N_pick, ~background_index, -1, is_on_volume_boundary);
float mis_weight = power_heuristic(state->ray_pdf, pdf);
return L*mis_weight;
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 2e494a884dd..409831081ae 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -35,11 +35,13 @@ typedef struct LightSample {
/* This normal is used in the light picking when using the light tree */
ccl_device void kernel_update_light_picking(
- ShaderData *sd)
+ ShaderData *sd,
+ ccl_addr_space PathState *state)
{
bool transmission = false;
bool reflective = false;
bool glass = false;
+ bool transparent = false;
for(int i = 0; i < sd->num_closure; ++i){
const ShaderClosure *sc = &sd->closure[i];
if(CLOSURE_IS_GLASS(sc->type)){
@@ -51,6 +53,9 @@ ccl_device void kernel_update_light_picking(
if(CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSDF_GLOSSY(sc->type)){
reflective = true;
}
+ if(CLOSURE_IS_BSDF_TRANSPARENT(sc->type)){
+ transparent = true;
+ }
}
if(glass || (reflective && transmission)){
@@ -62,6 +67,15 @@ ccl_device void kernel_update_light_picking(
}
sd->P_pick = sd->P;
+
+#if defined(__LAMP_MIS__) || defined(__EMISSION__) || defined(__BACKGROUND_MIS__)
+ if(!transparent){
+ state->ray_N = sd->N_pick;
+ }
+ // todo: what if there is a transparent but it is not this BSDF that is
+ // sampled in surface_bounce() ?
+#endif
+
}
/* Area light sampling */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 01d3d0e8129..097c5640f54 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -109,18 +109,25 @@ ccl_device_forceinline void kernel_path_lamp_emission(
if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
/* ray starting from previous non-transparent bounce */
Ray light_ray;
+ float3 N_pick;
+ if(state->ray_t == 0.0f){
+ light_ray.P = emission_sd->P_pick;
+ N_pick = emission_sd->N_pick;
+ } else {
+ /* Current bounce was on a transparent surface */
+ light_ray.P = ray->P - state->ray_t*ray->D;
+ N_pick = state->ray_N;
+ }
- light_ray.P = ray->P - state->ray_t*ray->D;
- state->ray_t += isect->t;
light_ray.D = ray->D;
- light_ray.t = state->ray_t;
+ light_ray.t = state->ray_t + isect->t;
light_ray.time = ray->time;
light_ray.dD = ray->dD;
light_ray.dP = ray->dP;
/* intersect with lamp */
float3 emission;
- if(indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission))
+ if(indirect_lamp_emission(kg, emission_sd, state, N_pick, &light_ray, &emission))
path_radiance_accum_emission(L, state, throughput, emission);
}
#endif /* __LAMP_MIS__ */
@@ -199,7 +206,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
kernel_volume_decoupled_record(kg, state,
&volume_ray, sd, &volume_segment, heterogeneous);
- kernel_update_light_picking(sd);
+ kernel_update_light_picking(sd, state);
volume_segment.sampling_method = sampling_method;
@@ -249,7 +256,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
VolumeIntegrateResult result = kernel_volume_integrate(
kg, state, sd, &volume_ray, L, throughput, heterogeneous);
- kernel_update_light_picking(sd);
+ kernel_update_light_picking(sd, state);
# ifdef __VOLUME_SCATTER__
if(result == VOLUME_PATH_SCATTERED) {
@@ -342,12 +349,30 @@ ccl_device_forceinline bool kernel_path_shader_apply(
#ifdef __EMISSION__
/* emission */
if(sd->flag & SD_EMISSION) {
+
+ /* ray starting from previous non-transparent bounce */
+ float3 P_pick;
+ float3 N_pick;
+ if(state->ray_t == 0.0f){ // Non-transparent bounce
+ P_pick = sd->P_pick;
+ N_pick = sd->N_pick;
+ } else { // Transparent bounce
+ P_pick = ray->P - state->ray_t*ray->D;
+ N_pick = state->ray_N;
+ }
+
+ float ray_length = state->ray_t + sd->ray_length;
+
bool is_volume_boundary = (state->volume_bounce > 0) || (state->volume_bounds_bounce > 0);
- float3 emission = indirect_primitive_emission(kg, sd, sd->ray_length, state->flag, state->ray_pdf, is_volume_boundary);
+ float3 emission = indirect_primitive_emission(kg, sd, ray_length, P_pick, N_pick, state->flag, state->ray_pdf, is_volume_boundary);
path_radiance_accum_emission(L, state, throughput, emission);
}
#endif /* __EMISSION__ */
+#if defined(__LAMP_MIS__) || defined(__EMISSION__) || defined(__BACKGROUND_MIS__)
+ state->ray_t += sd->ray_length;
+#endif
+
return true;
}
@@ -493,7 +518,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
throughput /= probability;
}
- kernel_update_light_picking(sd);
+ kernel_update_light_picking(sd, state);
kernel_update_denoising_features(kg, sd, state, L);
@@ -588,6 +613,7 @@ ccl_device_forceinline void kernel_path_integrate(
/* path iteration */
for(;;) {
+
/* Find intersection with objects in scene. */
Intersection isect;
bool hit = kernel_path_scene_intersect(kg, state, ray, &isect, L);
@@ -665,7 +691,7 @@ ccl_device_forceinline void kernel_path_integrate(
throughput /= probability;
}
- kernel_update_light_picking(&sd);
+ kernel_update_light_picking(&sd, state);
kernel_update_denoising_features(kg, &sd, state, L);
@@ -704,6 +730,7 @@ ccl_device_forceinline voi
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list