Cycles: slightly improve BSDF sample stratification for path tracing.
Similar to what we did for area lights previously, this should help preserve stratification when using multiple BSDFs in theory. Improvements are not easily noticeable in practice though, because the number of BSDFs is usually low. Still nice to eliminate one sampling dimension.
This commit is contained in:
@@ -51,8 +51,7 @@ ccl_device_inline void compute_light_pass(KernelGlobals *kg,
|
||||
path_state_init(kg, &emission_sd, &state, rng_hash, sample, NULL);
|
||||
|
||||
/* evaluate surface shader */
|
||||
float rbsdf = path_state_rng_1D(kg, &state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, sd, &state, rbsdf, state.flag);
|
||||
shader_eval_surface(kg, sd, &state, state.flag);
|
||||
|
||||
/* TODO, disable more closures we don't need besides transparent */
|
||||
shader_bsdf_disable_transparency(kg, sd);
|
||||
@@ -241,12 +240,12 @@ ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg,
|
||||
}
|
||||
else {
|
||||
/* surface color of the pass only */
|
||||
shader_eval_surface(kg, sd, state, 0.0f, 0);
|
||||
shader_eval_surface(kg, sd, state, 0);
|
||||
return kernel_bake_shader_bsdf(kg, sd, type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
shader_eval_surface(kg, sd, state, 0.0f, 0);
|
||||
shader_eval_surface(kg, sd, state, 0);
|
||||
color = kernel_bake_shader_bsdf(kg, sd, type);
|
||||
}
|
||||
|
||||
@@ -338,7 +337,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
case SHADER_EVAL_NORMAL:
|
||||
{
|
||||
if((sd.flag & SD_HAS_BUMP)) {
|
||||
shader_eval_surface(kg, &sd, &state, 0.f, 0);
|
||||
shader_eval_surface(kg, &sd, &state, 0);
|
||||
}
|
||||
|
||||
/* encoding: normal = (2 * color) - 1 */
|
||||
@@ -352,7 +351,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
||||
}
|
||||
case SHADER_EVAL_EMISSION:
|
||||
{
|
||||
shader_eval_surface(kg, &sd, &state, 0.f, 0);
|
||||
shader_eval_surface(kg, &sd, &state, 0);
|
||||
out = shader_emissive_eval(kg, &sd);
|
||||
break;
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
||||
/* no path flag, we're evaluating this for all closures. that's weak but
|
||||
* we'd have to do multiple evaluations otherwise */
|
||||
path_state_modify_bounce(state, true);
|
||||
shader_eval_surface(kg, emission_sd, state, 0.0f, 0);
|
||||
shader_eval_surface(kg, emission_sd, state, 0);
|
||||
path_state_modify_bounce(state, false);
|
||||
|
||||
/* evaluate emissive closure */
|
||||
|
@@ -210,7 +210,7 @@ ccl_device_forceinline VolumeIntegrateResult kernel_path_volume(
|
||||
/* indirect sample. if we use distance sampling and take just
|
||||
* one sample for direct and indirect light, we could share
|
||||
* this computation, but makes code a bit complex */
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE);
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
|
||||
float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
|
||||
|
||||
result = kernel_volume_decoupled_scatter(kg,
|
||||
@@ -434,8 +434,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
sd,
|
||||
&isect,
|
||||
ray);
|
||||
float rbsdf = path_state_rng_1D(kg, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, sd, state, rbsdf, state->flag);
|
||||
shader_eval_surface(kg, sd, state, state->flag);
|
||||
#ifdef __BRANCHED_PATH__
|
||||
shader_merge_closures(sd);
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
@@ -483,17 +482,18 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
|
||||
/* bssrdf scatter to a different location on the same object, replacing
|
||||
* the closures with a diffuse BSDF */
|
||||
if(sd->flag & SD_BSSRDF) {
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, &throughput);
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_state_init(state, 0x68bc21eb);
|
||||
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_state_rng_2D(kg,
|
||||
state,
|
||||
PRNG_BSDF_U,
|
||||
&bssrdf_u, &bssrdf_v);
|
||||
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, &throughput, &bssrdf_u);
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_state_init(state, 0x68bc21eb);
|
||||
|
||||
subsurface_scatter_step(kg,
|
||||
sd,
|
||||
state,
|
||||
@@ -587,8 +587,7 @@ ccl_device_forceinline void kernel_path_integrate(
|
||||
|
||||
/* Setup and evaluate shader. */
|
||||
shader_setup_from_ray(kg, &sd, &isect, ray);
|
||||
float rbsdf = path_state_rng_1D(kg, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, &sd, state, rbsdf, state->flag);
|
||||
shader_eval_surface(kg, &sd, state, state->flag);
|
||||
|
||||
/* Apply shadow catcher, holdout, emission. */
|
||||
if(!kernel_path_shader_apply(kg,
|
||||
|
@@ -339,7 +339,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
|
||||
/* scatter sample. if we use distance sampling and take just one
|
||||
* sample for direct and indirect light, we could share this
|
||||
* computation, but makes code a bit complex */
|
||||
float rphase = path_state_rng_1D(kg, &ps, PRNG_PHASE);
|
||||
float rphase = path_state_rng_1D(kg, &ps, PRNG_PHASE_CHANNEL);
|
||||
float rscatter = path_state_rng_1D(kg, &ps, PRNG_SCATTER_DISTANCE);
|
||||
|
||||
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
|
||||
@@ -439,7 +439,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
|
||||
|
||||
/* Setup and evaluate shader. */
|
||||
shader_setup_from_ray(kg, &sd, &isect, &ray);
|
||||
shader_eval_surface(kg, &sd, &state, 0.0f, state.flag);
|
||||
shader_eval_surface(kg, &sd, &state, state.flag);
|
||||
shader_merge_closures(&sd);
|
||||
|
||||
/* Apply shadow catcher, holdout, emission. */
|
||||
|
@@ -32,7 +32,10 @@ bool kernel_path_subsurface_scatter(
|
||||
ccl_addr_space float3 *throughput,
|
||||
ccl_addr_space SubsurfaceIndirectRays *ss_indirect)
|
||||
{
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput);
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput, &bssrdf_u);
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
@@ -45,8 +48,6 @@ bool kernel_path_subsurface_scatter(
|
||||
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
||||
|
||||
SubsurfaceIntersection ss_isect;
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_state_rng_2D(kg, state, PRNG_BSDF_U, &bssrdf_u, &bssrdf_v);
|
||||
int num_hits = subsurface_scatter_multi_intersect(kg,
|
||||
&ss_isect,
|
||||
sd,
|
||||
|
@@ -77,7 +77,7 @@ bool kernel_path_volume_bounce(
|
||||
float3 phase_omega_in;
|
||||
differential3 phase_domega_in;
|
||||
float phase_u, phase_v;
|
||||
path_state_rng_2D(kg, state, PRNG_PHASE_U, &phase_u, &phase_v);
|
||||
path_state_rng_2D(kg, state, PRNG_BSDF_U, &phase_u, &phase_v);
|
||||
int label;
|
||||
|
||||
label = shader_volume_phase_sample(kg, sd, phase_u, phase_v, &phase_eval,
|
||||
@@ -155,7 +155,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
|
||||
float3 tp = throughput;
|
||||
|
||||
/* sample position on volume segment */
|
||||
float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
|
||||
float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
|
||||
float rscatter = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
|
||||
|
||||
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
|
||||
@@ -201,7 +201,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
|
||||
float3 tp = throughput;
|
||||
|
||||
/* sample position on volume segment */
|
||||
float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE);
|
||||
float rphase = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
|
||||
float rscatter = path_branched_rng_1D(kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
|
||||
|
||||
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
|
||||
@@ -238,7 +238,7 @@ ccl_device void kernel_branched_path_volume_connect_light(
|
||||
float3 tp = throughput;
|
||||
|
||||
/* sample position on volume segment */
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE);
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
|
||||
float rscatter = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
|
||||
|
||||
VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
|
||||
|
@@ -575,7 +575,8 @@ void shader_bsdf_eval(KernelGlobals *kg,
|
||||
}
|
||||
}
|
||||
|
||||
ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd)
|
||||
ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd,
|
||||
float *randu)
|
||||
{
|
||||
int sampled = 0;
|
||||
|
||||
@@ -591,19 +592,25 @@ ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd)
|
||||
}
|
||||
}
|
||||
|
||||
float r = sd->randb_closure*sum;
|
||||
float r = (*randu)*sum;
|
||||
float partial_sum = 0.0f;
|
||||
|
||||
for(int i = 0; i < sd->num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(CLOSURE_IS_BSDF(sc->type)) {
|
||||
partial_sum += sc->sample_weight;
|
||||
float next_sum = partial_sum + sc->sample_weight;
|
||||
|
||||
if(r <= partial_sum) {
|
||||
if(r < next_sum) {
|
||||
sampled = i;
|
||||
|
||||
/* Rescale to reuse for direction sample, to better
|
||||
* preserve stratifaction. */
|
||||
*randu = (r - partial_sum) / sc->sample_weight;
|
||||
break;
|
||||
}
|
||||
|
||||
partial_sum = next_sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,7 +619,8 @@ ccl_device_inline const ShaderClosure *shader_bsdf_pick(ShaderData *sd)
|
||||
}
|
||||
|
||||
ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
|
||||
ccl_addr_space float3 *throughput)
|
||||
ccl_addr_space float3 *throughput,
|
||||
float *randu)
|
||||
{
|
||||
int sampled = 0;
|
||||
|
||||
@@ -632,16 +640,16 @@ ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
|
||||
}
|
||||
}
|
||||
|
||||
float r = sd->randb_closure*(sum_bsdf + sum_bssrdf);
|
||||
float r = (*randu)*(sum_bsdf + sum_bssrdf);
|
||||
float partial_sum = 0.0f;
|
||||
|
||||
for(int i = 0; i < sd->num_closure; i++) {
|
||||
const ShaderClosure *sc = &sd->closure[i];
|
||||
|
||||
if(CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
|
||||
partial_sum += sc->sample_weight;
|
||||
float next_sum = partial_sum + sc->sample_weight;
|
||||
|
||||
if(r <= partial_sum) {
|
||||
if(r < next_sum) {
|
||||
if(CLOSURE_IS_BSDF(sc->type)) {
|
||||
*throughput *= (sum_bsdf + sum_bssrdf) / sum_bsdf;
|
||||
return NULL;
|
||||
@@ -649,9 +657,15 @@ ccl_device_inline const ShaderClosure *shader_bssrdf_pick(ShaderData *sd,
|
||||
else {
|
||||
*throughput *= (sum_bsdf + sum_bssrdf) / sum_bssrdf;
|
||||
sampled = i;
|
||||
|
||||
/* Rescale to reuse for direction sample, to better
|
||||
* preserve stratifaction. */
|
||||
*randu = (r - partial_sum) / sc->sample_weight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
partial_sum = next_sum;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -667,7 +681,7 @@ ccl_device_inline int shader_bsdf_sample(KernelGlobals *kg,
|
||||
differential3 *domega_in,
|
||||
float *pdf)
|
||||
{
|
||||
const ShaderClosure *sc = shader_bsdf_pick(sd);
|
||||
const ShaderClosure *sc = shader_bsdf_pick(sd, &randu);
|
||||
if(!sc) {
|
||||
*pdf = 0.0f;
|
||||
return LABEL_NONE;
|
||||
@@ -923,11 +937,10 @@ ccl_device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd)
|
||||
/* Surface Evaluation */
|
||||
|
||||
ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
||||
ccl_addr_space PathState *state, float randb, int path_flag)
|
||||
ccl_addr_space PathState *state, int path_flag)
|
||||
{
|
||||
sd->num_closure = 0;
|
||||
sd->num_closure_extra = 0;
|
||||
sd->randb_closure = randb;
|
||||
|
||||
#ifdef __OSL__
|
||||
if(kg->osl)
|
||||
@@ -958,7 +971,6 @@ ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
|
||||
{
|
||||
sd->num_closure = 0;
|
||||
sd->num_closure_extra = 0;
|
||||
sd->randb_closure = 0.0f;
|
||||
|
||||
#ifdef __SVM__
|
||||
#ifdef __OSL__
|
||||
@@ -1040,18 +1052,23 @@ ccl_device int shader_volume_phase_sample(KernelGlobals *kg, const ShaderData *s
|
||||
sum += sc->sample_weight;
|
||||
}
|
||||
|
||||
float r = sd->randb_closure*sum;
|
||||
sum = 0.0f;
|
||||
float r = randu*sum;
|
||||
float partial_sum = 0.0f;
|
||||
|
||||
for(sampled = 0; sampled < sd->num_closure; sampled++) {
|
||||
const ShaderClosure *sc = &sd->closure[sampled];
|
||||
|
||||
if(CLOSURE_IS_PHASE(sc->type)) {
|
||||
sum += sc->sample_weight;
|
||||
float next_sum = partial_sum + sc->sample_weight;
|
||||
|
||||
if(r <= sum)
|
||||
if(r <= next_sum) {
|
||||
/* Rescale to reuse for BSDF direction sample. */
|
||||
randu = (r - partial_sum) / sc->sample_weight;
|
||||
break;
|
||||
}
|
||||
|
||||
partial_sum = next_sum;
|
||||
}
|
||||
}
|
||||
|
||||
if(sampled == sd->num_closure) {
|
||||
@@ -1154,7 +1171,6 @@ ccl_device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ccl_
|
||||
{
|
||||
sd->num_closure = 0;
|
||||
sd->num_closure_extra = 0;
|
||||
sd->randb_closure = 0.0f;
|
||||
|
||||
/* this will modify sd->P */
|
||||
#ifdef __SVM__
|
||||
|
@@ -86,7 +86,6 @@ ccl_device_forceinline bool shadow_handle_transparent_isect(
|
||||
shader_eval_surface(kg,
|
||||
shadow_sd,
|
||||
state,
|
||||
0.0f,
|
||||
PATH_RAY_SHADOW);
|
||||
path_state_modify_bounce(state, false);
|
||||
*throughput *= shader_bsdf_transparency(kg, shadow_sd);
|
||||
|
@@ -79,7 +79,6 @@ ccl_device_inline float3 subsurface_scatter_eval(ShaderData *sd,
|
||||
ccl_device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, const ShaderClosure *sc, float3 weight, bool hit, float3 N)
|
||||
{
|
||||
sd->flag &= ~SD_CLOSURE_FLAGS;
|
||||
sd->randb_closure = 0.0f;
|
||||
sd->num_closure = 0;
|
||||
sd->num_closure_extra = 0;
|
||||
|
||||
@@ -155,7 +154,7 @@ ccl_device void subsurface_color_bump_blur(KernelGlobals *kg,
|
||||
|
||||
if(bump || texture_blur > 0.0f) {
|
||||
/* average color and normal at incoming point */
|
||||
shader_eval_surface(kg, sd, state, 0.0f, state_flag);
|
||||
shader_eval_surface(kg, sd, state, state_flag);
|
||||
float3 in_color = shader_bssrdf_sum(sd, (bump)? N: NULL, NULL);
|
||||
|
||||
/* we simply divide out the average color and multiply with the average
|
||||
|
@@ -281,31 +281,21 @@ enum PathTraceDimension {
|
||||
PRNG_FILTER_V = 1,
|
||||
PRNG_LENS_U = 2,
|
||||
PRNG_LENS_V = 3,
|
||||
#ifdef __CAMERA_MOTION__
|
||||
PRNG_TIME = 4,
|
||||
PRNG_UNUSED_0 = 5,
|
||||
PRNG_UNUSED_1 = 6, /* for some reason (6, 7) is a bad sobol pattern */
|
||||
PRNG_UNUSED_2 = 7, /* with a low number of samples (< 64) */
|
||||
#endif
|
||||
PRNG_BASE_NUM = 8,
|
||||
PRNG_BASE_NUM = 10,
|
||||
|
||||
PRNG_BSDF_U = 0,
|
||||
PRNG_BSDF_V = 1,
|
||||
PRNG_BSDF = 2,
|
||||
PRNG_UNUSED3 = 3,
|
||||
PRNG_LIGHT_U = 4,
|
||||
PRNG_LIGHT_V = 5,
|
||||
PRNG_LIGHT_TERMINATE = 6,
|
||||
PRNG_TERMINATE = 7,
|
||||
|
||||
#ifdef __VOLUME__
|
||||
PRNG_PHASE_U = 8,
|
||||
PRNG_PHASE_V = 9,
|
||||
PRNG_PHASE = 10,
|
||||
PRNG_SCATTER_DISTANCE = 11,
|
||||
#endif
|
||||
|
||||
PRNG_BOUNCE_NUM = 12,
|
||||
PRNG_LIGHT_U = 2,
|
||||
PRNG_LIGHT_V = 3,
|
||||
PRNG_LIGHT_TERMINATE = 4,
|
||||
PRNG_TERMINATE = 5,
|
||||
PRNG_PHASE_CHANNEL = 6,
|
||||
PRNG_SCATTER_DISTANCE = 7,
|
||||
PRNG_BOUNCE_NUM = 8,
|
||||
};
|
||||
|
||||
enum SamplingPattern {
|
||||
|
@@ -379,9 +379,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_homogeneous(
|
||||
|
||||
/* pick random color channel, we use the Veach one-sample
|
||||
* model with balance heuristic for the channels */
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE);
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
|
||||
int channel = (int)(rphase*3.0f);
|
||||
sd->randb_closure = rphase*3.0f - channel;
|
||||
|
||||
/* decide if we will hit or miss */
|
||||
bool scatter = true;
|
||||
@@ -484,9 +483,8 @@ ccl_device VolumeIntegrateResult kernel_volume_integrate_heterogeneous_distance(
|
||||
/* pick random color channel, we use the Veach one-sample
|
||||
* model with balance heuristic for the channels */
|
||||
float xi = path_state_rng_1D(kg, state, PRNG_SCATTER_DISTANCE);
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE);
|
||||
float rphase = path_state_rng_1D(kg, state, PRNG_PHASE_CHANNEL);
|
||||
int channel = (int)(rphase*3.0f);
|
||||
sd->randb_closure = rphase*3.0f - channel;
|
||||
bool has_scatter = false;
|
||||
|
||||
for(int i = 0; i < max_steps; i++) {
|
||||
@@ -843,7 +841,6 @@ ccl_device VolumeIntegrateResult kernel_volume_decoupled_scatter(
|
||||
/* pick random color channel, we use the Veach one-sample
|
||||
* model with balance heuristic for the channels */
|
||||
int channel = (int)(rphase*3.0f);
|
||||
sd->randb_closure = rphase*3.0f - channel;
|
||||
float xi = rscatter;
|
||||
|
||||
/* probabilistic scattering decision based on transmittance */
|
||||
|
@@ -50,18 +50,8 @@ ccl_device void kernel_shader_eval(KernelGlobals *kg)
|
||||
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
|
||||
ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
|
||||
|
||||
#ifndef __BRANCHED_PATH__
|
||||
float rbsdf = path_state_rng_1D(kg, state, PRNG_BSDF);
|
||||
shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag);
|
||||
#else
|
||||
float rbsdf = 0.0f;
|
||||
|
||||
if(!kernel_data.integrator.branched || IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
rbsdf = path_state_rng_1D(kg, state, PRNG_BSDF);
|
||||
|
||||
}
|
||||
|
||||
shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, rbsdf, state->flag);
|
||||
shader_eval_surface(kg, &kernel_split_state.sd[ray_index], state, state->flag);
|
||||
#ifdef __BRANCHED_PATH__
|
||||
shader_merge_closures(&kernel_split_state.sd[ray_index]);
|
||||
#endif /* __BRANCHED_PATH__ */
|
||||
}
|
||||
|
@@ -250,16 +250,17 @@ ccl_device void kernel_subsurface_scatter(KernelGlobals *kg)
|
||||
#ifdef __BRANCHED_PATH__
|
||||
}
|
||||
else if(IS_FLAG(ray_state, ray_index, RAY_BRANCHED_INDIRECT)) {
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput);
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
||||
float bssrdf_u, bssrdf_v;
|
||||
path_state_rng_2D(kg,
|
||||
state,
|
||||
PRNG_BSDF_U,
|
||||
&bssrdf_u, &bssrdf_v);
|
||||
|
||||
const ShaderClosure *sc = shader_bssrdf_pick(sd, throughput, &bssrdf_u);
|
||||
|
||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||
if(sc) {
|
||||
uint lcg_state = lcg_state_init_addrspace(state, 0x68bc21eb);
|
||||
subsurface_scatter_step(kg,
|
||||
sd,
|
||||
state,
|
||||
|
Reference in New Issue
Block a user