Merge branch 'master' into blender2.8
The Eevee AO node supports the new Normal socket, but ignores Distance, Samples, Inside and Only Local settings.
This commit is contained in:
commit
01f576e87b
Notes:
blender-bot
2023-02-14 10:14:07 +01:00
Referenced by issue #55489, 2.8 crash on startup
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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++,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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_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_INT(samples, "Samples", 8);
|
||||
|
||||
SOCKET_OUT_CLOSURE(AO, "AO");
|
||||
SOCKET_IN_COLOR(color, "Color", make_float3(0.8f, 0.8f, 0.8f));
|
||||
SOCKET_IN_FLOAT(distance, "Distance", 1.0f);
|
||||
SOCKET_IN_NORMAL(normal, "Normal", make_float3(0.0f, 0.0f, 0.0f), SocketType::LINK_NORMAL);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -479,4 +479,4 @@ void CLOSURE_NAME(
|
|||
|
||||
#ifdef CLOSURE_SUBSURFACE
|
||||
#undef CLOSURE_SUBSURFACE
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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", "" )
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue