forked from bartvdbraak/blender
Cycles-Bake: Subsurface Scattering support (fix T40060)
This fixes the SSS Direct/Indirect passes as well as the Combined pass. Patch reviewed and with fixes and contributions from Brecht van Lommel. Note: displacement/bump map (related to the report) will be handled separately Reviewers: brecht Differential Revision: https://developer.blender.org/D503
This commit is contained in:
parent
3fbc984b06
commit
83cdd5887f
@ -17,7 +17,7 @@
|
|||||||
CCL_NAMESPACE_BEGIN
|
CCL_NAMESPACE_BEGIN
|
||||||
|
|
||||||
ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng,
|
ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng,
|
||||||
bool is_combined, bool is_ao)
|
bool is_combined, bool is_ao, bool is_sss)
|
||||||
{
|
{
|
||||||
int samples = kernel_data.integrator.aa_samples;
|
int samples = kernel_data.integrator.aa_samples;
|
||||||
|
|
||||||
@ -50,13 +50,21 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
|
|||||||
kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
|
kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sample subsurface scattering */
|
||||||
|
if((is_combined || is_sss) && (sd->flag & SD_BSSRDF)) {
|
||||||
|
#ifdef __SUBSURFACE__
|
||||||
|
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
|
||||||
|
if (kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput))
|
||||||
|
is_sss = true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/* sample light and BSDF */
|
/* sample light and BSDF */
|
||||||
if(!is_ao) {
|
if((!is_sss) && (!is_ao)) {
|
||||||
if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
|
if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
|
||||||
#ifdef __LAMP_MIS__
|
#ifdef __LAMP_MIS__
|
||||||
state.ray_t = 0.0f;
|
state.ray_t = 0.0f;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* compute indirect light */
|
/* compute indirect light */
|
||||||
kernel_path_indirect(kg, &rng, ray, throughput, state.num_samples, state, &L_sample);
|
kernel_path_indirect(kg, &rng, ray, throughput, state.num_samples, state, &L_sample);
|
||||||
|
|
||||||
@ -127,7 +135,9 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
|||||||
if(is_light_pass(type)) {
|
if(is_light_pass(type)) {
|
||||||
RNG rng = cmj_hash(i, 0);
|
RNG rng = cmj_hash(i, 0);
|
||||||
compute_light_pass(kg, &sd, &L, rng, (type == SHADER_EVAL_COMBINED),
|
compute_light_pass(kg, &sd, &L, rng, (type == SHADER_EVAL_COMBINED),
|
||||||
(type == SHADER_EVAL_AO));
|
(type == SHADER_EVAL_AO),
|
||||||
|
(type == SHADER_EVAL_SUBSURFACE_DIRECT ||
|
||||||
|
type == SHADER_EVAL_SUBSURFACE_INDIRECT));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -601,6 +601,52 @@ ccl_device void kernel_path_ao(KernelGlobals *kg, ShaderData *sd, PathRadiance *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __SUBSURFACE__
|
||||||
|
ccl_device bool kernel_path_subsurface_scatter(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, PathState *state, RNG *rng, Ray *ray, float3 *throughput)
|
||||||
|
{
|
||||||
|
float bssrdf_probability;
|
||||||
|
ShaderClosure *sc = subsurface_scatter_pick_closure(kg, sd, &bssrdf_probability);
|
||||||
|
|
||||||
|
/* modify throughput for picking bssrdf or bsdf */
|
||||||
|
*throughput *= bssrdf_probability;
|
||||||
|
|
||||||
|
/* do bssrdf scatter step if we picked a bssrdf closure */
|
||||||
|
if(sc) {
|
||||||
|
uint lcg_state = lcg_state_init(rng, state, 0x68bc21eb);
|
||||||
|
|
||||||
|
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
|
||||||
|
float 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 */
|
||||||
|
for(int hit = 0; hit < num_hits; hit++) {
|
||||||
|
float3 tp = *throughput;
|
||||||
|
PathState hit_state = *state;
|
||||||
|
Ray hit_ray = *ray;
|
||||||
|
|
||||||
|
hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
|
||||||
|
hit_state.rng_offset += PRNG_BOUNCE_NUM;
|
||||||
|
|
||||||
|
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, tp, state->num_samples, hit_state, L);
|
||||||
|
|
||||||
|
/* for render passes, sum and reset indirect light pass variables
|
||||||
|
* for the next samples */
|
||||||
|
path_radiance_sum_indirect(L);
|
||||||
|
path_radiance_reset_indirect(L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
|
ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, Ray ray, ccl_global float *buffer)
|
||||||
{
|
{
|
||||||
/* initialize */
|
/* initialize */
|
||||||
@ -776,46 +822,9 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
|
|||||||
/* bssrdf scatter to a different location on the same object, replacing
|
/* bssrdf scatter to a different location on the same object, replacing
|
||||||
* the closures with a diffuse BSDF */
|
* the closures with a diffuse BSDF */
|
||||||
if(sd.flag & SD_BSSRDF) {
|
if(sd.flag & SD_BSSRDF) {
|
||||||
float bssrdf_probability;
|
if(kernel_path_subsurface_scatter(kg, &sd, &L, &state, rng, &ray, &throughput))
|
||||||
ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability);
|
|
||||||
|
|
||||||
/* modify throughput for picking bssrdf or bsdf */
|
|
||||||
throughput *= bssrdf_probability;
|
|
||||||
|
|
||||||
/* do bssrdf scatter step if we picked a bssrdf closure */
|
|
||||||
if(sc) {
|
|
||||||
uint lcg_state = lcg_state_init(rng, &state, 0x68bc21eb);
|
|
||||||
|
|
||||||
ShaderData bssrdf_sd[BSSRDF_MAX_HITS];
|
|
||||||
float 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 */
|
|
||||||
for(int hit = 0; hit < num_hits; hit++) {
|
|
||||||
float3 tp = throughput;
|
|
||||||
PathState hit_state = state;
|
|
||||||
Ray hit_ray = ray;
|
|
||||||
|
|
||||||
hit_state.flag |= PATH_RAY_BSSRDF_ANCESTOR;
|
|
||||||
hit_state.rng_offset += PRNG_BOUNCE_NUM;
|
|
||||||
|
|
||||||
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, tp, state.num_samples, hit_state, &L);
|
|
||||||
|
|
||||||
/* for render passes, sum and reset indirect light pass variables
|
|
||||||
* for the next samples */
|
|
||||||
path_radiance_sum_indirect(&L);
|
|
||||||
path_radiance_reset_indirect(&L);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Same as kernel_path_integrate_lighting(kg, rng, &sd, &throughput, &state, &L, &ray),
|
/* Same as kernel_path_integrate_lighting(kg, rng, &sd, &throughput, &state, &L, &ray),
|
||||||
|
Loading…
Reference in New Issue
Block a user