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
path: root/intern
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2018-06-16 00:04:35 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-06-16 00:16:49 +0300
commit01f576e87b54159bb360cf1ed85518bb75231107 (patch)
tree0ac38f90154f8ee08a35fb88c5cf742403bbcb3c /intern
parent469408de725353b461d073097d88b6b810c16c38 (diff)
parent799779d432309e518922d23e3a1d1b5baaece71d (diff)
Merge branch 'master' into blender2.8
The Eevee AO node supports the new Normal socket, but ignores Distance, Samples, Inside and Only Local settings.
Diffstat (limited to 'intern')
-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
25 files changed, 350 insertions, 152 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 {