1 /*
2 * Copyright 2011-2013 Blender Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* Triangle Primitive
18 *
19 * Basic triangle with 3 vertices is used to represent mesh surfaces. For BVH
20 * ray intersection we use a precomputed triangle storage to accelerate
21 * intersection at the cost of more memory usage */
22
23 CCL_NAMESPACE_BEGIN
24
25 /* normal on triangle */
triangle_normal(KernelGlobals * kg,ShaderData * sd)26 ccl_device_inline float3 triangle_normal(KernelGlobals *kg, ShaderData *sd)
27 {
28 /* load triangle vertices */
29 const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
30 const float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
31 const float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
32 const float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
33
34 /* return normal */
35 if (sd->object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
36 return normalize(cross(v2 - v0, v1 - v0));
37 }
38 else {
39 return normalize(cross(v1 - v0, v2 - v0));
40 }
41 }
42
43 /* point and normal on triangle */
triangle_point_normal(KernelGlobals * kg,int object,int prim,float u,float v,float3 * P,float3 * Ng,int * shader)44 ccl_device_inline void triangle_point_normal(
45 KernelGlobals *kg, int object, int prim, float u, float v, float3 *P, float3 *Ng, int *shader)
46 {
47 /* load triangle vertices */
48 const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
49 float3 v0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
50 float3 v1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
51 float3 v2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
52 /* compute point */
53 float t = 1.0f - u - v;
54 *P = (u * v0 + v * v1 + t * v2);
55 /* get object flags */
56 int object_flag = kernel_tex_fetch(__object_flag, object);
57 /* compute normal */
58 if (object_flag & SD_OBJECT_NEGATIVE_SCALE_APPLIED) {
59 *Ng = normalize(cross(v2 - v0, v1 - v0));
60 }
61 else {
62 *Ng = normalize(cross(v1 - v0, v2 - v0));
63 }
64 /* shader`*/
65 *shader = kernel_tex_fetch(__tri_shader, prim);
66 }
67
68 /* Triangle vertex locations */
69
triangle_vertices(KernelGlobals * kg,int prim,float3 P[3])70 ccl_device_inline void triangle_vertices(KernelGlobals *kg, int prim, float3 P[3])
71 {
72 const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
73 P[0] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
74 P[1] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
75 P[2] = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
76 }
77
78 /* Interpolate smooth vertex normal from vertices */
79
80 ccl_device_inline float3
triangle_smooth_normal(KernelGlobals * kg,float3 Ng,int prim,float u,float v)81 triangle_smooth_normal(KernelGlobals *kg, float3 Ng, int prim, float u, float v)
82 {
83 /* load triangle vertices */
84 const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
85 float3 n0 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.x));
86 float3 n1 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.y));
87 float3 n2 = float4_to_float3(kernel_tex_fetch(__tri_vnormal, tri_vindex.z));
88
89 float3 N = safe_normalize((1.0f - u - v) * n2 + u * n0 + v * n1);
90
91 return is_zero(N) ? Ng : N;
92 }
93
94 /* Ray differentials on triangle */
95
triangle_dPdudv(KernelGlobals * kg,int prim,ccl_addr_space float3 * dPdu,ccl_addr_space float3 * dPdv)96 ccl_device_inline void triangle_dPdudv(KernelGlobals *kg,
97 int prim,
98 ccl_addr_space float3 *dPdu,
99 ccl_addr_space float3 *dPdv)
100 {
101 /* fetch triangle vertex coordinates */
102 const uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, prim);
103 const float3 p0 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 0));
104 const float3 p1 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 1));
105 const float3 p2 = float4_to_float3(kernel_tex_fetch(__prim_tri_verts, tri_vindex.w + 2));
106
107 /* compute derivatives of P w.r.t. uv */
108 *dPdu = (p0 - p2);
109 *dPdv = (p1 - p2);
110 }
111
112 /* Reading attributes on various triangle elements */
113
triangle_attribute_float(KernelGlobals * kg,const ShaderData * sd,const AttributeDescriptor desc,float * dx,float * dy)114 ccl_device float triangle_attribute_float(
115 KernelGlobals *kg, const ShaderData *sd, const AttributeDescriptor desc, float *dx, float *dy)
116 {
117 if (desc.element == ATTR_ELEMENT_FACE) {
118 if (dx)
119 *dx = 0.0f;
120 if (dy)
121 *dy = 0.0f;
122
123 return kernel_tex_fetch(__attributes_float, desc.offset + sd->prim);
124 }
125 else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
126 uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
127
128 float f0 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.x);
129 float f1 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.y);
130 float f2 = kernel_tex_fetch(__attributes_float, desc.offset + tri_vindex.z);
131
132 #ifdef __RAY_DIFFERENTIALS__
133 if (dx)
134 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
135 if (dy)
136 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
137 #endif
138
139 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
140 }
141 else if (desc.element == ATTR_ELEMENT_CORNER) {
142 int tri = desc.offset + sd->prim * 3;
143 float f0 = kernel_tex_fetch(__attributes_float, tri + 0);
144 float f1 = kernel_tex_fetch(__attributes_float, tri + 1);
145 float f2 = kernel_tex_fetch(__attributes_float, tri + 2);
146
147 #ifdef __RAY_DIFFERENTIALS__
148 if (dx)
149 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
150 if (dy)
151 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
152 #endif
153
154 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
155 }
156 else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
157 if (dx)
158 *dx = 0.0f;
159 if (dy)
160 *dy = 0.0f;
161
162 return kernel_tex_fetch(__attributes_float, desc.offset);
163 }
164 else {
165 if (dx)
166 *dx = 0.0f;
167 if (dy)
168 *dy = 0.0f;
169
170 return 0.0f;
171 }
172 }
173
triangle_attribute_float2(KernelGlobals * kg,const ShaderData * sd,const AttributeDescriptor desc,float2 * dx,float2 * dy)174 ccl_device float2 triangle_attribute_float2(KernelGlobals *kg,
175 const ShaderData *sd,
176 const AttributeDescriptor desc,
177 float2 *dx,
178 float2 *dy)
179 {
180 if (desc.element == ATTR_ELEMENT_FACE) {
181 if (dx)
182 *dx = make_float2(0.0f, 0.0f);
183 if (dy)
184 *dy = make_float2(0.0f, 0.0f);
185
186 return kernel_tex_fetch(__attributes_float2, desc.offset + sd->prim);
187 }
188 else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
189 uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
190
191 float2 f0 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.x);
192 float2 f1 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.y);
193 float2 f2 = kernel_tex_fetch(__attributes_float2, desc.offset + tri_vindex.z);
194
195 #ifdef __RAY_DIFFERENTIALS__
196 if (dx)
197 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
198 if (dy)
199 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
200 #endif
201
202 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
203 }
204 else if (desc.element == ATTR_ELEMENT_CORNER) {
205 int tri = desc.offset + sd->prim * 3;
206 float2 f0, f1, f2;
207
208 if (desc.element == ATTR_ELEMENT_CORNER) {
209 f0 = kernel_tex_fetch(__attributes_float2, tri + 0);
210 f1 = kernel_tex_fetch(__attributes_float2, tri + 1);
211 f2 = kernel_tex_fetch(__attributes_float2, tri + 2);
212 }
213
214 #ifdef __RAY_DIFFERENTIALS__
215 if (dx)
216 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
217 if (dy)
218 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
219 #endif
220
221 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
222 }
223 else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
224 if (dx)
225 *dx = make_float2(0.0f, 0.0f);
226 if (dy)
227 *dy = make_float2(0.0f, 0.0f);
228
229 return kernel_tex_fetch(__attributes_float2, desc.offset);
230 }
231 else {
232 if (dx)
233 *dx = make_float2(0.0f, 0.0f);
234 if (dy)
235 *dy = make_float2(0.0f, 0.0f);
236
237 return make_float2(0.0f, 0.0f);
238 }
239 }
240
triangle_attribute_float3(KernelGlobals * kg,const ShaderData * sd,const AttributeDescriptor desc,float3 * dx,float3 * dy)241 ccl_device float3 triangle_attribute_float3(KernelGlobals *kg,
242 const ShaderData *sd,
243 const AttributeDescriptor desc,
244 float3 *dx,
245 float3 *dy)
246 {
247 if (desc.element == ATTR_ELEMENT_FACE) {
248 if (dx)
249 *dx = make_float3(0.0f, 0.0f, 0.0f);
250 if (dy)
251 *dy = make_float3(0.0f, 0.0f, 0.0f);
252
253 return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset + sd->prim));
254 }
255 else if (desc.element == ATTR_ELEMENT_VERTEX || desc.element == ATTR_ELEMENT_VERTEX_MOTION) {
256 uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
257
258 float3 f0 = float4_to_float3(
259 kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x));
260 float3 f1 = float4_to_float3(
261 kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y));
262 float3 f2 = float4_to_float3(
263 kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z));
264
265 #ifdef __RAY_DIFFERENTIALS__
266 if (dx)
267 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
268 if (dy)
269 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
270 #endif
271
272 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
273 }
274 else if (desc.element == ATTR_ELEMENT_CORNER) {
275 int tri = desc.offset + sd->prim * 3;
276 float3 f0, f1, f2;
277
278 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 0));
279 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 1));
280 f2 = float4_to_float3(kernel_tex_fetch(__attributes_float3, tri + 2));
281
282 #ifdef __RAY_DIFFERENTIALS__
283 if (dx)
284 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
285 if (dy)
286 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
287 #endif
288
289 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
290 }
291 else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
292 if (dx)
293 *dx = make_float3(0.0f, 0.0f, 0.0f);
294 if (dy)
295 *dy = make_float3(0.0f, 0.0f, 0.0f);
296
297 return float4_to_float3(kernel_tex_fetch(__attributes_float3, desc.offset));
298 }
299 else {
300 if (dx)
301 *dx = make_float3(0.0f, 0.0f, 0.0f);
302 if (dy)
303 *dy = make_float3(0.0f, 0.0f, 0.0f);
304
305 return make_float3(0.0f, 0.0f, 0.0f);
306 }
307 }
308
triangle_attribute_float4(KernelGlobals * kg,const ShaderData * sd,const AttributeDescriptor desc,float4 * dx,float4 * dy)309 ccl_device float4 triangle_attribute_float4(KernelGlobals *kg,
310 const ShaderData *sd,
311 const AttributeDescriptor desc,
312 float4 *dx,
313 float4 *dy)
314 {
315 if (desc.element == ATTR_ELEMENT_CORNER_BYTE || desc.element == ATTR_ELEMENT_VERTEX) {
316 float4 f0, f1, f2;
317
318 if (desc.element == ATTR_ELEMENT_CORNER_BYTE) {
319 int tri = desc.offset + sd->prim * 3;
320 f0 = color_srgb_to_linear_v4(
321 color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 0)));
322 f1 = color_srgb_to_linear_v4(
323 color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 1)));
324 f2 = color_srgb_to_linear_v4(
325 color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, tri + 2)));
326 }
327 else {
328 uint4 tri_vindex = kernel_tex_fetch(__tri_vindex, sd->prim);
329 f0 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.x);
330 f1 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.y);
331 f2 = kernel_tex_fetch(__attributes_float3, desc.offset + tri_vindex.z);
332 }
333
334 #ifdef __RAY_DIFFERENTIALS__
335 if (dx)
336 *dx = sd->du.dx * f0 + sd->dv.dx * f1 - (sd->du.dx + sd->dv.dx) * f2;
337 if (dy)
338 *dy = sd->du.dy * f0 + sd->dv.dy * f1 - (sd->du.dy + sd->dv.dy) * f2;
339 #endif
340
341 return sd->u * f0 + sd->v * f1 + (1.0f - sd->u - sd->v) * f2;
342 }
343 else if (desc.element == ATTR_ELEMENT_OBJECT || desc.element == ATTR_ELEMENT_MESH) {
344 if (dx)
345 *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
346 if (dy)
347 *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
348
349 return color_srgb_to_linear_v4(
350 color_uchar4_to_float4(kernel_tex_fetch(__attributes_uchar4, desc.offset)));
351 }
352 else {
353 if (dx)
354 *dx = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
355 if (dy)
356 *dy = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
357
358 return make_float4(0.0f, 0.0f, 0.0f, 0.0f);
359 }
360 }
361
362 CCL_NAMESPACE_END
363