[Bf-blender-cvs] [776ce62] soc-2014-cycles: Cycles: Further optimizations for Volume Light Sampling.

Thomas Dinges noreply at git.blender.org
Tue Jul 29 18:00:52 CEST 2014


Commit: 776ce62bee4df7ad59b7c2172e9eec9435607d60
Author: Thomas Dinges
Date:   Tue Jul 29 17:58:14 2014 +0200
Branches: soc-2014-cycles
https://developer.blender.org/rB776ce62bee4df7ad59b7c2172e9eec9435607d60

Cycles: Further optimizations for Volume Light Sampling.

* Now we calculate ls->P only, which is needed for equi-angular sampling. If the scattering is successful, we call the regular light_sample() functions.

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

M	intern/cycles/kernel/kernel_light.h
M	intern/cycles/kernel/kernel_path_volume.h

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

diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index 37230d4..199a2c2 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -208,46 +208,39 @@ ccl_device float lamp_light_pdf(KernelGlobals *kg, const float3 Ng, const float3
 	return t*t/cos_pi;
 }
 
-ccl_device void lamp_light_sample_new_position(KernelGlobals *kg, int lamp,
+ccl_device void lamp_light_sample_position(KernelGlobals *kg, int lamp,
 								  float randu, float randv, float3 P, LightSample *ls)
 {
-	if(ls->type == LIGHT_POINT || ls->type == LIGHT_SPOT) {
-		float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
-		float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
+	float4 data0 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 0);
+	float4 data1 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 1);
 
+	LightType type = (LightType)__float_as_int(data0.x);
+
+	if(type == LIGHT_DISTANT || type == LIGHT_BACKGROUND) {
+		/* Distant lights, no equi-angular sampling */
+		ls->t = FLT_MAX;
+	}
+	else {
+		/* calculate ls->P for equi-angular sampling */
 		ls->P = make_float3(data0.y, data0.z, data0.w);
 
-		float radius = data1.y;
+		if(type == LIGHT_POINT || type == LIGHT_SPOT) {
+			float radius = data1.y;
 
-		if(radius > 0.0f)
+			if(radius > 0.0f)
 			/* sphere light */
-			ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
-
-		ls->D = normalize_len(ls->P - P, &ls->t);
-		ls->Ng = -ls->D;
-
-		float invarea = data1.z;
-		ls->pdf = invarea;
-
-		if(ls->type == LIGHT_SPOT) {
-			/* spot light attenuation */
-			float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
-			ls->eval_fac = (0.25f*M_1_PI_F)*invarea*kernel_data.integrator.inv_pdf_lights;
-			ls->eval_fac *= spot_light_attenuation(data1, data2, ls);
+				ls->P += sphere_light_sample(P, ls->P, radius, randu, randv);
 		}
-	}
-	else if(ls->type == LIGHT_AREA) {
+		else {
+			/* area light */
 			float4 data2 = kernel_tex_fetch(__light_data, lamp*LIGHT_SIZE + 2);
-			ls->pdf = data2.x;
 
-			ls->D = normalize_len(ls->P - P, &ls->t);
-	}
-	else {
-		/* Distant Lights */
-		return;
-	}
+			float3 axisu = make_float3(data1.y, data1.z, data1.w);
+			float3 axisv = make_float3(data2.y, data2.z, data2.w);
 
-	ls->pdf *= lamp_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+			ls->P += area_light_sample(axisu, axisv, randu, randv);
+		}
+	}
 }
 
 ccl_device void lamp_light_sample(KernelGlobals *kg, int lamp,
@@ -554,8 +547,7 @@ ccl_device int light_distribution_sample(KernelGlobals *kg, float randt)
 	return clamp(first-1, 0, kernel_data.integrator.num_distribution-1);
 }
 
-/* ToDo: Better function name */
-ccl_device void light_sample_new_position(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls)
+ccl_device void light_sample_position(KernelGlobals *kg, float randt, float randu, float randv, float time, float3 P, LightSample *ls)
 {
 	/* sample index */
 	int index = light_distribution_sample(kg, randt);
@@ -565,13 +557,12 @@ ccl_device void light_sample_new_position(KernelGlobals *kg, float randt, float
 	int prim = __float_as_int(l.y);
 
 	if(prim >= 0) {
-		/* compute incoming direction, distance and pdf */
-		ls->D = normalize_len(ls->P - P, &ls->t);
-		ls->pdf = triangle_light_pdf(kg, ls->Ng, -ls->D, ls->t);
+		/* compute distance, although this probably never becomes FLT_MAX */
+		ls->t = len(ls->P - P);
 	}
 	else {
 		int lamp = -prim-1;
-		lamp_light_sample_new_position(kg, lamp, randu, randv, P, ls);
+		lamp_light_sample_position(kg, lamp, randu, randv, P, ls);
 	}
 }
 
diff --git a/intern/cycles/kernel/kernel_path_volume.h b/intern/cycles/kernel/kernel_path_volume.h
index 32980ad..731937d 100644
--- a/intern/cycles/kernel/kernel_path_volume.h
+++ b/intern/cycles/kernel/kernel_path_volume.h
@@ -134,7 +134,6 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 				path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
 
 				LightSample ls;
-				lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
 
 				float3 tp = throughput;
 
@@ -143,13 +142,18 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 					float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
 					float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
 
+					lamp_light_sample_position(kg, i, light_u, light_v, ray->P, &ls);
+
 					VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
 						state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
 
 					if(result != VOLUME_PATH_SCATTERED)
 						continue;
 
-					lamp_light_sample_new_position(kg, i, light_u, light_v, sd->P, &ls);
+					lamp_light_sample(kg, i, light_u, light_v, sd->P, &ls);
+				}
+				else {
+					lamp_light_sample(kg, i, light_u, light_v, ray->P, &ls);
 				}
 
 				if(ls.pdf == 0.0f)
@@ -186,7 +190,6 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 					light_t = 0.5f*light_t;
 
 				LightSample ls;
-				light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
 
 				float3 tp = throughput;
 
@@ -195,13 +198,18 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 					float rphase = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_PHASE);
 					float rscatter = path_branched_rng_1D_for_decision(kg, rng, state, j, num_samples, PRNG_SCATTER_DISTANCE);
 
+					light_sample_position(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
+
 					VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
 						state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
 
 					if(result != VOLUME_PATH_SCATTERED)
 						continue;
 
-					light_sample_new_position(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+					light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+				}
+				else {
+					light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
 				}
 
 				if(ls.pdf == 0.0f)
@@ -235,13 +243,18 @@ ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg, RNG
 			float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
 			float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
 
+			light_sample_position(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
+
 			VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
 				state, ray, sd, &tp, rphase, rscatter, segment, (ls.t != FLT_MAX)? &ls.P: NULL, false);
 
 			if(result != VOLUME_PATH_SCATTERED)
 				return;
 
-			light_sample_new_position(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+			light_sample(kg, light_t, light_u, light_v, sd->time, sd->P, &ls);
+		}
+		else {
+			light_sample(kg, light_t, light_u, light_v, sd->time, ray->P, &ls);
 		}
 
 		if(ls.pdf == 0.0f)




More information about the Bf-blender-cvs mailing list