diff options
Diffstat (limited to 'intern/cycles/kernel')
21 files changed, 260 insertions, 131 deletions
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) |