[Bf-blender-cvs] [108594d8c84] gsoc-2018-many-light-sampling: Cycles: Light tree: energy and light picking fixes

Erik Englesson noreply at git.blender.org
Fri Aug 3 17:32:03 CEST 2018


Commit: 108594d8c844edb09afdac1a355f0b6d99cb80db
Author: Erik Englesson
Date:   Mon Jul 30 15:42:52 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB108594d8c844edb09afdac1a355f0b6d99cb80db

Cycles: Light tree: energy and light picking fixes

When calculating the energy for a light source I previously returned
zero energy if is_constant_emission() returned false. This has now
been changed so it uses an emission of (1,1,1) instead.

The normal that is used for light picking for the BSDF approximation
in the importance calculations now takes into consideration if the
point is on glass, a reflective or transmissive surface. The position
and normal used for light picking is now stored in the ShaderData struct.

===================================================================

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_path_surface.h
M	intern/cycles/kernel/kernel_path_volume.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/split/kernel_direct_lighting.h
M	intern/cycles/kernel/split/kernel_do_volume.h
M	intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
M	intern/cycles/kernel/split/kernel_indirect_background.h
M	intern/cycles/kernel/split/kernel_lamp_emission.h
M	intern/cycles/render/light_tree.cpp

===================================================================

diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h
index 107c308e80f..b6d01fe0987 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, ray.P, sd->N, is_volume_boundary); // todo: is this the correct P and N?
+			float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf, is_volume_boundary);
 			path_radiance_accum_emission(&L_sample, &state, throughput, emission);
 		}
 
@@ -97,11 +97,12 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 					                                      &ray,
 					                                      &L_sample,
 					                                      &throughput);
+					indirect_sd.P_pick = sd->P_pick;
+					indirect_sd.N_pick = sd->N_pick;
 					kernel_path_indirect(kg,
 					                     &indirect_sd,
 					                     &emission_sd,
 					                     &ray,
-					                     sd->N,
 					                     throughput,
 					                     &state,
 					                     &L_sample);
@@ -120,7 +121,9 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
 				state.ray_t = 0.0f;
 #endif
 				/* compute indirect light */
-				kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, sd->N, throughput, &state, &L_sample); // todo: is this correct P and N?
+				indirect_sd.P_pick = sd->P_pick;
+				indirect_sd.N_pick = sd->N_pick;
+				kernel_path_indirect(kg, &indirect_sd, &emission_sd, &ray, throughput, &state, &L_sample);
 
 				/* sum and reset indirect light pass variables for the next samples */
 				path_radiance_sum_indirect(&L_sample);
@@ -140,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, ray.P, sd->N, is_volume_boundary); // todo: is this correct P and N?
+			float3 emission = indirect_primitive_emission(kg, sd, 0.0f, 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 a06250a515a..0f54ea66205 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, float3 P, float3 N, bool is_volume_boundary)
+ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, 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, P, N, sd->prim, sd->object, is_volume_boundary);
+		pdf *= light_distribution_pdf(kg, sd->P_pick, sd->N_pick, sd->prim, sd->object, is_volume_boundary);
 		float mis_weight = power_heuristic(bsdf_pdf, pdf);
 
 		return L*mis_weight;
@@ -226,7 +226,6 @@ 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)
 {
@@ -281,7 +280,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, N, ~ls.lamp, -1, is_inside_volume);
+			ls.pdf *= light_distribution_pdf(kg, ray->P, emission_sd->N_pick, ~ls.lamp, -1, is_inside_volume);
 			float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
 			L *= mis_weight;
 		}
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 976dd68b5ae..2e494a884dd 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -33,6 +33,37 @@ typedef struct LightSample {
 	LightType type;		/* type of light */
 } LightSample;
 
+/* This normal is used in the light picking when using the light tree */
+ccl_device void kernel_update_light_picking(
+	ShaderData *sd)
+{
+	bool transmission = false;
+	bool reflective = false;
+	bool glass = false;
+	for(int i = 0; i < sd->num_closure; ++i){
+		const ShaderClosure *sc = &sd->closure[i];
+		if(CLOSURE_IS_GLASS(sc->type)){
+			glass = true;
+		}
+		if(CLOSURE_IS_BSDF_TRANSMISSION(sc->type)) {
+			transmission = true;
+		}
+		if(CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSDF_GLOSSY(sc->type)){
+			reflective = true;
+		}
+	}
+
+	if(glass || (reflective && transmission)){
+		sd->N_pick = make_float3(0.0f, 0.0f, 0.0f);
+	} else if(!glass && !reflective && transmission){
+		sd->N_pick = -sd->N;
+	} else {
+		sd->N_pick = sd->N;
+	}
+
+	sd->P_pick = sd->P;
+}
+
 /* Area light sampling */
 
 /* Uses the following paper:
@@ -1124,15 +1155,19 @@ ccl_device float calc_importance(KernelGlobals *kg, float3 P, float3 N,
 	const float cos_theta_prime = fast_cosf(theta_prime);
 
 	/* f_a|cos(theta'_i)| -- diffuse approximation */
-	const float theta_i               = fast_acosf(dot(N, -centroidToPDir));
-	const float theta_i_prime         = fmaxf(theta_i - theta_u, 0.0f);
-	const float cos_theta_i_prime     = fast_cosf(theta_i_prime);
-	const float abs_cos_theta_i_prime = fabsf(cos_theta_i_prime);
-	/* doing something similar to bsdf_diffuse_eval_reflect() */
-	/* TODO: Use theta_i or theta_i_prime here? */
-	const float f_a                   = fmaxf(cos_theta_i_prime, 0.0f) * M_1_PI_F;
-
-	return f_a * abs_cos_theta_i_prime * energy * cos_theta_prime / d2;
+	if(N != make_float3(0.0f, 0.0f, 0.0f)){
+		const float theta_i               = fast_acosf(dot(N, -centroidToPDir));
+		const float theta_i_prime         = fmaxf(theta_i - theta_u, 0.0f);
+		const float cos_theta_i_prime     = fast_cosf(theta_i_prime);
+		const float abs_cos_theta_i_prime = fabsf(cos_theta_i_prime);
+		/* doing something similar to bsdf_diffuse_eval_reflect() */
+		/* TODO: Use theta_i or theta_i_prime here? */
+		const float f_a                   = fmaxf(cos_theta_i_prime, 0.0f) * M_1_PI_F;
+
+		return f_a * abs_cos_theta_i_prime * energy * cos_theta_prime / d2;
+	}
+
+	return energy * cos_theta_prime / d2;
 }
 
 ccl_device float calc_light_importance(KernelGlobals *kg, float3 P, float3 N,
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index a9235e5f446..01d3d0e8129 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -100,7 +100,6 @@ ccl_device_forceinline void kernel_path_lamp_emission(
 	KernelGlobals *kg,
 	ccl_addr_space PathState *state,
 	Ray *ray,
-	float3 N,
 	float3 throughput,
 	ccl_addr_space Intersection *isect,
 	ShaderData *emission_sd,
@@ -121,8 +120,7 @@ ccl_device_forceinline void kernel_path_lamp_emission(
 
 		/* intersect with lamp */
 		float3 emission;
-
-		if(indirect_lamp_emission(kg, emission_sd, state, N, &light_ray, &emission))
+		if(indirect_lamp_emission(kg, emission_sd, state, &light_ray, &emission))
 			path_radiance_accum_emission(L, state, throughput, emission);
 	}
 #endif  /* __LAMP_MIS__ */
@@ -132,7 +130,6 @@ ccl_device_forceinline void kernel_path_background(
 	KernelGlobals *kg,
 	ccl_addr_space PathState *state,
 	ccl_addr_space Ray *ray,
-	float3 N,
 	float3 throughput,
 	ShaderData *sd,
 	PathRadiance *L)
@@ -155,7 +152,7 @@ ccl_device_forceinline void kernel_path_background(
 
 #ifdef __BACKGROUND__
 	/* sample background shader */
-	float3 L_background = indirect_background(kg, sd, N, state, ray);
+	float3 L_background = indirect_background(kg, sd, sd->N_pick, state, ray);
 	path_radiance_accum_background(L, state, throughput, L_background);
 #endif  /* __BACKGROUND__ */
 }
@@ -202,6 +199,8 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
 		kernel_volume_decoupled_record(kg, state,
 			&volume_ray, sd, &volume_segment, heterogeneous);
 
+		kernel_update_light_picking(sd);
+
 		volume_segment.sampling_method = sampling_method;
 
 		/* emission */
@@ -250,6 +249,8 @@ 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);
+
 #  ifdef __VOLUME_SCATTER__
 		if(result == VOLUME_PATH_SCATTERED) {
 			/* direct lighting */
@@ -275,7 +276,6 @@ ccl_device_forceinline bool kernel_path_shader_apply(
 	ShaderData *sd,
 	ccl_addr_space PathState *state,
 	ccl_addr_space Ray *ray,
-	float3 MIS_N,
 	float3 throughput,
 	ShaderData *emission_sd,
 	PathRadiance *L,
@@ -289,7 +289,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(
 
 			float3 bg = make_float3(0.0f, 0.0f, 0.0f);
 			if(!kernel_data.background.transparent) {
-				bg = indirect_background(kg, emission_sd, MIS_N, state, ray);
+				bg = indirect_background(kg, emission_sd, sd->N_pick, state, ray);
 			}
 			path_radiance_accum_shadowcatcher(L, throughput, bg);
 		}


@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list