Blender V5.0
ao.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "kernel/globals.h"
8
10
11#include "kernel/bvh/bvh.h"
12
14
15#include "kernel/svm/util.h"
16
18
19#ifdef __SHADER_RAYTRACE__
20
21# ifdef __KERNEL_OPTIX__
22extern "C" __device__ float __direct_callable__svm_node_ao(
23# else
24ccl_device float svm_ao(
25# endif
28 ccl_private ShaderData *sd,
29 float3 N,
30 float max_dist,
31 const int num_samples,
32 const int flags)
33{
34 if (flags & NODE_AO_GLOBAL_RADIUS) {
35 max_dist = kernel_data.integrator.ao_bounces_distance;
36 }
37
38 /* Early out if no sampling needed. */
39 if (max_dist <= 0.0f || num_samples < 1 || sd->object == OBJECT_NONE) {
40 return 1.0f;
41 }
42
43 /* Can't ray-trace from shaders like displacement, before BVH exists. */
44 if (kernel_data.bvh.bvh_layout == BVH_LAYOUT_NONE) {
45 return 1.0f;
46 }
47
48 if (flags & NODE_AO_INSIDE) {
49 N = -N;
50 }
51
52 float3 T;
53 float3 B;
55
56 /* TODO: support ray-tracing in shadow shader evaluation? */
57 RNGState rng_state;
58 path_state_rng_load(state, &rng_state);
59
60 int unoccluded = 0;
61 for (int sample = 0; sample < num_samples; sample++) {
62 const float2 rand_disk = path_branched_rng_2D(
63 kg, &rng_state, sample, num_samples, PRNG_SURFACE_AO);
64
65 const float2 d = sample_uniform_disk(rand_disk);
66 const float3 D = make_float3(d.x, d.y, safe_sqrtf(1.0f - dot(d, d)));
67
68 /* Create ray. */
69 Ray ray;
70 ray.P = sd->P;
71 ray.D = to_global(D, T, B, N);
72 ray.tmin = 0.0f;
73 ray.tmax = max_dist;
74 ray.time = sd->time;
75 ray.self.object = sd->object;
76 ray.self.prim = sd->prim;
81
82 if (flags & NODE_AO_ONLY_LOCAL) {
83 if (!scene_intersect_local(kg, &ray, nullptr, sd->object, nullptr, 0)) {
84 unoccluded++;
85 }
86 }
87 else {
89 unoccluded++;
90 }
91 }
92 }
93
94 return ((float)unoccluded) / num_samples;
95}
96
97template<uint node_feature_mask, typename ConstIntegratorGenericState>
98# if defined(__KERNEL_OPTIX__)
100# else
102# endif
103 void
104 svm_node_ao(KernelGlobals kg,
105 ConstIntegratorGenericState state,
106 ccl_private ShaderData *sd,
107 ccl_private float *stack,
108 const uint4 node)
109{
110 uint flags;
111 uint dist_offset;
112 uint normal_offset;
113 uint out_ao_offset;
114 svm_unpack_node_uchar4(node.y, &flags, &dist_offset, &normal_offset, &out_ao_offset);
115
116 uint color_offset;
117 uint out_color_offset;
118 uint samples;
119 svm_unpack_node_uchar3(node.z, &color_offset, &out_color_offset, &samples);
120
121 float ao = 1.0f;
122
124 {
125 float dist = stack_load_float_default(stack, dist_offset, node.w);
126 float3 normal = stack_valid(normal_offset) ? stack_load_float3(stack, normal_offset) : sd->N;
127 normal = safe_normalize(normal);
128
129# ifdef __KERNEL_OPTIX__
130 ao = optixDirectCall<float>(0, kg, state, sd, normal, dist, samples, flags);
131# else
132 ao = svm_ao(kg, state, sd, normal, dist, samples, flags);
133# endif
134 }
135
136 if (stack_valid(out_ao_offset)) {
137 stack_store_float(stack, out_ao_offset, ao);
138 }
139
140 if (stack_valid(out_color_offset)) {
141 const float3 color = stack_load_float3(stack, color_offset);
142 stack_store_float3(stack, out_color_offset, ao * color);
143 }
144}
145
146#endif /* __SHADER_RAYTRACE__ */
147
#define D
MINLINE float safe_sqrtf(float a)
unsigned int uint
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
ccl_device_inline float stack_load_float_default(const ccl_private float *stack, const uint a, const uint value)
ccl_device_forceinline void svm_unpack_node_uchar3(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z)
ccl_device_forceinline void svm_unpack_node_uchar4(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z, ccl_private uint *w)
ccl_device_inline bool stack_valid(const uint a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
ccl_device_inline T to_global(const float2 p, const T X, const T Y)
#define kernel_data
#define IF_KERNEL_NODES_FEATURE(feature)
#define PRIM_NONE
#define OBJECT_NONE
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define ccl_device_noinline
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __device__
ccl_device_forceinline float differential_zero_compact()
ccl_device_intersect bool scene_intersect_shadow(KernelGlobals kg, const ccl_private Ray *ray, const uint visibility)
@ NODE_AO_INSIDE
@ NODE_AO_GLOBAL_RADIUS
@ NODE_AO_ONLY_LOCAL
@ PRNG_SURFACE_AO
@ PATH_RAY_SHADOW_OPAQUE
@ BVH_LAYOUT_NONE
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
static ulong state[N]
#define N
#define T
#define B
ccl_device_inline void path_state_rng_load(ConstIntegratorState state, ccl_private RNGState *rng_state)
Definition path_state.h:329
ccl_device_inline float2 path_branched_rng_2D(KernelGlobals kg, const ccl_private RNGState *rng_state, const int branch, const int num_branches, const int dimension)
Definition path_state.h:389
#define ccl_device
CCL_NAMESPACE_BEGIN ccl_device float2 sample_uniform_disk(const float2 rand)
const IntegratorStateCPU * ConstIntegratorState
Definition state.h:229
float tmax
float tmin
float dD
float3 P
float time
float dP
RaySelfPrimitives self
float3 D
float x
float y
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13