[Bf-blender-cvs] [35a683b] soc-2013-dingto: Cycles Volume: materials without a surface shader now act transparent when there is a volume shader.

Brecht Van Lommel noreply at git.blender.org
Sun Dec 8 13:03:15 CET 2013


Commit: 35a683bfe4ba32fd0dfe1499dd572c4f78c46274
Author: Brecht Van Lommel
Date:   Mon Dec 2 18:31:56 2013 +0100
http://developer.blender.org/rB35a683bfe4ba32fd0dfe1499dd572c4f78c46274

Cycles Volume: materials without a surface shader now act transparent when
there is a volume shader.

This is the behavior you would expect I think and makes setup easier. More
optimizations are possible in this case to avoid surface shading altogether, but
it's probably not so noticeable altogether as this will early out and not get to
any expensive computations as far as I know.

Note that these still count as transparent bounces even if there is no BSDF. Not
entirely happy with that, but there should be some way to limit the depth?

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

M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_types.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/render/shader.cpp

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

diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index af960f3..7a06ca6 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -774,60 +774,76 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
 		}
 #endif
 
-		/* no BSDF? we can stop here */
-		if(!(sd.flag & SD_BSDF))
-			break;
-
-		/* sample BSDF */
-		float bsdf_pdf;
-		BsdfEval bsdf_eval;
-		float3 bsdf_omega_in;
-		differential3 bsdf_domega_in;
-		float bsdf_u, bsdf_v;
-		path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
-		int label;
+		if(sd.flag & SD_BSDF) {
+			/* sample BSDF */
+			float bsdf_pdf;
+			BsdfEval bsdf_eval;
+			float3 bsdf_omega_in;
+			differential3 bsdf_domega_in;
+			float bsdf_u, bsdf_v;
+			path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+			int label;
 
-		label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
-			&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
+			label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
+				&bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
 
-		if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
-			break;
+			if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
+				break;
 
-		/* modify throughput */
+			/* modify throughput */
 #ifdef __VOLUME__
-		bsdf_eval_mul(&bsdf_eval, volume_eval/volume_pdf);
+			bsdf_eval_mul(&bsdf_eval, volume_eval/volume_pdf);
 #endif
-		path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
+			path_radiance_bsdf_bounce(&L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
 
-		/* set labels */
-		if(!(label & LABEL_TRANSPARENT)) {
-			ray_pdf = bsdf_pdf;
+			/* set labels */
+			if(!(label & LABEL_TRANSPARENT)) {
+				ray_pdf = bsdf_pdf;
 #ifdef __LAMP_MIS__
-			ray_t = 0.0f;
+				ray_t = 0.0f;
+#endif
+				min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+			}
+
+			/* update path state */
+			path_state_next(kg, &state, label);
+
+			/* setup ray */
+			ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
+			ray.D = bsdf_omega_in;
+
+#ifdef __RAY_DIFFERENTIALS__
+			ray.dP = sd.dP;
+			ray.dD = bsdf_domega_in;
 #endif
-			min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+		}
+		else if(sd.flag & SD_HAS_ONLY_VOLUME) {
+			/* no surface shader but have a volume shader? act transparent */
+
+			/* update path state, count as transparent */
+			path_state_next(kg, &state, LABEL_TRANSPARENT);
+
+			/* setup ray position, direction stays unchanged */
+			ray.P = ray_offset(sd.P, -sd.Ng);
+#ifdef __RAY_DIFFERENTIALS__
+			ray.dP = sd.dP;
+#endif
+		}
+		else {
+			/* no bsdf or volume? we're done */
+			break;
 		}
 
 #ifdef __VOLUME__
 		ray_pdf *= volume_pdf;
 #endif
 
-		/* update path state */
-		path_state_next(kg, &state, label);
-
-		/* setup ray */
-		ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
-		ray.D = bsdf_omega_in;
-
+		/* adjust ray distance for clipping */
 		if(state.bounce == 0)
 			ray.t -= sd.ray_length; /* clipping works through transparent */
 		else
 			ray.t = FLT_MAX;
 
-#ifdef __RAY_DIFFERENTIALS__
-		ray.dP = sd.dP;
-		ray.dD = bsdf_domega_in;
-#endif
 #ifdef __VOLUME__
 		if (sd.flag & SD_BACKFACING)
 			media_volume_shader = kernel_data.background.shader;
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 3996950..e1cd0e0 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -521,13 +521,14 @@ enum ShaderDataFlag {
 	SD_USE_MIS = 512,					/* direct light sample */
 	SD_HAS_TRANSPARENT_SHADOW = 1024,	/* has transparent shadow */
 	SD_HAS_VOLUME = 2048,				/* has volume shader */
-	SD_HOMOGENEOUS_VOLUME = 4096,		/* has homogeneous volume */
-	SD_HAS_BSSRDF_BUMP = 8192,			/* bssrdf normal uses bump */
+	SD_HAS_ONLY_VOLUME = 4096,			/* has only volume shader, no surface */
+	SD_HOMOGENEOUS_VOLUME = 8192,		/* has homogeneous volume */
+	SD_HAS_BSSRDF_BUMP = 16384,			/* bssrdf normal uses bump */
 
 	/* object flags */
-	SD_HOLDOUT_MASK = 16384,			/* holdout for camera rays */
-	SD_OBJECT_MOTION = 32768,			/* has object motion blur */
-	SD_TRANSFORM_APPLIED = 65536 		/* vertices have transform applied */
+	SD_HOLDOUT_MASK = 32768,			/* holdout for camera rays */
+	SD_OBJECT_MOTION = 65536,			/* has object motion blur */
+	SD_TRANSFORM_APPLIED = 131072 		/* vertices have transform applied */
 };
 
 struct KernelGlobals;
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 1a6de55..a50ffe6 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -793,12 +793,15 @@ ccl_device_inline bool shadow_blocked_volume(KernelGlobals *kg, PathState *state
 				v_ray.t = isect.t;
 				float3 attenuation = kernel_volume_get_shadow_attenuation(kg, rng, rng_offset, rng_congruential, sample, &v_ray, media_volume_shader, &tmp_volume_pdf);
 				*volume_pdf *= tmp_volume_pdf;
+				throughput *= attenuation;
 
 				ShaderData sd;
 				shader_setup_from_ray(kg, &sd, &isect, ray, state->bounce);
-				shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_MAIN);
 
-				throughput *= shader_bsdf_transparency(kg, &sd) * attenuation;
+				if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
+					shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_MAIN);
+					throughput *= shader_bsdf_transparency(kg, &sd);
+				}
 
 				ray->P = ray_offset(sd.P, -sd.Ng);
 				if(ray->t != FLT_MAX)
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 450bb66..2e7deee 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -230,6 +230,15 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc
 		if(shader->has_volume) {
 			flag |= SD_HAS_VOLUME;
 			has_volumetrics = true;
+
+			/* in this case we can assume transparent surface */
+			if(!shader->has_surface)
+				flag |= SD_HAS_ONLY_VOLUME;
+
+			/* todo: this could check more fine grained, to skip useless volumes
+			 * enclosed inside an opaque bsdf, although we still need to handle
+			 * the case with camera inside volumes too */
+			flag |= SD_HAS_TRANSPARENT_SHADOW;
 		}
 		if(shader->homogeneous_volume)
 			flag |= SD_HOMOGENEOUS_VOLUME;




More information about the Bf-blender-cvs mailing list