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:
Dalai Felinto 2014-05-07 11:55:09 -03:00
parent 3fbc984b06
commit 83cdd5887f
Notes: blender-bot 2023-02-14 10:41:23 +01:00
Referenced by issue #40060, SSS direct/indirect turns out black in texture bake
2 changed files with 61 additions and 42 deletions

View File

@ -17,7 +17,7 @@
CCL_NAMESPACE_BEGIN
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;
@ -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);
}
/* 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 */
if(!is_ao) {
if((!is_sss) && (!is_ao)) {
if(kernel_path_integrate_lighting(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
#ifdef __LAMP_MIS__
state.ray_t = 0.0f;
#endif
/* compute indirect light */
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)) {
RNG rng = cmj_hash(i, 0);
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) {

View File

@ -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)
{
/* initialize */
@ -776,45 +822,8 @@ ccl_device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample,
/* bssrdf scatter to a different location on the same object, replacing
* the closures with a diffuse BSDF */
if(sd.flag & SD_BSSRDF) {
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);
}
}
if(kernel_path_subsurface_scatter(kg, &sd, &L, &state, rng, &ray, &throughput))
break;
}
}
#endif