[Bf-blender-cvs] [e369a5c] master: Cycles Volume Render: support for rendering of homogeneous volume with absorption.

Brecht Van Lommel noreply at git.blender.org
Sat Dec 28 17:40:30 CET 2013


Commit: e369a5c48529864118d49222dde3d530d58ebeae
Author: Brecht Van Lommel
Date:   Sat Dec 28 16:56:19 2013 +0100
https://developer.blender.org/rBe369a5c48529864118d49222dde3d530d58ebeae

Cycles Volume Render: support for rendering of homogeneous volume with absorption.

This is the simplest possible volume rendering case, constant density inside
the volume and no scattering or emission. My plan is to tweak, verify and commit
more volume rendering effects one by one, doing it all at once makes it
difficult to verify correctness and track down bugs.

Documentation is here:
http://wiki.blender.org/index.php/Doc:2.6/Manual/Render/Cycles/Materials/Volume

Currently this hooks into path tracing in 3 ways, which should get us pretty
far until we add more advanced light sampling. These 3 hooks are repeated in
the path tracing, branched path tracing and transparent shadow code:

* Determine active volume shader at start of the path
* Change active volume shader on transmission through a surface
* Light attenuation over line segments between camera, surfaces and background

This is work by "storm", Stuart Broadfoot, Thomas Dinges and myself.

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/kernel/CMakeLists.txt
M	intern/cycles/kernel/kernel_path.h
M	intern/cycles/kernel/kernel_path_state.h
M	intern/cycles/kernel/kernel_shader.h
M	intern/cycles/kernel/kernel_shadow.h
M	intern/cycles/kernel/kernel_types.h
A	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/svm/svm_closure.h
M	intern/cycles/render/scene.cpp
M	release/scripts/startup/nodeitems_builtins.py
M	source/blender/blenkernel/intern/node.c
M	source/blender/editors/space_node/drawnode.c

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index f5c052e..e446e47 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -577,6 +577,12 @@ class CyclesWorldSettings(bpy.types.PropertyGroup):
                 min=1, max=10000,
                 default=4,
                 )
+        cls.homogeneous_volume = BoolProperty(
+                name="Homogeneous Volume",
+                description="When using volume rendering, assume volume has the same density everywhere, "
+                            "for faster rendering",
+                default=False,
+                )
 
     @classmethod
     def unregister(cls):
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 83483cb..02d1dfb 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -780,9 +780,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
 
     @classmethod
     def poll(cls, context):
-        # world = context.world
-        # world and world.node_tree and CyclesButtonsPanel.poll(context)
-        return False
+        world = context.world
+        return world and world.node_tree and CyclesButtonsPanel.poll(context)
 
     def draw(self, context):
         layout = self.layout
@@ -790,6 +789,8 @@ class CyclesWorld_PT_volume(CyclesButtonsPanel, Panel):
         world = context.world
         panel_node_draw(layout, world, 'OUTPUT_WORLD', 'Volume')
 
+        layout.prop(world.cycles, "homogeneous_volume")
+
 
 class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
     bl_label = "Ambient Occlusion"
@@ -926,9 +927,8 @@ class CyclesMaterial_PT_volume(CyclesButtonsPanel, Panel):
 
     @classmethod
     def poll(cls, context):
-        # mat = context.material
-        # mat and mat.node_tree and CyclesButtonsPanel.poll(context)
-        return False
+        mat = context.material
+        return mat and mat.node_tree and CyclesButtonsPanel.poll(context)
 
     def draw(self, context):
         layout = self.layout
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index 0c3a32a..6ec72c3 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -956,6 +956,9 @@ void BlenderSync::sync_world(bool update_all)
 			out = graph->output();
 
 			graph->connect(closure->output("Background"), out->input("Surface"));
+
+			PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles");
+			shader->homogeneous_volume = get_boolean(cworld, "homogeneous_volume");
 		}
 
 		if(b_world) {
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index 6363799..8609098 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -51,6 +51,7 @@ set(SRC_HEADERS
 	kernel_textures.h
 	kernel_triangle.h
 	kernel_types.h
+	kernel_volume.h
 )
 
 set(SRC_CLOSURE_HEADERS
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 903efc9..d318a85 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -40,6 +40,10 @@
 #include "kernel_subsurface.h"
 #endif
 
+#ifdef __VOLUME__
+#include "kernel_volume.h"
+#endif
+
 #include "kernel_shadow.h"
 
 CCL_NAMESPACE_BEGIN
@@ -87,6 +91,15 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
 		}
 #endif
 
+#ifdef __VOLUME__
+		/* volume attenuation */
+		if(state.volume_shader != SHADER_NO_ID) {
+			Ray segment_ray = ray;
+			segment_ray.t = (hit)? isect.t: FLT_MAX;
+			throughput *= kernel_volume_get_shadow_attenuation(kg, &state, &segment_ray, state.volume_shader);
+		}
+#endif
+
 		if(!hit) {
 #ifdef __BACKGROUND__
 			/* sample background shader */
@@ -235,47 +248,73 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
 #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_total_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_total_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 */
-		path_radiance_bsdf_bounce(L, &throughput, &bsdf_eval, bsdf_pdf, state.bounce, label);
+			/* modify throughput */
+			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;
+			ray.t = FLT_MAX;
+#ifdef __RAY_DIFFERENTIALS__
+			ray.dP = sd.dP;
+			ray.dD = bsdf_domega_in;
+#endif
+
+#ifdef __VOLUME__
+			/* enter/exit volume */
+			if(label & LABEL_TRANSMIT)
+				kernel_volume_enter_exit(kg, &sd, &state.volume_shader);
 #endif
-			min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
 		}
+#ifdef __VOLUME__
+		else if(sd.flag & SD_HAS_ONLY_VOLUME) {
+			/* no surface shader but have a volume shader? act transparent */
 
-		/* update path state */
-		path_state_next(kg, &state, label);
+			/* update path state, count as transparent */
+			path_state_next(kg, &state, LABEL_TRANSPARENT);
 
-		/* setup ray */
-		ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
-		ray.D = bsdf_omega_in;
-		ray.t = FLT_MAX;
+			/* setup ray position, direction stays unchanged */
+			ray.P = ray_offset(sd.P, -sd.Ng);
 #ifdef __RAY_DIFFERENTIALS__
-		ray.dP = sd.dP;
-		ray.dD = bsdf_domega_in;
+			ray.dP = sd.dP;
 #endif
+
+			/* enter/exit volume */
+			kernel_volume_enter_exit(kg, &sd, &state.volume_shader);
+		}
+#endif
+		else {
+			/* no bsdf or volume? we're done */
+			break;
+		}
 	}
 }
 
@@ -324,54 +363,80 @@ ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn
 #endif
 
 	/* no BSDF? we can stop here */
-	if(!(sd->flag & SD_BSDF))
-		return false;
-
-	/* 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))
-		return false;
+		if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
+			return false;
 
-	/* modify throughput */
-	path_radiance_bsdf_bounce(L, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
+		/* modify throughput */
+		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);
-	}
+			*min_ray_pdf = fminf(bsdf_pdf, *min_ray_pdf);
+		}
 
-	/* update path state */
-	path_state_next(kg, state, label);
+		/* 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;
+		/* setup ray */
+		ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng);
+		ray->D = bsdf_omega_in;
 
-	if(state->bounce == 0)
-		ray->t -= sd->ray_length; /* clipping works through transparent */
-	else
-		ray->t = FLT_MAX;
+		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__
+		/* enter/exit volume */
+		if(label & LABEL_TRANSMIT)
+			kernel_volume_enter_exit(kg, sd, &state->volume_shader);
+#endif
+		return true;
+	}
+#ifdef __VOLUME__
+	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;
-	ray->dD = bsdf_domega_in;
+		ray->dP = sd->dP;
+#endif
+
+		/* enter/exit volume */
+		kernel_volume_enter_exit(kg, sd, &state->volume_shader);
+		return true;
+	}
 #endif
-	
-	return true;
+	else {
+		/* no bsdf or volume? */
+		return false;
+	}
 }
 
 #endif
@@ -398,7 +463,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
 	int num_samples = 0;
 #endif
 
-	path_state_init(&state);
+	path_state_init(kg, &state);
 
 	/* path iteration */
 	for(;; rng_offset += PRNG_BOUNCE_NUM)

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list