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:
Brecht Van Lommel 2018-06-15 23:04:35 +02:00
commit 01f576e87b
Notes: blender-bot 2023-02-14 10:14:07 +01:00
Referenced by issue #55489, 2.8 crash on startup
36 changed files with 411 additions and 168 deletions

View File

@ -271,6 +271,40 @@ def custom_bake_remap(scene):
scene.render.bake.use_pass_indirect = False
def ambient_occlusion_node_relink(material, nodetree, traversed):
if nodetree in traversed:
return
traversed.add(nodetree)
for node in nodetree.nodes:
if node.bl_idname == 'ShaderNodeAmbientOcclusion':
node.samples = 1
node.only_local = False
node.inputs['Distance'].default_value = 0.0
elif node.bl_idname == 'ShaderNodeGroup':
ambient_occlusion_node_relink(material, node.node_tree, traversed)
# Gather links to replace
ao_links = []
for link in nodetree.links:
if link.from_node.bl_idname == 'ShaderNodeAmbientOcclusion':
ao_links.append(link)
# Replace links
for link in ao_links:
from_node = link.from_node
to_socket = link.to_socket
nodetree.links.remove(link)
nodetree.links.new(from_node.outputs['Color'], to_socket)
def ambient_occlusion_nodes_relink():
traversed = set()
for material in bpy.data.materials:
if check_is_new_shading_material(material):
ambient_occlusion_node_relink(material, material.node_tree, traversed)
@persistent
def do_versions(self):
if bpy.context.user_preferences.version <= (2, 78, 1):
@ -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()

View File

@ -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();

View File

@ -160,6 +160,7 @@ set(SRC_CLOSURE_HEADERS
set(SRC_SVM_HEADERS
svm/svm.h
svm/svm_ao.h
svm/svm_attribute.h
svm/svm_bevel.h
svm/svm_blackbody.h

View File

@ -203,7 +203,7 @@ ccl_device_intersect bool scene_intersect(KernelGlobals *kg,
#ifdef __BVH_LOCAL__
/* Note: ray is passed by value to work around a possible CUDA compiler bug. */
ccl_device_intersect void scene_intersect_local(KernelGlobals *kg,
ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
const Ray ray,
LocalIntersection *local_isect,
int local_object,

View File

@ -41,7 +41,7 @@ ccl_device
#else
ccl_device_inline
#endif
void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
const Ray *ray,
LocalIntersection *local_isect,
int local_object,
@ -70,7 +70,11 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
int object = OBJECT_NONE;
float isect_t = ray->t;
local_isect->num_hits = 0;
if(local_isect) {
local_isect->num_hits = 0;
}
kernel_assert((local_isect == NULL) == (max_hits == 0));
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
@ -194,16 +198,18 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* intersect ray against primitive */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
if(triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits)) {
return true;
}
}
break;
}
@ -212,17 +218,19 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
/* intersect ray against primitive */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
if(motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits)) {
return true;
}
}
break;
}
@ -234,9 +242,11 @@ void BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg,
}
} while(node_addr != ENTRYPOINT_SENTINEL);
} while(node_addr != ENTRYPOINT_SENTINEL);
return false;
}
ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
ccl_device_inline bool BVH_FUNCTION_NAME(KernelGlobals *kg,
const Ray *ray,
LocalIntersection *local_isect,
int local_object,
@ -262,6 +272,7 @@ ccl_device_inline void BVH_FUNCTION_NAME(KernelGlobals *kg,
max_hits);
}
kernel_assert(!"Should not happen");
return false;
}
#undef BVH_FUNCTION_NAME

View File

@ -29,7 +29,7 @@
# define NODE_INTERSECT qbvh_aligned_node_intersect
#endif
ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
const Ray *ray,
LocalIntersection *local_isect,
int local_object,
@ -59,7 +59,11 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
int object = OBJECT_NONE;
float isect_t = ray->t;
local_isect->num_hits = 0;
if(local_isect) {
local_isect->num_hits = 0;
}
kernel_assert((local_isect == NULL) == (max_hits == 0));
const int object_flag = kernel_tex_fetch(__object_flag, local_object);
if(!(object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
@ -81,7 +85,7 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
#ifndef __KERNEL_SSE41__
if(!isfinite(P.x)) {
return;
return false;
}
#endif
@ -250,16 +254,18 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Intersect ray against primitive, */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
if(triangle_intersect_local(kg,
local_isect,
P,
dir,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits)) {
return true;
}
}
break;
}
@ -268,17 +274,19 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
/* Intersect ray against primitive. */
for(; prim_addr < prim_addr2; prim_addr++) {
kernel_assert(kernel_tex_fetch(__prim_type, prim_addr) == type);
motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits);
if(motion_triangle_intersect_local(kg,
local_isect,
P,
dir,
ray->time,
object,
local_object,
prim_addr,
isect_t,
lcg_state,
max_hits)) {
return true;
}
}
break;
}
@ -289,6 +297,8 @@ ccl_device void BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg,
}
} while(node_addr != ENTRYPOINT_SENTINEL);
} while(node_addr != ENTRYPOINT_SENTINEL);
return false;
}
#undef NODE_INTERSECT

View File

@ -218,9 +218,10 @@ ccl_device_inline bool motion_triangle_intersect(
/* Special ray intersection routines for local intersections. In that case we
* only want to intersect with primitives in the same object, and if case of
* multiple hits we pick a single random primitive as the intersection point.
* Returns whether traversal should be stopped.
*/
#ifdef __BVH_LOCAL__
ccl_device_inline void motion_triangle_intersect_local(
ccl_device_inline bool motion_triangle_intersect_local(
KernelGlobals *kg,
LocalIntersection *local_isect,
float3 P,
@ -237,7 +238,7 @@ ccl_device_inline void motion_triangle_intersect_local(
* already know we are only intersecting the right object. */
if(object == OBJECT_NONE) {
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
return;
return false;
}
}
@ -258,7 +259,12 @@ ccl_device_inline void motion_triangle_intersect_local(
#endif
&u, &v, &t))
{
return;
return false;
}
/* If no actual hit information is requested, just return here. */
if(max_hits == 0) {
return true;
}
int hit;
@ -266,7 +272,7 @@ ccl_device_inline void motion_triangle_intersect_local(
/* Record up to max_hits intersections. */
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if(local_isect->hits[i].t == t) {
return;
return false;
}
}
@ -282,13 +288,13 @@ ccl_device_inline void motion_triangle_intersect_local(
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
if(hit >= max_hits)
return;
return false;
}
}
else {
/* Record closest intersection only. */
if(local_isect->num_hits && t > local_isect->hits[0].t) {
return;
return false;
}
hit = 0;
@ -307,6 +313,8 @@ ccl_device_inline void motion_triangle_intersect_local(
/* Record geometric normal. */
local_isect->Ng[hit] = normalize(cross(verts[1] - verts[0],
verts[2] - verts[0]));
return false;
}
#endif /* __BVH_LOCAL__ */

View File

@ -73,10 +73,11 @@ ccl_device_inline bool triangle_intersect(KernelGlobals *kg,
/* Special ray intersection routines for local intersection. In that case we
* only want to intersect with primitives in the same object, and if case of
* multiple hits we pick a single random primitive as the intersection point.
* Returns whether traversal should be stopped.
*/
#ifdef __BVH_LOCAL__
ccl_device_inline void triangle_intersect_local(
ccl_device_inline bool triangle_intersect_local(
KernelGlobals *kg,
LocalIntersection *local_isect,
float3 P,
@ -92,7 +93,7 @@ ccl_device_inline void triangle_intersect_local(
* already know we are only intersecting the right object. */
if(object == OBJECT_NONE) {
if(kernel_tex_fetch(__prim_object, prim_addr) != local_object) {
return;
return false;
}
}
@ -115,7 +116,12 @@ ccl_device_inline void triangle_intersect_local(
#endif
&u, &v, &t))
{
return;
return false;
}
/* If no actual hit information is requested, just return here. */
if(max_hits == 0) {
return true;
}
int hit;
@ -123,7 +129,7 @@ ccl_device_inline void triangle_intersect_local(
/* Record up to max_hits intersections. */
for(int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
if(local_isect->hits[i].t == t) {
return;
return false;
}
}
@ -138,13 +144,13 @@ ccl_device_inline void triangle_intersect_local(
hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
if(hit >= max_hits)
return;
return false;
}
}
else {
/* Record closest intersection only. */
if(local_isect->num_hits && t > local_isect->hits[0].t) {
return;
return false;
}
hit = 0;
@ -167,6 +173,8 @@ ccl_device_inline void triangle_intersect_local(
tri_c = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex+2));
#endif
local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
return false;
}
#endif /* __BVH_LOCAL__ */

View File

@ -491,7 +491,7 @@ ccl_device void kernel_path_indirect(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
if(kernel_data.integrator.use_ambient_occlusion) {
kernel_path_ao(kg, sd, emission_sd, L, state, throughput, make_float3(0.0f, 0.0f, 0.0f));
}
#endif /* __AO__ */
@ -661,7 +661,7 @@ ccl_device_forceinline void kernel_path_integrate(
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
if(kernel_data.integrator.use_ambient_occlusion) {
kernel_path_ao(kg, &sd, emission_sd, L, state, throughput, shader_bsdf_alpha(kg, &sd));
}
#endif /* __AO__ */

View File

@ -526,7 +526,7 @@ ccl_device void kernel_branched_path_integrate(KernelGlobals *kg,
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) {
if(kernel_data.integrator.use_ambient_occlusion) {
kernel_branched_path_ao(kg, &sd, emission_sd, L, &state, throughput);
}
#endif /* __AO__ */

View File

@ -914,10 +914,6 @@ ccl_device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_fac
eval += sc->weight*ao_factor;
N += bsdf->N*fabsf(average(sc->weight));
}
else if(CLOSURE_IS_AMBIENT_OCCLUSION(sc->type)) {
eval += sc->weight;
N += sd->N*fabsf(average(sc->weight));
}
}
*N_ = (is_zero(N))? sd->N : normalize(N);

View File

@ -881,8 +881,6 @@ enum ShaderDataFlag {
SD_EXTINCTION = (1 << 6),
/* Shader has have volume phase (scatter) closure. */
SD_SCATTER = (1 << 7),
/* Shader has AO closure. */
SD_AO = (1 << 8),
/* Shader has transparent closure. */
SD_TRANSPARENT = (1 << 9),
/* BSDF requires LCG for evaluation. */
@ -895,7 +893,6 @@ enum ShaderDataFlag {
SD_HOLDOUT |
SD_EXTINCTION |
SD_SCATTER |
SD_AO |
SD_BSDF_NEEDS_LCG),
/* Shader flags. */

View File

@ -74,21 +74,6 @@ public:
}
};
/// ambient occlusion closure
///
/// We only have a ambient occlusion closure for the shaders
/// to return a color in ambient occlusion shaders. No methods,
/// only the weight is taking into account
///
class AmbientOcclusionClosure : public CClosurePrimitive {
public:
void setup(ShaderData *sd, int /* path_flag */, float3 weight)
{
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, weight);
sd->flag |= SD_AO;
}
};
ClosureParam *closure_background_params()
{
static ClosureParam params[] = {
@ -110,16 +95,5 @@ ClosureParam *closure_holdout_params()
CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
ClosureParam *closure_ambient_occlusion_params()
{
static ClosureParam params[] = {
CLOSURE_STRING_KEYPARAM(AmbientOcclusionClosure, label, "label"),
CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
};
return params;
}
CCLOSURE_PREPARE(closure_ambient_occlusion_prepare, AmbientOcclusionClosure)
CCL_NAMESPACE_END

View File

@ -310,8 +310,6 @@ void OSLShader::register_closures(OSLShadingSystem *ss_)
closure_background_params(), closure_background_prepare);
register_closure(ss, "holdout", id++,
closure_holdout_params(), closure_holdout_prepare);
register_closure(ss, "ambient_occlusion", id++,
closure_ambient_occlusion_params(), closure_ambient_occlusion_prepare);
register_closure(ss, "diffuse_ramp", id++,
closure_bsdf_diffuse_ramp_params(), closure_bsdf_diffuse_ramp_prepare);
register_closure(ss, "phong_ramp", id++,

View File

@ -45,7 +45,6 @@ CCL_NAMESPACE_BEGIN
OSL::ClosureParam *closure_emission_params();
OSL::ClosureParam *closure_background_params();
OSL::ClosureParam *closure_holdout_params();
OSL::ClosureParam *closure_ambient_occlusion_params();
OSL::ClosureParam *closure_bsdf_diffuse_ramp_params();
OSL::ClosureParam *closure_bsdf_phong_ramp_params();
OSL::ClosureParam *closure_bsdf_transparent_params();
@ -65,7 +64,6 @@ OSL::ClosureParam *closure_bsdf_principled_clearcoat_params();
void closure_emission_prepare(OSL::RendererServices *, int id, void *data);
void closure_background_prepare(OSL::RendererServices *, int id, void *data);
void closure_holdout_prepare(OSL::RendererServices *, int id, void *data);
void closure_ambient_occlusion_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data);
void closure_bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data);

View File

@ -125,6 +125,7 @@ ustring OSLRenderServices::u_u("u");
ustring OSLRenderServices::u_v("v");
ustring OSLRenderServices::u_empty;
ustring OSLRenderServices::u_at_bevel("@bevel");
ustring OSLRenderServices::u_at_ao("@ao");
OSLRenderServices::OSLRenderServices()
{
@ -957,6 +958,25 @@ bool OSLRenderServices::texture(ustring filename,
status = true;
}
}
else if(filename == u_at_ao) {
/* AO shader hack. */
PathState *state = sd->osl_path_state;
int num_samples = (int)s;
float radius = t;
float3 N = make_float3(dsdx, dtdx, dsdy);
int flags = 0;
if((int)dtdy) {
flags |= NODE_AO_INSIDE;
}
if((int)options.sblur) {
flags |= NODE_AO_ONLY_LOCAL;
}
if((int)options.tblur) {
flags |= NODE_AO_GLOBAL_RADIUS;
}
result[0] = svm_ao(kg, sd, N, state, radius, num_samples, flags);
status = true;
}
else if(filename[1] == 'l') {
/* IES light. */
int slot = atoi(filename.c_str() + 2);

View File

@ -182,6 +182,7 @@ public:
static ustring u_v;
static ustring u_empty;
static ustring u_at_bevel;
static ustring u_at_ao;
private:
KernelGlobals *kernel_globals;

View File

@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 Blender Foundation
* Copyright 2011-2018 Blender Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -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;
}

View File

@ -149,7 +149,7 @@ ccl_device void kernel_holdout_emission_blurring_pathtermination_ao(
#ifdef __AO__
if(IS_STATE(ray_state, ray_index, RAY_ACTIVE)) {
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) {
if(kernel_data.integrator.use_ambient_occlusion) {
enqueue_flag = 1;
}
}

View File

@ -144,6 +144,7 @@ CCL_NAMESPACE_END
#include "kernel/svm/svm_color_util.h"
#include "kernel/svm/svm_math_util.h"
#include "kernel/svm/svm_ao.h"
#include "kernel/svm/svm_attribute.h"
#include "kernel/svm/svm_gradient.h"
#include "kernel/svm/svm_blackbody.h"
@ -324,9 +325,6 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
case NODE_CLOSURE_HOLDOUT:
svm_node_closure_holdout(sd, stack, node);
break;
case NODE_CLOSURE_AMBIENT_OCCLUSION:
svm_node_closure_ambient_occlusion(sd, stack, node);
break;
case NODE_FRESNEL:
svm_node_fresnel(sd, stack, node.y, node.z, node.w);
break;
@ -480,6 +478,9 @@ ccl_device_noinline void svm_eval_nodes(KernelGlobals *kg, ShaderData *sd, ccl_a
case NODE_BEVEL:
svm_node_bevel(kg, sd, state, stack, node);
break;
case NODE_AMBIENT_OCCLUSION:
svm_node_ao(kg, sd, state, stack, node);
break;
# endif /* __SHADER_RAYTRACE__ */
#endif /* NODES_GROUP(NODE_GROUP_LEVEL_3) */
case NODE_END:

View File

@ -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

View File

@ -996,24 +996,6 @@ ccl_device void svm_node_closure_holdout(ShaderData *sd, float *stack, uint4 nod
sd->flag |= SD_HOLDOUT;
}
ccl_device void svm_node_closure_ambient_occlusion(ShaderData *sd, float *stack, uint4 node)
{
uint mix_weight_offset = node.y;
if(stack_valid(mix_weight_offset)) {
float mix_weight = stack_load_float(stack, mix_weight_offset);
if(mix_weight == 0.0f)
return;
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight * mix_weight);
}
else
closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_AMBIENT_OCCLUSION_ID, sd->svm_closure_weight);
sd->flag |= SD_AO;
}
/* Closure Nodes */
ccl_device_inline void svm_node_closure_store_weight(ShaderData *sd, float3 weight)

View File

@ -124,7 +124,7 @@ typedef enum ShaderNodeType {
NODE_PARTICLE_INFO,
NODE_TEX_BRICK,
NODE_CLOSURE_SET_NORMAL,
NODE_CLOSURE_AMBIENT_OCCLUSION,
NODE_AMBIENT_OCCLUSION,
NODE_TANGENT,
NODE_NORMAL_MAP,
NODE_HAIR_INFO,
@ -386,6 +386,12 @@ typedef enum NodeTexVoxelSpace {
NODE_TEX_VOXEL_SPACE_WORLD = 1,
} NodeTexVoxelSpace;
typedef enum NodeAO {
NODE_AO_ONLY_LOCAL = (1 << 0),
NODE_AO_INSIDE = (1 << 1),
NODE_AO_GLOBAL_RADIUS = (1 << 2),
} NodeAO;
typedef enum ShaderType {
SHADER_TYPE_SURFACE,
SHADER_TYPE_VOLUME,
@ -456,7 +462,6 @@ typedef enum ClosureType {
/* Other */
CLOSURE_HOLDOUT_ID,
CLOSURE_AMBIENT_OCCLUSION_ID,
/* Volume */
CLOSURE_VOLUME_ID,
@ -491,7 +496,6 @@ typedef enum ClosureType {
#define CLOSURE_IS_VOLUME_SCATTER(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_VOLUME_ABSORPTION(type) (type == CLOSURE_VOLUME_ABSORPTION_ID)
#define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID)
#define CLOSURE_IS_AMBIENT_OCCLUSION(type) (type == CLOSURE_AMBIENT_OCCLUSION_ID)
#define CLOSURE_IS_PHASE(type) (type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID)
#define CLOSURE_IS_GLASS(type) (type >= CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID)
#define CLOSURE_IS_PRINCIPLED(type) (type == CLOSURE_BSDF_PRINCIPLED_ID)

View File

@ -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");
}

View File

@ -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 {

View File

@ -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),

View File

@ -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

View File

@ -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) {

View File

@ -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) {

View File

@ -479,4 +479,4 @@ void CLOSURE_NAME(
#ifdef CLOSURE_SUBSURFACE
#undef CLOSURE_SUBSURFACE
#endif
#endif

View File

@ -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;
}
}

View File

@ -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 */

View File

@ -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

View File

@ -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[] = {

View File

@ -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", "" )

View File

@ -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);