Fix T46550: Cycles combined baking black in some cases.

Now pass_filter is modified to have exactly the flags for the light components
that need to be baked, based on the shader type. This simplifies the logic.
This commit is contained in:
Brecht Van Lommel 2016-02-06 20:35:36 +01:00
parent c502114ee1
commit 7faa9d1304
4 changed files with 42 additions and 83 deletions

@ -611,7 +611,6 @@ void BlenderSession::bake(BL::Object& b_object,
ShaderEvalType shader_type = get_shader_type(pass_type); ShaderEvalType shader_type = get_shader_type(pass_type);
size_t object_index = OBJECT_NONE; size_t object_index = OBJECT_NONE;
int tri_offset = 0; int tri_offset = 0;
int bake_pass_filter = bake_pass_filter_get(pass_filter);
/* Set baking flag in advance, so kernel loading can check if we need /* Set baking flag in advance, so kernel loading can check if we need
* any baking capabilities. * any baking capabilities.
@ -629,8 +628,11 @@ void BlenderSession::bake(BL::Object& b_object,
Pass::add(PASS_UV, scene->film->passes); Pass::add(PASS_UV, scene->film->passes);
} }
if(BakeManager::is_light_pass(shader_type, bake_pass_filter)) { int bake_pass_filter = bake_pass_filter_get(pass_filter);
/* force use_light_pass to be true */ bake_pass_filter = BakeManager::shader_type_to_pass_filter(shader_type, bake_pass_filter);
/* force use_light_pass to be true if we bake more than just colors */
if (bake_pass_filter & ~BAKE_FILTER_COLOR) {
Pass::add(PASS_LIGHT, scene->film->passes); Pass::add(PASS_LIGHT, scene->film->passes);
} }

@ -21,7 +21,7 @@ CCL_NAMESPACE_BEGIN
#ifndef __NO_BAKING__ #ifndef __NO_BAKING__
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,
const bool is_ao, const bool is_sss, int sample) int pass_filter, int sample)
{ {
/* initialize master radiance accumulator */ /* initialize master radiance accumulator */
kernel_assert(kernel_data.film.use_light_pass); kernel_assert(kernel_data.film.use_light_pass);
@ -31,7 +31,6 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
PathState state; PathState state;
Ray ray; Ray ray;
float3 throughput = make_float3(1.0f, 1.0f, 1.0f); float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
bool is_sss_sample = is_sss;
ray.P = sd->P + sd->Ng; ray.P = sd->P + sd->Ng;
ray.D = -sd->Ng; ray.D = -sd->Ng;
@ -58,13 +57,21 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
#endif #endif
/* sample ambient occlusion */ /* sample ambient occlusion */
if(is_ao) { if(pass_filter & BAKE_FILTER_AO) {
kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput); kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
} }
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
}
bool is_sss_sample = false;
#ifdef __SUBSURFACE__ #ifdef __SUBSURFACE__
/* sample subsurface scattering */ /* sample subsurface scattering */
if(is_sss_sample && (sd->flag & SD_BSSRDF)) { if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
SubsurfaceIndirectRays ss_indirect; SubsurfaceIndirectRays ss_indirect;
kernel_path_subsurface_init_indirect(&ss_indirect); kernel_path_subsurface_init_indirect(&ss_indirect);
@ -99,13 +106,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
#endif #endif
/* sample light and BSDF */ /* sample light and BSDF */
if((!is_sss_sample) && (!is_ao)) { if(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) {
if(sd->flag & SD_EMISSION) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
}
kernel_path_surface_connect_light(kg, &rng, sd, throughput, &state, &L_sample); kernel_path_surface_connect_light(kg, &rng, sd, throughput, &state, &L_sample);
if(kernel_path_surface_bounce(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) { if(kernel_path_surface_bounce(kg, &rng, sd, &throughput, &state, &L_sample, &ray)) {
@ -126,26 +127,26 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian
/* branched path tracer */ /* branched path tracer */
/* sample ambient occlusion */ /* sample ambient occlusion */
if(is_ao) { if(pass_filter & BAKE_FILTER_AO) {
kernel_branched_path_ao(kg, sd, &L_sample, &state, &rng, throughput); kernel_branched_path_ao(kg, sd, &L_sample, &state, &rng, throughput);
} }
/* sample emission */
if((pass_filter & BAKE_FILTER_EMISSION) && (sd->flag & SD_EMISSION)) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
}
#ifdef __SUBSURFACE__ #ifdef __SUBSURFACE__
/* sample subsurface scattering */ /* sample subsurface scattering */
if(is_sss_sample && (sd->flag & SD_BSSRDF)) { if((pass_filter & BAKE_FILTER_SUBSURFACE) && (sd->flag & SD_BSSRDF)) {
/* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */
kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, throughput); kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, throughput);
} }
#endif #endif
/* sample light and BSDF */ /* sample light and BSDF */
if((!is_sss_sample) && (!is_ao)) { if(pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT)) {
if(sd->flag & SD_EMISSION) {
float3 emission = indirect_primitive_emission(kg, sd, 0.0f, state.flag, state.ray_pdf);
path_radiance_accum_emission(&L_sample, throughput, emission, state.bounce);
}
#if defined(__EMISSION__) #if defined(__EMISSION__)
/* direct light */ /* direct light */
if(kernel_data.integrator.use_direct_light) { if(kernel_data.integrator.use_direct_light) {
@ -177,32 +178,6 @@ ccl_device bool is_aa_pass(ShaderEvalType type)
} }
} }
/* Keep it synced with BakeManager::is_light_pass. */
ccl_device bool is_light_pass(ShaderEvalType type, const int pass_filter)
{
switch(type) {
case SHADER_EVAL_AO:
case SHADER_EVAL_SHADOW:
return true;
case SHADER_EVAL_DIFFUSE:
case SHADER_EVAL_GLOSSY:
case SHADER_EVAL_TRANSMISSION:
return ((pass_filter & BAKE_FILTER_DIRECT) != 0) ||
((pass_filter & BAKE_FILTER_INDIRECT) != 0);
case SHADER_EVAL_COMBINED:
return ((pass_filter & BAKE_FILTER_AO) != 0) ||
((pass_filter & BAKE_FILTER_EMISSION) != 0) ||
((((pass_filter & BAKE_FILTER_DIRECT) != 0) ||
((pass_filter & BAKE_FILTER_INDIRECT) != 0)) &&
(((pass_filter & BAKE_FILTER_DIFFUSE) != 0) ||
((pass_filter & BAKE_FILTER_GLOSSY) != 0) ||
((pass_filter & BAKE_FILTER_TRANSMISSION) != 0) ||
((pass_filter & BAKE_FILTER_SUBSURFACE) != 0)));
default:
return false;
}
}
/* this helps with AA but it's not the real solution as it does not AA the geometry /* this helps with AA but it's not the real solution as it does not AA the geometry
* but it's better than nothing, thus committed */ * but it's better than nothing, thus committed */
ccl_device_inline float bake_clamp_mirror_repeat(float u) ccl_device_inline float bake_clamp_mirror_repeat(float u)
@ -348,25 +323,9 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
sd.dv.dx = dvdx; sd.dv.dx = dvdx;
sd.dv.dy = dvdy; sd.dv.dy = dvdy;
/* light passes */ /* light passes if we need more than color */
if(is_light_pass(type, pass_filter)) { if(pass_filter & ~BAKE_FILTER_COLOR)
bool is_ao, is_sss; compute_light_pass(kg, &sd, &L, rng, pass_filter, sample);
if (type == SHADER_EVAL_COMBINED) {
is_ao = (pass_filter & BAKE_FILTER_AO) != 0;
is_sss = ((pass_filter & BAKE_FILTER_SUBSURFACE) != 0) &&
(((pass_filter & BAKE_FILTER_DIRECT) != 0) ||
((pass_filter & BAKE_FILTER_INDIRECT) != 0));
}
else {
is_ao = (type == SHADER_EVAL_AO);
is_sss = (type == SHADER_EVAL_SUBSURFACE) &&
(((pass_filter & BAKE_FILTER_DIRECT) != 0) ||
((pass_filter & BAKE_FILTER_INDIRECT) != 0));
}
compute_light_pass(kg, &sd, &L, rng, is_ao, is_sss, sample);
}
switch(type) { switch(type) {
/* data passes */ /* data passes */

@ -255,30 +255,28 @@ bool BakeManager::is_aa_pass(ShaderEvalType type)
} }
} }
/* Keep it synced with kernel_bake.h::is_light_pass. */ /* Keep it synced with kernel_bake.h logic */
bool BakeManager::is_light_pass(ShaderEvalType type, const int pass_filter) int BakeManager::shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter)
{ {
const int component_flags = pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT | BAKE_FILTER_COLOR);
switch(type) { switch(type) {
case SHADER_EVAL_AO: case SHADER_EVAL_AO:
return BAKE_FILTER_AO;
case SHADER_EVAL_SHADOW: case SHADER_EVAL_SHADOW:
return true; return BAKE_FILTER_DIRECT;
case SHADER_EVAL_DIFFUSE: case SHADER_EVAL_DIFFUSE:
return BAKE_FILTER_DIFFUSE | component_flags;
case SHADER_EVAL_GLOSSY: case SHADER_EVAL_GLOSSY:
return BAKE_FILTER_GLOSSY | component_flags;
case SHADER_EVAL_TRANSMISSION: case SHADER_EVAL_TRANSMISSION:
return BAKE_FILTER_TRANSMISSION | component_flags;
case SHADER_EVAL_SUBSURFACE: case SHADER_EVAL_SUBSURFACE:
return ((pass_filter & BAKE_FILTER_DIRECT) != 0) || return BAKE_FILTER_SUBSURFACE | component_flags;
((pass_filter & BAKE_FILTER_INDIRECT) != 0);
case SHADER_EVAL_COMBINED: case SHADER_EVAL_COMBINED:
return ((pass_filter & BAKE_FILTER_AO) != 0) || return pass_filter;
((pass_filter & BAKE_FILTER_EMISSION) != 0) ||
((((pass_filter & BAKE_FILTER_DIRECT) != 0) ||
((pass_filter & BAKE_FILTER_INDIRECT) != 0)) &&
(((pass_filter & BAKE_FILTER_DIFFUSE) != 0) ||
((pass_filter & BAKE_FILTER_GLOSSY) != 0) ||
((pass_filter & BAKE_FILTER_TRANSMISSION) != 0) ||
((pass_filter & BAKE_FILTER_SUBSURFACE) != 0)));
default: default:
return false; return 0;
} }
} }

@ -68,7 +68,7 @@ public:
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress);
void device_free(Device *device, DeviceScene *dscene); void device_free(Device *device, DeviceScene *dscene);
static bool is_light_pass(ShaderEvalType type, const int pass_filter); static int shader_type_to_pass_filter(ShaderEvalType type, const int pass_filter);
static bool is_aa_pass(ShaderEvalType type); static bool is_aa_pass(ShaderEvalType type);
bool need_update; bool need_update;