Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2013-12-29 18:49:16 +0400
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2013-12-30 03:04:02 +0400
commit30aa0c2482367fd5a99f2b791206b9e72d9ca7e3 (patch)
tree5cd2ab2810b93cc4e2d71c39ccc1d61557953f7e /intern
parent5d3adafcbb72f3c4273d80d36b34364313ae8c49 (diff)
Code refactor: better distinguish scatter and absorption for volume integration.
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/kernel/closure/volume.h4
-rw-r--r--intern/cycles/kernel/kernel_path.h21
-rw-r--r--intern/cycles/kernel/kernel_types.h25
-rw-r--r--intern/cycles/kernel/kernel_volume.h75
4 files changed, 68 insertions, 57 deletions
diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h
index 4cf918f32b8..951a03bce71 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_VOLUME;
+ return SD_BSDF|SD_BSDF_HAS_EVAL|SD_SCATTER;
}
ccl_device float3 volume_henyey_greenstein_eval_phase(const ShaderClosure *sc, const float3 I, float3 omega_in, float *pdf)
@@ -98,7 +98,7 @@ ccl_device int volume_absorption_setup(ShaderClosure *sc)
{
sc->type = CLOSURE_VOLUME_ABSORPTION_ID;
- return SD_VOLUME;
+ return SD_ABSORPTION;
}
/* VOLUME CLOSURE */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index 7aea673528a..204f782e5f4 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -92,11 +92,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
#endif
#ifdef __VOLUME__
- /* volume attenuation */
+ /* volume attenuation, emission, scatter */
if(state.volume_stack[0].shader != SHADER_NO_ID) {
- Ray segment_ray = ray;
- segment_ray.t = (hit)? isect.t: FLT_MAX;
- kernel_volume_integrate(kg, &state, &segment_ray, L, &throughput);
+ ray.t = (hit)? isect.t: FLT_MAX;
+ kernel_volume_integrate(kg, &state, &ray, L, &throughput);
}
#endif
@@ -514,11 +513,10 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#endif
#ifdef __VOLUME__
- /* volume attenuation */
+ /* volume attenuation, emission, scatter */
if(state.volume_stack[0].shader != SHADER_NO_ID) {
- Ray segment_ray = ray;
- segment_ray.t = (hit)? isect.t: FLT_MAX;
- kernel_volume_integrate(kg, &state, &segment_ray, &L, &throughput);
+ ray.t = (hit)? isect.t: FLT_MAX;
+ kernel_volume_integrate(kg, &state, &ray, &L, &throughput);
}
#endif
@@ -1018,11 +1016,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif
#ifdef __VOLUME__
- /* volume attenuation */
+ /* volume attenuation, emission, scatter */
if(state.volume_stack[0].shader != SHADER_NO_ID) {
- Ray segment_ray = ray;
- segment_ray.t = (hit)? isect.t: FLT_MAX;
- kernel_volume_integrate(kg, &state, &segment_ray, &L, &throughput);
+ ray.t = (hit)? isect.t: FLT_MAX;
+ kernel_volume_integrate(kg, &state, &ray, &L, &throughput);
}
#endif
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 3091defd465..63cd2b223a3 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -500,25 +500,26 @@ enum ShaderDataFlag {
SD_BSDF_GLOSSY = 16, /* have glossy bsdf */
SD_BSSRDF = 32, /* have bssrdf */
SD_HOLDOUT = 64, /* have holdout closure? */
- SD_VOLUME = 128, /* have volume closure? */
- SD_AO = 256, /* have ao closure? */
+ SD_ABSORPTION = 128, /* have volume absorption closure? */
+ SD_SCATTER = 256, /* have volume scattering closure? */
+ SD_AO = 512, /* have ao closure? */
- SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_VOLUME|SD_AO),
+ SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_ABSORPTION|SD_SCATTER|SD_AO),
/* shader flags */
- SD_USE_MIS = 512, /* direct light sample */
- SD_HAS_TRANSPARENT_SHADOW = 1024, /* has transparent shadow */
- SD_HAS_VOLUME = 2048, /* has volume shader */
- 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 */
+ SD_USE_MIS = 1024, /* direct light sample */
+ SD_HAS_TRANSPARENT_SHADOW = 2048, /* has transparent shadow */
+ SD_HAS_VOLUME = 4096, /* has volume shader */
+ SD_HAS_ONLY_VOLUME = 8192, /* has only volume shader, no surface */
+ SD_HOMOGENEOUS_VOLUME = 16384, /* has homogeneous volume */
+ SD_HAS_BSSRDF_BUMP = 32768, /* bssrdf normal uses bump */
SD_SHADER_FLAGS = (SD_USE_MIS|SD_HAS_TRANSPARENT_SHADOW|SD_HAS_VOLUME|SD_HAS_ONLY_VOLUME|SD_HOMOGENEOUS_VOLUME|SD_HAS_BSSRDF_BUMP),
/* object flags */
- SD_HOLDOUT_MASK = 32768, /* holdout for camera rays */
- SD_OBJECT_MOTION = 65536, /* has object motion blur */
- SD_TRANSFORM_APPLIED = 131072, /* vertices have transform applied */
+ SD_HOLDOUT_MASK = 65536, /* holdout for camera rays */
+ SD_OBJECT_MOTION = 131072, /* has object motion blur */
+ SD_TRANSFORM_APPLIED = 262144, /* vertices have transform applied */
SD_OBJECT_FLAGS = (SD_HOLDOUT_MASK|SD_OBJECT_MOTION|SD_TRANSFORM_APPLIED)
};
diff --git a/intern/cycles/kernel/kernel_volume.h b/intern/cycles/kernel/kernel_volume.h
index 6b198ed9173..ee9e28999ed 100644
--- a/intern/cycles/kernel/kernel_volume.h
+++ b/intern/cycles/kernel/kernel_volume.h
@@ -16,16 +16,23 @@
CCL_NAMESPACE_BEGIN
+typedef enum VolumeIntegrateResult {
+ VOLUME_PATH_TERMINATED = 0,
+ VOLUME_PATH_SCATTERED = 1,
+ VOLUME_PATH_ATTENUATED = 2,
+ VOLUME_PATH_MISSED = 3
+} VolumeIntegrateResult;
+
/* Volume shader properties
*
* extinction coefficient = absorption coefficient + scattering coefficient
* sigma_t = sigma_a + sigma_s */
-typedef struct VolumeShaderSample {
+typedef struct VolumeShaderCoefficients {
float3 sigma_a;
float3 sigma_s;
float3 emission;
-} VolumeShaderSample;
+} VolumeShaderCoefficients;
/* evaluate shader to get extinction coefficient at P */
ccl_device bool volume_shader_extinction_sample(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack, int path_flag, ShaderContext ctx, float3 P, float3 *extinction)
@@ -33,7 +40,7 @@ ccl_device bool volume_shader_extinction_sample(KernelGlobals *kg, ShaderData *s
sd->P = P;
shader_eval_volume(kg, sd, stack, 0.0f, path_flag, ctx);
- if(!(sd->flag & SD_VOLUME))
+ if(!(sd->flag & (SD_ABSORPTION|SD_SCATTER)))
return false;
float3 sigma_t = make_float3(0.0f, 0.0f, 0.0f);
@@ -50,12 +57,12 @@ ccl_device bool volume_shader_extinction_sample(KernelGlobals *kg, ShaderData *s
}
/* evaluate shader to get absorption, scattering and emission at P */
-ccl_device bool volume_shader_sample(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack, int path_flag, ShaderContext ctx, float3 P, VolumeShaderSample *sample)
+ccl_device bool volume_shader_sample(KernelGlobals *kg, ShaderData *sd, VolumeStack *stack, int path_flag, ShaderContext ctx, float3 P, VolumeShaderCoefficients *sample)
{
sd->P = P;
shader_eval_volume(kg, sd, stack, 0.0f, path_flag, ctx);
- if(!(sd->flag & (SD_VOLUME|SD_EMISSION)))
+ if(!(sd->flag & (SD_ABSORPTION|SD_SCATTER|SD_EMISSION)))
return false;
sample->sigma_a = make_float3(0.0f, 0.0f, 0.0f);
@@ -83,12 +90,12 @@ ccl_device float3 volume_color_attenuation(float3 sigma, float t)
/* Volumetric Shadows */
-/* get the volume attenuation over line segment defined by segment_ray, with the
+/* get the volume attenuation over line segment defined by ray, with the
* assumption that there are no surfaces blocking light between the endpoints */
-ccl_device void kernel_volume_get_shadow_attenuation(KernelGlobals *kg, PathState *state, Ray *segment_ray, float3 *throughput)
+ccl_device void kernel_volume_get_shadow_attenuation(KernelGlobals *kg, PathState *state, Ray *ray, float3 *throughput)
{
ShaderData sd;
- shader_setup_from_volume(kg, &sd, segment_ray, state->bounce);
+ shader_setup_from_volume(kg, &sd, ray, state->bounce);
ShaderContext ctx = SHADER_CONTEXT_SHADOW;
int path_flag = PATH_RAY_SHADOW;
@@ -96,54 +103,58 @@ ccl_device void kernel_volume_get_shadow_attenuation(KernelGlobals *kg, PathStat
/* homogenous volume: assume shader evaluation at the starts gives
* the extinction coefficient for the entire line segment */
- if(!volume_shader_extinction_sample(kg, &sd, state->volume_stack, path_flag, ctx, segment_ray->P, &sigma_t))
+ if(!volume_shader_extinction_sample(kg, &sd, state->volume_stack, path_flag, ctx, ray->P, &sigma_t))
return;
- *throughput *= volume_color_attenuation(sigma_t, segment_ray->t);
+ *throughput *= volume_color_attenuation(sigma_t, ray->t);
}
/* Volumetric Path */
/* get the volume attenuation and emission over line segment defined by
- * segment_ray, with the assumption that there are no surfaces blocking light
+ * ray, with the assumption that there are no surfaces blocking light
* between the endpoints */
-ccl_device void kernel_volume_integrate(KernelGlobals *kg, PathState *state, Ray *segment_ray, PathRadiance *L, float3 *throughput)
+ccl_device VolumeIntegrateResult kernel_volume_integrate(KernelGlobals *kg, PathState *state, Ray *ray, PathRadiance *L, float3 *throughput)
{
ShaderData sd;
- shader_setup_from_volume(kg, &sd, segment_ray, state->bounce);
+ shader_setup_from_volume(kg, &sd, ray, state->bounce);
ShaderContext ctx = SHADER_CONTEXT_VOLUME;
int path_flag = PATH_RAY_SHADOW;
- VolumeShaderSample sample;
+ VolumeShaderCoefficients coeff;
/* homogenous volume: assume shader evaluation at the starts gives
* the extinction coefficient for the entire line segment */
- if(!volume_shader_sample(kg, &sd, state->volume_stack, path_flag, ctx, segment_ray->P, &sample))
- return;
+ if(!volume_shader_sample(kg, &sd, state->volume_stack, path_flag, ctx, ray->P, &coeff))
+ return VOLUME_PATH_MISSED;
+
+ /* todo: in principle the SD_EMISSION, SD_ABSORPTION and SD_SCATTER flags
+ * should ensure that one of the components is > 0 and so no division by
+ * zero occurs, however this needs to be double-checked and tested */
int closure_flag = sd.flag;
- float t = segment_ray->t;
+ float t = ray->t;
/* compute attenuation from absorption (+ scattering for now) */
- float3 sigma_t, attenuation;
+ float3 attenuation;
- if(closure_flag & SD_VOLUME) {
- sigma_t = sample.sigma_a + sample.sigma_s;
- attenuation = volume_color_attenuation(sigma_t, t);
- }
+ if(closure_flag & SD_ABSORPTION)
+ attenuation = volume_color_attenuation(coeff.sigma_a, t);
/* integrate emission attenuated by absorption
- * integral E * exp(-sigma_t * t) from 0 to t = E * (1 - exp(-sigma_t * t))/sigma_t
- * this goes to E * t as sigma_t goes to zero
+ * integral E * exp(-sigma_a * t) from 0 to t = E * (1 - exp(-sigma_a * t))/sigma_a
+ * this goes to E * t as sigma_a goes to zero
*
- * todo: we should use an epsilon to avoid precision issues near zero sigma_t */
+ * todo: we should use an epsilon to avoid precision issues near zero sigma_a */
if(closure_flag & SD_EMISSION) {
- float3 emission = sample.emission;
+ float3 emission = coeff.emission;
+
+ if(closure_flag & SD_ABSORPTION) {
+ float3 sigma_a = coeff.sigma_a;
- if(closure_flag & SD_VOLUME) {
- emission.x *= (sigma_t.x > 0.0f)? (1.0f - attenuation.x)/sigma_t.x: t;
- emission.y *= (sigma_t.y > 0.0f)? (1.0f - attenuation.y)/sigma_t.y: t;
- emission.z *= (sigma_t.z > 0.0f)? (1.0f - attenuation.z)/sigma_t.z: t;
+ emission.x *= (sigma_a.x > 0.0f)? (1.0f - attenuation.x)/sigma_a.x: t;
+ emission.y *= (sigma_a.y > 0.0f)? (1.0f - attenuation.y)/sigma_a.y: t;
+ emission.z *= (sigma_a.z > 0.0f)? (1.0f - attenuation.z)/sigma_a.z: t;
}
else
emission *= t;
@@ -152,8 +163,10 @@ ccl_device void kernel_volume_integrate(KernelGlobals *kg, PathState *state, Ray
}
/* modify throughput */
- if(closure_flag & SD_VOLUME)
+ if(closure_flag & SD_ABSORPTION)
*throughput *= attenuation;
+
+ return VOLUME_PATH_ATTENUATED;
}
/* Volume Stack */