Blender  V3.3
cycles/kernel/light/sample.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
8 
9 #include "kernel/light/light.h"
10 
11 #include "kernel/sample/mapping.h"
12 #include "kernel/sample/mis.h"
13 
15 
16 /* Evaluate shader on light. */
20  ccl_private ShaderData *ccl_restrict emission_sd,
22  float time)
23 {
24  /* setup shading at emitter */
25  float3 eval = zero_float3();
26 
27  if (shader_constant_emission_eval(kg, ls->shader, &eval)) {
28  if ((ls->prim != PRIM_NONE) && dot(ls->Ng, ls->D) > 0.0f) {
29  ls->Ng = -ls->Ng;
30  }
31  }
32  else {
33  /* Setup shader data and call shader_eval_surface once, better
34  * for GPU coherence and compile times. */
36 #ifdef __BACKGROUND_MIS__
37  if (ls->type == LIGHT_BACKGROUND) {
38  shader_setup_from_background(kg, emission_sd, ls->P, ls->D, time);
39  }
40  else
41 #endif
42  {
44  emission_sd,
45  ls->P,
46  ls->Ng,
47  -ls->D,
48  ls->shader,
49  ls->object,
50  ls->prim,
51  ls->u,
52  ls->v,
53  ls->t,
54  time,
55  false,
56  ls->lamp);
57 
58  ls->Ng = emission_sd->Ng;
59  }
60 
61  PROFILING_SHADER(emission_sd->object, emission_sd->shader);
63 
64  /* No proper path flag, we're evaluating this for all closures. that's
65  * weak but we'd have to do multiple evaluations otherwise. */
66  shader_eval_surface<KERNEL_FEATURE_NODE_MASK_SURFACE_LIGHT>(
67  kg, state, emission_sd, NULL, PATH_RAY_EMISSION);
68 
69  /* Evaluate closures. */
70 #ifdef __BACKGROUND_MIS__
71  if (ls->type == LIGHT_BACKGROUND) {
72  eval = shader_background_eval(emission_sd);
73  }
74  else
75 #endif
76  {
77  eval = shader_emissive_eval(emission_sd);
78  }
79  }
80 
81  eval *= ls->eval_fac;
82 
83  if (ls->lamp != LAMP_NONE) {
84  ccl_global const KernelLight *klight = &kernel_data_fetch(lights, ls->lamp);
85  eval *= make_float3(klight->strength[0], klight->strength[1], klight->strength[2]);
86  }
87 
88  return eval;
89 }
90 
91 /* Test if light sample is from a light or emission from geometry. */
93 {
94  /* return if it's a lamp for shadow pass */
95  return (ls->prim == PRIM_NONE && ls->type != LIGHT_BACKGROUND);
96 }
97 
98 /* Early path termination of shadow rays. */
102  const float rand_terminate)
103 {
104  if (bsdf_eval_is_zero(eval)) {
105  return true;
106  }
107 
108  if (kernel_data.integrator.light_inv_rr_threshold > 0.0f) {
109  float probability = reduce_max(fabs(bsdf_eval_sum(eval))) *
110  kernel_data.integrator.light_inv_rr_threshold;
111  if (probability < 1.0f) {
112  if (rand_terminate >= probability) {
113  return true;
114  }
115  bsdf_eval_mul(eval, 1.0f / probability);
116  }
117  }
118 
119  return false;
120 }
121 
122 /* This function should be used to compute a modified ray start position for
123  * rays leaving from a surface. The algorithm slightly distorts flat surface
124  * of a triangle. Surface is lifted by amount h along normal n in the incident
125  * point. */
126 
129 {
130  float3 V[3], N[3];
131 
132  if (sd->type == PRIMITIVE_MOTION_TRIANGLE) {
133  motion_triangle_vertices_and_normals(kg, sd->object, sd->prim, sd->time, V, N);
134  }
135  else {
136  kernel_assert(sd->type == PRIMITIVE_TRIANGLE);
137  triangle_vertices_and_normals(kg, sd->prim, V, N);
138  }
139 
140  const float u = 1.0f - sd->u - sd->v;
141  const float v = sd->u;
142  const float w = sd->v;
143  float3 P = V[0] * u + V[1] * v + V[2] * w; /* Local space */
144  float3 n = N[0] * u + N[1] * v + N[2] * w; /* We get away without normalization */
145 
146  if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
147  object_dir_transform(kg, sd, &n); /* Normal x scale, to world space */
148  }
149 
150  /* Parabolic approximation */
151  float a = dot(N[2] - N[0], V[0] - V[2]);
152  float b = dot(N[2] - N[1], V[1] - V[2]);
153  float c = dot(N[1] - N[0], V[1] - V[0]);
154  float h = a * u * (u - 1) + (a + b + c) * u * v + b * v * (v - 1);
155 
156  /* Check flipped normals */
157  if (dot(n, Ng) > 0) {
158  /* Local linear envelope */
159  float h0 = max(max(dot(V[1] - V[0], N[0]), dot(V[2] - V[0], N[0])), 0.0f);
160  float h1 = max(max(dot(V[0] - V[1], N[1]), dot(V[2] - V[1], N[1])), 0.0f);
161  float h2 = max(max(dot(V[0] - V[2], N[2]), dot(V[1] - V[2], N[2])), 0.0f);
162  h0 = max(dot(V[0] - P, N[0]) + h0, 0.0f);
163  h1 = max(dot(V[1] - P, N[1]) + h1, 0.0f);
164  h2 = max(dot(V[2] - P, N[2]) + h2, 0.0f);
165  h = max(min(min(h0, h1), h2), h * 0.5f);
166  }
167  else {
168  float h0 = max(max(dot(V[0] - V[1], N[0]), dot(V[0] - V[2], N[0])), 0.0f);
169  float h1 = max(max(dot(V[1] - V[0], N[1]), dot(V[1] - V[2], N[1])), 0.0f);
170  float h2 = max(max(dot(V[2] - V[0], N[2]), dot(V[2] - V[1], N[2])), 0.0f);
171  h0 = max(dot(P - V[0], N[0]) + h0, 0.0f);
172  h1 = max(dot(P - V[1], N[1]) + h1, 0.0f);
173  h2 = max(dot(P - V[2], N[2]) + h2, 0.0f);
174  h = min(-min(min(h0, h1), h2), h * 0.5f);
175  }
176 
177  return n * h;
178 }
179 
180 /* Ray offset to avoid shadow terminator artifact. */
181 
184  float3 L,
185  ccl_private bool *r_skip_self)
186 {
187  float3 P = sd->P;
188 
189  if ((sd->type & PRIMITIVE_TRIANGLE) && (sd->shader & SHADER_SMOOTH_NORMAL)) {
190  const float offset_cutoff =
191  kernel_data_fetch(objects, sd->object).shadow_terminator_geometry_offset;
192  /* Do ray offset (heavy stuff) only for close to be terminated triangles:
193  * offset_cutoff = 0.1f means that 10-20% of rays will be affected. Also
194  * make a smooth transition near the threshold. */
195  if (offset_cutoff > 0.0f) {
196  float NL = dot(sd->N, L);
197  const bool transmit = (NL < 0.0f);
198  if (NL < 0) {
199  NL = -NL;
200  }
201 
202  const float3 Ng = (transmit ? -sd->Ng : sd->Ng);
203  const float NgL = dot(Ng, L);
204 
205  const float offset_amount = (NL < offset_cutoff) ?
206  clamp(2.0f - (NgL + NL) / offset_cutoff, 0.0f, 1.0f) :
207  clamp(1.0f - NgL / offset_cutoff, 0.0f, 1.0f);
208 
209  if (offset_amount > 0.0f) {
210  P += shadow_ray_smooth_surface_offset(kg, sd, Ng) * offset_amount;
211 
212  /* Only skip self intersections if light direction and geometric normal point in the same
213  * direction, otherwise we're meant to hit this surface. */
214  *r_skip_self = (NgL > 0.0f);
215  }
216  }
217  }
218 
219  return P;
220 }
221 
224  const float3 P,
225  ccl_private Ray *ray,
226  const bool skip_self)
227 {
228  if (ls->shader & SHADER_CAST_SHADOW) {
229  /* setup ray */
230  ray->P = P;
231  ray->tmin = 0.0f;
232 
233  if (ls->t == FLT_MAX) {
234  /* distant light */
235  ray->D = ls->D;
236  ray->tmax = ls->t;
237  }
238  else {
239  /* other lights, avoid self-intersection */
240  ray->D = ls->P - P;
241  ray->D = normalize_len(ray->D, &ray->tmax);
242  }
243  }
244  else {
245  /* signal to not cast shadow ray */
246  ray->P = zero_float3();
247  ray->D = zero_float3();
248  ray->tmax = 0.0f;
249  }
250 
251  ray->dP = differential_make_compact(sd->dP);
252  ray->dD = differential_zero_compact();
253  ray->time = sd->time;
254 
255  /* Fill in intersection surface and light details. */
256  ray->self.object = (skip_self) ? sd->object : OBJECT_NONE;
257  ray->self.prim = (skip_self) ? sd->prim : PRIM_NONE;
258  ray->self.light_object = ls->object;
259  ray->self.light_prim = ls->prim;
260 }
261 
262 /* Create shadow ray towards light sample. */
264  KernelGlobals kg,
267  ccl_private Ray *ray)
268 {
269  bool skip_self = true;
270  const float3 P = shadow_ray_offset(kg, sd, ls->D, &skip_self);
271  shadow_ray_setup(sd, ls, P, ray, skip_self);
272 }
273 
274 /* Create shadow ray towards light sample. */
276  KernelGlobals kg,
279  const float3 P,
280  ccl_private Ray *ray)
281 {
282  shadow_ray_setup(sd, ls, P, ray, false);
283 }
284 
286  const float forward_pdf,
287  const float nee_pdf)
288 {
289 #ifdef WITH_CYCLES_DEBUG
290  if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_FORWARD) {
291  return 1.0f;
292  }
293  else if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_NEE) {
294  return 0.0f;
295  }
296  else
297 #endif
298  return power_heuristic(forward_pdf, nee_pdf);
299 }
300 
302  const float nee_pdf,
303  const float forward_pdf)
304 {
305 #ifdef WITH_CYCLES_DEBUG
306  if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_FORWARD) {
307  return 0.0f;
308  }
309  else if (kernel_data.integrator.direct_light_sampling_type == DIRECT_LIGHT_SAMPLING_NEE) {
310  return 1.0f;
311  }
312  else
313 #endif
314  return power_heuristic(nee_pdf, forward_pdf);
315 }
316 
ccl_device_inline void bsdf_eval_mul(ccl_private BsdfEval *eval, float value)
Definition: accumulate.h:58
ccl_device_inline bool bsdf_eval_is_zero(ccl_private BsdfEval *eval)
Definition: accumulate.h:53
ccl_device_inline float3 bsdf_eval_sum(ccl_private const BsdfEval *eval)
Definition: accumulate.h:72
__forceinline int reduce_max(const avxi &v)
Definition: avxi.h:692
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_restrict
Definition: cuda/compat.h:50
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_noinline_cpu
Definition: cuda/compat.h:41
#define ccl_device_inline
Definition: cuda/compat.h:34
#define ccl_global
Definition: cuda/compat.h:43
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device_inline float light_sample_mis_weight_forward(KernelGlobals kg, const float forward_pdf, const float nee_pdf)
ccl_device_inline float light_sample_mis_weight_nee(KernelGlobals kg, const float nee_pdf, const float forward_pdf)
CCL_NAMESPACE_BEGIN ccl_device_noinline_cpu float3 light_sample_shader_eval(KernelGlobals kg, IntegratorState state, ccl_private ShaderData *ccl_restrict emission_sd, ccl_private LightSample *ccl_restrict ls, float time)
ccl_device_inline float3 shadow_ray_offset(KernelGlobals kg, ccl_private const ShaderData *ccl_restrict sd, float3 L, ccl_private bool *r_skip_self)
ccl_device_inline void light_sample_to_volume_shadow_ray(KernelGlobals kg, ccl_private const ShaderData *ccl_restrict sd, ccl_private const LightSample *ccl_restrict ls, const float3 P, ccl_private Ray *ray)
ccl_device_inline float3 shadow_ray_smooth_surface_offset(KernelGlobals kg, ccl_private const ShaderData *ccl_restrict sd, float3 Ng)
ccl_device_inline void shadow_ray_setup(ccl_private const ShaderData *ccl_restrict sd, ccl_private const LightSample *ccl_restrict ls, const float3 P, ccl_private Ray *ray, const bool skip_self)
ccl_device_inline bool light_sample_is_light(ccl_private const LightSample *ccl_restrict ls)
ccl_device_inline void light_sample_to_surface_shadow_ray(KernelGlobals kg, ccl_private const ShaderData *ccl_restrict sd, ccl_private const LightSample *ccl_restrict ls, ccl_private Ray *ray)
ccl_device_inline bool light_sample_terminate(KernelGlobals kg, ccl_private const LightSample *ccl_restrict ls, ccl_private BsdfEval *ccl_restrict eval, const float rand_terminate)
#define NL
double time
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
ccl_device_forceinline float differential_make_compact(const differential3 D)
Definition: differential.h:117
ccl_device_forceinline float differential_zero_compact()
Definition: differential.h:112
const int state
ccl_device_inline void object_dir_transform(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private float3 *D)
ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd)
ccl_device float3 shader_background_eval(ccl_private const ShaderData *sd)
ccl_device bool shader_constant_emission_eval(KernelGlobals kg, int shader, ccl_private float3 *eval)
@ PRIMITIVE_MOTION_TRIANGLE
Definition: kernel/types.h:559
@ PRIMITIVE_TRIANGLE
Definition: kernel/types.h:551
@ DIRECT_LIGHT_SAMPLING_NEE
Definition: kernel/types.h:497
@ DIRECT_LIGHT_SAMPLING_FORWARD
Definition: kernel/types.h:496
#define PRIM_NONE
Definition: kernel/types.h:41
@ PATH_RAY_EMISSION
Definition: kernel/types.h:255
#define OBJECT_NONE
Definition: kernel/types.h:40
ShaderData
Definition: kernel/types.h:925
@ SHADER_SMOOTH_NORMAL
Definition: kernel/types.h:435
@ SHADER_CAST_SHADOW
Definition: kernel/types.h:436
@ SD_OBJECT_TRANSFORM_APPLIED
Definition: kernel/types.h:808
@ LIGHT_BACKGROUND
Definition: kernel/types.h:458
#define LAMP_NONE
Definition: kernel/types.h:42
#define PROFILING_INIT_FOR_SHADER(kg, event)
#define PROFILING_EVENT(event)
#define PROFILING_SHADER(object, shader)
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
static float P(float k)
Definition: math_interp.c:25
#define N
#define L
#define make_float3(x, y, z)
Definition: metal/compat.h:204
ccl_device float power_heuristic(float a, float b)
Definition: mis.h:25
ccl_device_inline void motion_triangle_vertices_and_normals(KernelGlobals kg, int object, int prim, float time, float3 verts[3], float3 normals[3])
static unsigned c
Definition: RandGen.cpp:83
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T clamp(const T &a, const T &min, const T &max)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
ccl_device_inline void shader_setup_from_sample(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 P, const float3 Ng, const float3 I, int shader, int object, int prim, float u, float v, float t, float time, bool object_space, int lamp)
Definition: shader_data.h:134
ccl_device_inline void shader_setup_from_background(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, const float3 ray_P, const float3 ray_D, const float ray_time)
Definition: shader_data.h:360
#define min(a, b)
Definition: sort.c:35
IntegratorStateCPU *ccl_restrict IntegratorState
Definition: state.h:147
float max
ccl_device_inline void triangle_vertices_and_normals(KernelGlobals kg, int prim, float3 P[3], float3 N[3])
Definition: triangle.h:75
@ PROFILING_SHADE_LIGHT_SETUP
@ PROFILING_SHADE_LIGHT_EVAL
CCL_NAMESPACE_BEGIN struct Window V