Cycles: change Ambient Occlusion shader to output colors.
authorLukas Stockner <lukas.stockner@freenet.de>
Fri, 15 Jun 2018 09:03:29 +0000 (11:03 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Fri, 15 Jun 2018 20:16:06 +0000 (22:16 +0200)
This means the shader can now be used for procedural texturing. New
settings on the node are Samples, Inside, Local Only and Distance.

Original patch by Lukas with further changes by Brecht.

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

34 files changed:
intern/cycles/blender/addon/version_update.py
intern/cycles/blender/blender_shader.cpp
intern/cycles/kernel/CMakeLists.txt
intern/cycles/kernel/bvh/bvh.h
intern/cycles/kernel/bvh/bvh_local.h
intern/cycles/kernel/bvh/qbvh_local.h
intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
intern/cycles/kernel/geom/geom_triangle_intersect.h
intern/cycles/kernel/kernel_path.h
intern/cycles/kernel/kernel_path_branched.h
intern/cycles/kernel/kernel_shader.h
intern/cycles/kernel/kernel_types.h
intern/cycles/kernel/osl/background.cpp
intern/cycles/kernel/osl/osl_closures.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/osl/osl_services.cpp
intern/cycles/kernel/osl/osl_services.h
intern/cycles/kernel/shaders/node_ambient_occlusion.osl
intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
intern/cycles/kernel/svm/svm.h
intern/cycles/kernel/svm/svm_ao.h [new file with mode: 0644]
intern/cycles/kernel/svm/svm_closure.h
intern/cycles/kernel/svm/svm_types.h
intern/cycles/render/nodes.cpp
intern/cycles/render/nodes.h
release/scripts/startup/nodeitems_builtins.py
source/blender/blenkernel/BKE_blender_version.h
source/blender/blenloader/intern/versioning_270.c
source/blender/editors/space_node/drawnode.c
source/blender/gpu/shaders/gpu_shader_material.glsl
source/blender/makesdna/DNA_node_types.h
source/blender/makesrna/intern/rna_nodetree.c
source/blender/nodes/NOD_static_types.h
source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c

index dc28bc647b59897168a937487d28f7097646715a..922ea9d9d7f263846d04a2c0a8cc91a307874fa8 100644 (file)
@@ -271,6 +271,40 @@ def custom_bake_remap(scene):
         scene.render.bake.use_pass_indirect = False
 
 
+def ambient_occlusion_node_relink(material, nodetree, traversed):
+    if nodetree in traversed:
+        return
+    traversed.add(nodetree)
+
+    for node in nodetree.nodes:
+        if node.bl_idname == 'ShaderNodeAmbientOcclusion':
+            node.samples = 1
+            node.only_local = False
+            node.inputs['Distance'].default_value = 0.0
+        elif node.bl_idname == 'ShaderNodeGroup':
+            ambient_occlusion_node_relink(material, node.node_tree, traversed)
+
+    # Gather links to replace
+    ao_links = []
+    for link in nodetree.links:
+        if link.from_node.bl_idname == 'ShaderNodeAmbientOcclusion':
+           ao_links.append(link)
+
+    # Replace links
+    for link in ao_links:
+        from_node = link.from_node
+        to_socket = link.to_socket
+
+        nodetree.links.remove(link)
+        nodetree.links.new(from_node.outputs['Color'], to_socket)
+
+def ambient_occlusion_nodes_relink():
+    traversed = set()
+    for material in bpy.data.materials:
+        if check_is_new_shading_material(material):
+            ambient_occlusion_node_relink(material, material.node_tree, traversed)
+
+
 @persistent
 def do_versions(self):
     if bpy.context.user_preferences.version <= (2, 78, 1):
@@ -428,11 +462,14 @@ def do_versions(self):
         # Switch to squared roughness convention
         square_roughness_nodes_insert()
 
-    for world in bpy.data.worlds:
-        cworld = world.cycles
-        # World MIS
-        if not cworld.is_property_set("sampling_method"):
-            if cworld.get("sample_as_light", False):
-                cworld.sampling_method = 'MANUAL'
-            else:
-                cworld.sampling_method = 'NONE'
+    if bpy.data.version <= (2, 79, 4):
+        for world in bpy.data.worlds:
+            cworld = world.cycles
+            # World MIS
+            if not cworld.is_property_set("sampling_method"):
+                if cworld.get("sample_as_light", False):
+                    cworld.sampling_method = 'MANUAL'
+                else:
+                    cworld.sampling_method = 'NONE'
+
+        ambient_occlusion_nodes_relink()
index 9896dd1d94fd2da1205f0e7535f553c01506d6f4..89612b74c39caa0fc8d092e0fd9f11326508402a 100644 (file)
@@ -558,7 +558,12 @@ static ShaderNode *add_node(Scene *scene,
                node = new EmissionNode();
        }
        else if(b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
-               node = new AmbientOcclusionNode();
+               BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
+               AmbientOcclusionNode *ao = new AmbientOcclusionNode();
+               ao->samples = b_ao_node.samples();
+               ao->inside = b_ao_node.inside();
+               ao->only_local = b_ao_node.only_local();
+               node = ao;
        }
        else if(b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
                node = new ScatterVolumeNode();
index b1956bfb13aa38787b509cff869a8e76d66d4bbc..c2688cd71f754a608060ddfd2362669e7e341e22 100644 (file)
@@ -160,6 +160,7 @@ set(SRC_CLOSURE_HEADERS
 
 set(SRC_SVM_HEADERS
        svm/svm.h
+       svm/svm_ao.h
        svm/svm_attribute.h
        svm/svm_bevel.h
        svm/svm_blackbody.h
index d3e0b25a20063958611472211ee4f5d170342df6..de1503e55647da44c63339e036fbae89b556d6bb 100644 (file)
@@ -203,7 +203,7 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
 
 #ifdef __BVH_LOCAL__
 /* Note: ray is passed by value to work around a possible CUDA compiler bug. */
-ccl_device_intersect void scene_intersect_local(KernelGlobals *kg,
+ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
                                                 const Ray ray,
                                                 LocalIntersection *local_isect,
                                                 int local_object,
index 9292cc76a5cc81030e73d04cdf3ba6344bd2f265..6356c197dd1c01e38dd38f45ca588e65429a90bb 100644 (file)
@@ -41,7 +41,7 @@ ccl_device
 #else
 ccl_device_inline
 #endif
-void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
+bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
                                  const Ray *ray,
                                  LocalIntersection *local_isect,
                                  int local_object,
@@ -70,7 +70,11 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
        int object = OBJECT_NONE;
        float isect_t = ray->t;
 
-       local_isect->num_hits = 0;
+       if(local_isect) {
+               local_isect->num_hits = 0;
+       }
+
+       kernel_assert((local_isect == NULL) == (max_hits == 0));
 
        const int object_flag = kernel_tex_fetch(__object_flag, local_object);
        if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
@@ -194,16 +198,18 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
                                                /* intersect ray against primitive */
                                                for(; prim_addr < prim_addr2; prim_addr++) {
                                                        kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
-                                                       triangle_intersect_local(kg,
-                                                                                local_isect,
-                                                                                P,
-                                                                                dir,
-                                                                                object,
-                                                                                local_object,
-                                                                                prim_addr,
-                                                                                isect_t,
-                                                                                lcg_state,
-                                                                                max_hits);
+                                                       if(triangle_intersect_local(kg,
+                                                                                   local_isect,
+                                                                                   P,
+                                                                                   dir,
+                                                                                   object,
+                                                                                   local_object,
+                                                                                   prim_addr,
+                                                                                   isect_t,
+                                                                                   lcg_state,
+                                                                                   max_hits)) {
+                                                               return true;
+                                                       }
                                                }
                                                break;
                                        }
@@ -212,17 +218,19 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
                                                /* intersect ray against primitive */
                                                for(; prim_addr < prim_addr2; prim_addr++) {
                                                        kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
-                                                       motion_triangle_intersect_local(kg,
-                                                                                       local_isect,
-                                                                                       P,
-                                                                                       dir,
-                                                                                       ray->time,
-                                                                                       object,
-                                                                                       local_object,
-                                                                                       prim_addr,
-                                                                                       isect_t,
-                                                                                       lcg_state,
-                                                                                       max_hits);
+                                                       if(motion_triangle_intersect_local(kg,
+                                                                                          local_isect,
+                                                                                          P,
+                                                                                          dir,
+                                                                                          ray->time,
+                                                                                          object,
+                                                                                          local_object,
+                                                                                          prim_addr,
+                                                                                          isect_t,
+                                                                                          lcg_state,
+                                                                                          max_hits)) {
+                                                               return true;
+                                                       }
                                                }
                                                break;
                                        }
@@ -234,9 +242,11 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
                        }
                } while(node_addr != ENTRYPOINT_SENTINEL);
        } while(node_addr != ENTRYPOINT_SENTINEL);
+
+       return false;
 }
 
-ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
+ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
                                          const Ray *ray,
                                          LocalIntersection *local_isect,
                                          int local_object,
@@ -262,6 +272,7 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
                                                           max_hits);
        }
        kernel_assert(!"Should not happen");
+       return false;
 }
 
 #undef BVH_FUNCTION_NAME
index 2386fa1a1e82311743bb679885a3cb015285bbf3..0dc0575556c18a274fd81e6cf9584586201aa2a9 100644 (file)
@@ -29,7 +29,7 @@
 #  define NODE_INTERSECT qbvh_aligned_node_intersect
 #endif
 
-ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
+ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
                                              const Ray *ray,
                                              LocalIntersection *local_isect,
                                              int local_object,
@@ -59,7 +59,11 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
        int object = OBJECT_NONE;
        float isect_t = ray->t;
 
-       local_isect->num_hits = 0;
+       if(local_isect) {
+               local_isect->num_hits = 0;
+       }
+
+       kernel_assert((local_isect == NULL) == (max_hits == 0));
 
        const int object_flag = kernel_tex_fetch(__object_flag, local_object);
        if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
@@ -81,7 +85,7 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
 
 #ifndef __KERNEL_SSE41__
        if(!isfinite(P.x)) {
-               return;
+               return false;
        }
 #endif
 
@@ -250,16 +254,18 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
                                                /* Intersect ray against primitive, */
                                                for(; prim_addr < prim_addr2; prim_addr++) {
                                                        kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
-                                                       triangle_intersect_local(kg,
-                                                                                local_isect,
-                                                                                P,
-                                                                                dir,
-                                                                                object,
-                                                                                local_object,
-                                                                                prim_addr,
-                                                                                isect_t,
-                                                                                lcg_state,
-                                                                                max_hits);
+                                                       if(triangle_intersect_local(kg,
+                                                                                   local_isect,
+                                                                                   P,
+                                                                                   dir,
+                                                                                   object,
+                                                                                   local_object,
+                                                                                   prim_addr,
+                                                                                   isect_t,
+                                                                                   lcg_state,
+                                                                                   max_hits)) {
+                                                               return true;
+                                                       }
                                                }
                                                break;
                                        }
@@ -268,17 +274,19 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
                                                /* Intersect ray against primitive. */
                                                for(; prim_addr < prim_addr2; prim_addr++) {
                                                        kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
-                                                       motion_triangle_intersect_local(kg,
-                                                                                       local_isect,
-                                                                                       P,
-                                                                                       dir,
-                                                                                       ray->time,
-                                                                                       object,
-                                                                                       local_object,
-                                                                                       prim_addr,
-                                                                                       isect_t,
-                                                                                       lcg_state,
-                                                                                       max_hits);
+                                                       if(motion_triangle_intersect_local(kg,
+                                                                                          local_isect,
+                                                                                          P,
+                                                                                          dir,
+                                                                                          ray->time,
+                                                                                          object,
+                                                                                          local_object,
+                                                                                          prim_addr,
+                                                                                          isect_t,
+                                                                                          lcg_state,
+                                                                                          max_hits)) {
+                                                               return true;
+                                                       }
                                                }
                                                break;
                                        }
@@ -289,6 +297,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
                        }
                } while(node_addr != ENTRYPOINT_SENTINEL);
        } while(node_addr != ENTRYPOINT_SENTINEL);
+
+       return false;
 }
 
 #undef NODE_INTERSECT
index 542843edc8463369802d46d175183332f01ffbb2..ec7bfad7349e3cc7d4a125e6c07607064e5a47ff 100644 (file)
@@ -218,9 +218,10 @@ ccl_device_inline bool motion_triangle_intersect(
 /* Special ray intersection routines for local intersections. In that case we
  * only want to intersect with primitives in the same object, and if case of
  * multiple hits we pick a single random primitive as the intersection point.
+ * Returns whether traversal should be stopped.
  */
 #ifdef __BVH_LOCAL__
-ccl_device_inline void motion_triangle_intersect_local(
+ccl_device_inline bool motion_triangle_intersect_local(
         KernelGlobals *kg,
         LocalIntersection *local_isect,
         float3 P,
@@ -237,7 +238,7 @@ ccl_device_inline void motion_triangle_intersect_local(
         * already know we are only intersecting the right object. */
        if(object == OBJECT_NONE) {
                if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
-                       return;
+                       return false;
                }
        }
 
@@ -258,7 +259,12 @@ ccl_device_inline void motion_triangle_intersect_local(
 #endif
                                   &u, &v, &t))
        {
-               return;
+               return false;
+       }
+
+       /* If no actual hit information is requested, just return here. */
+       if(max_hits == 0) {
+               return true;
        }
 
        int hit;
@@ -266,7 +272,7 @@ ccl_device_inline void motion_triangle_intersect_local(
                /* Record up to max_hits intersections. */
                for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
                        if(local_isect->hits[i].t == t) {
-                               return;
+                               return false;
                        }
                }
 
@@ -282,13 +288,13 @@ ccl_device_inline void motion_triangle_intersect_local(
                        hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
 
                        if(hit >= max_hits)
-                               return;
+                               return false;
                }
        }
        else {
                /* Record closest intersection only. */
                if(local_isect->num_hits && t > local_isect->hits[0].t) {
-                       return;
+                       return false;
                }
 
                hit = 0;
@@ -307,6 +313,8 @@ ccl_device_inline void motion_triangle_intersect_local(
        /* Record geometric normal. */
        local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
                                               verts[2] - verts[0]));
+
+       return false;
 }
 #endif  /* __BVH_LOCAL__ */
 
index a3b23115ae433012c3519ce4ebfbd62b8e33d5f9..a2b1e050e58a5ccc0b3cf1e1bf49b161b5d65ef6 100644 (file)
@@ -73,10 +73,11 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
 /* Special ray intersection routines for local intersection. In that case we
  * only want to intersect with primitives in the same object, and if case of
  * multiple hits we pick a single random primitive as the intersection point.
+ * Returns whether traversal should be stopped.
  */
 
 #ifdef __BVH_LOCAL__
-ccl_device_inline void triangle_intersect_local(
+ccl_device_inline bool triangle_intersect_local(
         KernelGlobals *kg,
         LocalIntersection *local_isect,
         float3 P,
@@ -92,7 +93,7 @@ ccl_device_inline void triangle_intersect_local(
         * already know we are only intersecting the right object. */
        if(object == OBJECT_NONE) {
                if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
-                       return;
+                       return false;
                }
        }
 
@@ -115,7 +116,12 @@ ccl_device_inline void triangle_intersect_local(
 #endif
                                   &u, &v, &t))
        {
-               return;
+               return false;
+       }
+
+       /* If no actual hit information is requested, just return here. */
+       if(max_hits == 0) {
+               return true;
        }
 
        int hit;
@@ -123,7 +129,7 @@ ccl_device_inline void triangle_intersect_local(
                /* Record up to max_hits intersections. */
                for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
                        if(local_isect->hits[i].t == t) {
-                               return;
+                               return false;
                        }
                }
 
@@ -138,13 +144,13 @@ ccl_device_inline void triangle_intersect_local(
                        hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
 
                        if(hit >= max_hits)
-                               return;
+                               return false;
                }
        }
        else {
                /* Record closest intersection only. */
                if(local_isect->num_hits && t > local_isect->hits[0].t) {
-                       return;
+                       return false;
                }
 
                hit = 0;
@@ -167,6 +173,8 @@ ccl_device_inline void triangle_intersect_local(
                     tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
 #endif
        local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
+
+       return false;
 }
 #endif  /* __BVH_LOCAL__ */
 
index b0f53aef2d5f9dc5f243cb1cd10a7c28482d9073..d79b556c2ce9ee0f3a1e27ea1ea81c4218dc5a64 100644 (file)
@@ -491,7 +491,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
 
 #ifdef __AO__
                /* ambient occlusion */
-               if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
+               if(kernel_data.integrator.use_ambient_occlusion) {
                        kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
                }
 #endif  /* __AO__ */
@@ -661,7 +661,7 @@ ccl_device_forceinline void kernel_path_integrate(
 
 #ifdef __AO__
                /* ambient occlusion */
-               if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
+               if(kernel_data.integrator.use_ambient_occlusion) {
                        kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd));
                }
 #endif  /* __AO__ */
index 66f67c3e2c4388af8075147774c7dc330063c4c7..80fcf5b056557153e55a7b03891167cc1a5f4488 100644 (file)
@@ -526,7 +526,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
 
 #ifdef __AO__
                /* ambient occlusion */
-               if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
+               if(kernel_data.integrator.use_ambient_occlusion) {
                        kernel_branched_path_ao(kg, &sd, emission_sd, L, &state, throughput);
                }
 #endif  /* __AO__ */
index 937a50cba8b55d2a5415e066b3744bd80c7df4a5..b83460b3ffb932ee29f0b9b04375fec2fc82feda 100644 (file)
@@ -914,10 +914,6 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
                        eval += sc->weight*ao_factor;
                        N += bsdf->N*fabsf(average(sc->weight));
                }
-               else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
-                       eval += sc->weight;
-                       N += sd->N*fabsf(average(sc->weight));
-               }
        }
 
        *N_ = (is_zero(N))? sd->N : normalize(N);
index 8df7c36979979df33a2772f92a5241ac795930ee..c2a65dc99993f3991183a60c890c75e24dfde5ea 100644 (file)
@@ -881,8 +881,6 @@ enum ShaderDataFlag {
        SD_EXTINCTION      = (1 << 6),
        /* Shader has have volume phase (scatter) closure. */
        SD_SCATTER         = (1 << 7),
-       /* Shader has AO closure. */
-       SD_AO              = (1 << 8),
        /* Shader has transparent closure. */
        SD_TRANSPARENT     = (1 << 9),
        /* BSDF requires LCG for evaluation. */
@@ -895,7 +893,6 @@ enum ShaderDataFlag {
                            SD_HOLDOUT |
                            SD_EXTINCTION |
                            SD_SCATTER |
-                           SD_AO |
                            SD_BSDF_NEEDS_LCG),
 
        /* Shader flags. */
index 8fff19407d98efb3b11a9bcba3077c6604776385..30a9e84c3994b6c373bfd6725b73ab97eccf245f 100644 (file)
@@ -74,21 +74,6 @@ public:
        }
 };
 
-/// ambient occlusion closure
-///
-/// We only have a ambient occlusion closure for the shaders
-/// to return a color in ambient occlusion shaders. No methods,
-/// only the weight is taking into account
-///
-class AmbientOcclusionClosure : public CClosurePrimitive {
-public:
-       void setup(ShaderData *sd, int /* path_flag */, float3 weight)
-       {
-               closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, weight);
-               sd->flag |= SD_AO;
-       }
-};
-
 ClosureParam *closure_background_params()
 {
        static ClosureParam params[] = {
@@ -110,16 +95,5 @@ ClosureParam *closure_holdout_params()
 
 CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
 
-ClosureParam *closure_ambient_occlusion_params()
-{
-       static ClosureParam params[] = {
-               CLOSURE_STRING_KEYPARAM(AmbientOcclusionClosure, label, "label"),
-               CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
-       };
-       return params;
-}
-
-CCLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
-
 CCL_NAMESPACE_END
 
index ee16ddaf0fddf041deadb743dd597dc0b954ae27..6a1e52d7d1690c7015d3798912504835b347c9a7 100644 (file)
@@ -310,8 +310,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
                closure_background_params(), closure_background_prepare);
        register_closure(ss, "holdout", id++,
                closure_holdout_params(), closure_holdout_prepare);
-       register_closure(ss, "ambient_occlusion", id++,
-               closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
        register_closure(ss, "diffuse_ramp", id++,
                closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
        register_closure(ss, "phong_ramp", id++,
index dca7e74f154ffd4c10f788c9b4abb753894c1eca..68dfa9a46504a0ec21c12e7f3f5e675908b5ac90 100644 (file)
@@ -45,7 +45,6 @@ CCL_NAMESPACE_BEGIN
 OSL::ClosureParam *closure_emission_params();
 OSL::ClosureParam *closure_background_params();
 OSL::ClosureParam *closure_holdout_params();
-OSL::ClosureParam *closure_ambient_occlusion_params();
 OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
 OSL::ClosureParam *closure_bsdf_phong_ramp_params();
 OSL::ClosureParam *closure_bsdf_transparent_params();
@@ -65,7 +64,6 @@ OSL::ClosureParam *closure_bsdf_principled_clearcoat_params();
 void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
 void closure_background_prepare(OSL::RendererServices *, int id, void *data);
 void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
-void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
 void closure_bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data);
index 1aca54d2ad56881e52dcbea2f0396449b2b8733c..4b7a4cb34b7d35f4599e5a45f44718026fde16f9 100644 (file)
@@ -125,6 +125,7 @@ ustring OSLRenderServices::u_u("u");
 ustring OSLRenderServices::u_v("v");
 ustring OSLRenderServices::u_empty;
 ustring OSLRenderServices::u_at_bevel("@bevel");
+ustring OSLRenderServices::u_at_ao("@ao");
 
 OSLRenderServices::OSLRenderServices()
 {
@@ -957,6 +958,25 @@ bool OSLRenderServices::texture(ustring filename,
                                status = true;
                        }
                }
+               else if(filename == u_at_ao) {
+                       /* AO shader hack. */
+                       PathState *state = sd->osl_path_state;
+                       int num_samples = (int)s;
+                       float radius = t;
+                       float3 N = make_float3(dsdx, dtdx, dsdy);
+                       int flags = 0;
+                       if((int)dtdy) {
+                               flags |= NODE_AO_INSIDE;
+                       }
+                       if((int)options.sblur) {
+                               flags |= NODE_AO_ONLY_LOCAL;
+                       }
+                       if((int)options.tblur) {
+                               flags |= NODE_AO_GLOBAL_RADIUS;
+                       }
+                       result[0] = svm_ao(kg, sd, N, state, radius, num_samples, flags);
+                       status = true;
+               }
                else if(filename[1] == 'l') {
                        /* IES light. */
                        int slot = atoi(filename.c_str() + 2);
index d96048e26f29d561d700e1904dfa53b1bd0bb543..1a40e2ece2ba4061fae8a0ac1b5eab6a84c8d13a 100644 (file)
@@ -182,6 +182,7 @@ public:
        static ustring u_v;
        static ustring u_empty;
        static ustring u_at_bevel;
+       static ustring u_at_ao;
 
 private:
        KernelGlobals *kernel_globals;
index 5f056122bbededfc4a757a5b5ad4df74e70ada59..d7ffa3c1606fc484184c199fdd368824503db327 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2013 Blender Foundation
+ * Copyright 2011-2018 Blender Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "stdosl.h"
 
 shader node_ambient_occlusion(
-       normal NormalIn = N,
-       color Color = 0.8,
-       output closure color AO = 0)
+       color ColorIn = color(0.8, 0.8, 0.8),
+       int samples = 8,
+       float Distance = 1.0,
+       normal Normal = N,
+       int inside = 0,
+       int only_local = 1,
+       output color ColorOut = color(0.8, 0.8, 0.8),
+       output float AO = 1.0)
 {
-       AO = Color * ambient_occlusion();
+       int global_radius = (Distance == 0.0 && !isconnected(Distance));
+
+       /* Abuse texture call with special @ao token. */
+       AO = texture("@ao", samples, Distance, Normal[0], Normal[1], Normal[2], inside, "sblur", only_local, "tblur", global_radius);
+       ColorOut = ColorIn * AO;
 }
 
index 88919f47c7a1d1b0d56306d12b1bf8021e1f3f19..f14eecec2f2f8079fc336bd46ca8e79855f13682 100644 (file)
@@ -149,7 +149,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
 #ifdef __AO__
        if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
                /* ambient occlusion */
-               if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
+               if(kernel_data.integrator.use_ambient_occlusion) {
                        enqueue_flag = 1;
                }
        }
index ce2affe96c871f98089da818cb0706832f7878bf..10d5fe0e42b77e620cf29f102f337e5739ef0065 100644 (file)
@@ -144,6 +144,7 @@ CCL_NAMESPACE_END
 #include "kernel/svm/svm_color_util.h"
 #include "kernel/svm/svm_math_util.h"
 
+#include "kernel/svm/svm_ao.h"
 #include "kernel/svm/svm_attribute.h"
 #include "kernel/svm/svm_gradient.h"
 #include "kernel/svm/svm_blackbody.h"
@@ -324,9 +325,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
                        case NODE_CLOSURE_HOLDOUT:
                                svm_node_closure_holdout(sd, stack, node);
                                break;
-                       case NODE_CLOSURE_AMBIENT_OCCLUSION:
-                               svm_node_closure_ambient_occlusion(sd, stack, node);
-                               break;
                        case NODE_FRESNEL:
                                svm_node_fresnel(sd, stack, node.y, node.z, node.w);
                                break;
@@ -480,6 +478,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
                        case NODE_BEVEL:
                                svm_node_bevel(kg, sd, state, stack, node);
                                break;
+                       case NODE_AMBIENT_OCCLUSION:
+                               svm_node_ao(kg, sd, state, stack, node);
+                               break;
 #  endif  /* __SHADER_RAYTRACE__ */
 #endif  /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
                        case NODE_END:
diff --git a/intern/cycles/kernel/svm/svm_ao.h b/intern/cycles/kernel/svm/svm_ao.h
new file mode 100644 (file)
index 0000000..3f76162
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+* Copyright 2011-2018 Blender Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+CCL_NAMESPACE_BEGIN
+
+ccl_device_noinline float svm_ao(KernelGlobals *kg,
+                                 ShaderData *sd,
+                                 float3 N,
+                                 ccl_addr_space PathState *state,
+                                 float max_dist,
+                                 int num_samples,
+                                 int flags)
+{
+       if(flags & NODE_AO_GLOBAL_RADIUS) {
+               max_dist = kernel_data.background.ao_distance;
+       }
+
+       /* Early out if no sampling needed. */
+       if(max_dist <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
+               return 0.0f;
+       }
+
+       if(flags & NODE_AO_INSIDE) {
+               N = -N;
+       }
+
+       float3 T, B;
+       make_orthonormals(N, &T, &B);
+
+       int unoccluded = 0;
+       for(int sample = 0; sample < num_samples; sample++) {
+               float disk_u, disk_v;
+               path_branched_rng_2D(kg, state->rng_hash, state, sample, num_samples,
+                                    PRNG_BEVEL_U, &disk_u, &disk_v);
+
+               float2 d = concentric_sample_disk(disk_u, disk_v);
+               float3 D = make_float3(d.x, d.y, safe_sqrtf(1.0f - dot(d, d)));
+
+               /* Create ray. */
+               Ray ray;
+               ray.P = ray_offset(sd->P, N);
+               ray.D = D.x*T + D.y*B + D.z*N;
+               ray.t = max_dist;
+               ray.time = sd->time;
+
+               if(flags & NODE_AO_ONLY_LOCAL) {
+                       if(!scene_intersect_local(kg,
+                                                 ray,
+                                                 NULL,
+                                                 sd->object,
+                                                 NULL,
+                                                 0)) {
+                               unoccluded++;
+                       }
+               }
+               else {
+                       Intersection isect;
+                       if(!scene_intersect(kg,
+                                           ray,
+                                           PATH_RAY_SHADOW_OPAQUE,
+                                           &isect,
+                                           NULL,
+                                           0.0f, 0.0f)) {
+                               unoccluded++;
+                       }
+               }
+       }
+
+       return ((float) unoccluded) / num_samples;
+}
+
+ccl_device void svm_node_ao(KernelGlobals *kg,
+                            ShaderData *sd,
+                            ccl_addr_space PathState *state,
+                            float *stack,
+                            uint4 node)
+{
+       uint flags, dist_offset, normal_offset, out_ao_offset;
+       decode_node_uchar4(node.y, &flags, &dist_offset, &normal_offset, &out_ao_offset);
+
+       uint color_offset, out_color_offset, samples;
+       decode_node_uchar4(node.z, &color_offset, &out_color_offset, &samples, NULL);
+
+       float dist = stack_load_float_default(stack, dist_offset, node.w);
+       float3 normal = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
+       float ao = svm_ao(kg, sd, normal, state, dist, samples, flags);
+
+       if (stack_valid(out_ao_offset)) {
+               stack_store_float(stack, out_ao_offset, ao);
+       }
+
+       if (stack_valid(out_color_offset)) {
+               float3 color = stack_load_float3(stack, color_offset);
+               stack_store_float3(stack, out_color_offset, ao * color);
+       }
+}
+
+CCL_NAMESPACE_END
index 76464e37c664dd9283ac612967fe1a46c1855a29..f5b316c67dab55ba12a2c5982f9e7ad126bc7c78 100644 (file)
@@ -996,24 +996,6 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
        sd->flag |= SD_HOLDOUT;
 }
 
-ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
-{
-       uint mix_weight_offset = node.y;
-
-       if(stack_valid(mix_weight_offset)) {
-               float mix_weight = stack_load_float(stack, mix_weight_offset);
-
-               if(mix_weight == 0.0f)
-                       return;
-
-               closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight * mix_weight);
-       }
-       else
-               closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight);
-
-       sd->flag |= SD_AO;
-}
-
 /* Closure Nodes */
 
 ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)
index ac24d23ecd21273fa6e8f26a87061e2d0252eb7b..54db18cd7bb30c080c0e3da620290106283412be 100644 (file)
@@ -124,7 +124,7 @@ typedef enum ShaderNodeType {
        NODE_PARTICLE_INFO,
        NODE_TEX_BRICK,
        NODE_CLOSURE_SET_NORMAL,
-       NODE_CLOSURE_AMBIENT_OCCLUSION,
+       NODE_AMBIENT_OCCLUSION,
        NODE_TANGENT,
        NODE_NORMAL_MAP,
        NODE_HAIR_INFO,
@@ -386,6 +386,12 @@ typedef enum NodeTexVoxelSpace {
        NODE_TEX_VOXEL_SPACE_WORLD  = 1,
 } NodeTexVoxelSpace;
 
+typedef enum NodeAO {
+       NODE_AO_ONLY_LOCAL = (1 << 0),
+       NODE_AO_INSIDE = (1 << 1),
+       NODE_AO_GLOBAL_RADIUS = (1 << 2),
+} NodeAO;
+
 typedef enum ShaderType {
        SHADER_TYPE_SURFACE,
        SHADER_TYPE_VOLUME,
@@ -456,7 +462,6 @@ typedef enum ClosureType {
 
        /* Other */
        CLOSURE_HOLDOUT_ID,
-       CLOSURE_AMBIENT_OCCLUSION_ID,
 
        /* Volume */
        CLOSURE_VOLUME_ID,
@@ -491,7 +496,6 @@ typedef enum ClosureType {
 #define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
 #define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
 #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
-#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
 #define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
 #define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
 #define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)
index 0f2581b2a2e89b851e204257ddc8fb887d9f11bc..680174f6d989f371c8b4c079eb4a0a669610f192 100644 (file)
@@ -2795,11 +2795,17 @@ NODE_DEFINE(AmbientOcclusionNode)
 {
        NodeType* type = NodeType::add("ambient_occlusion", create, NodeType::SHADER);
 
-       SOCKET_IN_NORMAL(normal_osl, "NormalIn", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL | SocketType::OSL_INTERNAL);
+       SOCKET_INT(samples, "Samples", 8);
+
        SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
-       SOCKET_IN_FLOAT(surface_mix_weight, "SurfaceMixWeight", 0.0f, SocketType::SVM_INTERNAL);
+       SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
+       SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
 
-       SOCKET_OUT_CLOSURE(AO, "AO");
+       SOCKET_BOOLEAN(inside, "Inside", false);
+       SOCKET_BOOLEAN(only_local, "Only Local", true);
+
+       SOCKET_OUT_COLOR(color, "Color");
+       SOCKET_OUT_FLOAT(ao, "AO");
 
        return type;
 }
@@ -2812,17 +2818,33 @@ AmbientOcclusionNode::AmbientOcclusionNode()
 void AmbientOcclusionNode::compile(SVMCompiler& compiler)
 {
        ShaderInput *color_in = input("Color");
+       ShaderInput *distance_in = input("Distance");
+       ShaderInput *normal_in = input("Normal");
+       ShaderOutput *color_out = output("Color");
+       ShaderOutput *ao_out = output("AO");
 
-       if(color_in->link)
-               compiler.add_node(NODE_CLOSURE_WEIGHT, compiler.stack_assign(color_in));
-       else
-               compiler.add_node(NODE_CLOSURE_SET_WEIGHT, color);
+       int flags = (inside? NODE_AO_INSIDE : 0) | (only_local? NODE_AO_ONLY_LOCAL : 0);
 
-       compiler.add_node(NODE_CLOSURE_AMBIENT_OCCLUSION, compiler.closure_mix_weight_offset());
+       if (!distance_in->link && distance == 0.0f) {
+               flags |= NODE_AO_GLOBAL_RADIUS;
+       }
+
+       compiler.add_node(NODE_AMBIENT_OCCLUSION,
+               compiler.encode_uchar4(flags,
+                                      compiler.stack_assign_if_linked(distance_in),
+                                      compiler.stack_assign_if_linked(normal_in),
+                                      compiler.stack_assign(ao_out)),
+               compiler.encode_uchar4(compiler.stack_assign(color_in),
+                                      compiler.stack_assign(color_out),
+                                      samples),
+               __float_as_uint(distance));
 }
 
 void AmbientOcclusionNode::compile(OSLCompiler& compiler)
 {
+       compiler.parameter(this, "samples");
+       compiler.parameter(this, "inside");
+       compiler.parameter(this, "only_local");
        compiler.add(this, "node_ambient_occlusion");
 }
 
index 35a7df690c39b005886580f9a7d1538633955f0f..be52cf40a17baed41b261e0236559814a681cbd4 100644 (file)
@@ -538,12 +538,16 @@ public:
        SHADER_NODE_CLASS(AmbientOcclusionNode)
 
        bool has_spatial_varying() { return true; }
-       virtual int get_group() { return NODE_GROUP_LEVEL_1; }
-       virtual ClosureType get_closure_type() { return CLOSURE_AMBIENT_OCCLUSION_ID; }
+       virtual int get_group() { return NODE_GROUP_LEVEL_3; }
+       virtual bool has_raytrace() { return true; }
 
-       float3 normal_osl;
        float3 color;
-       float surface_mix_weight;
+       float distance;
+       float3 normal;
+       int samples;
+
+       bool only_local;
+       bool inside;
 };
 
 class VolumeNode : public ShaderNode {
index 60a8471ca3b3ae8ee260377cf266a12adf26931c..3826b2b10de827a97155bfe47105c42f6e1d884d 100644 (file)
@@ -208,6 +208,7 @@ shader_node_categories = [
         NodeItem("ShaderNodeNewGeometry"),
         NodeItem("ShaderNodeWireframe"),
         NodeItem("ShaderNodeBevel"),
+        NodeItem("ShaderNodeAmbientOcclusion"),
         NodeItem("ShaderNodeObjectInfo"),
         NodeItem("ShaderNodeHairInfo"),
         NodeItem("ShaderNodeParticleInfo"),
@@ -240,7 +241,6 @@ shader_node_categories = [
         NodeItem("ShaderNodeEmission", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeBsdfHair", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll),
-        NodeItem("ShaderNodeAmbientOcclusion", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeHoldout", poll=object_shader_nodes_poll),
         NodeItem("ShaderNodeVolumeAbsorption"),
         NodeItem("ShaderNodeVolumeScatter"),
index b5d906b2968cbc4c96d7c93f2a9f7ef750120a4e..a3da6d5016e50e642a51660840c9c8543933946f 100644 (file)
@@ -28,7 +28,7 @@
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION         279
-#define BLENDER_SUBVERSION      4
+#define BLENDER_SUBVERSION      5
 /* Several breakages with 270, e.g. constraint deg vs rad */
 #define BLENDER_MINVERSION      270
 #define BLENDER_MINSUBVERSION   6
index e1b917268212901de56866df4026a5f31e3ad1bf..6d352bd7b130bc2b88a399d0f622839eabf0ee70 100644 (file)
@@ -1753,7 +1753,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
                }
        }
 
-       {
+       if (!MAIN_VERSION_ATLEAST(bmain, 279, 4)) {
                /* Fix for invalid state of screen due to bug in older versions. */
                for (bScreen *sc = bmain->screen.first; sc; sc = sc->id.next) {
                        for (ScrArea *sa = sc->areabase.first; sa; sa = sa->next) {
index 63bd305c13d02b46540fc1804f75c4781ad285eb..fff6c5d9f2cbb89a017851da6d0a1cbdcb89784a 100644 (file)
@@ -1168,6 +1168,13 @@ static void node_shader_buts_bevel(uiLayout *layout, bContext *UNUSED(C), Pointe
        uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
 }
 
+static void node_shader_buts_ambient_occlusion(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
+{
+       uiItemR(layout, ptr, "samples", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "inside", 0, NULL, ICON_NONE);
+       uiItemR(layout, ptr, "only_local", 0, NULL, ICON_NONE);
+}
+
 /* only once called */
 static void node_shader_set_butfunc(bNodeType *ntype)
 {
@@ -1311,6 +1318,9 @@ static void node_shader_set_butfunc(bNodeType *ntype)
                case SH_NODE_BEVEL:
                        ntype->draw_buttons = node_shader_buts_bevel;
                        break;
+               case SH_NODE_AMBIENT_OCCLUSION:
+                       ntype->draw_buttons = node_shader_buts_ambient_occlusion;
+                       break;
        }
 }
 
index ba8f33f75be2a009d3f7d53ec2d715c6650346fc..ce9e82b34f8f5244317e6cba25a38ca93d2480d7 100644 (file)
@@ -2785,9 +2785,10 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out ve
        node_bsdf_diffuse(color, 0.0, N, result);
 }
 
-void node_ambient_occlusion(vec4 color, out vec4 result)
+void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
 {
-       result = color;
+       result_color = color;
+       result_ao = 1.0;
 }
 
 /* emission */
index 6aa87cdbde2c0caf3a739d0b6db54d8d2d33b7bf..3cbcc86a69277d2969048a96251816e4f69a09f9 100644 (file)
@@ -1045,6 +1045,9 @@ typedef struct NodeSunBeams {
 #define SHD_SPACE_BLENDER_OBJECT       3
 #define SHD_SPACE_BLENDER_WORLD                4
 
+#define SHD_AO_INSIDE                          1
+#define SHD_AO_LOCAL                           2
+
 /* math node clamp */
 #define SHD_MATH_CLAMP         1
 
index 9bb5117cba3705aa6a502e47f6fae96047bf3340..1c7875873c2dec0996076784e66f96acffbcc13b 100644 (file)
@@ -4484,6 +4484,27 @@ static void def_sh_bevel(StructRNA *srna)
        RNA_def_property_update(prop, 0, "rna_Node_update");
 }
 
+static void def_sh_ambient_occlusion(StructRNA *srna)
+{
+       PropertyRNA *prop;
+
+       prop = RNA_def_property(srna, "samples", PROP_INT, PROP_UNSIGNED);
+       RNA_def_property_int_sdna(prop, NULL, "custom1");
+       RNA_def_property_range(prop, 1, 128);
+       RNA_def_property_ui_text(prop, "Samples", "Number of rays to trace per shader evaluation");
+       RNA_def_property_update(prop, 0, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "inside", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_AO_INSIDE);
+       RNA_def_property_ui_text(prop, "Inside", "Trace rays towards the inside of the object");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+       prop = RNA_def_property(srna, "only_local", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "custom2", SHD_AO_LOCAL);
+       RNA_def_property_ui_text(prop, "Only Local", "Only consider the object itself when computing AO");
+       RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+}
+
 static void def_sh_subsurface(StructRNA *srna)
 {
        static const EnumPropertyItem prop_subsurface_falloff_items[] = {
index 5864b3deb39554f62fc48ce022120f125e79474b..5217c7dc6e76047c891c2c9b2de57fc9bd8faa75 100644 (file)
@@ -75,7 +75,7 @@ DefNode( ShaderNode,     SH_NODE_LAYER_WEIGHT,       0,                      "LA
 DefNode( ShaderNode,     SH_NODE_MIX_SHADER,         0,                      "MIX_SHADER",         MixShader,        "Mix Shader",        ""       )
 DefNode( ShaderNode,     SH_NODE_ADD_SHADER,         0,                      "ADD_SHADER",         AddShader,        "Add Shader",        ""       )
 DefNode( ShaderNode,     SH_NODE_ATTRIBUTE,          def_sh_attribute,       "ATTRIBUTE",          Attribute,        "Attribute",         ""       )
-DefNode( ShaderNode,     SH_NODE_AMBIENT_OCCLUSION,  0,                      "AMBIENT_OCCLUSION",  AmbientOcclusion, "Ambient Occlusion", ""       )
+DefNode( ShaderNode,     SH_NODE_AMBIENT_OCCLUSION,  def_sh_ambient_occlusion,"AMBIENT_OCCLUSION", AmbientOcclusion, "Ambient Occlusion", ""       )
 DefNode( ShaderNode,     SH_NODE_BACKGROUND,         0,                      "BACKGROUND",         Background,       "Background",        ""       )
 DefNode( ShaderNode,     SH_NODE_HOLDOUT,            0,                      "HOLDOUT",            Holdout,          "Holdout",           ""       )
 DefNode( ShaderNode,     SH_NODE_BSDF_ANISOTROPIC,   def_anisotropic,        "BSDF_ANISOTROPIC",   BsdfAnisotropic,  "Anisotropic BSDF",  ""       )
index f0a0b70eecb65de2cb1309cca63a0b0d6a8dafd9..cad0fcaa14fb0275188b979ed9fdbfe9b616ced7 100644 (file)
 
 static bNodeSocketTemplate sh_node_ambient_occlusion_in[] = {
        {       SOCK_RGBA, 1, N_("Color"),              0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_FLOAT, 0, N_("Distance"),  1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1000.0f},
+       {       SOCK_VECTOR, 1, N_("Normal"),   0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE},
        {       -1, 0, ""       }
 };
 
 static bNodeSocketTemplate sh_node_ambient_occlusion_out[] = {
-       {       SOCK_SHADER, 0, N_("AO")},
+       {       SOCK_RGBA, 1, N_("Color"),      0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       SOCK_FLOAT, 0, N_("AO"),        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
        {       -1, 0, ""       }
 };
 
@@ -44,15 +47,21 @@ static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *UNUSED(nod
        return GPU_stack_link(mat, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
 }
 
+static void node_shader_init_ambient_occlusion(bNodeTree *UNUSED(ntree), bNode *node)
+{
+       node->custom1 = 8; /* samples */
+       node->custom2 = SHD_AO_LOCAL;
+}
+
 /* node type definition */
 void register_node_type_sh_ambient_occlusion(void)
 {
        static bNodeType ntype;
 
-       sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_SHADER, 0);
+       sh_node_type_base(&ntype, SH_NODE_AMBIENT_OCCLUSION, "Ambient Occlusion", NODE_CLASS_INPUT, 0);
        node_type_compatibility(&ntype, NODE_NEW_SHADING);
        node_type_socket_templates(&ntype, sh_node_ambient_occlusion_in, sh_node_ambient_occlusion_out);
-       node_type_init(&ntype, NULL);
+       node_type_init(&ntype, node_shader_init_ambient_occlusion);
        node_type_storage(&ntype, "", NULL, NULL);
        node_type_gpu(&ntype, node_shader_gpu_ambient_occlusion);