diff options
Diffstat (limited to 'intern/cycles/kernel/kernel_bake.h')
-rw-r--r-- | intern/cycles/kernel/kernel_bake.h | 364 |
1 files changed, 221 insertions, 143 deletions
diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 2b305e5488d..8e7a2c1b62b 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -16,10 +16,10 @@ CCL_NAMESPACE_BEGIN -#undef USE_BAKE_JITTER +#ifndef __NO_BAKING__ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadiance *L, RNG rng, - const bool is_combined, const bool is_ao, const bool is_sss, int sample) + int pass_filter, int sample) { /* initialize master radiance accumulator */ kernel_assert(kernel_data.film.use_light_pass); @@ -29,7 +29,6 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian PathState state; Ray ray; float3 throughput = make_float3(1.0f, 1.0f, 1.0f); - bool is_sss_sample = is_sss; ray.P = sd->P + sd->Ng; ray.D = -sd->Ng; @@ -46,7 +45,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* evaluate surface shader */ float rbsdf = path_state_rng_1D(kg, &rng, &state, PRNG_BSDF); - shader_eval_surface(kg, sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); + shader_eval_surface(kg, sd, &state, rbsdf, state.flag, SHADER_CONTEXT_MAIN); /* TODO, disable the closures we won't need */ @@ -56,27 +55,56 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian #endif /* sample ambient occlusion */ - if(is_combined || is_ao) { + if(pass_filter & BAKE_FILTER_AO) { 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__ /* sample subsurface scattering */ - if((is_combined || 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 */ - if(kernel_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, &throughput)) + SubsurfaceIndirectRays ss_indirect; + kernel_path_subsurface_init_indirect(&ss_indirect); + if(kernel_path_subsurface_scatter(kg, + sd, + &L_sample, + &state, + &rng, + &ray, + &throughput, + &ss_indirect)) + { + while(ss_indirect.num_rays) { + kernel_path_subsurface_setup_indirect(kg, + &ss_indirect, + &state, + &ray, + &L_sample, + &throughput); + kernel_path_indirect(kg, + &rng, + &ray, + throughput, + state.num_samples, + &state, + &L_sample); + kernel_path_subsurface_accum_indirect(&ss_indirect, &L_sample); + } is_sss_sample = true; + } } #endif /* sample light and BSDF */ - if((!is_sss_sample) && (!is_ao)) { - - 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(!is_sss_sample && (pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT))) { 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)) { @@ -84,7 +112,7 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian state.ray_t = 0.0f; #endif /* compute indirect light */ - kernel_path_indirect(kg, &rng, ray, throughput, 1, state, &L_sample); + kernel_path_indirect(kg, &rng, &ray, throughput, 1, &state, &L_sample); /* sum and reset indirect light pass variables for the next samples */ path_radiance_sum_indirect(&L_sample); @@ -97,30 +125,30 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* branched path tracer */ /* sample ambient occlusion */ - if(is_combined || is_ao) { + if(pass_filter & BAKE_FILTER_AO) { 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__ /* sample subsurface scattering */ - if((is_combined || 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 */ kernel_branched_path_subsurface_scatter(kg, sd, &L_sample, &state, &rng, &ray, throughput); } #endif /* sample light and BSDF */ - if((!is_sss_sample) && (!is_ao)) { - - 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(pass_filter & (BAKE_FILTER_DIRECT | BAKE_FILTER_INDIRECT)) { #if defined(__EMISSION__) /* direct light */ if(kernel_data.integrator.use_direct_light) { - bool all = kernel_data.integrator.sample_all_lights_direct; + int all = kernel_data.integrator.sample_all_lights_direct; kernel_branched_path_surface_connect_light(kg, &rng, sd, &state, throughput, 1.0f, &L_sample, all); } @@ -148,47 +176,91 @@ ccl_device bool is_aa_pass(ShaderEvalType type) } } -ccl_device bool is_light_pass(ShaderEvalType type) -{ - switch (type) { - case SHADER_EVAL_AO: - case SHADER_EVAL_COMBINED: - case SHADER_EVAL_SHADOW: - case SHADER_EVAL_DIFFUSE_DIRECT: - case SHADER_EVAL_GLOSSY_DIRECT: - case SHADER_EVAL_TRANSMISSION_DIRECT: - case SHADER_EVAL_SUBSURFACE_DIRECT: - case SHADER_EVAL_DIFFUSE_INDIRECT: - case SHADER_EVAL_GLOSSY_INDIRECT: - case SHADER_EVAL_TRANSMISSION_INDIRECT: - case SHADER_EVAL_SUBSURFACE_INDIRECT: - return true; - default: - return false; - } -} - /* 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 */ -ccl_device_inline float bake_clamp_mirror_repeat(float u) +ccl_device_inline float bake_clamp_mirror_repeat(float u, float max) { /* use mirror repeat (like opengl texture) so that if the barycentric * coordinate goes past the end of the triangle it is not always clamped * to the same value, gives ugly patterns */ + u /= max; float fu = floorf(u); u = u - fu; - return (((int)fu) & 1)? 1.0f - u: u; + return ((((int)fu) & 1)? 1.0f - u: u) * max; +} + +ccl_device_inline float3 kernel_bake_shader_bsdf(KernelGlobals *kg, + ShaderData *sd, + const ShaderEvalType type) +{ + switch(type) { + case SHADER_EVAL_DIFFUSE: + return shader_bsdf_diffuse(kg, sd); + case SHADER_EVAL_GLOSSY: + return shader_bsdf_glossy(kg, sd); + case SHADER_EVAL_TRANSMISSION: + return shader_bsdf_transmission(kg, sd); +#ifdef __SUBSURFACE__ + case SHADER_EVAL_SUBSURFACE: + return shader_bsdf_subsurface(kg, sd); +#endif + default: + kernel_assert(!"Unknown bake type passed to BSDF evaluate"); + return make_float3(0.0f, 0.0f, 0.0f); + } +} + +ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg, + ShaderData *sd, + PathState *state, + float3 direct, + float3 indirect, + const ShaderEvalType type, + const int pass_filter) +{ + float3 color; + const bool is_color = (pass_filter & BAKE_FILTER_COLOR) != 0; + const bool is_direct = (pass_filter & BAKE_FILTER_DIRECT) != 0; + const bool is_indirect = (pass_filter & BAKE_FILTER_INDIRECT) != 0; + float3 out = make_float3(0.0f, 0.0f, 0.0f); + + if(is_color) { + if(is_direct || is_indirect) { + /* Leave direct and diffuse channel colored. */ + color = make_float3(1.0f, 1.0f, 1.0f); + } + else { + /* surface color of the pass only */ + shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN); + return kernel_bake_shader_bsdf(kg, sd, type); + } + } + else { + shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN); + color = kernel_bake_shader_bsdf(kg, sd, type); + } + + if(is_direct) { + out += safe_divide_color(direct, color); + } + + if(is_indirect) { + out += safe_divide_color(indirect, color); + } + + return out; } ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, - ShaderEvalType type, int i, int offset, int sample) + ShaderEvalType type, int pass_filter, int i, int offset, int sample) { ShaderData sd; + PathState state = {0}; uint4 in = input[i * 2]; uint4 diff = input[i * 2 + 1]; - float3 out; + float3 out = make_float3(0.0f, 0.0f, 0.0f); int object = in.x; int prim = in.y; @@ -209,7 +281,6 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, /* random number generator */ RNG rng = cmj_hash(offset + i, kernel_data.integrator.seed); -#ifdef USE_BAKE_JITTER float filter_x, filter_y; if(sample == 0) { filter_x = filter_y = 0.5f; @@ -220,10 +291,9 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, /* subpixel u/v offset */ if(sample > 0) { - u = bake_clamp_mirror_repeat(u + dudx*(filter_x - 0.5f) + dudy*(filter_y - 0.5f)); - v = bake_clamp_mirror_repeat(v + dvdx*(filter_x - 0.5f) + dvdy*(filter_y - 0.5f)); + u = bake_clamp_mirror_repeat(u + dudx*(filter_x - 0.5f) + dudy*(filter_y - 0.5f), 1.0f); + v = bake_clamp_mirror_repeat(v + dvdx*(filter_x - 0.5f) + dvdy*(filter_y - 0.5f), 1.0f - u); } -#endif /* triangle */ int shader; @@ -235,13 +305,11 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, float3 I = Ng; float t = 0.0f; float time = TIME_INVALID; - int bounce = 0; - int transparent_bounce = 0; /* light passes */ PathRadiance L; - shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time, bounce, transparent_bounce); + shader_setup_from_sample(kg, &sd, P, Ng, I, shader, object, prim, u, v, t, time); sd.I = sd.N; /* update differentials */ @@ -252,22 +320,16 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, sd.dv.dx = dvdx; sd.dv.dy = dvdy; - /* light passes */ - if(is_light_pass(type)) { - compute_light_pass(kg, &sd, &L, rng, - (type == SHADER_EVAL_COMBINED), - (type == SHADER_EVAL_AO), - (type == SHADER_EVAL_SUBSURFACE_DIRECT || - type == SHADER_EVAL_SUBSURFACE_INDIRECT), - sample); - } + /* light passes if we need more than color */ + if(pass_filter & ~BAKE_FILTER_COLOR) + compute_light_pass(kg, &sd, &L, rng, pass_filter, sample); - switch (type) { + switch(type) { /* data passes */ case SHADER_EVAL_NORMAL: { if((sd.flag & SD_HAS_BUMP)) { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); + shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); } /* compression: normal = (2 * color) - 1 */ @@ -279,35 +341,9 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, out = primitive_uv(kg, &sd); break; } - case SHADER_EVAL_DIFFUSE_COLOR: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_diffuse(kg, &sd); - break; - } - case SHADER_EVAL_GLOSSY_COLOR: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_glossy(kg, &sd); - break; - } - case SHADER_EVAL_TRANSMISSION_COLOR: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_transmission(kg, &sd); - break; - } - case SHADER_EVAL_SUBSURFACE_COLOR: - { -#ifdef __SUBSURFACE__ - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_subsurface(kg, &sd); -#endif - break; - } case SHADER_EVAL_EMISSION: { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_EMISSION); + shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_EMISSION); out = shader_emissive_eval(kg, &sd); break; } @@ -321,7 +357,34 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, } case SHADER_EVAL_COMBINED: { - out = path_radiance_clamp_and_sum(kg, &L); + if((pass_filter & BAKE_FILTER_COMBINED) == BAKE_FILTER_COMBINED) { + out = path_radiance_clamp_and_sum(kg, &L); + break; + } + + if((pass_filter & BAKE_FILTER_DIFFUSE_DIRECT) == BAKE_FILTER_DIFFUSE_DIRECT) + out += L.direct_diffuse; + if((pass_filter & BAKE_FILTER_DIFFUSE_INDIRECT) == BAKE_FILTER_DIFFUSE_INDIRECT) + out += L.indirect_diffuse; + + if((pass_filter & BAKE_FILTER_GLOSSY_DIRECT) == BAKE_FILTER_GLOSSY_DIRECT) + out += L.direct_glossy; + if((pass_filter & BAKE_FILTER_GLOSSY_INDIRECT) == BAKE_FILTER_GLOSSY_INDIRECT) + out += L.indirect_glossy; + + if((pass_filter & BAKE_FILTER_TRANSMISSION_DIRECT) == BAKE_FILTER_TRANSMISSION_DIRECT) + out += L.direct_transmission; + if((pass_filter & BAKE_FILTER_TRANSMISSION_INDIRECT) == BAKE_FILTER_TRANSMISSION_INDIRECT) + out += L.indirect_transmission; + + if((pass_filter & BAKE_FILTER_SUBSURFACE_DIRECT) == BAKE_FILTER_SUBSURFACE_DIRECT) + out += L.direct_subsurface; + if((pass_filter & BAKE_FILTER_SUBSURFACE_INDIRECT) == BAKE_FILTER_SUBSURFACE_INDIRECT) + out += L.indirect_subsurface; + + if((pass_filter & BAKE_FILTER_EMISSION) != 0) + out += L.emission; + break; } case SHADER_EVAL_SHADOW: @@ -329,55 +392,49 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, out = make_float3(L.shadow.x, L.shadow.y, L.shadow.z); break; } - case SHADER_EVAL_DIFFUSE_DIRECT: + case SHADER_EVAL_DIFFUSE: { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_diffuse, shader_bsdf_diffuse(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, + &sd, + &state, + L.direct_diffuse, + L.indirect_diffuse, + type, + pass_filter); break; } - case SHADER_EVAL_GLOSSY_DIRECT: + case SHADER_EVAL_GLOSSY: { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_glossy, shader_bsdf_glossy(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, + &sd, + &state, + L.direct_glossy, + L.indirect_glossy, + type, + pass_filter); break; } - case SHADER_EVAL_TRANSMISSION_DIRECT: + case SHADER_EVAL_TRANSMISSION: { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_transmission, shader_bsdf_transmission(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, + &sd, + &state, + L.direct_transmission, + L.indirect_transmission, + type, + pass_filter); break; } - case SHADER_EVAL_SUBSURFACE_DIRECT: + case SHADER_EVAL_SUBSURFACE: { #ifdef __SUBSURFACE__ - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_subsurface, shader_bsdf_subsurface(kg, &sd)); -#endif - break; - } - case SHADER_EVAL_DIFFUSE_INDIRECT: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_diffuse, shader_bsdf_diffuse(kg, &sd)); - break; - } - case SHADER_EVAL_GLOSSY_INDIRECT: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_glossy, shader_bsdf_glossy(kg, &sd)); - break; - } - case SHADER_EVAL_TRANSMISSION_INDIRECT: - { - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_transmission, shader_bsdf_transmission(kg, &sd)); - break; - } - case SHADER_EVAL_SUBSURFACE_INDIRECT: - { -#ifdef __SUBSURFACE__ - shader_eval_surface(kg, &sd, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_subsurface, shader_bsdf_subsurface(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, + &sd, + &state, + L.direct_subsurface, + L.indirect_subsurface, + type, + pass_filter); #endif break; } @@ -402,11 +459,11 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, #endif /* setup shader data */ - shader_setup_from_background(kg, &sd, &ray, 0, 0); + shader_setup_from_background(kg, &sd, &ray); /* evaluate */ int flag = 0; /* we can't know which type of BSDF this is for */ - out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN); + out = shader_eval_background(kg, &sd, &state, flag, SHADER_CONTEXT_MAIN); break; } default: @@ -426,9 +483,18 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, output[i] += make_float4(out.x, out.y, out.z, 1.0f) * output_fac; } -ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *input, ccl_global float4 *output, ShaderEvalType type, int i, int sample) +#endif /* __NO_BAKING__ */ + +ccl_device void kernel_shader_evaluate(KernelGlobals *kg, + ccl_global uint4 *input, + ccl_global float4 *output, + ccl_global float *output_luma, + ShaderEvalType type, + int i, + int sample) { ShaderData sd; + PathState state = {0}; uint4 in = input[i]; float3 out; @@ -443,7 +509,7 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *inpu /* evaluate */ float3 P = sd.P; - shader_eval_displacement(kg, &sd, SHADER_CONTEXT_MAIN); + shader_eval_displacement(kg, &sd, &state, SHADER_CONTEXT_MAIN); out = sd.P - P; } else { // SHADER_EVAL_BACKGROUND @@ -465,18 +531,30 @@ ccl_device void kernel_shader_evaluate(KernelGlobals *kg, ccl_global uint4 *inpu #endif /* setup shader data */ - shader_setup_from_background(kg, &sd, &ray, 0, 0); + shader_setup_from_background(kg, &sd, &ray); /* evaluate */ int flag = 0; /* we can't know which type of BSDF this is for */ - out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN); + out = shader_eval_background(kg, &sd, &state, flag, SHADER_CONTEXT_MAIN); } /* write output */ - if(sample == 0) - output[i] = make_float4(out.x, out.y, out.z, 0.0f); - else - output[i] += make_float4(out.x, out.y, out.z, 0.0f); + if(sample == 0) { + if(output != NULL) { + output[i] = make_float4(out.x, out.y, out.z, 0.0f); + } + if(output_luma != NULL) { + output_luma[i] = average(out); + } + } + else { + if(output != NULL) { + output[i] += make_float4(out.x, out.y, out.z, 0.0f); + } + if(output_luma != NULL) { + output_luma[i] += average(out); + } + } } CCL_NAMESPACE_END |