Cycles: Add option to replace GI with AO approximation after certain amount of bounces
authorSergey Sharybin <sergey.vfx@gmail.com>
Fri, 25 Nov 2016 17:59:43 +0000 (18:59 +0100)
committerSergey Sharybin <sergey.vfx@gmail.com>
Fri, 27 Jan 2017 13:21:49 +0000 (14:21 +0100)
This is a speed up option which is mainly useful for viewport. Gives nice speedup in
the barbershop scene of 2x when replacing GI with AO after 2nd bounce without loosing
too much details.

Reviewers: brecht

Subscribers: eyecandy, venomgfx

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

intern/cycles/blender/addon/properties.py
intern/cycles/blender/addon/ui.py
intern/cycles/blender/blender_sync.cpp
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_types.h
intern/cycles/render/integrator.cpp
intern/cycles/render/integrator.h

index 802b9b76c5d97397867be77bf33b8c408c5a8731..5c51f9afc28aa1ed490a795ba382e742fed13002 100644 (file)
@@ -638,6 +638,20 @@ class CyclesRenderSettings(bpy.types.PropertyGroup):
             items=enum_texture_limit
             )
 
+        cls.ao_bounces = IntProperty(
+            name="AO Bounces",
+            default=0,
+            description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+            min=0, max=1024,
+            )
+
+        cls.ao_bounces_render = IntProperty(
+            name="AO Bounces Render",
+            default=0,
+            description="Approximate indirect light with background tinted ambient occlusion at the specified bounce, 0 disables this feature",
+            min=0, max=1024,
+            )
+
         # Various fine-tuning debug flags
 
         def devices_update_callback(self, context):
index ddcefaf4c012d2dde147d4867f57027d66a98946..44af5f7efedbe8e180194cef6f12adb09e37af0d 100644 (file)
@@ -1038,10 +1038,11 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
         layout = self.layout
 
         light = context.world.light_settings
+        scene = context.scene
 
         row = layout.row()
         sub = row.row()
-        sub.active = light.use_ambient_occlusion
+        sub.active = light.use_ambient_occlusion or scene.render.use_simplify
         sub.prop(light, "ao_factor", text="Factor")
         row.prop(light, "distance", text="Distance")
 
@@ -1612,6 +1613,13 @@ class CyclesScene_PT_simplify(CyclesButtonsPanel, Panel):
         row.active = cscene.use_distance_cull
         row.prop(cscene, "distance_cull_margin", text="Distance")
 
+        split = layout.split()
+        col = split.column()
+        col.prop(cscene, "ao_bounces")
+
+        col = split.column()
+        col.prop(cscene, "ao_bounces_render")
+
 def draw_device(self, context):
     scene = context.scene
     layout = self.layout
index f8f2303ec7681965de073ab317604aab7c782f5c..d8043105cd82eee0249ad0cd255a2e94c7cfbac7 100644 (file)
@@ -322,6 +322,15 @@ void BlenderSync::sync_integrator()
                integrator->volume_samples = volume_samples;
        }
 
+       if(b_scene.render().use_simplify()) {
+               if(preview) {
+                       integrator->ao_bounces = get_int(cscene, "ao_bounces");
+               }
+               else {
+                       integrator->ao_bounces = get_int(cscene, "ao_bounces_render");
+               }
+       }
+
        if(integrator->modified(previntegrator))
                integrator->tag_update(scene);
 }
index 8ce9a4f02ecd671a0c0162af445a1cfa88cbd15a..f90701a8260b9b2a4e974f6bf7d0ce7fdacee667 100644 (file)
@@ -109,6 +109,10 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
                /* intersect scene */
                Intersection isect;
                uint visibility = path_state_ray_visibility(kg, state);
+               if(state->bounce > kernel_data.integrator.ao_bounces) {
+                       visibility = PATH_RAY_SHADOW;
+                       ray->t = kernel_data.background.ao_distance;
+               }
                bool hit = scene_intersect(kg,
                                           *ray,
                                           visibility,
@@ -292,6 +296,9 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                        break;
                }
+               else if(state->bounce > kernel_data.integrator.ao_bounces) {
+                       break;
+               }
 
                /* setup shading */
                shader_setup_from_ray(kg,
@@ -627,6 +634,11 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
                        lcg_state = lcg_state_init(rng, &state, 0x51633e2d);
                }
 
+               if(state.bounce > kernel_data.integrator.ao_bounces) {
+                       visibility = PATH_RAY_SHADOW;
+                       ray.t = kernel_data.background.ao_distance;
+               }
+
                bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
 #else
                bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
@@ -769,6 +781,9 @@ ccl_device_inline float4 kernel_path_integrate(KernelGlobals *kg,
 
                        break;
                }
+               else if(state.bounce > kernel_data.integrator.ao_bounces) {
+                       break;
+               }
 
                /* setup shading */
                shader_setup_from_ray(kg, &sd, &isect, &ray);
index b7af90cd739cd5a98788537c2689d89f41e2b505..4d9c4b2e6f10e5270b94938e97a646a8c1dad827 100644 (file)
@@ -1143,6 +1143,8 @@ typedef struct KernelIntegrator {
        int max_transmission_bounce;
        int max_volume_bounce;
 
+       int ao_bounces;
+
        /* transparent */
        int transparent_min_bounce;
        int transparent_max_bounce;
@@ -1185,8 +1187,6 @@ typedef struct KernelIntegrator {
        int volume_samples;
 
        float light_inv_rr_threshold;
-
-       int pad1;
 } KernelIntegrator;
 static_assert_align(KernelIntegrator, 16);
 
index a9a33d2e7890e6269cb6b367f72c873e401a977d..41e1dae2745bdc53e5fde42712f9af80a598b136 100644 (file)
@@ -43,6 +43,8 @@ NODE_DEFINE(Integrator)
        SOCKET_INT(transparent_max_bounce, "Transparent Max Bounce", 7);
        SOCKET_BOOLEAN(transparent_shadows, "Transparent Shadows", false);
 
+       SOCKET_INT(ao_bounces, "AO Bounces", 0);
+
        SOCKET_INT(volume_max_steps, "Volume Max Steps", 1024);
        SOCKET_FLOAT(volume_step_size, "Volume Step Size", 0.1f);
 
@@ -111,6 +113,13 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene
        kintegrator->transparent_max_bounce = transparent_max_bounce + 1;
        kintegrator->transparent_min_bounce = transparent_min_bounce + 1;
 
+       if(ao_bounces == 0) {
+               kintegrator->ao_bounces = INT_MAX;
+       }
+       else {
+               kintegrator->ao_bounces = ao_bounces - 1;
+       }
+
        /* Transparent Shadows
         * We only need to enable transparent shadows, if we actually have 
         * transparent shaders in the scene. Otherwise we can disable it
index 17fdd0ef1db2fff2158efbea8015f6d23d77aa66..f8cc0507ada455092be20179b02a077d511be591 100644 (file)
@@ -43,6 +43,8 @@ public:
        int transparent_max_bounce;
        bool transparent_shadows;
 
+       int ao_bounces;
+
        int volume_max_steps;
        float volume_step_size;