Blender V4.3
triangle_intersect.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5/* Triangle/Ray intersections.
6 *
7 * For BVH ray intersection we use a precomputed triangle storage to accelerate
8 * intersection at the cost of more memory usage.
9 */
10
11#pragma once
12
13#include "kernel/sample/lcg.h"
14
16
19 float3 P,
20 float3 dir,
21 float tmin,
22 float tmax,
23 uint visibility,
24 int object,
25 int prim,
26 int prim_addr)
27{
28 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
29 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x),
30 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y),
31 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
32
33 float t, u, v;
34 if (ray_triangle_intersect(P, dir, tmin, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) {
35#ifdef __VISIBILITY_FLAG__
36 /* Visibility flag test. we do it here under the assumption
37 * that most triangles are culled by node flags.
38 */
39 if (kernel_data_fetch(prim_visibility, prim_addr) & visibility)
40#endif
41 {
42 isect->object = object;
43 isect->prim = prim;
44 isect->type = PRIMITIVE_TRIANGLE;
45 isect->u = u;
46 isect->v = v;
47 isect->t = t;
48 return true;
49 }
50 }
51 return false;
52}
53
54/* Special ray intersection routines for subsurface scattering. In that case we
55 * only want to intersect with primitives in the same object, and if case of
56 * multiple hits we pick a single random primitive as the intersection point.
57 * Returns whether traversal should be stopped.
58 */
59
60#ifdef __BVH_LOCAL__
61ccl_device_inline bool triangle_intersect_local(KernelGlobals kg,
62 ccl_private LocalIntersection *local_isect,
63 float3 P,
64 float3 dir,
65 int object,
66 int prim,
67 int prim_addr,
68 float tmin,
69 float tmax,
70 ccl_private uint *lcg_state,
71 int max_hits)
72{
73 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
74 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x),
75 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y),
76 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
77
78 float t, u, v;
79 if (!ray_triangle_intersect(P, dir, tmin, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) {
80 return false;
81 }
82
83 /* If no actual hit information is requested, just return here. */
84 if (max_hits == 0) {
85 return true;
86 }
87
88 int hit;
89 if (lcg_state) {
90 /* Record up to max_hits intersections. */
91 for (int i = min(max_hits, local_isect->num_hits) - 1; i >= 0; --i) {
92 if (local_isect->hits[i].t == t) {
93 return false;
94 }
95 }
96
97 local_isect->num_hits++;
98
99 if (local_isect->num_hits <= max_hits) {
100 hit = local_isect->num_hits - 1;
101 }
102 else {
103 /* reservoir sampling: if we are at the maximum number of
104 * hits, randomly replace element or skip it */
105 hit = lcg_step_uint(lcg_state) % local_isect->num_hits;
106
107 if (hit >= max_hits)
108 return false;
109 }
110 }
111 else {
112 /* Record closest intersection only. */
113 if (local_isect->num_hits && t > local_isect->hits[0].t) {
114 return false;
115 }
116
117 hit = 0;
118 local_isect->num_hits = 1;
119 }
120
121 /* Record intersection. */
122 ccl_private Intersection *isect = &local_isect->hits[hit];
123 isect->prim = prim;
124 isect->object = object;
125 isect->type = PRIMITIVE_TRIANGLE;
126 isect->u = u;
127 isect->v = v;
128 isect->t = t;
129
130 /* Record geometric normal. */
131 local_isect->Ng[hit] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
132
133 return false;
134}
135#endif /* __BVH_LOCAL__ */
136
142 const int isect_prim,
143 const float u,
144 const float v)
145{
146 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, isect_prim);
147 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x),
148 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y),
149 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
150
151 /* This appears to give slightly better precision than interpolating with w = (1 - u - v). */
152 float3 P = tri_a + u * (tri_b - tri_a) + v * (tri_c - tri_a);
153
154 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
155 const Transform tfm = object_get_transform(kg, sd);
156 P = transform_point(&tfm, P);
157 }
158
159 return P;
160}
161
163{
164 sd->shader = kernel_data_fetch(tri_shader, sd->prim);
165
166 sd->P = triangle_point_from_uv(kg, sd, sd->prim, sd->u, sd->v);
167
168 /* Normals. */
169 float3 Ng = triangle_normal(kg, sd);
170 sd->Ng = Ng;
171 sd->N = Ng;
172
173 /* Smooth normal. */
174 if (sd->shader & SHADER_SMOOTH_NORMAL) {
175 sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
176 }
177
178#ifdef __DPDU__
179 /* dPdu/dPdv */
180 triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
181#endif
182}
183
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
#define ccl_private
#define ccl_device_inline
#define CCL_NAMESPACE_END
CCL_NAMESPACE_BEGIN ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, float3 Ng, int prim, float u, float v)
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device_inline Transform object_get_transform(KernelGlobals kg, ccl_private const ShaderData *sd)
@ PRIMITIVE_TRIANGLE
ShaderData
@ SHADER_SMOOTH_NORMAL
@ SD_OBJECT_TRANSFORM_APPLIED
CCL_NAMESPACE_BEGIN ccl_device uint lcg_step_uint(T rng)
Definition lcg.h:14
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_forceinline bool ray_triangle_intersect(const float3 ray_P, const float3 ray_D, const float ray_tmin, const float ray_tmax, const float3 tri_a, const float3 tri_b, const float3 tri_c, ccl_private float *isect_u, ccl_private float *isect_v, ccl_private float *isect_t)
#define min(a, b)
Definition sort.c:32
uint y
Definition types_uint3.h:15
uint z
Definition types_uint3.h:15
uint x
Definition types_uint3.h:15
CCL_NAMESPACE_END CCL_NAMESPACE_BEGIN ccl_device_inline float3 transform_point(ccl_private const Transform *t, const float3 a)
Definition transform.h:63
ccl_device_inline float3 triangle_point_from_uv(KernelGlobals kg, ccl_private ShaderData *sd, const int isect_prim, const float u, const float v)
ccl_device_inline void triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)
CCL_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, float3 P, float3 dir, float tmin, float tmax, uint visibility, int object, int prim, int prim_addr)