Fix T54935: Particle group instances don't render when hidden in viewport
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 4 May 2018 09:40:27 +0000 (11:40 +0200)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 4 May 2018 09:40:27 +0000 (11:40 +0200)
Seems to be only related on linked nature of particles.

This is caused by some conflicting optimization done for viewport, which
does not do particles re-calculation if they do not depend on time
(which is crucial for big layout scene grass fields) and particle render
setting  switch which was relying on fact that render pipeline will do
particle update via time dependency.

Now we extent an old workaround for invisible objects, which now also
deals with particles in the same way as old dependency graph was dealing
with this: tag object data for update if there is particle system.

There shouldn't be any speed difference between old and new depsgraph,
since tagging was already needed and was happening.

In Blender 2.8 such things should be easier to deal with since the whole
depsgraph is to be evaluated for render engine anyway.

source/blender/render/intern/source/pipeline.c

index 67c87d5d9b84ce51b82fdf5430a047b336f8600d..d1de985e4d63d1888a368d5f486081605934742b 100644 (file)
@@ -2058,77 +2058,103 @@ bool RE_allow_render_generic_object(Object *ob)
 #define DEPSGRAPH_WORKAROUND_HACK
 
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-static void tag_dependend_objects_for_render(Scene *scene, int renderlay)
+static void tag_dependend_object_for_render(Scene *scene, Object *object);
+
+static void tag_dependend_group_for_render(Scene *scene, Group *group)
 {
-       Scene *sce_iter;
-       Base *base;
-       for (SETLOOPER(scene, sce_iter, base)) {
-               Object *object = base->object;
+       if (group->id.tag & LIB_TAG_DOIT) {
+               return;
+       }
+       group->id.tag |= LIB_TAG_DOIT;
 
-               if ((base->lay & renderlay) == 0) {
-                       continue;
-               }
+       for (GroupObject *go = group->gobject.first; go != NULL; go = go->next) {
+               Object *object = go->ob;
+               tag_dependend_object_for_render(scene, object);
+       }
+}
 
-               if (object->type == OB_MESH) {
-                       if (RE_allow_render_generic_object(object)) {
-                               ModifierData *md;
-                               VirtualModifierData virtualModifierData;
+static void tag_dependend_object_for_render(Scene *scene, Object *object)
+{
+       if (object->type == OB_MESH) {
+               if (RE_allow_render_generic_object(object)) {
+                       ModifierData *md;
+                       VirtualModifierData virtualModifierData;
 
-                               for (md = modifiers_getVirtualModifierList(object, &virtualModifierData);
-                                    md;
-                                    md = md->next)
-                               {
-                                       if (!modifier_isEnabled(scene, md, eModifierMode_Render)) {
-                                               continue;
-                                       }
+                       if (object->particlesystem.first) {
+                               DAG_id_tag_update(&object->id, OB_RECALC_DATA);
+                       }
 
-                                       if (md->type == eModifierType_Boolean) {
-                                               BooleanModifierData *bmd = (BooleanModifierData *)md;
-                                               if (bmd->object && bmd->object->type == OB_MESH) {
-                                                       DAG_id_tag_update(&bmd->object->id, OB_RECALC_DATA);
-                                               }
+                       for (md = modifiers_getVirtualModifierList(object, &virtualModifierData);
+                            md;
+                            md = md->next)
+                       {
+                               if (!modifier_isEnabled(scene, md, eModifierMode_Render)) {
+                                       continue;
+                               }
+
+                               if (md->type == eModifierType_Boolean) {
+                                       BooleanModifierData *bmd = (BooleanModifierData *)md;
+                                       if (bmd->object && bmd->object->type == OB_MESH) {
+                                               DAG_id_tag_update(&bmd->object->id, OB_RECALC_DATA);
                                        }
-                                       else if (md->type == eModifierType_Array) {
-                                               ArrayModifierData *amd = (ArrayModifierData *)md;
-                                               if (amd->start_cap && amd->start_cap->type == OB_MESH) {
-                                                       DAG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA);
-                                               }
-                                               if (amd->end_cap && amd->end_cap->type == OB_MESH) {
-                                                       DAG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA);
-                                               }
+                               }
+                               else if (md->type == eModifierType_Array) {
+                                       ArrayModifierData *amd = (ArrayModifierData *)md;
+                                       if (amd->start_cap && amd->start_cap->type == OB_MESH) {
+                                               DAG_id_tag_update(&amd->start_cap->id, OB_RECALC_DATA);
                                        }
-                                       else if (md->type == eModifierType_Shrinkwrap) {
-                                               ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
-                                               if (smd->target  && smd->target->type == OB_MESH) {
-                                                       DAG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
-                                               }
+                                       if (amd->end_cap && amd->end_cap->type == OB_MESH) {
+                                               DAG_id_tag_update(&amd->end_cap->id, OB_RECALC_DATA);
                                        }
-                                       else if (md->type == eModifierType_ParticleSystem) {
-                                               ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
-                                               ParticleSystem *psys = psmd->psys;
-                                               ParticleSettings *part = psys->part;
-                                               switch (part->ren_as) {
-                                                       case PART_DRAW_OB:
-                                                               if (part->dup_ob != NULL) {
-                                                                       DAG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA);
-                                                               }
-                                                               break;
-                                                       case PART_DRAW_GR:
-                                                               if (part->dup_group != NULL) {
-                                                                       for (GroupObject *go = part->dup_group->gobject.first;
-                                                                            go != NULL;
-                                                                            go = go->next)
-                                                                       {
-                                                                               DAG_id_tag_update(&go->ob->id, OB_RECALC_DATA);
-                                                                       }
+                               }
+                               else if (md->type == eModifierType_Shrinkwrap) {
+                                       ShrinkwrapModifierData *smd = (ShrinkwrapModifierData *)md;
+                                       if (smd->target  && smd->target->type == OB_MESH) {
+                                               DAG_id_tag_update(&smd->target->id, OB_RECALC_DATA);
+                                       }
+                               }
+                               else if (md->type == eModifierType_ParticleSystem) {
+                                       ParticleSystemModifierData *psmd = (ParticleSystemModifierData *)md;
+                                       ParticleSystem *psys = psmd->psys;
+                                       ParticleSettings *part = psys->part;
+                                       switch (part->ren_as) {
+                                               case PART_DRAW_OB:
+                                                       if (part->dup_ob != NULL) {
+                                                               DAG_id_tag_update(&part->dup_ob->id, OB_RECALC_DATA);
+                                                       }
+                                                       break;
+                                               case PART_DRAW_GR:
+                                                       if (part->dup_group != NULL) {
+                                                               for (GroupObject *go = part->dup_group->gobject.first;
+                                                                    go != NULL;
+                                                                    go = go->next)
+                                                               {
+                                                                       DAG_id_tag_update(&go->ob->id, OB_RECALC_DATA);
                                                                }
-                                                               break;
-                                               }
+                                                       }
+                                                       break;
                                        }
                                }
                        }
                }
        }
+       if (object->dup_group != NULL) {
+               tag_dependend_group_for_render(scene, object->dup_group);
+       }
+}
+
+static void tag_dependend_objects_for_render(Main *bmain, Scene *scene, int renderlay)
+{
+       Scene *sce_iter;
+       Base *base;
+       BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
+       for (SETLOOPER(scene, sce_iter, base)) {
+               Object *object = base->object;
+               if ((base->lay & renderlay) == 0) {
+                       continue;
+               }
+               tag_dependend_object_for_render(scene, object);
+       }
 }
 #endif
 
@@ -2143,7 +2169,7 @@ static void tag_scenes_for_render(Render *re)
        for (sce = re->main->scene.first; sce; sce = sce->id.next) {
                sce->id.tag &= ~LIB_TAG_DOIT;
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-               tag_dependend_objects_for_render(sce, renderlay);
+               tag_dependend_objects_for_render(re->main, sce, renderlay);
 #endif
        }
        
@@ -2152,7 +2178,7 @@ static void tag_scenes_for_render(Render *re)
                for (sce = re->freestyle_bmain->scene.first; sce; sce = sce->id.next) {
                        sce->id.tag &= ~LIB_TAG_DOIT;
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-                       tag_dependend_objects_for_render(sce, renderlay);
+                       tag_dependend_objects_for_render(re->freestyle_bmain, sce, renderlay);
 #endif
                }
        }
@@ -2161,7 +2187,7 @@ static void tag_scenes_for_render(Render *re)
        if (RE_GetCamera(re) && composite_needs_render(re->scene, 1)) {
                re->scene->id.tag |= LIB_TAG_DOIT;
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-               tag_dependend_objects_for_render(re->scene, renderlay);
+               tag_dependend_objects_for_render(re->main, re->scene, renderlay);
 #endif
        }
        
@@ -2194,7 +2220,7 @@ static void tag_scenes_for_render(Render *re)
                                                        node->flag |= NODE_TEST;
                                                        node->id->tag |= LIB_TAG_DOIT;
 #ifdef DEPSGRAPH_WORKAROUND_HACK
-                                                       tag_dependend_objects_for_render(scene, renderlay);
+                                                       tag_dependend_objects_for_render(re->main, scene, renderlay);
 #endif
                                                }
                                        }