[Bf-blender-cvs] [01df756] master: Cycles Volume Render: scattering support.

Brecht Van Lommel noreply at git.blender.org
Tue Jan 7 15:04:10 CET 2014


Commit: 01df756bd10709bb707d4f88f14c50e5680d05a5
Author: Brecht Van Lommel
Date:   Sun Dec 29 15:40:43 2013 +0100
https://developer.blender.org/rB01df756bd10709bb707d4f88f14c50e5680d05a5

Cycles Volume Render: scattering support.

This is done by adding a Volume Scatter node. In many cases you will want to
add together a Volume Absorption and Volume Scatter node with the same color
and density to get the expected results.

This should work with branched path tracing, mixing closures, overlapping
volumes, etc. However there's still various optimizations needed for sampling.
The main missing thing from the volume branch is the equiangular sampling for
homogeneous volumes.

The heterogeneous scattering code was arranged such that we can use a single
stratified random number for distance sampling, which gives less noise than
pseudo random numbers for each step. For volumes where the color is textured
there still seems to be something off, needs to be investigated.

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

M	intern/cycles/blender/addon/properties.py
M	intern/cycles/blender/addon/ui.py
M	intern/cycles/blender/blender_sync.cpp
M	intern/cycles/kernel/closure/bsdf.h
M	intern/cycles/kernel/closure/volume.h
M	intern/cycles/kernel/kernel_accumulate.h
M	intern/cycles/kernel/kernel_emission.h
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_types.h
M	intern/cycles/kernel/kernel_volume.h
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/integrator.cpp
M	intern/cycles/render/integrator.h
M	source/blender/blenkernel/intern/node.c

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

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index aa2da00..74f94d6 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -220,6 +220,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 default=1,
                 )
 
+        cls.volume_samples = IntProperty(
+                name="Volume Samples",
+                description="Number of volume scattering samples to render for each AA sample",
+                min=1, max=10000,
+                default=1,
+                )
+
         cls.sampling_pattern = EnumProperty(
                 name="Sampling Pattern",
                 description="Random sampling pattern used by the integrator",
@@ -280,6 +287,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 min=0, max=1024,
                 default=12,
                 )
+        cls.volume_bounces = IntProperty(
+                name="Volume Bounces",
+                description="Maximum number of volumetric scattering events",
+                min=0, max=1024,
+                default=1,
+                )
 
         cls.transparent_min_bounces = IntProperty(
                 name="Transparent Min Bounces",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 969f130..d5f1447 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -139,6 +139,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel):
             sub.prop(cscene, "ao_samples", text="AO")
             sub.prop(cscene, "mesh_light_samples", text="Mesh Light")
             sub.prop(cscene, "subsurface_samples", text="Subsurface")
+            sub.prop(cscene, "volume_samples", text="Volume")
 
         if cscene.feature_set == 'EXPERIMENTAL' and (device_type == 'NONE' or cscene.device == 'CPU'):
             layout.row().prop(cscene, "sampling_pattern", text="Pattern")
@@ -208,6 +209,7 @@ class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel):
         sub.prop(cscene, "diffuse_bounces", text="Diffuse")
         sub.prop(cscene, "glossy_bounces", text="Glossy")
         sub.prop(cscene, "transmission_bounces", text="Transmission")
+        sub.prop(cscene, "volume_bounces", text="Volume")
 
 
 class CyclesRender_PT_motion_blur(CyclesButtonsPanel, Panel):
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index 826402c..14e9f27 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -166,6 +166,7 @@ void BlenderSync::sync_integrator()
 	integrator->max_diffuse_bounce = get_int(cscene, "diffuse_bounces");
 	integrator->max_glossy_bounce = get_int(cscene, "glossy_bounces");
 	integrator->max_transmission_bounce = get_int(cscene, "transmission_bounces");
+	integrator->max_volume_bounce = get_int(cscene, "volume_bounces");
 
 	integrator->transparent_max_bounce = get_int(cscene, "transparent_max_bounces");
 	integrator->transparent_min_bounce = get_int(cscene, "transparent_min_bounces");
@@ -201,6 +202,7 @@ void BlenderSync::sync_integrator()
 	int ao_samples = get_int(cscene, "ao_samples");
 	int mesh_light_samples = get_int(cscene, "mesh_light_samples");
 	int subsurface_samples = get_int(cscene, "subsurface_samples");
+	int volume_samples = get_int(cscene, "volume_samples");
 
 	if(get_boolean(cscene, "use_square_samples")) {
 		integrator->diffuse_samples = diffuse_samples * diffuse_samples;
@@ -209,6 +211,7 @@ void BlenderSync::sync_integrator()
 		integrator->ao_samples = ao_samples * ao_samples;
 		integrator->mesh_light_samples = mesh_light_samples * mesh_light_samples;
 		integrator->subsurface_samples = subsurface_samples * subsurface_samples;
+		integrator->volume_samples = volume_samples * volume_samples;
 	} 
 	else {
 		integrator->diffuse_samples = diffuse_samples;
@@ -217,6 +220,7 @@ void BlenderSync::sync_integrator()
 		integrator->ao_samples = ao_samples;
 		integrator->mesh_light_samples = mesh_light_samples;
 		integrator->subsurface_samples = subsurface_samples;
+		integrator->volume_samples = volume_samples;
 	}
 	
 
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index b3141d1..8d458c5 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -32,6 +32,9 @@
 #ifdef __SUBSURFACE__
 #include "../closure/bssrdf.h"
 #endif
+#ifdef __VOLUME__
+#include "../closure/volume.h"
+#endif
 
 CCL_NAMESPACE_BEGIN
 
@@ -124,6 +127,9 @@ ccl_device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const Shader
 				eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
 			break;
 #endif
+		case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+			label = volume_henyey_greenstein_sample(sc, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, eval, omega_in, &domega_in->dx, &domega_in->dy, pdf);
+			break;
 		default:
 			label = LABEL_NONE;
 			break;
@@ -204,6 +210,11 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
 				eval = bsdf_hair_transmission_eval_reflect(sc, sd->I, omega_in, pdf);
 				break;
 #endif
+#ifdef __VOLUME__
+			case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+				eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+				break;
+#endif
 			default:
 				eval = make_float3(0.0f, 0.0f, 0.0f);
 				break;
@@ -266,6 +277,11 @@ ccl_device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const Shade
 				eval = bsdf_hair_transmission_eval_transmit(sc, sd->I, omega_in, pdf);
 				break;
 #endif
+#ifdef __VOLUME__
+			case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
+				eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
+				break;
+#endif
 			default:
 				eval = make_float3(0.0f, 0.0f, 0.0f);
 				break;
@@ -344,6 +360,7 @@ ccl_device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness)
 			bsdf_hair_reflection_blur(sc, roughness);
 			break;
 #endif
+		/* todo: do we want to blur volume closures? */
 		default:
 			break;
 	}
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 951a03b..058c4b8 100644
--- a/intern/cycles/kernel/closure/volume.h
+++ b/intern/cycles/kernel/closure/volume.h
@@ -39,7 +39,7 @@ ccl_device int volume_henyey_greenstein_setup(ShaderClosure *sc)
 	/* clamp anisotropy to avoid delta function */
 	sc->data0 = signf(sc->data0) * min(fabsf(sc->data0), 1.0f - 1e-3f);
 
-	return SD_BSDF|SD_BSDF_HAS_EVAL|SD_SCATTER;
+	return SD_SCATTER|SD_PHASE_HAS_EVAL;
 }
 
 ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
@@ -103,13 +103,13 @@ ccl_device int volume_absorption_setup(ShaderClosure *sc)
 
 /* VOLUME CLOSURE */
 
-ccl_device float3 volume_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
+ccl_device float3 volume_phase_eval(const ShaderData *sd, const ShaderClosure *sc, float3 omega_in, float *pdf)
 {
 	float3 eval;
 
 	switch(sc->type) {
 		case CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID:
-			eval = volume_henyey_greenstein_eval_phase(sc, I, omega_in, pdf);
+			eval = volume_henyey_greenstein_eval_phase(sc, sd->I, omega_in, pdf);
 			break;
 		default:
 			eval = make_float3(0.0f, 0.0f, 0.0f);
@@ -119,7 +119,7 @@ ccl_device float3 volume_eval_phase(const ShaderClosure *sc, const float3 I, flo
 	return eval;
 }
 
-ccl_device int volume_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
+ccl_device int volume_phase_sample(const ShaderData *sd, const ShaderClosure *sc, float randu,
 	float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf)
 {
 	int label;
diff --git a/intern/cycles/kernel/kernel_accumulate.h b/intern/cycles/kernel/kernel_accumulate.h
index f4febd7..24e9d7b 100644
--- a/intern/cycles/kernel/kernel_accumulate.h
+++ b/intern/cycles/kernel/kernel_accumulate.h
@@ -35,7 +35,7 @@ ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 v
 
 		if(type == CLOSURE_BSDF_TRANSPARENT_ID)
 			eval->transparent = value;
-		else if(CLOSURE_IS_BSDF_DIFFUSE(type))
+		else if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
 			eval->diffuse = value;
 		else if(CLOSURE_IS_BSDF_GLOSSY(type))
 			eval->glossy = value;
@@ -55,7 +55,7 @@ ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3
 {
 #ifdef __PASSES__
 	if(eval->use_light_pass) {
-		if(CLOSURE_IS_BSDF_DIFFUSE(type))
+		if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
 			eval->diffuse += value;
 		else if(CLOSURE_IS_BSDF_GLOSSY(type))
 			eval->glossy += value;
diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h
index e0db943..1ec116b 100644
--- a/intern/cycles/kernel/kernel_emission.h
+++ b/intern/cycles/kernel/kernel_emission.h
@@ -103,7 +103,14 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg, ShaderData *sd, int
 	/* evaluate BSDF at shading point */
 	float bsdf_pdf;
 
+#ifdef __VOLUME__
+	if(sd->prim != ~0)
+		shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf);
+	else
+		shader_volume_phase_eval(kg, sd, ls.D, eval, &bsdf_pdf);
+#else
 	shader_bsdf_eval(kg, sd, ls.D, eval, &bsdf_pdf);
+#endif
 
 	if(ls.shader & SHADER_USE_MIS) {
 		/* multiple importance sampling */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index fda6b45..8460af8 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -48,6 +48,89 @@
 
 CCL_NAMESPACE_BEGIN
 
+#ifdef __VOLUME__
+
+ccl_device_inline bool kernel_path_integrate_scatter_lighting(KernelGlobals *kg, RNG *rng,
+	ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray,
+	float num_samples_adjust)
+{
+#ifdef __EMISSION__
+	if(kernel_data.integrator.use_direct_light) {
+		/* sample illumination from lights to find path contribution */
+		if(sd->flag & SD_BSDF_HAS_EVAL) {
+			float light_t = path_state_rng_1D(kg, rng, state, PRNG_LIGHT);
+#ifdef __MULTI_CLOSURE__
+			float light_o = 0.0f;
+#else
+			float light_o = path_state_rng_1D(kg, rng, state, PRNG_LIGHT_F);
+#endif
+			float light_u, light_v;
+			path_sta

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list