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