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
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2014-01-03 05:48:48 +0400
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2014-01-03 21:57:38 +0400
commitbb0a0315e28216e64190b3c6e5657438a28ad56d (patch)
tree02da099e09c58b6b3f8de559d9abe819fb3b9af3
parent57407d39b0230a1f1a137beaedb7a4771d8b8272 (diff)
Code refactor: move random number and MIS variables into PathState.
This makes it easier to pass this state around, and wraps some common RNG dimension computations in utility functions.
-rw-r--r--intern/cycles/kernel/kernel_path.h232
-rw-r--r--intern/cycles/kernel/kernel_path_state.h18
-rw-r--r--intern/cycles/kernel/kernel_random.h44
-rw-r--r--intern/cycles/kernel/kernel_types.h19
4 files changed, 185 insertions, 128 deletions
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index ee56dbd40d9..fda6b45e149 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -50,16 +50,11 @@ CCL_NAMESPACE_BEGIN
#if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__)
-ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer,
- float3 throughput, int num_samples, int num_total_samples,
- float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L)
+ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, Ray ray, ccl_global float *buffer,
+ float3 throughput, int num_samples, PathState state, PathRadiance *L)
{
-#ifdef __LAMP_MIS__
- float ray_t = 0.0f;
-#endif
-
/* path iteration */
- for(;; rng_offset += PRNG_BOUNCE_NUM) {
+ for(;;) {
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
@@ -74,19 +69,19 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* ray starting from previous non-transparent bounce */
Ray light_ray;
- light_ray.P = ray.P - ray_t*ray.D;
- ray_t += isect.t;
+ light_ray.P = ray.P - state.ray_t*ray.D;
+ state.ray_t += isect.t;
light_ray.D = ray.D;
- light_ray.t = ray_t;
+ light_ray.t = state.ray_t;
light_ray.time = ray.time;
light_ray.dD = ray.dD;
light_ray.dP = ray.dP;
/* intersect with lamp */
- float light_t = path_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT);
float3 emission;
- if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission, state.bounce))
+ if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce))
path_radiance_accum_emission(L, throughput, emission, state.bounce);
}
#endif
@@ -103,7 +98,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
if(!hit) {
#ifdef __BACKGROUND__
/* sample background shader */
- float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce);
+ float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce);
path_radiance_accum_background(L, throughput, L_background, state.bounce);
#endif
@@ -113,7 +108,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* setup shading */
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce);
- float rbsdf = path_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF);
+ float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT);
#ifdef __BRANCHED_PATH__
shader_merge_closures(&sd);
@@ -122,7 +117,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
if(kernel_data.integrator.filter_glossy != FLT_MAX) {
- float blur_pdf = kernel_data.integrator.filter_glossy*min_ray_pdf;
+ float blur_pdf = kernel_data.integrator.filter_glossy*state.min_ray_pdf;
if(blur_pdf < 1.0f) {
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
@@ -133,7 +128,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
path_radiance_accum_emission(L, throughput, emission, state.bounce);
}
#endif
@@ -147,7 +142,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
break;
}
else if(probability != 1.0f) {
- float terminate = path_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_TERMINATE);
+ float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -159,7 +154,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
float bsdf_u, bsdf_v;
- path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
@@ -201,10 +196,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, &state, 0x68bc21eb);
float bssrdf_u, bssrdf_v;
- path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
@@ -216,14 +211,14 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
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_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_LIGHT);
+ 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_rng_1D(kg, rng, sample, num_total_samples, rng_offset + PRNG_LIGHT_F);
+ float light_o = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT_F);
#endif
float light_u, light_v;
- path_rng_2D(kg, rng, sample, num_total_samples, rng_offset + PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_LIGHT_U, &light_u, &light_v);
Ray light_ray;
BsdfEval L_light;
@@ -255,7 +250,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
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);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
@@ -269,11 +264,11 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
/* set labels */
if(!(label & LABEL_TRANSPARENT)) {
- ray_pdf = bsdf_pdf;
+ state.ray_pdf = bsdf_pdf;
#ifdef __LAMP_MIS__
- ray_t = 0.0f;
+ state.ray_t = 0.0f;
#endif
- min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+ state.min_ray_pdf = fminf(bsdf_pdf, state.min_ray_pdf);
}
/* update path state */
@@ -323,23 +318,20 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ra
#ifdef __SUBSURFACE__
ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rng,
- int sample, int num_samples,
- ShaderData *sd, float3 *throughput,
- float *min_ray_pdf, float *ray_pdf, PathState *state,
- int rng_offset, PathRadiance *L, Ray *ray, float *ray_t)
+ ShaderData *sd, float3 *throughput, PathState *state, PathRadiance *L, Ray *ray)
{
#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_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT);
+ 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_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT_F);
+ float light_o = path_state_rng_1D(kg, rng, state, PRNG_LIGHT_F);
#endif
float light_u, light_v;
- path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, rng, state, PRNG_LIGHT_U, &light_u, &light_v);
Ray light_ray;
BsdfEval L_light;
@@ -370,7 +362,7 @@ ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn
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);
+ path_state_rng_2D(kg, rng, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample(kg, sd, bsdf_u, bsdf_v, &bsdf_eval,
@@ -384,11 +376,11 @@ ccl_device_inline bool kernel_path_integrate_lighting(KernelGlobals *kg, RNG *rn
/* set labels */
if(!(label & LABEL_TRANSPARENT)) {
- *ray_pdf = bsdf_pdf;
+ state->ray_pdf = bsdf_pdf;
#ifdef __LAMP_MIS__
- *ray_t = 0.0f;
+ state->ray_t = 0.0f;
#endif
- *min_ray_pdf = fminf(bsdf_pdf, *min_ray_pdf);
+ state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf);
}
/* update path state */
@@ -450,23 +442,11 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
path_radiance_init(&L, kernel_data.film.use_light_pass);
- float min_ray_pdf = FLT_MAX;
- float ray_pdf = 0.0f;
-#ifdef __LAMP_MIS__
- float ray_t = 0.0f;
-#endif
PathState state;
- int rng_offset = PRNG_BASE_NUM;
-#ifdef __CMJ__
- int num_samples = kernel_data.integrator.aa_samples;
-#else
- int num_samples = 0;
-#endif
-
path_state_init(kg, &state, rng, sample);
/* path iteration */
- for(;; rng_offset += PRNG_BOUNCE_NUM) {
+ for(;;) {
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
@@ -483,7 +463,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_init(*rng + rng_offset + sample*0x51633e2d);
+ lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
}
bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -496,19 +476,19 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* ray starting from previous non-transparent bounce */
Ray light_ray;
- light_ray.P = ray.P - ray_t*ray.D;
- ray_t += isect.t;
+ light_ray.P = ray.P - state.ray_t*ray.D;
+ state.ray_t += isect.t;
light_ray.D = ray.D;
- light_ray.t = ray_t;
+ light_ray.t = state.ray_t;
light_ray.time = ray.time;
light_ray.dD = ray.dD;
light_ray.dP = ray.dP;
/* intersect with lamp */
- float light_t = path_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT);
+ float light_t = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT);
float3 emission;
- if(indirect_lamp_emission(kg, &light_ray, state.flag, ray_pdf, light_t, &emission, state.bounce))
+ if(indirect_lamp_emission(kg, &light_ray, state.flag, state.ray_pdf, light_t, &emission, state.bounce))
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif
@@ -535,7 +515,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __BACKGROUND__
/* sample background shader */
- float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce);
+ float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce);
path_radiance_accum_background(&L, throughput, L_background, state.bounce);
#endif
@@ -545,7 +525,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* setup shading */
ShaderData sd;
shader_setup_from_ray(kg, &sd, &isect, &ray, state.bounce);
- float rbsdf = path_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF);
+ float rbsdf = path_state_rng_1D(kg, rng, &state, PRNG_BSDF);
shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN);
/* holdout */
@@ -574,7 +554,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* blurring of bsdf after bounces, for rays that have a small likelihood
* of following this particular path (diffuse, rough glossy) */
if(kernel_data.integrator.filter_glossy != FLT_MAX) {
- float blur_pdf = kernel_data.integrator.filter_glossy*min_ray_pdf;
+ float blur_pdf = kernel_data.integrator.filter_glossy*state.min_ray_pdf;
if(blur_pdf < 1.0f) {
float blur_roughness = sqrtf(1.0f - blur_pdf)*0.5f;
@@ -586,7 +566,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* emission */
if(sd.flag & SD_EMISSION) {
/* todo: is isect.t wrong here for transparent surfaces? */
- float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif
@@ -600,7 +580,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
break;
}
else if(probability != 1.0f) {
- float terminate = path_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_TERMINATE);
+ float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -613,7 +593,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
/* todo: solve correlation */
float bsdf_u, bsdf_v;
- path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float ao_factor = kernel_data.background.ao_factor;
float3 ao_N;
@@ -655,11 +635,11 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* do bssrdf scatter step if we picked a bssrdf closure */
if(sc) {
- uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, &state, 0x68bc21eb);
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
float bssrdf_u, bssrdf_v;
- path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
int num_hits = subsurface_scatter_multi_step(kg, &sd, bssrdf_sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, false);
/* compute lighting with the BSDF closure */
@@ -667,17 +647,16 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
float3 tp = throughput;
PathState hit_state = state;
Ray hit_ray = ray;
- float hit_ray_t = ray_t;
- float hit_ray_pdf = ray_pdf;
- float hit_min_ray_pdf = min_ray_pdf;
hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
+ hit_state.rng_offset += PRNG_BOUNCE_NUM;
- if(kernel_path_integrate_lighting(kg, rng, sample, num_samples, &bssrdf_sd[hit],
- &tp, &hit_min_ray_pdf, &hit_ray_pdf, &hit_state, rng_offset+PRNG_BOUNCE_NUM, &L, &hit_ray, &hit_ray_t)) {
- kernel_path_indirect(kg, rng, sample, hit_ray, buffer,
- tp, num_samples, num_samples,
- hit_min_ray_pdf, hit_ray_pdf, hit_state, rng_offset+PRNG_BOUNCE_NUM*2, &L);
+ if(kernel_path_integrate_lighting(kg, rng, &bssrdf_sd[hit], &tp, &hit_state, &L, &hit_ray)) {
+#ifdef __LAMP_MIS__
+ hit_state.ray_t = 0.0f;
+#endif
+
+ kernel_path_indirect(kg, rng, hit_ray, buffer, tp, state.num_samples, hit_state, &L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -696,14 +675,14 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
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_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT);
+ 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_rng_1D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT_F);
+ float light_o = path_state_rng_1D(kg, rng, &state, PRNG_LIGHT_F);
#endif
float light_u, light_v;
- path_rng_2D(kg, rng, sample, num_samples, rng_offset + PRNG_LIGHT_U, &light_u, &light_v);
+ path_state_rng_2D(kg, rng, &state, PRNG_LIGHT_U, &light_u, &light_v);
Ray light_ray;
BsdfEval L_light;
@@ -733,7 +712,7 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
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);
+ path_state_rng_2D(kg, rng, &state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
@@ -747,11 +726,11 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* set labels */
if(!(label & LABEL_TRANSPARENT)) {
- ray_pdf = bsdf_pdf;
+ state.ray_pdf = bsdf_pdf;
#ifdef __LAMP_MIS__
- ray_t = 0.0f;
+ state.ray_t = 0.0f;
#endif
- min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf);
+ state.min_ray_pdf = fminf(bsdf_pdf, state.min_ray_pdf);
}
/* update path state */
@@ -815,11 +794,9 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
#ifdef __BRANCHED_PATH__
-ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *kg, RNG *rng,
- int sample, int aa_samples,
- ShaderData *sd, float3 throughput, float num_samples_adjust,
- float min_ray_pdf, float ray_pdf, PathState state,
- int rng_offset, PathRadiance *L, ccl_global float *buffer)
+ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *kg,
+ RNG *rng, ShaderData *sd, float3 throughput, float num_samples_adjust,
+ PathState *state, PathRadiance *L, ccl_global float *buffer)
{
#ifdef __EMISSION__
/* sample illumination from lights to find path contribution */
@@ -843,15 +820,15 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
for(int j = 0; j < num_samples; j++) {
float light_u, light_v;
- path_rng_2D(kg, &lamp_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_LIGHT_U, &light_u, &light_v);
+ path_branched_rng_2D(kg, &lamp_rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
- if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) {
+ if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
+ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
}
}
@@ -866,21 +843,21 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
num_samples_inv *= 0.5f;
for(int j = 0; j < num_samples; j++) {
- float light_t = path_rng_1D(kg, rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_LIGHT);
+ float light_t = path_branched_rng_1D(kg, rng, state, j, num_samples, PRNG_LIGHT);
float light_u, light_v;
- path_rng_2D(kg, rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_LIGHT_U, &light_u, &light_v);
+ path_branched_rng_2D(kg, rng, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
/* only sample triangle lights */
if(kernel_data.integrator.num_all_lights)
light_t = 0.5f*light_t;
- if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state.bounce)) {
+ if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp, state->bounce)) {
/* trace shadow ray */
float3 shadow;
- if(!shadow_blocked(kg, &state, &light_ray, &shadow)) {
+ if(!shadow_blocked(kg, state, &light_ray, &shadow)) {
/* accumulate */
- path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp);
+ path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state->bounce, is_lamp);
}
}
}
@@ -920,7 +897,7 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
float3 bsdf_omega_in;
differential3 bsdf_domega_in;
float bsdf_u, bsdf_v;
- path_rng_2D(kg, &bsdf_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_branched_rng_2D(kg, &bsdf_rng, state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
int label;
label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval,
@@ -931,13 +908,10 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
/* modify throughput */
float3 tp = throughput;
- path_radiance_bsdf_bounce(L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label);
-
- /* set labels */
- float min_ray_pdf = fminf(bsdf_pdf, FLT_MAX);
+ path_radiance_bsdf_bounce(L, &tp, &bsdf_eval, bsdf_pdf, state->bounce, label);
/* modify path state */
- PathState ps = state;
+ PathState ps = *state;
path_state_next(kg, &ps, label);
/* setup ray */
@@ -960,9 +934,17 @@ ccl_device_noinline void kernel_branched_path_integrate_lighting(KernelGlobals *
kernel_volume_stack_enter_exit(kg, sd, ps.volume_stack);
#endif
- kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer,
- tp*num_samples_inv, num_samples, aa_samples*num_samples,
- min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, L);
+ /* update RNG state */
+ path_state_branch(&ps, j, num_samples);
+
+ /* set MIS state */
+ ps.min_ray_pdf = fminf(bsdf_pdf, FLT_MAX);
+ ps.ray_pdf = bsdf_pdf;
+#ifdef __LAMP_MIS__
+ ps.ray_t = 0.0f;
+#endif
+
+ kernel_path_indirect(kg, rng, bsdf_ray, buffer, tp*num_samples_inv, num_samples, ps, L);
/* for render passes, sum and reset indirect light pass variables
* for the next samples */
@@ -981,18 +963,10 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
path_radiance_init(&L, kernel_data.film.use_light_pass);
- float ray_pdf = 0.0f;
PathState state;
- int rng_offset = PRNG_BASE_NUM;
-#ifdef __CMJ__
- int aa_samples = kernel_data.integrator.aa_samples;
-#else
- int aa_samples = 0;
-#endif
-
path_state_init(kg, &state, rng, sample);
- for(;; rng_offset += PRNG_BOUNCE_NUM) {
+ for(;;) {
/* intersect scene */
Intersection isect;
uint visibility = path_state_ray_visibility(kg, &state);
@@ -1009,7 +983,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
}
extmax = kernel_data.curve.maximum_width;
- lcg_state = lcg_init(*rng + rng_offset + sample*0x51633e2d);
+ lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
}
bool hit = scene_intersect(kg, &ray, visibility, &isect, &lcg_state, difl, extmax);
@@ -1039,7 +1013,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __BACKGROUND__
/* sample background shader */
- float3 L_background = indirect_background(kg, &ray, state.flag, ray_pdf, state.bounce);
+ float3 L_background = indirect_background(kg, &ray, state.flag, state.ray_pdf, state.bounce);
path_radiance_accum_background(&L, throughput, L_background, state.bounce);
#endif
@@ -1078,7 +1052,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#ifdef __EMISSION__
/* emission */
if(sd.flag & SD_EMISSION) {
- float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, ray_pdf);
+ float3 emission = indirect_primitive_emission(kg, &sd, isect.t, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L, throughput, emission, state.bounce);
}
#endif
@@ -1094,7 +1068,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
break;
}
else if(probability != 1.0f) {
- float terminate = path_rng_1D(kg, rng, sample, aa_samples, rng_offset + PRNG_TERMINATE);
+ float terminate = path_state_rng_1D(kg, rng, &state, PRNG_TERMINATE);
if(terminate >= probability)
break;
@@ -1115,7 +1089,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
for(int j = 0; j < num_samples; j++) {
float bsdf_u, bsdf_v;
- path_rng_2D(kg, rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_BSDF_U, &bsdf_u, &bsdf_v);
+ path_branched_rng_2D(kg, rng, &state, j, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
float3 ao_D;
float ao_pdf;
@@ -1152,7 +1126,7 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
continue;
/* set up random number generator */
- uint lcg_state = lcg_init(*rng + rng_offset + sample*0x68bc21eb);
+ uint lcg_state = lcg_state_init(rng, &state, 0x68bc21eb);
int num_samples = kernel_data.integrator.subsurface_samples;
float num_samples_inv = 1.0f/num_samples;
RNG bssrdf_rng = cmj_hash(*rng, i);
@@ -1164,15 +1138,19 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
for(int j = 0; j < num_samples; j++) {
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
float bssrdf_u, bssrdf_v;
- path_rng_2D(kg, &bssrdf_rng, sample*num_samples + j, aa_samples*num_samples, rng_offset + PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
+ path_branched_rng_2D(kg, &bssrdf_rng, &state, j, num_samples, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
int num_hits = subsurface_scatter_multi_step(kg, &sd, bssrdf_sd, state.flag, sc, &lcg_state, bssrdf_u, bssrdf_v, true);
/* compute lighting with the BSDF closure */
- for(int hit = 0; hit < num_hits; hit++)
- kernel_branched_path_integrate_lighting(kg, rng, sample*num_samples + j,
- aa_samples*num_samples,
+ for(int hit = 0; hit < num_hits; hit++) {
+ PathState hit_state = state;
+
+ path_state_branch(&hit_state, j, num_samples);
+
+ kernel_branched_path_integrate_lighting(kg, rng,
&bssrdf_sd[hit], throughput, num_samples_inv,
- ray_pdf, ray_pdf, state, rng_offset+PRNG_BOUNCE_NUM, &L, buffer);
+ &hit_state, &L, buffer);
+ }
}
state.flag &= ~PATH_RAY_BSSRDF_ANCESTOR;
@@ -1181,9 +1159,11 @@ ccl_device float4 kernel_branched_path_integrate(KernelGlobals *kg, RNG *rng, in
#endif
if(!(sd.flag & SD_HAS_ONLY_VOLUME)) {
+ PathState hit_state = state;
+
/* lighting */
- kernel_branched_path_integrate_lighting(kg, rng, sample, aa_samples,
- &sd, throughput, 1.0f, ray_pdf, ray_pdf, state, rng_offset, &L, buffer);
+ kernel_branched_path_integrate_lighting(kg, rng,
+ &sd, throughput, 1.0f, &hit_state, &L, buffer);
/* continue in case of transparency */
throughput *= shader_bsdf_transparency(kg, &sd);
diff --git a/intern/cycles/kernel/kernel_path_state.h b/intern/cycles/kernel/kernel_path_state.h
index 3e0ad81c187..fe4d38b10d6 100644
--- a/intern/cycles/kernel/kernel_path_state.h
+++ b/intern/cycles/kernel/kernel_path_state.h
@@ -19,12 +19,27 @@ CCL_NAMESPACE_BEGIN
ccl_device_inline void path_state_init(KernelGlobals *kg, PathState *state, RNG *rng, int sample)
{
state->flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
+
+ state->rng_offset = PRNG_BASE_NUM;
+ state->sample = sample;
+#ifdef __CMJ__
+ state->num_samples = kernel_data.integrator.aa_samples;
+#else
+ state->num_samples = 0;
+#endif
+
state->bounce = 0;
state->diffuse_bounce = 0;
state->glossy_bounce = 0;
state->transmission_bounce = 0;
state->transparent_bounce = 0;
+ state->min_ray_pdf = FLT_MAX;
+ state->ray_pdf = 0.0f;
+#ifdef __LAMP_MIS__
+ state->ray_t = 0.0f;
+#endif
+
#ifdef __VOLUME__
if(kernel_data.integrator.use_volumes) {
/* initialize volume stack with volume we are inside of */
@@ -88,6 +103,9 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, PathState *state, int
state->flag |= PATH_RAY_GLOSSY|PATH_RAY_SINGULAR|PATH_RAY_MIS_SKIP;
state->flag &= ~PATH_RAY_DIFFUSE;
}
+
+ /* random number generator next bounce */
+ state->rng_offset += PRNG_BOUNCE_NUM;
}
ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h
index c435c27b7b4..e3b1c1d7822 100644
--- a/intern/cycles/kernel/kernel_random.h
+++ b/intern/cycles/kernel/kernel_random.h
@@ -227,6 +227,8 @@ ccl_device void path_rng_end(KernelGlobals *kg, ccl_global uint *rng_state, RNG
#endif
+/* Linear Congruential Generator */
+
ccl_device uint lcg_step_uint(uint *rng)
{
/* implicit mod 2^32 */
@@ -248,5 +250,47 @@ ccl_device uint lcg_init(uint seed)
return rng;
}
+/* Path Tracing Utility Functions
+ *
+ * For each random number in each step of the path we must have a unique
+ * dimension to avoid using the same sequence twice.
+ *
+ * For branches in the path we must be careful not to reuse the same number
+ * in a sequence and offset accordingly. */
+
+ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, RNG *rng, PathState *state, int dimension)
+{
+ return path_rng_1D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension);
+}
+
+ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, RNG *rng, PathState *state, int dimension, float *fx, float *fy)
+{
+ path_rng_2D(kg, rng, state->sample, state->num_samples, state->rng_offset + dimension, fx, fy);
+}
+
+ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, RNG *rng, PathState *state, int branch, int num_branches, int dimension)
+{
+ return path_rng_1D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension);
+}
+
+ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, RNG *rng, PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
+{
+ path_rng_2D(kg, rng, state->sample*num_branches + branch, state->num_samples*num_branches, state->rng_offset + dimension, fx, fy);
+}
+
+ccl_device_inline void path_state_branch(PathState *state, int branch, int num_branches)
+{
+ /* path is splitting into a branch, adjust so that each branch
+ * still gets a unique sample from the same sequence */
+ state->rng_offset += PRNG_BOUNCE_NUM;
+ state->sample = state->sample*num_branches + branch;
+ state->num_samples = state->num_samples*num_branches;
+}
+
+ccl_device inline uint lcg_state_init(RNG *rng, PathState *state, uint scramble)
+{
+ return lcg_init(*rng + state->rng_offset + state->sample*scramble);
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 00cb73b1e34..faed1e7a71e 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -622,14 +622,29 @@ typedef struct VolumeStack {
#endif
typedef struct PathState {
- int flag;
- int bounce;
+ /* see enum PathRayFlag */
+ int flag;
+
+ /* random number generator state */
+ int rng_offset; /* dimension offset */
+ int sample; /* path sample number */
+ int num_samples; /* total number of times this path will be sampled */
+ /* bounce counting */
+ int bounce;
int diffuse_bounce;
int glossy_bounce;
int transmission_bounce;
int transparent_bounce;
+ /* multiple importance sampling */
+ float min_ray_pdf; /* smallest bounce pdf over entire path up to now */
+ float ray_pdf; /* last bounce pdf */
+#ifdef __LAMP_MIS__
+ float ray_t; /* accumulated distance through transparent surfaces */
+#endif
+
+ /* volume rendering */
#ifdef __VOLUME__
RNG rng_congruential;
VolumeStack volume_stack[VOLUME_STACK_SIZE];