[Bf-blender-cvs] [bf2856c] cycles_memory_experiments: Cycles: Experiment with culling objects based on the camera frustum

Sergey Sharybin noreply at git.blender.org
Fri Apr 10 17:56:08 CEST 2015


Commit: bf2856c758fbdbaaf4ae872a5f9540654f754309
Author: Sergey Sharybin
Date:   Fri Apr 10 18:09:58 2015 +0500
Branches: cycles_memory_experiments
https://developer.blender.org/rBbf2856c758fbdbaaf4ae872a5f9540654f754309

Cycles: Experiment with culling objects based on the camera frustum

The idea is to give artists a simplier way to control memory usage in such
scenes as grass fields by doing automatic object culling based on whether
they're visible in the frame or not.

This is controlled on per-object level. In order to use this option few
steps are required:

- Allow renderer to use camera culling (Performance panel of render settings)
- Set camera cull margin (measured in relative value to the render resolution)
- Enable Camera Cull for objects which are desired to be culled
  (object culling option could be found in Option panel in object buttons).

Interface decisions are not final for sure and to be refined if this
option is considered good enough for production.

Reviewers: juicyfruit, brecht, campbellbarton

Subscribers: venomgfx, eyecandy

Differential Revision: https://developer.blender.org/D1230

===================================================================

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

===================================================================

diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index a86f162..633ce1a 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -504,6 +504,19 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
                 ),
             )
 
+        cls.use_camera_cull = BoolProperty(
+                name="Use Camera Cull",
+                description="Allow objects to be culled based on the camera frustum",
+                default=False,
+                )
+
+        cls.camera_cull_margin = FloatProperty(
+                name="Camera Cull Margin",
+                description="Margin for the camera space culling",
+                default=0.1,
+                min=0.0, max=5.0
+                )
+
     @classmethod
     def unregister(cls):
         del bpy.types.Scene.cycles
@@ -877,6 +890,12 @@ class CyclesObjectBlurSettings(bpy.types.PropertyGroup):
                 default=1,
                 )
 
+        cls.use_camera_cull = BoolProperty(
+                name="Use Camera Cull",
+                description="Allow this object and it's duplicators to be culled by camera space culling",
+                default=False,
+                )
+
     @classmethod
     def unregister(cls):
         del bpy.types.Object.cycles
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index 74de318..2631e26 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -303,6 +303,11 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel):
         subsub.enabled = not rd.use_border
         subsub.prop(rd, "use_save_buffers")
 
+        sub.prop(cscene, "use_camera_cull")
+        subsub = col.column()
+        subsub.active = cscene.use_camera_cull
+        subsub.prop(cscene, "camera_cull_margin")
+
         col = split.column(align=True)
 
         col.label(text="Viewport:")
@@ -649,8 +654,8 @@ class CyclesObject_PT_motion_blur(CyclesButtonsPanel, Panel):
         sub.prop(cob, "motion_steps", text="Steps")
 
 
-class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
-    bl_label = "Ray Visibility"
+class CyclesObject_PT_cycles_settings(CyclesButtonsPanel, Panel):
+    bl_label = "Cycles Settings"
     bl_context = "object"
     bl_options = {'DEFAULT_CLOSED'}
 
@@ -665,8 +670,10 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
         layout = self.layout
 
         ob = context.object
+        cob = ob.cycles
         visibility = ob.cycles_visibility
 
+        layout.label(text="Ray Visibility:")
         flow = layout.column_flow()
 
         flow.prop(visibility, "camera")
@@ -678,6 +685,9 @@ class CyclesObject_PT_ray_visibility(CyclesButtonsPanel, Panel):
         if ob.type != 'LAMP':
             flow.prop(visibility, "shadow")
 
+        layout.label(text="Performance:")
+        layout.prop(cob, "use_camera_cull")
+
 
 class CYCLES_OT_use_shading_nodes(Operator):
     """Enable nodes on a material, world or lamp"""
@@ -1393,7 +1403,8 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
     def draw(self, context):
         layout = self.layout
 
-        rd = context.scene.render
+        scene = context.scene
+        rd = scene.render
 
         layout.active = rd.use_simplify
 
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index 7364a8b..a4cdb3e 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -222,8 +222,52 @@ 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)
+static bool object_boundbox_clip(Scene *scene,
+                                 BL::Object b_ob,
+                                 Transform& tfm,
+                                 float margin)
+{
+	Camera *cam = scene->camera;
+	Transform& worldtondc = cam->worldtondc;
+	BL::Array<float, 24> boundbox = b_ob.bound_box();
+	float3 bb_min = make_float3(FLT_MAX, FLT_MAX, FLT_MAX),
+	       bb_max = make_float3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
+	bool all_behind = true;
+	for(int i = 0; i < 8; ++i) {
+		float3 p = make_float3(boundbox[3 * i + 0],
+		                       boundbox[3 * i + 1],
+		                       boundbox[3 * i + 2]);
+		p = transform_point(&tfm, p);
+		p = transform_point(&worldtondc, p);
+		if(p.z >= -margin) {
+			all_behind = false;
+		}
+		p /= p.z;
+		bb_min = min(bb_min, p);
+		bb_max = max(bb_max, p);
+	}
+	if(!all_behind) {
+		if(bb_min.x >= 1.0f + margin ||
+		   bb_min.y >= 1.0f + margin ||
+		   bb_max.x <= -margin ||
+		   bb_max.y <= -margin)
+		{
+			return true;
+		}
+		return false;
+	}
+	return true;
+}
+
+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,
+                                 bool use_camera_cull,
+                                 float camera_cull_margin)
 {
 	BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent);
 	bool motion = motion_time != 0.0f;
@@ -241,6 +285,11 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P
 	if(!object_is_mesh(b_ob))
 		return NULL;
 
+	/* Perform camera space culling. */
+	if(use_camera_cull && object_boundbox_clip(scene, b_ob, tfm, camera_cull_margin)) {
+		return NULL;
+	}
+
 	/* key to lookup object */
 	ObjectKey key(b_parent, persistent_id, b_ob);
 	Object *object;
@@ -466,6 +515,15 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
 		mesh_motion_synced.clear();
 	}
 
+	PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles");
+	bool allow_camera_cull = scene->camera->type != CAMERA_PANORAMA &&
+	                         !b_scene.render().use_multiview() &&
+	                         get_boolean(cscene, "use_camera_cull");
+	float camera_cull_margin = 0.0f;
+	if(allow_camera_cull) {
+		camera_cull_margin = get_float(cscene, "camera_cull_margin");
+	}
+
 	/* object loop */
 	BL::Scene::object_bases_iterator b_base;
 	BL::Scene b_sce = b_scene;
@@ -487,6 +545,12 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, float motion_time)
 			if(!hide) {
 				progress.set_sync_status("Synchronizing object", b_ob.name());
 
+				PointerRNA cobject = RNA_pointer_get(&b_ob.ptr, "cycles");
+				bool use_camera_cull = allow_camera_cull && get_boolean(cobject, "use_camera_cull");
+				if(use_camera_cull) {
+					/* Need to have proper projection matrix. */
+					scene->camera->update();
+				}
 				if(b_ob.is_duplicator() && !object_render_hide_duplis(b_ob)) {
 					/* dupli objects */
 					b_ob.dupli_list_create(b_scene, dupli_settings);
@@ -506,7 +570,15 @@ 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_camera_cull,
+							                             camera_cull_margin);
 
 							/* sync possible particle data, note particle_id
 							 * starts counting at 1, first is dummy particle */
@@ -526,7 +598,15 @@ 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_camera_cull,
+					            camera_cull_margin);
 				}
 			}
 
diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h
index 5fbf2c3..04c26ef 100644
--- a/intern/cycles/blender/blender_sync.h
+++ b/intern/cycles/blender/blender_sync.h
@@ -85,8 +85,15 @@ private:
 	void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree);
 	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);
+	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,
+	                    bool use_camera_cull,
+	                    float camera_cull_margin);
 	void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm);
 	void sync_background_light();
 	void sync_mesh_motion(BL::Object b_ob, Object *object, float motion_time);




More information about the Bf-blender-cvs mailing list