[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