Commit: f478c2cfbd3861cfca1d1a019066d30a4410a1f7 Author: Lukas Stockner Date: Tue Apr 28 00:51:55 2015 +0500 Branches: master https://developer.blender.org/rBf478c2cfbd3861cfca1d1a019066d30a4410a1f7
Cycles: Added support for light portals This patch adds support for light portals: objects that help sampling the environment light, therefore improving convergence. Using them tor other lights in a unidirectional pathtracer is virtually useless. The sampling is done with the area-preserving code already used for area lamps. MIS is used both for combination of different portals and for combining portal- and envmap-sampling. The direction of portals is considered, they aren't used if the sampling point is behind them. Reviewers: sergey, dingto, #cycles Reviewed By: dingto, #cycles Subscribers: Lapineige, nutel, jtheninja, dsisco11, januz, vitorbalbio, candreacchio, TARDISMaker, lichtwerk, ace_dragon, marcog, mib2berlin, Tunge, lopataasdf, lordodin, sergey, dingto Differential Revision: https://developer.blender.org/D1133 =================================================================== M intern/cycles/blender/addon/properties.py M intern/cycles/blender/addon/ui.py M intern/cycles/blender/blender_object.cpp M intern/cycles/blender/blender_sync.h M intern/cycles/kernel/kernel_emission.h M intern/cycles/kernel/kernel_light.h M intern/cycles/kernel/kernel_types.h M intern/cycles/render/light.cpp M intern/cycles/render/light.h =================================================================== diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 875b5d3..538876a 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -694,6 +694,12 @@ class CyclesLampSettings(bpy.types.PropertyGroup): "reduces noise for area lamps and sharp glossy materials", default=False, ) + cls.is_portal = BoolProperty( + name="Is Portal", + description="Use this area lamp to guide sampling of the background, " + "note that this will make the lamp invisible", + default=False, + ) @classmethod def unregister(cls): diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 74de318..cdacad7 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -743,7 +743,10 @@ class CyclesLamp_PT_preview(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - return context.lamp and CyclesButtonsPanel.poll(context) + return context.lamp and \ + not (context.lamp.type == 'AREA' and + context.lamp.cycles.is_portal) \ + and CyclesButtonsPanel.poll(context) def draw(self, context): self.layout.template_preview(context.lamp) @@ -781,13 +784,21 @@ class CyclesLamp_PT_lamp(CyclesButtonsPanel, Panel): sub.prop(lamp, "size", text="Size X") sub.prop(lamp, "size_y", text="Size Y") - if cscene.progressive == 'BRANCHED_PATH': - col.prop(clamp, "samples") - col.prop(clamp, "max_bounces") + if not (lamp.type == 'AREA' and clamp.is_portal): + sub = col.column(align=True) + if cscene.progressive == 'BRANCHED_PATH': + sub.prop(clamp, "samples") + sub.prop(clamp, "max_bounces") col = split.column() - col.prop(clamp, "cast_shadow") - col.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") + + sub = col.column(align=True) + sub.active = not (lamp.type == 'AREA' and clamp.is_portal) + sub.prop(clamp, "cast_shadow") + sub.prop(clamp, "use_multiple_importance_sampling", text="Multiple Importance") + + if lamp.type == 'AREA': + col.prop(clamp, "is_portal", text="Portal") if lamp.type == 'HEMI': layout.label(text="Not supported, interpreted as sun lamp") @@ -799,7 +810,9 @@ class CyclesLamp_PT_nodes(CyclesButtonsPanel, Panel): @classmethod def poll(cls, context): - return context.lamp and CyclesButtonsPanel.poll(context) + return context.lamp and not (context.lamp.type == 'AREA' and + context.lamp.cycles.is_portal) and \ + CyclesButtonsPanel.poll(context) def draw(self, context): layout = self.layout diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 7364a8b..bcc3667 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -90,14 +90,17 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal) { /* test if we need to sync */ Light *light; ObjectKey key(b_parent, persistent_id, b_ob); - if(!light_map.sync(&light, b_ob, b_parent, key)) + if(!light_map.sync(&light, b_ob, b_parent, key)) { + if(light->is_portal) + *use_portal = true; return; + } BL::Lamp b_lamp(b_ob.data()); @@ -171,6 +174,14 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->max_bounces = get_int(clamp, "max_bounces"); + if(light->type == LIGHT_AREA) + light->is_portal = get_boolean(clamp, "is_portal"); + else + light->is_portal = false; + + if(light->is_portal) + *use_portal = true; + /* visibility */ uint visibility = object_ray_visibility(b_ob); light->use_diffuse = (visibility & PATH_RAY_DIFFUSE) != 0; @@ -182,7 +193,7 @@ void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSI light->tag_update(scene); } -void BlenderSync::sync_background_light() +void BlenderSync::sync_background_light(bool use_portal) { BL::World b_world = b_scene.world(); @@ -191,19 +202,20 @@ void BlenderSync::sync_background_light() PointerRNA cworld = RNA_pointer_get(&b_world.ptr, "cycles"); bool sample_as_light = get_boolean(cworld, "sample_as_light"); - if(sample_as_light) { + if(sample_as_light || use_portal) { /* test if we need to sync */ Light *light; ObjectKey key(b_world, 0, b_world); if(light_map.sync(&light, b_world, b_world, key) || - world_recalc || - b_world.ptr.data != world_map) + world_recalc || + b_world.ptr.data != world_map) { light->type = LIGHT_BACKGROUND; light->map_resolution = get_int(cworld, "sample_map_resolution"); light->shader = scene->default_background; - + light->use_mis = sample_as_light; + int samples = get_int(cworld, "samples"); if(get_boolean(cscene, "use_square_samples")) light->samples = samples * samples; @@ -223,7 +235,7 @@ void BlenderSync::sync_background_light() /* Object */ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, - Transform& tfm, uint layer_flag, float motion_time, bool hide_tris) + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); bool motion = motion_time != 0.0f; @@ -232,7 +244,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P if(object_is_light(b_ob)) { /* don't use lamps for excluded layers used as mask layer */ if(!motion && !((layer_flag & render_layer.holdout_layer) && (layer_flag & render_layer.exclude_layer))) - sync_light(b_parent, persistent_id, b_ob, tfm); + sync_light(b_parent, persistent_id, b_ob, tfm, use_portal); return NULL; } @@ -476,6 +488,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) int dupli_settings = preview ? 1 : 2; bool cancel = false; + bool use_portal = false; for(; b_sce && !cancel; b_sce = b_sce.background_set()) { for(b_sce.object_bases.begin(b_base); b_base != b_sce.object_bases.end() && !cancel; ++b_base) { @@ -506,7 +519,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) BL::Array<int, OBJECT_PERSISTENT_ID_SIZE> persistent_id = b_dup->persistent_id(); /* sync object and mesh or light data */ - Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris); + Object *object = sync_object(b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion_time, hide_tris, &use_portal); /* sync possible particle data, note particle_id * starts counting at 1, first is dummy particle */ @@ -526,7 +539,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) if(!object_render_hide(b_ob, true, true, hide_tris)) { /* object itself */ Transform tfm = get_transform(b_ob.matrix_world()); - sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris); + sync_object(b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion_time, hide_tris, &use_portal); } } @@ -537,7 +550,7 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time) progress.set_sync_status(""); if(!cancel && !motion) { - sync_background_light(); + sync_background_light(use_portal); /* handle removed data and modified pointers */ if(light_map.post_sync()) diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 5fbf2c3..89d93e1 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -86,9 +86,9 @@ private: Mesh *sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tris); void sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, bool motion, int time_index = 0); Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, - Transform& tfm, uint layer_flag, float motion_time, bool hide_tris); - void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); - void sync_background_light(); + Transform& tfm, uint layer_flag, float motion_time, bool hide_tris, bool *use_portal); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm, bool *use_portal); + void sync_background_light(bool use_portal); void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time); void sync_camera_motion(BL::Object b_ob, float motion_time); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index d3cbc5c..6c5a5fa 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -254,7 +254,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg, PathState *sta if(!(state->flag & PATH_RAY_MIS_SKIP) && res) { /* multiple importance sampling, get background light pdf for ray * direction, and compute weight with respect to BSDF pdf */ - float pdf = background_light_pdf(kg, ray->D); + float pdf = background_light_pdf(kg, ray->P, ray->D); float mis_weight = power_heuristic(state->ray_pdf, pdf); return L*mis_weight; diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h index 76fa754..d1b8db2 100644 --- @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] http://lists.blender.org/mailman/listinfo/bf-blender-cvs
