Cycles: change AO bounces approximation to do more glossy and transmission.
authorMathieu Menuet <bliblubli>
Tue, 12 Sep 2017 13:13:55 +0000 (15:13 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 12 Sep 2017 13:37:35 +0000 (15:37 +0200)
Rather than treating all ray types equally, we now always render 1 glossy
bounce and unlimited transmission bounces. This makes it possible to get
good looking results with low AO bounces settings, making it useful to
speed up interior renders for example.

Reviewed By: brecht

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

intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_path_state.h
intern/cycles/kernel/split/kernel_indirect_background.h
intern/cycles/kernel/split/kernel_scene_intersect.h

index 3319e2c2435b05e3d046862af18252c8aabf89df..bc8f8ec09f868f68b46e3cb47ec18fbaf6bad3ee 100644 (file)
@@ -111,7 +111,7 @@ 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) {
+               if(path_state_ao_bounce(kg, state)) {
                        visibility = PATH_RAY_SHADOW;
                        ray->t = kernel_data.background.ao_distance;
                }
@@ -294,7 +294,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
                        break;
                }
-               else if(state->bounce > kernel_data.integrator.ao_bounces) {
+               else if(path_state_ao_bounce(kg, state))  {
                        break;
                }
 
@@ -473,13 +473,18 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
                        lcg_state = lcg_state_init(&state, 0x51633e2d);
                }
 
-               if(state.bounce > kernel_data.integrator.ao_bounces) {
+               if(path_state_ao_bounce(kg, &state)) {
                        visibility = PATH_RAY_SHADOW;
                        ray.t = kernel_data.background.ao_distance;
                }
 
                bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
 #else
+               if(path_state_ao_bounce(kg, state)) {
+                       visibility = PATH_RAY_SHADOW;
+                       ray.t = kernel_data.background.ao_distance;
+               }
+
                bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
 #endif  /* __HAIR__ */
 
@@ -620,7 +625,7 @@ ccl_device_inline void kernel_path_integrate(KernelGlobals *kg,
 
                        break;
                }
-               else if(state.bounce > kernel_data.integrator.ao_bounces) {
+               else if(path_state_ao_bounce(kg, &state)) {
                        break;
                }
 
index af208ff37f120e3fff76dc88aaa935e90e25dafd..bedcd655bc6c1643f69ac010f047ca93c3715ab5 100644 (file)
@@ -143,7 +143,7 @@ ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathSta
 #endif
 }
 
-ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, PathState *state)
+ccl_device_inline uint path_state_ray_visibility(KernelGlobals *kg, ccl_addr_space PathState *state)
 {
        uint flag = state->flag & PATH_RAY_ALL_VISIBILITY;
 
@@ -214,5 +214,15 @@ ccl_device_inline void path_state_modify_bounce(ccl_addr_space PathState *state,
                state->bounce -= 1;
 }
 
+ccl_device_inline bool path_state_ao_bounce(KernelGlobals *kg, ccl_addr_space PathState *state)
+{
+    if(state->bounce <= kernel_data.integrator.ao_bounces) {
+        return false;
+    }
+
+    int bounce = state->bounce - state->transmission_bounce - (state->glossy_bounce > 0);
+    return (bounce > kernel_data.integrator.ao_bounces);
+}
+
 CCL_NAMESPACE_END
 
index 04d5769ef0db233b2c7dc1ffc7c75fdbed65ce06..2e9231caa3e6c0178757a25008c50a98c7ab1a10 100644 (file)
@@ -33,7 +33,7 @@ ccl_device void kernel_indirect_background(KernelGlobals *kg)
                if(ray_index != QUEUE_EMPTY_SLOT) {
                        if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
                                ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
-                               if(state->bounce > kernel_data.integrator.ao_bounces) {
+                               if(path_state_ao_bounce(kg, state)) {
                                        kernel_split_path_end(kg, ray_index);
                                }
                        }
index d0afd39ef296850505841ab2f1234665d13bead6..99095f8fcbc42e1ea8d84a6605e79bc6464294f4 100644 (file)
@@ -60,13 +60,13 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
        }
 
        Intersection isect;
-       PathState state = kernel_split_state.path_state[ray_index];
+       ccl_global PathState *state = &kernel_split_state.path_state[ray_index];
        Ray ray = kernel_split_state.ray[ray_index];
 
        /* intersect scene */
-       uint visibility = path_state_ray_visibility(kg, &state);
+       uint visibility = path_state_ray_visibility(kg, state);
 
-       if(state.bounce > kernel_data.integrator.ao_bounces) {
+       if(path_state_ao_bounce(kg, state)) {
                visibility = PATH_RAY_SHADOW;
                ray.t = kernel_data.background.ao_distance;
        }
@@ -76,18 +76,22 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
        uint lcg_state = 0;
 
        if(kernel_data.bvh.have_curves) {
-               if((kernel_data.cam.resolution == 1) && (state.flag & PATH_RAY_CAMERA)) {
+               if((kernel_data.cam.resolution == 1) && (state->flag & PATH_RAY_CAMERA)) {
                        float3 pixdiff = ray.dD.dx + ray.dD.dy;
                        /*pixdiff = pixdiff - dot(pixdiff, ray.D)*ray.D;*/
                        difl = kernel_data.curve.minimum_width * len(pixdiff) * 0.5f;
                }
 
                extmax = kernel_data.curve.maximum_width;
-               lcg_state = lcg_state_init(&state, 0x51633e2d);
+               lcg_state = lcg_state_init_addrspace(state, 0x51633e2d);
        }
 
        bool hit = scene_intersect(kg, ray, visibility, &isect, &lcg_state, difl, extmax);
 #else
+       if(path_state_ao_bounce(kg, state)) {
+               visibility = PATH_RAY_SHADOW;
+               ray.t = kernel_data.background.ao_distance;
+       }
        bool hit = scene_intersect(kg, ray, visibility, &isect, NULL, 0.0f, 0.0f);
 #endif
        kernel_split_state.isect[ray_index] = isect;
@@ -95,7 +99,7 @@ ccl_device void kernel_scene_intersect(KernelGlobals *kg)
 #ifdef __KERNEL_DEBUG__
        PathRadiance *L = &kernel_split_state.path_radiance[ray_index];
 
-       if(state.flag & PATH_RAY_CAMERA) {
+       if(state->flag & PATH_RAY_CAMERA) {
                L->debug_data.num_bvh_traversed_nodes += isect.num_traversed_nodes;
                L->debug_data.num_bvh_traversed_instances += isect.num_traversed_instances;
                L->debug_data.num_bvh_intersections += isect.num_intersections;