Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--intern/cycles/blender/addon/version_update.py54
-rw-r--r--intern/cycles/blender/blender_shader.cpp7
-rw-r--r--intern/cycles/kernel/CMakeLists.txt1
-rw-r--r--intern/cycles/kernel/bvh/bvh.h2
-rw-r--r--intern/cycles/kernel/bvh/bvh_local.h59
-rw-r--r--intern/cycles/kernel/bvh/qbvh_local.h58
-rw-r--r--intern/cycles/kernel/geom/geom_motion_triangle_intersect.h20
-rw-r--r--intern/cycles/kernel/geom/geom_triangle_intersect.h20
-rw-r--r--intern/cycles/kernel/kernel_path.h4
-rw-r--r--intern/cycles/kernel/kernel_path_branched.h2
-rw-r--r--intern/cycles/kernel/kernel_shader.h4
-rw-r--r--intern/cycles/kernel/kernel_types.h3
-rw-r--r--intern/cycles/kernel/osl/background.cpp26
-rw-r--r--intern/cycles/kernel/osl/osl_closures.cpp2
-rw-r--r--intern/cycles/kernel/osl/osl_closures.h2
-rw-r--r--intern/cycles/kernel/osl/osl_services.cpp20
-rw-r--r--intern/cycles/kernel/osl/osl_services.h1
-rw-r--r--intern/cycles/kernel/shaders/node_ambient_occlusion.osl19
-rw-r--r--intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h2
-rw-r--r--intern/cycles/kernel/svm/svm.h7
-rw-r--r--intern/cycles/kernel/svm/svm_ao.h111
-rw-r--r--intern/cycles/kernel/svm/svm_closure.h18
-rw-r--r--intern/cycles/kernel/svm/svm_types.h10
-rw-r--r--intern/cycles/render/nodes.cpp38
-rw-r--r--intern/cycles/render/nodes.h12
-rw-r--r--release/scripts/startup/nodeitems_builtins.py2
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h2
-rw-r--r--source/blender/blenloader/intern/versioning_270.c2
-rw-r--r--source/blender/blenloader/intern/versioning_280.c3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/editors/space_node/drawnode.c10
-rw-r--r--source/blender/gpu/shaders/gpu_shader_material.glsl8
-rw-r--r--source/blender/makesdna/DNA_node_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_nodetree.c21
-rw-r--r--source/blender/nodes/NOD_static_types.h2
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c20
36 files changed, 410 insertions, 167 deletions
diff --git a/intern/cycles/blender/addon/version_update.py b/intern/cycles/blender/addon/version_update.py
index 2db4def9dcb..d3948f8fbb5 100644
--- a/intern/cycles/blender/addon/version_update.py
+++ b/intern/cycles/blender/addon/version_update.py
@@ -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):
@@ -441,11 +475,15 @@ def do_versions(self):
part.radius_scale = cpart.get("radius_scale", 0.01)
part.use_close_tip = cpart.get("use_closetip", True)
- 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) or \
+ (bpy.data.version >= (2, 80, 0) and bpy.data.version <= (2, 80, 18)):
+ 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()
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index f9ba8a6e6b7..66034919145 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -551,7 +551,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();
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt
index b1956bfb13a..c2688cd71f7 100644
--- a/intern/cycles/kernel/CMakeLists.txt
+++ b/intern/cycles/kernel/CMakeLists.txt
@@ -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
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index d3e0b25a200..de1503e5564 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -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,
diff --git a/intern/cycles/kernel/bvh/bvh_local.h b/intern/cycles/kernel/bvh/bvh_local.h
index 9292cc76a5c..6356c197dd1 100644
--- a/intern/cycles/kernel/bvh/bvh_local.h
+++ b/intern/cycles/kernel/bvh/bvh_local.h
@@ -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
diff --git a/intern/cycles/kernel/bvh/qbvh_local.h b/intern/cycles/kernel/bvh/qbvh_local.h
index 2386fa1a1e8..0dc0575556c 100644
--- a/intern/cycles/kernel/bvh/qbvh_local.h
+++ b/intern/cycles/kernel/bvh/qbvh_local.h
@@ -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
diff --git a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
index 542843edc84..ec7bfad7349 100644
--- a/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_motion_triangle_intersect.h
@@ -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__ */
diff --git a/intern/cycles/kernel/geom/geom_triangle_intersect.h b/intern/cycles/kernel/geom/geom_triangle_intersect.h
index a3b23115ae4..a2b1e050e58 100644
--- a/intern/cycles/kernel/geom/geom_triangle_intersect.h
+++ b/intern/cycles/kernel/geom/geom_triangle_intersect.h
@@ -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__ */
diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h
index b0f53aef2d5..d79b556c2ce 100644
--- a/intern/cycles/kernel/kernel_path.h
+++ b/intern/cycles/kernel/kernel_path.h
@@ -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__ */
diff --git a/intern/cycles/kernel/kernel_path_branched.h b/intern/cycles/kernel/kernel_path_branched.h
index 66f67c3e2c4..80fcf5b0565 100644
--- a/intern/cycles/kernel/kernel_path_branched.h
+++ b/intern/cycles/kernel/kernel_path_branched.h
@@ -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__ */
diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h
index 937a50cba8b..b83460b3ffb 100644
--- a/intern/cycles/kernel/kernel_shader.h
+++ b/intern/cycles/kernel/kernel_shader.h
@@ -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);
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 8df7c369799..c2a65dc9999 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -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. */
diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp
index 8fff19407d9..30a9e84c399 100644
--- a/intern/cycles/kernel/osl/background.cpp
+++ b/intern/cycles/kernel/osl/background.cpp
@@ -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
diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp
index ee16ddaf0fd..6a1e52d7d16 100644
--- a/intern/cycles/kernel/osl/osl_closures.cpp
+++ b/intern/cycles/kernel/osl/osl_closures.cpp
@@ -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++,
diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h
index dca7e74f154..68dfa9a4650 100644
--- a/intern/cycles/kernel/osl/osl_closures.h
+++ b/intern/cycles/kernel/osl/osl_closures.h
@@ -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);
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 1aca54d2ad5..4b7a4cb34b7 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -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);
diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h
index d96048e26f2..1a40e2ece2b 100644
--- a/intern/cycles/kernel/osl/osl_services.h
+++ b/intern/cycles/kernel/osl/osl_services.h
@@ -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;
diff --git a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
index 5f056122bbe..d7ffa3c1606 100644
--- a/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
+++ b/intern/cycles/kernel/shaders/node_ambient_occlusion.osl
@@ -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.
@@ -17,10 +17,19 @@
#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;
}
diff --git a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
index 88919f47c7a..f14eecec2f2 100644
--- a/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
+++ b/intern/cycles/kernel/split/kernel_holdout_emission_blurring_pathtermination_ao.h
@@ -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;
}
}
diff --git a/intern/cycles/kernel/svm/svm.h b/intern/cycles/kernel/svm/svm.h
index ce2affe96c8..10d5fe0e42b 100644
--- a/intern/cycles/kernel/svm/svm.h
+++ b/intern/cycles/kernel/svm/svm.h
@@ -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
index 00000000000..3f761627e2c
--- /dev/null
+++ b/intern/cycles/kernel/svm/svm_ao.h
@@ -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
diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h
index 76464e37c66..f5b316c67da 100644
--- a/intern/cycles/kernel/svm/svm_closure.h
+++ b/intern/cycles/kernel/svm/svm_closure.h
@@ -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)
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index ac24d23ecd2..54db18cd7bb 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -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)
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index 1ddc84848cc..59ac6257499 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -2792,11 +2792,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;
}
@@ -2809,17 +2815,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");
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index d1c7c9176e1..996c582d206 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -540,12 +540,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 {
diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py
index d60710db4aa..713dbdafcc5 100644
--- a/release/scripts/startup/nodeitems_builtins.py
+++ b/release/scripts/startup/nodeitems_builtins.py
@@ -177,6 +177,7 @@ shader_node_categories = [
NodeItem("ShaderNodeNewGeometry"),
NodeItem("ShaderNodeWireframe"),
NodeItem("ShaderNodeBevel"),
+ NodeItem("ShaderNodeAmbientOcclusion"),
NodeItem("ShaderNodeObjectInfo"),
NodeItem("ShaderNodeHairInfo"),
NodeItem("ShaderNodeParticleInfo"),
@@ -209,7 +210,6 @@ shader_node_categories = [
NodeItem("ShaderNodeEmission", poll=object_eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBsdfHair", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeBackground", poll=world_shader_nodes_poll),
- NodeItem("ShaderNodeAmbientOcclusion", poll=object_eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeHoldout", poll=object_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumeAbsorption", poll=eevee_cycles_shader_nodes_poll),
NodeItem("ShaderNodeVolumeScatter", poll=eevee_cycles_shader_nodes_poll),
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index c3dbb362206..0dddb8e7b0b 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -28,7 +28,7 @@
* and keep comment above the defines.
* Use STRINGIFY() rather than defining with quotes */
#define BLENDER_VERSION 280
-#define BLENDER_SUBVERSION 17
+#define BLENDER_SUBVERSION 18
/* Several breakages with 280, e.g. collections vs layers */
#define BLENDER_MINVERSION 280
#define BLENDER_MINSUBVERSION 0
diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c
index ba714405cc0..7f5646eddc2 100644
--- a/source/blender/blenloader/intern/versioning_270.c
+++ b/source/blender/blenloader/intern/versioning_270.c
@@ -1665,7 +1665,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) {
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index e7d4e4f33ae..0324161f6e1 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -1493,7 +1493,8 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
- {
+
+ if (!MAIN_VERSION_ATLEAST(bmain, 280, 18)) {
if (!DNA_struct_elem_find(fd->filesdna, "Material", "float", "roughness")) {
for (Material *mat = bmain->mat.first; mat; mat = mat->id.next) {
if (mat->use_nodes) {
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index ac1dd071a29..69c96eed3f3 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -479,4 +479,4 @@ void CLOSURE_NAME(
#ifdef CLOSURE_SUBSURFACE
#undef CLOSURE_SUBSURFACE
-#endif \ No newline at end of file
+#endif
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index db718da12ef..a162a863038 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -1080,6 +1080,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)
{
@@ -1210,6 +1217,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;
}
}
diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl
index 1a07b26ff4d..3affacf5203 100644
--- a/source/blender/gpu/shaders/gpu_shader_material.glsl
+++ b/source/blender/gpu/shaders/gpu_shader_material.glsl
@@ -1203,14 +1203,12 @@ void node_bsdf_refraction(vec4 color, float roughness, float ior, vec3 N, out Cl
result.ssr_id = REFRACT_CLOSURE_FLAG;
}
-void node_ambient_occlusion(vec4 color, vec3 vN, out Closure result)
+void node_ambient_occlusion(vec4 color, float distance, vec3 normal, out vec4 result_color, out float result_ao)
{
vec3 bent_normal;
vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0);
- float final_ao = occlusion_compute(normalize(worldNormal), viewPosition, 1.0, rand, bent_normal);
- result = CLOSURE_DEFAULT;
- result.ssr_normal = normal_encode(vN, viewCameraVec);
- result.radiance = final_ao * color.rgb;
+ result_ao = occlusion_compute(normalize(normal), viewPosition, 1.0, rand, bent_normal);
+ result_color = result_ao * color;
}
#endif /* VOLUMETRICS */
diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 7d8d1883100..4dd2579883b 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1043,6 +1043,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
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 3790dffec3b..56065df45bb 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -4398,6 +4398,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[] = {
diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h
index 437093a9cb3..ec4e88768de 100644
--- a/source/blender/nodes/NOD_static_types.h
+++ b/source/blender/nodes/NOD_static_types.h
@@ -71,7 +71,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", "" )
diff --git a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
index f835822469c..eae35b4cd22 100644
--- a/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
+++ b/source/blender/nodes/shader/nodes/node_shader_ambient_occlusion.c
@@ -31,17 +31,29 @@
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, "" }
};
static int node_shader_gpu_ambient_occlusion(GPUMaterial *mat, bNode *node, bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out)
{
- return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out, GPU_builtin(GPU_VIEW_NORMAL));
+ if (!in[2].link)
+ GPU_link(mat, "world_normals_get", &in[2].link);
+
+ return GPU_stack_link(mat, node, "node_ambient_occlusion", in, out);
+}
+
+static void node_shader_init_ambient_occlusion(bNodeTree *UNUSED(ntree), bNode *node)
+{
+ node->custom1 = 8; /* samples */
+ node->custom2 = SHD_AO_LOCAL;
}
/* node type definition */
@@ -49,10 +61,10 @@ 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);