diff options
30 files changed, 557 insertions, 176 deletions
diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 0783c1c4cba..e883413d935 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -67,8 +67,8 @@ class CyclesRender(bpy.types.RenderEngine): def render(self, scene): engine.render(self) - def bake(self, scene, obj, pass_type, object_id, pixel_array, num_pixels, depth, result): - engine.bake(self, obj, pass_type, object_id, pixel_array, num_pixels, depth, result) + def bake(self, scene, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): + engine.bake(self, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result) # viewport render def view_update(self, context): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index 19fa23bd74a..42ec253613f 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -110,11 +110,11 @@ def render(engine): _cycles.render(engine.session) -def bake(engine, obj, pass_type, object_id, pixel_array, num_pixels, depth, result): +def bake(engine, obj, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result): import _cycles session = getattr(engine, "session", None) if session is not None: - _cycles.bake(engine.session, obj.as_pointer(), pass_type, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) + _cycles.bake(engine.session, obj.as_pointer(), pass_type, pass_filter, object_id, pixel_array.as_pointer(), num_pixels, depth, result.as_pointer()) def reset(engine, data, scene): diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index ed6cea2bcb2..c83da3d5b54 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -493,18 +493,10 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): ('UV', "UV", ""), ('EMIT', "Emit", ""), ('ENVIRONMENT', "Environment", ""), - ('DIFFUSE_DIRECT', "Diffuse Direct", ""), - ('DIFFUSE_INDIRECT', "Diffuse Indirect", ""), - ('DIFFUSE_COLOR', "Diffuse Color", ""), - ('GLOSSY_DIRECT', "Glossy Direct", ""), - ('GLOSSY_INDIRECT', "Glossy Indirect", ""), - ('GLOSSY_COLOR', "Glossy Color", ""), - ('TRANSMISSION_DIRECT', "Transmission Direct", ""), - ('TRANSMISSION_INDIRECT', "Transmission Indirect", ""), - ('TRANSMISSION_COLOR', "Transmission Color", ""), - ('SUBSURFACE_DIRECT', "Subsurface Direct", ""), - ('SUBSURFACE_INDIRECT', "Subsurface Indirect", ""), - ('SUBSURFACE_COLOR', "Subsurface Color", ""), + ('DIFFUSE', "Diffuse", ""), + ('GLOSSY', "Glossy", ""), + ('TRANSMISSION', "Transmission", ""), + ('SUBSURFACE', "Subsurface", ""), ), ) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 8d00e4850d7..22df14201e8 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1448,16 +1448,49 @@ class CyclesRender_PT_bake(CyclesButtonsPanel, Panel): if cscene.bake_type == 'NORMAL': layout.separator() - box = layout.box() - box.label(text="Normal Settings:") - box.prop(cbk, "normal_space", text="Space") + col = layout.column() + col.label(text="Normal Settings:") + col.prop(cbk, "normal_space", text="Space") - row = box.row(align=True) + row = col.row(align=True) row.label(text="Swizzle:") row.prop(cbk, "normal_r", text="") row.prop(cbk, "normal_g", text="") row.prop(cbk, "normal_b", text="") + elif cscene.bake_type == 'COMBINED': + col = layout.column() + col.label(text="Combined Settings:") + + row = col.row() + row.prop(cbk, "use_pass_ambient_occlusion") + row.prop(cbk, "use_pass_emit") + + row = col.row(align=True) + row.prop(cbk, "use_pass_direct", toggle=True) + row.prop(cbk, "use_pass_indirect", toggle=True) + + split = col.split() + split.active = cbk.use_pass_direct or cbk.use_pass_indirect + + col = split.column() + col.prop(cbk, "use_pass_diffuse") + col.prop(cbk, "use_pass_glossy") + + col = split.column() + col.prop(cbk, "use_pass_transmission") + col.prop(cbk, "use_pass_subsurface") + + elif cscene.bake_type in {'DIFFUSE', 'GLOSSY', 'TRANSMISSION', 'SUBSURFACE'}: + layout.separator() + col = layout.column() + col.label(text="{0} Settings:".format(cscene.bake_type.title())) + + row = col.row(align=True) + row.prop(cbk, "use_pass_direct", toggle=True) + row.prop(cbk, "use_pass_indirect", toggle=True) + row.prop(cbk, "use_pass_color", toggle=True) + class CyclesRender_PT_debug(CyclesButtonsPanel, Panel): bl_label = "Debug" diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py index eb6d5d957ad..d8b3f5bc672 100644 --- a/intern/cycles/blender/addon/version_update.py +++ b/intern/cycles/blender/addon/version_update.py @@ -113,6 +113,64 @@ def vector_curve_node_remap(node): point.location.y = (point.location.y - 0.5) * 2.0 node.mapping.update() + +def custom_bake_remap(scene): + """ + Remap bake types into the new types and set the flags accordingly + """ + bake_lookup = ( + 'COMBINED', + 'AO', + 'SHADOW', + 'NORMAL', + 'UV', + 'EMIT', + 'ENVIRONMENT', + 'DIFFUSE_DIRECT', + 'DIFFUSE_INDIRECT', + 'DIFFUSE_COLOR', + 'GLOSSY_DIRECT', + 'GLOSSY_INDIRECT', + 'GLOSSY_COLOR', + 'TRANSMISSION_DIRECT', + 'TRANSMISSION_INDIRECT', + 'TRANSMISSION_COLOR', + 'SUBSURFACE_DIRECT', + 'SUBSURFACE_INDIRECT', + 'SUBSURFACE_COLOR') + + diffuse_direct_idx = bake_lookup.index('DIFFUSE_DIRECT') + + cscene = scene.cycles + + # Old bake type + bake_type_idx = cscene.get("bake_type") + + if bake_type_idx is None: + cscene.bake_type = 'COMBINED' + return + + # File doesn't need versioning + if bake_type_idx < diffuse_direct_idx: + return + + # File needs versioning + bake_type = bake_lookup[bake_type_idx] + cscene.bake_type, end = bake_type.split('_') + + if end == 'DIRECT': + scene.render.bake.use_pass_indirect = False + scene.render.bake.use_pass_color = False + + elif end == 'INDIRECT': + scene.render.bake.use_pass_direct = False + scene.render.bake.use_pass_color = False + + elif end == 'COLOR': + scene.render.bake.use_pass_direct = False + scene.render.bake.use_pass_indirect = False + + @persistent def do_versions(self): # We don't modify startup file because it assumes to @@ -156,3 +214,8 @@ def do_versions(self): if bpy.data.version <= (2, 76, 5): foreach_cycles_node(vector_curve_node_remap) + + # Baking types changed + if bpy.data.version <= (2, 76, 6): + for scene in bpy.data.scenes: + custom_bake_remap(scene) diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index acc6f4cde95..006301eead7 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -269,9 +269,9 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) PyObject *pysession, *pyobject; PyObject *pypixel_array, *pyresult; const char *pass_type; - int num_pixels, depth, object_id; + int num_pixels, depth, object_id, pass_filter; - if(!PyArg_ParseTuple(args, "OOsiOiiO", &pysession, &pyobject, &pass_type, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult)) + if(!PyArg_ParseTuple(args, "OOsiiOiiO", &pysession, &pyobject, &pass_type, &pass_filter, &object_id, &pypixel_array, &num_pixels, &depth, &pyresult)) return NULL; BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); @@ -288,7 +288,7 @@ static PyObject *bake_func(PyObject * /*self*/, PyObject *args) python_thread_state_save(&session->python_thread_state); - session->bake(b_object, pass_type, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); + session->bake(b_object, pass_type, pass_filter, object_id, b_bake_pixel, (size_t)num_pixels, depth, (float *)b_result); python_thread_state_restore(&session->python_thread_state); diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 088748cc0ae..a2a399e6152 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -316,22 +316,14 @@ static ShaderEvalType get_shader_type(const string& pass_type) return SHADER_EVAL_COMBINED; else if(strcmp(shader_type, "SHADOW")==0) return SHADER_EVAL_SHADOW; - else if(strcmp(shader_type, "DIFFUSE_DIRECT")==0) - return SHADER_EVAL_DIFFUSE_DIRECT; - else if(strcmp(shader_type, "GLOSSY_DIRECT")==0) - return SHADER_EVAL_GLOSSY_DIRECT; - else if(strcmp(shader_type, "TRANSMISSION_DIRECT")==0) - return SHADER_EVAL_TRANSMISSION_DIRECT; - else if(strcmp(shader_type, "SUBSURFACE_DIRECT")==0) - return SHADER_EVAL_SUBSURFACE_DIRECT; - else if(strcmp(shader_type, "DIFFUSE_INDIRECT")==0) - return SHADER_EVAL_DIFFUSE_INDIRECT; - else if(strcmp(shader_type, "GLOSSY_INDIRECT")==0) - return SHADER_EVAL_GLOSSY_INDIRECT; - else if(strcmp(shader_type, "TRANSMISSION_INDIRECT")==0) - return SHADER_EVAL_TRANSMISSION_INDIRECT; - else if(strcmp(shader_type, "SUBSURFACE_INDIRECT")==0) - return SHADER_EVAL_SUBSURFACE_INDIRECT; + else if(strcmp(shader_type, "DIFFUSE")==0) + return SHADER_EVAL_DIFFUSE; + else if(strcmp(shader_type, "GLOSSY")==0) + return SHADER_EVAL_GLOSSY; + else if(strcmp(shader_type, "TRANSMISSION")==0) + return SHADER_EVAL_TRANSMISSION; + else if(strcmp(shader_type, "SUBSURFACE")==0) + return SHADER_EVAL_SUBSURFACE; /* extra */ else if(strcmp(shader_type, "ENVIRONMENT")==0) @@ -543,11 +535,47 @@ static void populate_bake_data(BakeData *data, const int object_id, BL::BakePixe } } -void BlenderSession::bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int /*depth*/, float result[]) +static int bake_pass_filter_get(const int pass_filter) +{ + int flag = BAKE_FILTER_NONE; + + if((pass_filter & BL::BakeSettings::pass_filter_DIRECT) != 0) + flag |= BAKE_FILTER_DIRECT; + if((pass_filter & BL::BakeSettings::pass_filter_INDIRECT) != 0) + flag |= BAKE_FILTER_INDIRECT; + if((pass_filter & BL::BakeSettings::pass_filter_COLOR) != 0) + flag |= BAKE_FILTER_COLOR; + + if((pass_filter & BL::BakeSettings::pass_filter_DIFFUSE) != 0) + flag |= BAKE_FILTER_DIFFUSE; + if((pass_filter & BL::BakeSettings::pass_filter_GLOSSY) != 0) + flag |= BAKE_FILTER_GLOSSY; + if((pass_filter & BL::BakeSettings::pass_filter_TRANSMISSION) != 0) + flag |= BAKE_FILTER_TRANSMISSION; + if((pass_filter & BL::BakeSettings::pass_filter_SUBSURFACE) != 0) + flag |= BAKE_FILTER_SUBSURFACE; + + if((pass_filter & BL::BakeSettings::pass_filter_EMIT) != 0) + flag |= BAKE_FILTER_EMISSION; + if((pass_filter & BL::BakeSettings::pass_filter_AO) != 0) + flag |= BAKE_FILTER_AO; + + return flag; +} + +void BlenderSession::bake(BL::Object b_object, + const string& pass_type, + const int pass_filter, + const int object_id, + BL::BakePixel pixel_array, + const size_t num_pixels, + const int /*depth*/, + float result[]) { ShaderEvalType shader_type = get_shader_type(pass_type); size_t object_index = OBJECT_NONE; 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 * any baking capabilities. @@ -565,7 +593,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, const in Pass::add(PASS_UV, scene->film->passes); } - if(BakeManager::is_light_pass(shader_type)) { + if(BakeManager::is_light_pass(shader_type, bake_pass_filter)) { /* force use_light_pass to be true */ Pass::add(PASS_LIGHT, scene->film->passes); } @@ -617,7 +645,7 @@ void BlenderSession::bake(BL::Object b_object, const string& pass_type, const in session->progress.set_update_callback(function_bind(&BlenderSession::update_bake_progress, this)); - scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_data, result); + scene->bake_manager->bake(scene->device, &scene->dscene, scene, session->progress, shader_type, bake_pass_filter, bake_data, result); /* free all memory used (host and device), so we wouldn't leave render * engine with extra memory allocated diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index 708776dc8ca..0d391cadc98 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -52,7 +52,14 @@ public: /* offline render */ void render(); - void bake(BL::Object b_object, const string& pass_type, const int object_id, BL::BakePixel pixel_array, const size_t num_pixels, const int depth, float pixels[]); + void bake(BL::Object b_object, + const string& pass_type, + const int custom_flag, + const int object_id, + BL::BakePixel pixel_array, + const size_t num_pixels, + const int depth, + float pixels[]); void write_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile); void write_render_tile(RenderTile& rtile); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 3241f32e006..83447b7a5f3 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -397,7 +397,7 @@ public: #ifdef WITH_OSL OSLShader::thread_init(&kg, &kernel_globals, &osl_globals); #endif - void(*shader_kernel)(KernelGlobals*, uint4*, float4*, float*, int, int, int, int); + void(*shader_kernel)(KernelGlobals*, uint4*, float4*, float*, int, int, int, int, int); #ifdef WITH_CYCLES_OPTIMIZED_KERNEL_AVX2 if(system_cpu_support_avx2()) { @@ -440,6 +440,7 @@ public: (float4*)task.shader_output, (float*)task.shader_output_luma, task.shader_eval_type, + task.shader_filter, x, task.offset, sample); diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index 0cae118a692..1f1128a28f8 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -30,7 +30,7 @@ DeviceTask::DeviceTask(Type type_) : type(type_), x(0), y(0), w(0), h(0), rgba_byte(0), rgba_half(0), buffer(0), sample(0), num_samples(1), shader_input(0), shader_output(0), shader_output_luma(0), - shader_eval_type(0), shader_x(0), shader_w(0) + shader_eval_type(0), shader_filter(0), shader_x(0), shader_w(0) { last_update_time = time_dt(); } diff --git a/intern/cycles/device/device_task.h b/intern/cycles/device/device_task.h index 7654508d4a5..d7912f386f5 100644 --- a/intern/cycles/device/device_task.h +++ b/intern/cycles/device/device_task.h @@ -48,6 +48,7 @@ public: device_ptr shader_input; device_ptr shader_output, shader_output_luma; int shader_eval_type; + int shader_filter; int shader_x, shader_w; DeviceTask(Type type = PATH_TRACE); diff --git a/intern/cycles/kernel/kernel_bake.h b/intern/cycles/kernel/kernel_bake.h index 2a2220ceb99..31e58de0b48 100644 --- a/intern/cycles/kernel/kernel_bake.h +++ b/intern/cycles/kernel/kernel_bake.h @@ -19,7 +19,7 @@ CCL_NAMESPACE_BEGIN #undef USE_BAKE_JITTER 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) + const bool is_ao, const bool is_sss, int sample) { /* initialize master radiance accumulator */ kernel_assert(kernel_data.film.use_light_pass); @@ -56,13 +56,13 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian #endif /* sample ambient occlusion */ - if(is_combined || is_ao) { + if(is_ao) { kernel_path_ao(kg, sd, &L_sample, &state, &rng, throughput); } #ifdef __SUBSURFACE__ /* sample subsurface scattering */ - if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) { + if(is_sss_sample && (sd->flag & SD_BSSRDF)) { /* when mixing BSSRDF and BSDF closures we should skip BSDF lighting if scattering was successful */ SubsurfaceIndirectRays ss_indirect; kernel_path_subsurface_init_indirect(&ss_indirect); @@ -124,13 +124,13 @@ ccl_device void compute_light_pass(KernelGlobals *kg, ShaderData *sd, PathRadian /* branched path tracer */ /* sample ambient occlusion */ - if(is_combined || is_ao) { + if(is_ao) { kernel_branched_path_ao(kg, sd, &L_sample, &state, &rng, throughput); } #ifdef __SUBSURFACE__ /* sample subsurface scattering */ - if((is_combined || is_sss_sample) && (sd->flag & SD_BSSRDF)) { + if(is_sss_sample && (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); } @@ -175,21 +175,27 @@ ccl_device bool is_aa_pass(ShaderEvalType type) } } -ccl_device bool is_light_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_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; + 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; } @@ -208,15 +214,52 @@ ccl_device_inline float bake_clamp_mirror_repeat(float u) return (((int)fu) & 1)? 1.0f - u: u; } +ccl_device float3 kernel_bake_evaluate_direct_indirect(KernelGlobals *kg, ShaderData *sd, PathState *state, + float3 (*shader_bsdf)(KernelGlobals *kg, ShaderData *sd), + float3 direct, float3 indirect, 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 shader_bsdf(kg, sd); + } + } + else { + shader_eval_surface(kg, sd, state, 0.0f, 0, SHADER_CONTEXT_MAIN); + color = shader_bsdf(kg, sd); + } + + 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; @@ -279,13 +322,23 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input, 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); + if(is_light_pass(type, pass_filter)) { + bool is_ao, is_sss; + + 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) { @@ -305,32 +358,6 @@ 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, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_diffuse(kg, &sd); - break; - } - case SHADER_EVAL_GLOSSY_COLOR: - { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_glossy(kg, &sd); - break; - } - case SHADER_EVAL_TRANSMISSION_COLOR: - { - shader_eval_surface(kg, &sd, &state, 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, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = shader_bsdf_subsurface(kg, &sd); -#endif - break; - } case SHADER_EVAL_EMISSION: { shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_EMISSION); @@ -347,7 +374,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: @@ -355,55 +409,25 @@ 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: - { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_diffuse, shader_bsdf_diffuse(kg, &sd)); - break; - } - case SHADER_EVAL_GLOSSY_DIRECT: - { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_glossy, shader_bsdf_glossy(kg, &sd)); - break; - } - case SHADER_EVAL_TRANSMISSION_DIRECT: - { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.direct_transmission, shader_bsdf_transmission(kg, &sd)); - break; - } - case SHADER_EVAL_SUBSURFACE_DIRECT: - { -#ifdef __SUBSURFACE__ - shader_eval_surface(kg, &sd, &state, 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: + case SHADER_EVAL_DIFFUSE: { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_diffuse, shader_bsdf_diffuse(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, &sd, &state, &shader_bsdf_diffuse, L.direct_diffuse, L.indirect_diffuse, pass_filter); break; } - case SHADER_EVAL_GLOSSY_INDIRECT: + case SHADER_EVAL_GLOSSY: { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_glossy, shader_bsdf_glossy(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, &sd, &state, &shader_bsdf_glossy, L.direct_glossy, L.indirect_glossy, pass_filter); break; } - case SHADER_EVAL_TRANSMISSION_INDIRECT: + case SHADER_EVAL_TRANSMISSION: { - shader_eval_surface(kg, &sd, &state, 0.f, 0, SHADER_CONTEXT_MAIN); - out = safe_divide_color(L.indirect_transmission, shader_bsdf_transmission(kg, &sd)); + out = kernel_bake_evaluate_direct_indirect(kg, &sd, &state, &shader_bsdf_transmission, L.direct_transmission, L.indirect_transmission, pass_filter); break; } - case SHADER_EVAL_SUBSURFACE_INDIRECT: + case SHADER_EVAL_SUBSURFACE: { #ifdef __SUBSURFACE__ - shader_eval_surface(kg, &sd, &state, 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, &shader_bsdf_subsurface, L.direct_subsurface, L.indirect_subsurface, pass_filter); #endif break; } diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index 77fc16e3d35..da2416bc09b 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -218,14 +218,10 @@ typedef enum ShaderEvalType { SHADER_EVAL_AO, SHADER_EVAL_COMBINED, SHADER_EVAL_SHADOW, - SHADER_EVAL_DIFFUSE_DIRECT, - SHADER_EVAL_GLOSSY_DIRECT, - SHADER_EVAL_TRANSMISSION_DIRECT, - SHADER_EVAL_SUBSURFACE_DIRECT, - SHADER_EVAL_DIFFUSE_INDIRECT, - SHADER_EVAL_GLOSSY_INDIRECT, - SHADER_EVAL_TRANSMISSION_INDIRECT, - SHADER_EVAL_SUBSURFACE_INDIRECT, + SHADER_EVAL_DIFFUSE, + SHADER_EVAL_GLOSSY, + SHADER_EVAL_TRANSMISSION, + SHADER_EVAL_SUBSURFACE, /* extra */ SHADER_EVAL_ENVIRONMENT, @@ -355,6 +351,39 @@ typedef enum PassType { #define PASS_ALL (~0) +typedef enum BakePassFilter { + BAKE_FILTER_NONE = 0, + BAKE_FILTER_DIRECT = (1 << 0), + BAKE_FILTER_INDIRECT = (1 << 1), + BAKE_FILTER_COLOR = (1 << 2), + BAKE_FILTER_DIFFUSE = (1 << 3), + BAKE_FILTER_GLOSSY = (1 << 4), + BAKE_FILTER_TRANSMISSION = (1 << 5), + BAKE_FILTER_SUBSURFACE = (1 << 6), + BAKE_FILTER_EMISSION = (1 << 7), + BAKE_FILTER_AO = (1 << 8), +} BakePassFilter; + +typedef enum BakePassFilterCombos { + BAKE_FILTER_COMBINED = ( + BAKE_FILTER_DIRECT | + BAKE_FILTER_INDIRECT | + BAKE_FILTER_DIFFUSE | + BAKE_FILTER_GLOSSY | + BAKE_FILTER_TRANSMISSION | + BAKE_FILTER_SUBSURFACE | + BAKE_FILTER_EMISSION | + BAKE_FILTER_AO), + BAKE_FILTER_DIFFUSE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_DIFFUSE), + BAKE_FILTER_GLOSSY_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_GLOSSY), + BAKE_FILTER_TRANSMISSION_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_TRANSMISSION), + BAKE_FILTER_SUBSURFACE_DIRECT = (BAKE_FILTER_DIRECT | BAKE_FILTER_SUBSURFACE), + BAKE_FILTER_DIFFUSE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_DIFFUSE), + BAKE_FILTER_GLOSSY_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_GLOSSY), + BAKE_FILTER_TRANSMISSION_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_TRANSMISSION), + BAKE_FILTER_SUBSURFACE_INDIRECT = (BAKE_FILTER_INDIRECT | BAKE_FILTER_SUBSURFACE), +} BakePassFilterCombos; + #ifdef __PASSES__ typedef ccl_addr_space struct PathRadiance { diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h index 1ce1e41272b..1a07c705f1c 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu.h @@ -44,6 +44,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg, float4 *output, float *output_luma, int type, + int filter, int i, int offset, int sample); diff --git a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h index 0249610b381..1454f925ab9 100644 --- a/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h +++ b/intern/cycles/kernel/kernels/cpu/kernel_cpu_impl.h @@ -101,6 +101,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg, float4 *output, float *output_luma, int type, + int filter, int i, int offset, int sample) @@ -111,6 +112,7 @@ void KERNEL_FUNCTION_FULL_NAME(shader)(KernelGlobals *kg, input, output, (ShaderEvalType)type, + filter, i, offset, sample); diff --git a/intern/cycles/kernel/kernels/cuda/kernel.cu b/intern/cycles/kernel/kernels/cuda/kernel.cu index e094612de01..c8940b981bb 100644 --- a/intern/cycles/kernel/kernels/cuda/kernel.cu +++ b/intern/cycles/kernel/kernels/cuda/kernel.cu @@ -183,12 +183,12 @@ kernel_cuda_shader(uint4 *input, extern "C" __global__ void CUDA_LAUNCH_BOUNDS(CUDA_THREADS_BLOCK_WIDTH, CUDA_KERNEL_MAX_REGISTERS) -kernel_cuda_bake(uint4 *input, float4 *output, int type, int sx, int sw, int offset, int sample) +kernel_cuda_bake(uint4 *input, float4 *output, int type, int filter, int sx, int sw, int offset, int sample) { int x = sx + blockDim.x*blockIdx.x + threadIdx.x; if(x < sx + sw) - kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, x, offset, sample); + kernel_bake_evaluate(NULL, input, output, (ShaderEvalType)type, filter, x, offset, sample); } #endif diff --git a/intern/cycles/kernel/kernels/opencl/kernel.cl b/intern/cycles/kernel/kernels/opencl/kernel.cl index 4c9f7ba1d7c..0a44a4d0301 100644 --- a/intern/cycles/kernel/kernels/opencl/kernel.cl +++ b/intern/cycles/kernel/kernels/opencl/kernel.cl @@ -99,7 +99,7 @@ __kernel void kernel_ocl_bake( ccl_global type *name, #include "../../kernel_textures.h" - int type, int sx, int sw, int offset, int sample) + int type, int filter, int sx, int sw, int offset, int sample) { KernelGlobals kglobals, *kg = &kglobals; @@ -115,7 +115,7 @@ __kernel void kernel_ocl_bake( #ifdef __NO_BAKING__ output[x] = make_float4(0.0f, 0.0f, 0.0f, 0.0f); #else - kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, x, offset, sample); + kernel_bake_evaluate(kg, input, output, (ShaderEvalType)type, filter, x, offset, sample); #endif } } @@ -174,4 +174,4 @@ __kernel void kernel_ocl_convert_to_half_float( kernel_film_convert_to_half_float(kg, rgba, buffer, sample_scale, x, y, offset, stride); } -#endif // __COMPILE_ONLY_MEGAKERNEL__
\ No newline at end of file +#endif // __COMPILE_ONLY_MEGAKERNEL__ diff --git a/intern/cycles/render/bake.cpp b/intern/cycles/render/bake.cpp index 4bbac0f91d1..6a3adcabeb1 100644 --- a/intern/cycles/render/bake.cpp +++ b/intern/cycles/render/bake.cpp @@ -131,7 +131,7 @@ void BakeManager::set_shader_limit(const size_t x, const size_t y) m_shader_limit = (size_t)pow(2, ceil(log(m_shader_limit)/log(2))); } -bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[]) +bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[]) { size_t num_pixels = bake_data->size(); @@ -183,6 +183,7 @@ bool BakeManager::bake(Device *device, DeviceScene *dscene, Scene *scene, Progre task.shader_input = d_input.device_pointer; task.shader_output = d_output.device_pointer; task.shader_eval_type = shader_type; + task.shader_filter = pass_filter; task.shader_x = 0; task.offset = shader_offset; task.shader_w = d_output.size(); @@ -254,21 +255,28 @@ bool BakeManager::is_aa_pass(ShaderEvalType type) } } -bool BakeManager::is_light_pass(ShaderEvalType type) +/* Keep it synced with kernel_bake.h::is_light_pass. */ +bool BakeManager::is_light_pass(ShaderEvalType type, const int pass_filter) { 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; + case SHADER_EVAL_DIFFUSE: + case SHADER_EVAL_GLOSSY: + case SHADER_EVAL_TRANSMISSION: + case SHADER_EVAL_SUBSURFACE: + 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; } diff --git a/intern/cycles/render/bake.h b/intern/cycles/render/bake.h index 14d975a4b4e..b731b213065 100644 --- a/intern/cycles/render/bake.h +++ b/intern/cycles/render/bake.h @@ -63,12 +63,12 @@ public: void set_shader_limit(const size_t x, const size_t y); - bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, BakeData *bake_data, float result[]); + bool bake(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress, ShaderEvalType shader_type, const int pass_filter, BakeData *bake_data, float result[]); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); void device_free(Device *device, DeviceScene *dscene); - static bool is_light_pass(ShaderEvalType type); + static bool is_light_pass(ShaderEvalType type, const int pass_filter); static bool is_aa_pass(ShaderEvalType type); bool need_update; diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index f1d90c13f67..18edfdacd79 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 276 -#define BLENDER_SUBVERSION 5 +#define BLENDER_SUBVERSION 7 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index ca0896e5211..dee6a9f8f6c 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -528,6 +528,7 @@ void BKE_scene_init(Scene *sce) sce->r.bake_biasdist = 0.001; sce->r.bake.flag = R_BAKE_CLEAR; + sce->r.bake.pass_filter = R_BAKE_PASS_FILTER_ALL; sce->r.bake.width = 512; sce->r.bake.height = 512; sce->r.bake.margin = 16; diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index b975a39a301..1ce9bcabc72 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1050,4 +1050,11 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!MAIN_VERSION_ATLEAST(main, 276, 7)) { + Scene *scene; + for (scene = main->scene.first; scene != NULL; scene = scene->id.next) { + scene->r.bake.pass_filter = R_BAKE_PASS_FILTER_ALL; + } + } } diff --git a/source/blender/editors/object/object_bake_api.c b/source/blender/editors/object/object_bake_api.c index 616c4370448..bceda8ef620 100644 --- a/source/blender/editors/object/object_bake_api.c +++ b/source/blender/editors/object/object_bake_api.c @@ -87,6 +87,7 @@ typedef struct BakeAPIRender { ListBase selected_objects; ScenePassType pass_type; + int pass_filter; int margin; int save_mode; @@ -428,6 +429,66 @@ static bool bake_object_check(Object *ob, ReportList *reports) return true; } +static bool bake_pass_filter_check(ScenePassType pass_type, const int pass_filter, ReportList *reports) +{ + switch (pass_type) { + case SCE_PASS_COMBINED: + if ((pass_filter & R_BAKE_PASS_FILTER_EMIT) != 0) { + return true; + } + + if (((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) + { + if (((pass_filter & R_BAKE_PASS_FILTER_DIFFUSE) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_GLOSSY) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_TRANSM) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_SUBSURFACE) != 0)) + { + return true; + } + + if ((pass_filter & R_BAKE_PASS_FILTER_AO) != 0) { + BKE_report(reports, RPT_ERROR, + "Combined bake pass Ambient Occlusion contribution requires an enabled light pass. " + "Bake the Ambient Occlusion pass type instead."); + } + else { + BKE_report(reports, RPT_ERROR, "Combined bake pass requires Emit, or a light pass with " + "Direct or Indirect contributions enabled"); + } + + return false; + } + else { + BKE_report(reports, RPT_ERROR, + "Combined bake pass requires Emit, or a light pass with " + "Direct or Indirect contributions enabled"); + return false; + } + break; + case SCE_PASS_DIFFUSE_COLOR: + case SCE_PASS_GLOSSY_COLOR: + case SCE_PASS_TRANSM_COLOR: + case SCE_PASS_SUBSURFACE_COLOR: + if (((pass_filter & R_BAKE_PASS_FILTER_COLOR) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_DIRECT) != 0) || + ((pass_filter & R_BAKE_PASS_FILTER_INDIRECT) != 0)) + { + return true; + } + else { + BKE_report(reports, RPT_ERROR, + "Bake pass requires Direct, Indirect, or Color contributions to be enabled"); + return false; + } + break; + default: + return true; + break; + } +} + /* before even getting in the bake function we check for some basic errors */ static bool bake_objects_check(Main *bmain, Object *ob, ListBase *selected_objects, ReportList *reports, const bool is_selected_to_active) @@ -552,7 +613,7 @@ static size_t initialize_internal_images(BakeImages *bake_images, ReportList *re static int bake( Render *re, Main *bmain, Scene *scene, Object *ob_low, ListBase *selected_objects, ReportList *reports, - const ScenePassType pass_type, const int margin, + const ScenePassType pass_type, const int pass_filter, const int margin, const BakeSaveMode save_mode, const bool is_clear, const bool is_split_materials, const bool is_automatic_name, const bool is_selected_to_active, const bool is_cage, const float cage_extrusion, const int normal_space, const BakeNormalSwizzle normal_swizzle[], @@ -794,7 +855,7 @@ static int bake( /* the baking itself */ for (i = 0; i < tot_highpoly; i++) { ok = RE_bake_engine(re, highpoly[i].ob, i, pixel_array_high, - num_pixels, depth, pass_type, result); + num_pixels, depth, pass_type, pass_filter, result); if (!ok) { BKE_reportf(reports, RPT_ERROR, "Error baking from object \"%s\"", highpoly[i].ob->id.name + 2); goto cage_cleanup; @@ -820,7 +881,7 @@ cage_cleanup: ob_low->restrictflag &= ~OB_RESTRICT_RENDER; if (RE_bake_has_engine(re)) { - ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, result); + ok = RE_bake_engine(re, ob_low, 0, pixel_array_low, num_pixels, depth, pass_type, pass_filter, result); } else { BKE_report(reports, RPT_ERROR, "Current render engine does not support baking"); @@ -1032,6 +1093,7 @@ static void bake_init_api_data(wmOperator *op, bContext *C, BakeAPIRender *bkr) bkr->sa = sc ? BKE_screen_find_big_area(sc, SPACE_IMAGE, 10) : NULL; bkr->pass_type = RNA_enum_get(op->ptr, "type"); + bkr->pass_filter = RNA_enum_get(op->ptr, "pass_filter"); bkr->margin = RNA_int_get(op->ptr, "margin"); bkr->save_mode = RNA_enum_get(op->ptr, "save_mode"); @@ -1090,6 +1152,10 @@ static int bake_exec(bContext *C, wmOperator *op) /* setup new render */ RE_test_break_cb(re, NULL, bake_break); + if (!bake_pass_filter_check(bkr.pass_type, bkr.pass_filter, bkr.reports)) { + goto finally; + } + if (!bake_objects_check(bkr.main, bkr.ob, &bkr.selected_objects, bkr.reports, bkr.is_selected_to_active)) { goto finally; } @@ -1104,7 +1170,7 @@ static int bake_exec(bContext *C, wmOperator *op) if (bkr.is_selected_to_active) { result = bake( bkr.render, bkr.main, bkr.scene, bkr.ob, &bkr.selected_objects, bkr.reports, - bkr.pass_type, bkr.margin, bkr.save_mode, + bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, bkr.is_clear, bkr.is_split_materials, bkr.is_automatic_name, true, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, @@ -1117,7 +1183,7 @@ static int bake_exec(bContext *C, wmOperator *op) Object *ob_iter = link->ptr.data; result = bake( bkr.render, bkr.main, bkr.scene, ob_iter, NULL, bkr.reports, - bkr.pass_type, bkr.margin, bkr.save_mode, + bkr.pass_type, bkr.pass_filter, bkr.margin, bkr.save_mode, is_clear, bkr.is_split_materials, bkr.is_automatic_name, false, bkr.is_cage, bkr.cage_extrusion, bkr.normal_space, bkr.normal_swizzle, bkr.custom_cage, bkr.filepath, bkr.width, bkr.height, bkr.identifier, bkr.sa, @@ -1143,6 +1209,11 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa RE_SetReports(bkr->render, bkr->reports); + if (!bake_pass_filter_check(bkr->pass_type, bkr->pass_filter, bkr->reports)) { + bkr->result = OPERATOR_CANCELLED; + return; + } + if (!bake_objects_check(bkr->main, bkr->ob, &bkr->selected_objects, bkr->reports, bkr->is_selected_to_active)) { bkr->result = OPERATOR_CANCELLED; return; @@ -1156,7 +1227,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa if (bkr->is_selected_to_active) { bkr->result = bake( bkr->render, bkr->main, bkr->scene, bkr->ob, &bkr->selected_objects, bkr->reports, - bkr->pass_type, bkr->margin, bkr->save_mode, + bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode, bkr->is_clear, bkr->is_split_materials, bkr->is_automatic_name, true, bkr->is_cage, bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, @@ -1169,7 +1240,7 @@ static void bake_startjob(void *bkv, short *UNUSED(stop), short *do_update, floa Object *ob_iter = link->ptr.data; bkr->result = bake( bkr->render, bkr->main, bkr->scene, ob_iter, NULL, bkr->reports, - bkr->pass_type, bkr->margin, bkr->save_mode, + bkr->pass_type, bkr->pass_filter, bkr->margin, bkr->save_mode, is_clear, bkr->is_split_materials, bkr->is_automatic_name, false, bkr->is_cage, bkr->cage_extrusion, bkr->normal_space, bkr->normal_swizzle, bkr->custom_cage, bkr->filepath, bkr->width, bkr->height, bkr->identifier, bkr->sa, @@ -1277,6 +1348,11 @@ static void bake_set_props(wmOperator *op, Scene *scene) if (!RNA_property_is_set(op->ptr, prop)) { RNA_property_boolean_set(op->ptr, prop, (bake->flag & R_BAKE_AUTO_NAME) != 0); } + + prop = RNA_struct_find_property(op->ptr, "pass_filter"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_enum_set(op->ptr, prop, bake->pass_filter); + } } static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) @@ -1325,6 +1401,8 @@ static int bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event) void OBJECT_OT_bake(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Bake"; ot->description = "Bake image textures of selected objects"; @@ -1336,8 +1414,11 @@ void OBJECT_OT_bake(wmOperatorType *ot) ot->invoke = bake_invoke; ot->poll = ED_operator_object_active_editable_mesh; - RNA_def_enum(ot->srna, "type", rna_enum_render_pass_type_items, SCE_PASS_COMBINED, "Type", + RNA_def_enum(ot->srna, "type", rna_enum_bake_pass_type_items, SCE_PASS_COMBINED, "Type", "Type of pass to bake, some of them may not be supported by the current render engine"); + prop = RNA_def_enum(ot->srna, "pass_filter", rna_enum_bake_pass_filter_type_items, R_BAKE_PASS_FILTER_NONE, "Pass Filter", + "Filter to combined, diffuse, glossy, transmission and subsurface passes"); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); RNA_def_string_file_path(ot->srna, "filepath", NULL, FILE_MAX, "File Path", "Image filepath to use when saving externally"); RNA_def_int(ot->srna, "width", 512, 1, INT_MAX, "Width", diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index f0b55e8b9be..1a3ddff6130 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -462,7 +462,7 @@ typedef struct BakeData { short margin, flag; float cage_extrusion; - float pad2; + int pass_filter; char normal_swizzle[3]; char normal_space; @@ -489,6 +489,22 @@ typedef enum BakeSaveMode { R_BAKE_SAVE_EXTERNAL = 1, } BakeSaveMode; +/* bake->pass_filter */ +typedef enum BakePassFilter{ + R_BAKE_PASS_FILTER_NONE = 0, + R_BAKE_PASS_FILTER_AO = (1 << 0), + R_BAKE_PASS_FILTER_EMIT = (1 << 1), + R_BAKE_PASS_FILTER_DIFFUSE = (1 << 2), + R_BAKE_PASS_FILTER_GLOSSY = (1 << 3), + R_BAKE_PASS_FILTER_TRANSM = (1 << 4), + R_BAKE_PASS_FILTER_SUBSURFACE = (1 << 5), + R_BAKE_PASS_FILTER_DIRECT = (1 << 6), + R_BAKE_PASS_FILTER_INDIRECT = (1 << 7), + R_BAKE_PASS_FILTER_COLOR = (1 << 8), +} BakePassFilter; + +#define R_BAKE_PASS_FILTER_ALL (~0) + /* *************************************************************** */ /* Render Data */ diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index dd646ec12de..b1048f72022 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -141,6 +141,9 @@ extern EnumPropertyItem rna_enum_controller_type_items[]; extern EnumPropertyItem rna_enum_render_pass_type_items[]; extern EnumPropertyItem rna_enum_render_pass_debug_type_items[]; +extern EnumPropertyItem rna_enum_bake_pass_type_items[]; +extern EnumPropertyItem rna_enum_bake_pass_filter_type_items[]; + extern EnumPropertyItem rna_enum_keymap_propvalue_items[]; extern EnumPropertyItem rna_enum_operator_context_items[]; diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c index dd07f3cb038..6fce93dd9f6 100644 --- a/source/blender/makesrna/intern/rna_render.c +++ b/source/blender/makesrna/intern/rna_render.c @@ -84,6 +84,21 @@ EnumPropertyItem rna_enum_render_pass_debug_type_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem rna_enum_bake_pass_type_items[] = { + {SCE_PASS_COMBINED, "COMBINED", 0, "Combined", ""}, + {SCE_PASS_AO, "AO", 0, "AO", ""}, + {SCE_PASS_SHADOW, "SHADOW", 0, "Shadow", ""}, + {SCE_PASS_NORMAL, "NORMAL", 0, "Normal", ""}, + {SCE_PASS_UV, "UV", 0, "UV", ""}, + {SCE_PASS_EMIT, "EMIT", 0, "Emit", ""}, + {SCE_PASS_ENVIRONMENT, "ENVIRONMENT", 0, "Environment", ""}, + {SCE_PASS_DIFFUSE_COLOR, "DIFFUSE", 0, "Diffuse", ""}, + {SCE_PASS_GLOSSY_COLOR, "GLOSSY", 0, "Glossy", ""}, + {SCE_PASS_TRANSM_COLOR, "TRANSMISSION", 0, "Transmission", ""}, + {SCE_PASS_SUBSURFACE_COLOR, "SUBSURFACE", 0, "Subsurface", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "MEM_guardedalloc.h" @@ -162,7 +177,7 @@ static void engine_render(RenderEngine *engine, struct Scene *scene) } static void engine_bake(RenderEngine *engine, struct Scene *scene, - struct Object *object, const int pass_type, + struct Object *object, const int pass_type, const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result) { @@ -178,6 +193,7 @@ static void engine_bake(RenderEngine *engine, struct Scene *scene, RNA_parameter_set_lookup(&list, "scene", &scene); RNA_parameter_set_lookup(&list, "object", &object); RNA_parameter_set_lookup(&list, "pass_type", &pass_type); + RNA_parameter_set_lookup(&list, "pass_filter", &pass_filter); RNA_parameter_set_lookup(&list, "object_id", &object_id); RNA_parameter_set_lookup(&list, "pixel_array", &pixel_array); RNA_parameter_set_lookup(&list, "num_pixels", &num_pixels); @@ -432,7 +448,9 @@ static void rna_def_render_engine(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_pointer(func, "object", "Object", "", ""); RNA_def_property_flag(prop, PROP_REQUIRED); - prop = RNA_def_enum(func, "pass_type", rna_enum_render_pass_type_items, 0, "Pass", "Pass to bake"); + prop = RNA_def_enum(func, "pass_type", rna_enum_bake_pass_type_items, 0, "Pass", "Pass to bake"); + RNA_def_property_flag(prop, PROP_REQUIRED); + prop = RNA_def_int(func, "pass_filter", 0, 0, INT_MAX, "Pass Filter", "Filter to combined, diffuse, glossy, transmission and subsurface passes", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); prop = RNA_def_int(func, "object_id", 0, 0, INT_MAX, "Object Id", "Id of the current object being baked in relation to the others", 0, INT_MAX); RNA_def_property_flag(prop, PROP_REQUIRED); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index 137661a744b..434a6c24952 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -391,6 +391,20 @@ EnumPropertyItem rna_enum_stereo3d_interlace_type_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem rna_enum_bake_pass_filter_type_items[] = { + {R_BAKE_PASS_FILTER_NONE, "NONE", 0, "None", ""}, + {R_BAKE_PASS_FILTER_AO, "AO", 0, "AO", ""}, + {R_BAKE_PASS_FILTER_EMIT, "EMIT", 0, "Emit", ""}, + {R_BAKE_PASS_FILTER_DIRECT, "DIRECT", 0, "Direct", ""}, + {R_BAKE_PASS_FILTER_INDIRECT, "INDIRECT", 0, "Indirect", ""}, + {R_BAKE_PASS_FILTER_COLOR, "COLOR", 0, "Color", ""}, + {R_BAKE_PASS_FILTER_DIFFUSE, "DIFFUSE", 0, "Diffuse", ""}, + {R_BAKE_PASS_FILTER_GLOSSY, "GLOSSY", 0, "Glossy", ""}, + {R_BAKE_PASS_FILTER_TRANSM, "TRANSMISSION", 0, "Transmission", ""}, + {R_BAKE_PASS_FILTER_SUBSURFACE, "SUBSURFACE", 0, "Subsurface", ""}, + {0, NULL, 0, NULL, NULL} +}; + #ifdef RNA_RUNTIME #include "DNA_anim_types.h" @@ -3747,6 +3761,57 @@ static void rna_def_bake_data(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Cage", "Cast rays to active object from a cage"); RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + /* custom passes flags */ + prop = RNA_def_property(srna, "use_pass_ambient_occlusion", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_AO); + RNA_def_property_ui_text(prop, "AO", "Add ambient occlusion contribution"); + + prop = RNA_def_property(srna, "use_pass_emit", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_EMIT); + RNA_def_property_ui_text(prop, "Emit", "Add emission contribution"); + + prop = RNA_def_property(srna, "use_pass_direct", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_DIRECT); + RNA_def_property_ui_text(prop, "Direct", "Add direct lighting contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_indirect", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_INDIRECT); + RNA_def_property_ui_text(prop, "Indirect", "Add indirect lighting contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_color", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_COLOR); + RNA_def_property_ui_text(prop, "Color", "Color the pass"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_diffuse", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_DIFFUSE); + RNA_def_property_ui_text(prop, "Diffuse", "Add diffuse contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_glossy", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_GLOSSY); + RNA_def_property_ui_text(prop, "Glossy", "Add glossy contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_transmission", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_TRANSM); + RNA_def_property_ui_text(prop, "Transmission", "Add transmission contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "use_pass_subsurface", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "pass_filter", R_BAKE_PASS_FILTER_SUBSURFACE); + RNA_def_property_ui_text(prop, "Subsurface", "Add subsurface contribution"); + RNA_def_property_update(prop, NC_SCENE | ND_RENDER_OPTIONS, NULL); + + prop = RNA_def_property(srna, "pass_filter", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "pass_filter"); + RNA_def_property_enum_items(prop, rna_enum_bake_pass_filter_type_items); + RNA_def_property_flag(prop, PROP_ENUM_FLAG); + RNA_def_property_ui_text(prop, "Pass Filter", "Passes to include in the active baking pass"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); } static void rna_def_scene_game_data(BlenderRNA *brna) diff --git a/source/blender/render/extern/include/RE_bake.h b/source/blender/render/extern/include/RE_bake.h index 0750ea1aa28..a04d1d6632c 100644 --- a/source/blender/render/extern/include/RE_bake.h +++ b/source/blender/render/extern/include/RE_bake.h @@ -72,7 +72,7 @@ bool RE_bake_has_engine(struct Render *re); bool RE_bake_engine( struct Render *re, struct Object *object, const int object_id, const BakePixel pixel_array[], - const size_t num_pixels, const int depth, const ScenePassType pass_type, float result[]); + const size_t num_pixels, const int depth, const ScenePassType pass_type, const int pass_filter, float result[]); /* bake.c */ int RE_pass_depth(const ScenePassType pass_type); diff --git a/source/blender/render/extern/include/RE_engine.h b/source/blender/render/extern/include/RE_engine.h index 4e48060c54f..d08b637454b 100644 --- a/source/blender/render/extern/include/RE_engine.h +++ b/source/blender/render/extern/include/RE_engine.h @@ -89,7 +89,7 @@ typedef struct RenderEngineType { void (*update)(struct RenderEngine *engine, struct Main *bmain, struct Scene *scene); void (*render)(struct RenderEngine *engine, struct Scene *scene); - void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result); + void (*bake)(struct RenderEngine *engine, struct Scene *scene, struct Object *object, const int pass_type, const int pass_filter, const int object_id, const struct BakePixel *pixel_array, const int num_pixels, const int depth, void *result); void (*view_update)(struct RenderEngine *engine, const struct bContext *context); void (*view_draw)(struct RenderEngine *engine, const struct bContext *context); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 441729ab782..5abad9ea01a 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -471,7 +471,8 @@ bool RE_bake_engine( Render *re, Object *object, const int object_id, const BakePixel pixel_array[], const size_t num_pixels, const int depth, - const ScenePassType pass_type, float result[]) + const ScenePassType pass_type, const int pass_filter, + float result[]) { RenderEngineType *type = RE_engines_find(re->r.engine); RenderEngine *engine; @@ -507,7 +508,7 @@ bool RE_bake_engine( type->update(engine, re->main, re->scene); if (type->bake) - type->bake(engine, re->scene, object, pass_type, object_id, pixel_array, num_pixels, depth, result); + type->bake(engine, re->scene, object, pass_type, pass_filter, object_id, pixel_array, num_pixels, depth, result); engine->tile_x = 0; engine->tile_y = 0; |