Blender V5.0
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/globals.h"
14
16#include "kernel/geom/object.h"
18
19#include "util/math_float3.h"
20#include "util/math_intersect.h"
21
23
26 const float3 P,
27 const float3 dir,
28 const float tmin,
29 const float tmax,
30 const uint visibility,
31 const int object,
32 const int prim,
33 const int prim_addr)
34{
35 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
36 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x);
37 const float3 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y);
38 const float3 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
39
40 float t;
41 float u;
42 float v;
43 if (ray_triangle_intersect(P, dir, tmin, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) {
44#ifdef __VISIBILITY_FLAG__
45 /* Visibility flag test. we do it here under the assumption
46 * that most triangles are culled by node flags.
47 */
48 if (kernel_data_fetch(prim_visibility, prim_addr) & visibility)
49#endif
50 {
51 isect->object = object;
52 isect->prim = prim;
53 isect->type = PRIMITIVE_TRIANGLE;
54 isect->u = u;
55 isect->v = v;
56 isect->t = t;
57 return true;
58 }
59 }
60 return false;
61}
62
63/* Special ray intersection routines for subsurface scattering. In that case we
64 * only want to intersect with primitives in the same object, and if case of
65 * multiple hits we pick a single random primitive as the intersection point.
66 * Returns whether traversal should be stopped.
67 */
68
69#ifdef __BVH_LOCAL__
70ccl_device_inline bool triangle_intersect_local(KernelGlobals kg,
71 ccl_private LocalIntersection *local_isect,
72 const float3 P,
73 const float3 dir,
74 const int object,
75 const int prim,
76 const float tmin,
77 const float tmax,
78 ccl_private uint *lcg_state,
79 const int max_hits)
80{
81 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, prim);
82 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x);
83 const float3 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y);
84 const float3 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
85
86 float t;
87 float u;
88 float v;
89 if (!ray_triangle_intersect(P, dir, tmin, tmax, tri_a, tri_b, tri_c, &u, &v, &t)) {
90 return false;
91 }
92
93 /* If no actual hit information is requested, just return here. */
94 if (max_hits == 0) {
95 return true;
96 }
97
98 const int hit_index = local_intersect_get_record_index(local_isect, t, lcg_state, max_hits);
99 if (hit_index == -1) {
100 return false;
101 }
102
103 /* Record intersection. */
104 ccl_private Intersection *isect = &local_isect->hits[hit_index];
105 isect->prim = prim;
106 isect->object = object;
107 isect->type = PRIMITIVE_TRIANGLE;
108 isect->u = u;
109 isect->v = v;
110 isect->t = t;
111
112 /* Record geometric normal. */
113 local_isect->Ng[hit_index] = normalize(cross(tri_b - tri_a, tri_c - tri_a));
114
115 return false;
116}
117#endif /* __BVH_LOCAL__ */
118
123 ccl_private ShaderData *sd,
124 const int isect_prim,
125 const float u,
126 const float v)
127{
128 const uint3 tri_vindex = kernel_data_fetch(tri_vindex, isect_prim);
129 const float3 tri_a = kernel_data_fetch(tri_verts, tri_vindex.x);
130 const float3 tri_b = kernel_data_fetch(tri_verts, tri_vindex.y);
131 const float3 tri_c = kernel_data_fetch(tri_verts, tri_vindex.z);
132
133 /* This appears to give slightly better precision than interpolating with w = (1 - u - v). */
134 float3 P = tri_a + u * (tri_b - tri_a) + v * (tri_c - tri_a);
135
136 if (!(sd->object_flag & SD_OBJECT_TRANSFORM_APPLIED)) {
137 const Transform tfm = object_get_transform(kg, sd);
138 P = transform_point(&tfm, P);
139 }
140
141 return P;
142}
143
145{
146 sd->shader = kernel_data_fetch(tri_shader, sd->prim);
147
148 sd->P = triangle_point_from_uv(kg, sd, sd->prim, sd->u, sd->v);
149
150 /* Normals. */
151 const float3 Ng = triangle_normal(kg, sd);
152 sd->Ng = Ng;
153 sd->N = Ng;
154
155 /* Smooth normal. */
156 if (sd->shader & SHADER_SMOOTH_NORMAL) {
157 sd->N = triangle_smooth_normal(kg, Ng, sd->prim, sd->u, sd->v);
158 }
159
160#ifdef __DPDU__
161 /* dPdu/dPdv */
162 triangle_dPdudv(kg, sd->prim, &sd->dPdu, &sd->dPdv);
163#endif
164}
165
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define kernel_data_fetch(name, index)
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_inline float3 triangle_normal(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device_inline void triangle_dPdudv(KernelGlobals kg, const int prim, ccl_private float3 *dPdu, ccl_private float3 *dPdv)
ccl_device_inline float3 triangle_smooth_normal(KernelGlobals kg, const float3 Ng, const int prim, const float u, float v)
VecBase< float, D > normalize(VecOp< float, D >) RET
VecBase< float, 3 > cross(VecOp< float, 3 >, VecOp< float, 3 >) RET
ccl_device_inline Transform object_get_transform(KernelGlobals kg, const ccl_private ShaderData *sd)
@ PRIMITIVE_TRIANGLE
@ SHADER_SMOOTH_NORMAL
@ SD_OBJECT_TRANSFORM_APPLIED
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)
uint y
Definition types_uint3.h:13
uint z
Definition types_uint3.h:13
uint x
Definition types_uint3.h:13
ccl_device_inline float3 transform_point(const ccl_private Transform *t, const float3 a)
Definition transform.h:56
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_NAMESPACE_BEGIN ccl_device_inline bool triangle_intersect(KernelGlobals kg, ccl_private Intersection *isect, const float3 P, const float3 dir, const float tmin, const float tmax, const uint visibility, const int object, const int prim, const int prim_addr)
ccl_device_inline void triangle_shader_setup(KernelGlobals kg, ccl_private ShaderData *sd)