[Bf-blender-cvs] [94af4326e3f] gsoc-2018-many-light-sampling: Cycles: Light tree: volume and MIS fixes

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


Commit: 94af4326e3fc22fe1b229a3e2435fb6ccfe36ce9
Author: Erik Englesson
Date:   Thu Aug 2 19:21:01 2018 +0200
Branches: gsoc-2018-many-light-sampling
https://developer.blender.org/rB94af4326e3fc22fe1b229a3e2435fb6ccfe36ce9

Cycles: Light tree: volume and MIS fixes

Now using a more reliable way of knowing if a shading point
is inside or on the boundary of a volume.

Fixed a bug in light_background_sample() that used an index
into the lights array as an index into the distribution array.

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

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/split/kernel_holdout_emission_blurring_pathtermination_ao.h

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

diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index 8fe773f5a4b..95aebe1246f 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, float3 P, float3 N, 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 has_volume)
 {
 	/* 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, P, N, sd->prim, sd->object, has_volume);
 		float mis_weight = power_heuristic(bsdf_pdf, pdf);
 
 		return L*mis_weight;
@@ -260,7 +260,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
 		                                ls.t,
 		                                ray->time);
 
-		bool is_inside_volume = false;
+		bool has_volume = false;
 #ifdef __VOLUME__
 		if(state->volume_stack[0].shader != SHADER_NONE) {
 			/* shadow attenuation */
@@ -271,9 +271,7 @@ ccl_device_noinline bool indirect_lamp_emission(KernelGlobals *kg,
 			L *= volume_tp;
 		}
 
-		if((state->volume_bounce > 0 || (state->volume_bounds_bounce > 0)) && (emission_sd->flag & SD_HAS_VOLUME)) {
-			is_inside_volume = true;
-		}
+		has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
 #endif
 
 		if(!(state->flag & PATH_RAY_MIS_SKIP)) {
@@ -281,7 +279,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, N, ~ls.lamp, -1, has_volume);
 			float mis_weight = power_heuristic(state->ray_pdf, ls.pdf);
 			L *= mis_weight;
 		}
@@ -315,6 +313,11 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
 			return make_float3(0.0f, 0.0f, 0.0f);
 	}
 
+	bool has_volume = false;
+#if defined(__BACKGROUND_MIS__) && defined(__VOLUME__)
+	/* This has to be done before shader_setup_* below. */
+	has_volume = ((emission_sd->flag & SD_HAS_VOLUME) != 0);
+#endif
 	/* evaluate background closure */
 #  ifdef __SPLIT_KERNEL__
 	Ray priv_ray = *ray;
@@ -340,15 +343,6 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
 		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;
-#ifdef __VOLUME__
-	if((state->volume_bounce > 0) || (state->volume_bounds_bounce > 0)) {
-		is_on_volume_boundary = true;
-	}
-#endif
-
 	/* check if background light exists or if we should skip pdf */
 	int res_x = kernel_data.integrator.pdf_background_res_x;
 
@@ -357,7 +351,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
 		 * direction, and compute weight with respect to BSDF pdf */
 		float pdf = background_light_pdf(kg, P_pick, ray->D);
 		int background_index = kernel_data.integrator.background_light_index;
-		pdf *= light_distribution_pdf(kg, P_pick, N_pick, ~background_index, -1, is_on_volume_boundary);
+		pdf *= light_distribution_pdf(kg, P_pick, N_pick, ~background_index, -1, has_volume);
 		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 409831081ae..26f93aba12a 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -1256,7 +1256,7 @@ ccl_device void light_distant_sample(KernelGlobals *kg, float3 P, float *randu,
 /* picks one of the background lights and computes the probability of picking it */
 ccl_device void light_background_sample(KernelGlobals *kg, float3 P, float *randu,
                                      int *index, float *pdf){
-	*index = kernel_data.integrator.background_light_index;
+	*index = kernel_tex_fetch(__lamp_to_distribution, kernel_data.integrator.background_light_index);
 	*pdf = 1.0f;
 }
 
@@ -1464,7 +1464,7 @@ ccl_device float light_bvh_pdf(KernelGlobals *kg, float3 P, float3 N,
 /* computes the the probability of picking the given light out of all lights */
 ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, float3 N,
                                         int prim_id, int object_id,
-                                        bool is_inside_volume)
+                                        bool has_volume)
 {
 	/* convert from triangle/lamp to light distribution */
 	int distribution_id;
@@ -1479,7 +1479,7 @@ ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, float3 N,
 	              (distribution_id < kernel_data.integrator.num_distribution));
 
 	/* compute picking pdf for this light */
-	if (kernel_data.integrator.use_light_bvh && !is_inside_volume){
+	if (kernel_data.integrator.use_light_bvh && !has_volume){
 		/* find out which group of lights to sample */
 		int group;
 		if(prim_id >= 0){
@@ -1520,10 +1520,10 @@ ccl_device float light_distribution_pdf(KernelGlobals *kg, float3 P, float3 N,
 
 /* picks a light and returns its index and the probability of picking it */
 ccl_device void light_distribution_sample(KernelGlobals *kg, float3 P, float3 N,
-                                          bool is_in_volume, float *randu,
+                                          bool has_volume, float *randu,
                                           int *index, float *pdf)
 {
-	if (kernel_data.integrator.use_light_bvh && !is_in_volume){
+	if (kernel_data.integrator.use_light_bvh && !has_volume){
 		/* sample light type distribution */
 		int   group      = light_group_distribution_sample(kg, randu);
 		float group_prob = kernel_tex_fetch(__light_group_sample_prob, group);
@@ -1592,12 +1592,12 @@ ccl_device_noinline bool light_sample(KernelGlobals *kg,
                                       float3 N,
                                       int bounce,
                                       LightSample *ls,
-                                      bool is_in_volume)
+                                      bool has_volume)
 {
 	/* sample index and compute light picking pdf */
 	float pdf_factor = 0.0f;
 	int index = -1;
-	light_distribution_sample(kg, P, N, is_in_volume, &randu, &index, &pdf_factor);
+	light_distribution_sample(kg, P, N, has_volume, &randu, &index, &pdf_factor);
 
 	if(pdf_factor == 0.0f){
 		return false;
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 097c5640f54..83283247483 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -286,7 +286,8 @@ ccl_device_forceinline bool kernel_path_shader_apply(
 	float3 throughput,
 	ShaderData *emission_sd,
 	PathRadiance *L,
-	ccl_global float *buffer)
+	ccl_global float *buffer,
+	bool has_volume)
 {
 #ifdef __SHADOW_TRICKS__
 	if((sd->object_flag & SD_OBJECT_SHADOW_CATCHER)) {
@@ -363,8 +364,7 @@ ccl_device_forceinline bool kernel_path_shader_apply(
 
 		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, ray_length, P_pick, N_pick, 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, has_volume);
 		path_radiance_accum_emission(L, state, throughput, emission);
 	}
 #endif  /* __EMISSION__ */
@@ -477,6 +477,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 		}
 
 		/* Setup shader data. */
+		bool has_volume = (sd->flag & SD_HAS_VOLUME) != 0;
 		shader_setup_from_ray(kg, sd, &isect, ray);
 
 		/* Skip most work for volume bounding surface. */
@@ -496,7 +497,8 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 		                             throughput,
 		                             emission_sd,
 		                             L,
-		                             NULL))
+		                             NULL,
+		                             has_volume))
 		{
 			break;
 		}
@@ -651,6 +653,7 @@ ccl_device_forceinline void kernel_path_integrate(
 		}
 
 		/* Setup shader data. */
+		bool has_volume = (sd.flag & SD_HAS_VOLUME) != 0;
 		shader_setup_from_ray(kg, &sd, &isect, ray);
 
 		/* Skip most work for volume bounding surface. */
@@ -670,7 +673,8 @@ ccl_device_forceinline void kernel_path_integrate(
 		                             throughput,
 		                             emission_sd,
 		                             L,
-		                             buffer))
+		                             buffer,
+		                             has_volume))
 		{
 			break;
 		}
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index d9e1433acda..b1c815b6a15 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -463,6 +463,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 	 * Indirect bounces are handled in kernel_branched_path_surface_indirect_light().
 	 */
 	for(;;) {
+
 		/* Find intersection with objects in scene. */
 		Intersection isect;
 		bool hit = kernel_path_scene_intersect(kg, &state, &ray, &isect, L);
@@ -488,6 +489,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 		}
 
 		/* Setup and evaluate shader. */
+		bool has_volume = (sd.flag & SD_HAS_VOLUME) != 0;
 		shader_setup_from_ray(kg, &sd, &isect, &ray);
 
 		/* Skip most work for volume bounding surface. */
@@ -50

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list