Cycles: change __device and similar qualifiers to ccl_device in kernel code.
[blender.git] / intern / cycles / kernel / svm / svm_tex_coord.h
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 CCL_NAMESPACE_BEGIN
18
19 /* Texture Coordinate Node */
20
21 ccl_device void svm_node_tex_coord(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
22 {
23         float3 data;
24
25         switch(type) {
26                 case NODE_TEXCO_OBJECT: {
27                         if(sd->object != ~0) {
28                                 data = sd->P;
29                                 object_inverse_position_transform(kg, sd, &data);
30                         }
31                         else
32                                 data = sd->P;
33                         break;
34                 }
35                 case NODE_TEXCO_NORMAL: {
36                         if(sd->object != ~0) {
37                                 data = sd->N;
38                                 object_inverse_normal_transform(kg, sd, &data);
39                         }
40                         else
41                                 data = sd->N;
42                         break;
43                 }
44                 case NODE_TEXCO_CAMERA: {
45                         Transform tfm = kernel_data.cam.worldtocamera;
46
47                         if(sd->object != ~0)
48                                 data = transform_point(&tfm, sd->P);
49                         else
50                                 data = transform_point(&tfm, sd->P + camera_position(kg));
51                         break;
52                 }
53                 case NODE_TEXCO_WINDOW: {
54                         if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
55                                 data = camera_world_to_ndc(kg, sd, sd->ray_P);
56                         else
57                                 data = camera_world_to_ndc(kg, sd, sd->P);
58                         data.z = 0.0f;
59                         break;
60                 }
61                 case NODE_TEXCO_REFLECTION: {
62                         if(sd->object != ~0)
63                                 data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
64                         else
65                                 data = sd->I;
66                         break;
67                 }
68                 case NODE_TEXCO_DUPLI_GENERATED: {
69                         data = object_dupli_generated(kg, sd->object);
70                         break;
71                 }
72                 case NODE_TEXCO_DUPLI_UV: {
73                         data = object_dupli_uv(kg, sd->object);
74                         break;
75                 }
76         }
77
78         stack_store_float3(stack, out_offset, data);
79 }
80
81 ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
82 {
83 #ifdef __RAY_DIFFERENTIALS__
84         float3 data;
85
86         switch(type) {
87                 case NODE_TEXCO_OBJECT: {
88                         if(sd->object != ~0) {
89                                 data = sd->P + sd->dP.dx;
90                                 object_inverse_position_transform(kg, sd, &data);
91                         }
92                         else
93                                 data = sd->P + sd->dP.dx;
94                         break;
95                 }
96                 case NODE_TEXCO_NORMAL: {
97                         if(sd->object != ~0) {
98                                 data = sd->N;
99                                 object_inverse_normal_transform(kg, sd, &data);
100                         }
101                         else
102                                 data = sd->N;
103                         break;
104                 }
105                 case NODE_TEXCO_CAMERA: {
106                         Transform tfm = kernel_data.cam.worldtocamera;
107
108                         if(sd->object != ~0)
109                                 data = transform_point(&tfm, sd->P + sd->dP.dx);
110                         else
111                                 data = transform_point(&tfm, sd->P + sd->dP.dx + camera_position(kg));
112                         break;
113                 }
114                 case NODE_TEXCO_WINDOW: {
115                         if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
116                                 data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dx);
117                         else
118                                 data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dx);
119                         data.z = 0.0f;
120                         break;
121                 }
122                 case NODE_TEXCO_REFLECTION: {
123                         if(sd->object != ~0)
124                                 data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
125                         else
126                                 data = sd->I;
127                         break;
128                 }
129                 case NODE_TEXCO_DUPLI_GENERATED: {
130                         data = object_dupli_generated(kg, sd->object);
131                         break;
132                 }
133                 case NODE_TEXCO_DUPLI_UV: {
134                         data = object_dupli_uv(kg, sd->object);
135                         break;
136                 }
137         }
138
139         stack_store_float3(stack, out_offset, data);
140 #else
141         svm_node_tex_coord(kg, sd, stack, type, out_offset);
142 #endif
143 }
144
145 ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, int path_flag, float *stack, uint type, uint out_offset)
146 {
147 #ifdef __RAY_DIFFERENTIALS__
148         float3 data;
149
150         switch(type) {
151                 case NODE_TEXCO_OBJECT: {
152                         if(sd->object != ~0) {
153                                 data = sd->P + sd->dP.dy;
154                                 object_inverse_position_transform(kg, sd, &data);
155                         }
156                         else
157                                 data = sd->P + sd->dP.dy;
158                         break;
159                 }
160                 case NODE_TEXCO_NORMAL: {
161                         if(sd->object != ~0) {
162                                 data = sd->N;
163                                 object_inverse_normal_transform(kg, sd, &data);
164                         }
165                         else
166                                 data = sd->N;
167                         break;
168                 }
169                 case NODE_TEXCO_CAMERA: {
170                         Transform tfm = kernel_data.cam.worldtocamera;
171
172                         if(sd->object != ~0)
173                                 data = transform_point(&tfm, sd->P + sd->dP.dy);
174                         else
175                                 data = transform_point(&tfm, sd->P + sd->dP.dy + camera_position(kg));
176                         break;
177                 }
178                 case NODE_TEXCO_WINDOW: {
179                         if((path_flag & PATH_RAY_CAMERA) && sd->object == ~0 && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
180                                 data = camera_world_to_ndc(kg, sd, sd->ray_P + sd->ray_dP.dy);
181                         else
182                                 data = camera_world_to_ndc(kg, sd, sd->P + sd->dP.dy);
183                         data.z = 0.0f;
184                         break;
185                 }
186                 case NODE_TEXCO_REFLECTION: {
187                         if(sd->object != ~0)
188                                 data = 2.0f*dot(sd->N, sd->I)*sd->N - sd->I;
189                         else
190                                 data = sd->I;
191                         break;
192                 }
193                 case NODE_TEXCO_DUPLI_GENERATED: {
194                         data = object_dupli_generated(kg, sd->object);
195                         break;
196                 }
197                 case NODE_TEXCO_DUPLI_UV: {
198                         data = object_dupli_uv(kg, sd->object);
199                         break;
200                 }
201         }
202
203         stack_store_float3(stack, out_offset, data);
204 #else
205         svm_node_tex_coord(kg, sd, stack, type, out_offset);
206 #endif
207 }
208
209 ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
210 {
211         uint color_offset, strength_offset, normal_offset, space;
212         decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
213
214         float3 color = stack_load_float3(stack, color_offset);
215         color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
216
217         float3 N;
218
219         if(space == NODE_NORMAL_MAP_TANGENT) {
220                 /* tangent space */
221                 if(sd->object == ~0) {
222                         stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
223                         return;
224                 }
225
226                 /* first try to get tangent attribute */
227                 AttributeElement attr_elem, attr_sign_elem, attr_normal_elem;
228                 int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
229                 int attr_sign_offset = find_attribute(kg, sd, node.w, &attr_sign_elem);
230                 int attr_normal_offset = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL, &attr_normal_elem);
231
232                 if(attr_offset == ATTR_STD_NOT_FOUND || attr_sign_offset == ATTR_STD_NOT_FOUND || attr_normal_offset == ATTR_STD_NOT_FOUND) {
233                         stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
234                         return;
235                 }
236
237                 /* get _unnormalized_ interpolated normal and tangent */
238                 float3 tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
239                 float sign = primitive_attribute_float(kg, sd, attr_sign_elem, attr_sign_offset, NULL, NULL);
240                 float3 normal;
241
242                 if(sd->shader & SHADER_SMOOTH_NORMAL) {
243                         normal = primitive_attribute_float3(kg, sd, attr_normal_elem, attr_normal_offset, NULL, NULL);
244                 }
245                 else {
246                         normal = sd->Ng;
247                         object_inverse_normal_transform(kg, sd, &normal);
248                 }
249
250                 /* apply normal map */
251                 float3 B = sign * cross(normal, tangent);
252                 N = normalize(color.x * tangent + color.y * B + color.z * normal);
253
254                 /* transform to world space */
255                 object_normal_transform(kg, sd, &N);
256         }
257         else {
258                 /* strange blender convention */
259                 if(space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
260                         color.y = -color.y;
261                         color.z = -color.z;
262                 }
263         
264                 /* object, world space */
265                 N = color;
266
267                 if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
268                         object_normal_transform(kg, sd, &N);
269                 else
270                         N = normalize(N);
271         }
272
273         float strength = stack_load_float(stack, strength_offset);
274
275         if(strength != 1.0f) {
276                 strength = max(strength, 0.0f);
277                 N = normalize(sd->N + (N - sd->N)*strength);
278         }
279
280         stack_store_float3(stack, normal_offset, N);
281 }
282
283 ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
284 {
285         uint tangent_offset, direction_type, axis;
286         decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
287
288         float3 tangent;
289
290         if(direction_type == NODE_TANGENT_UVMAP) {
291                 /* UV map */
292                 AttributeElement attr_elem;
293                 int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
294
295                 if(attr_offset == ATTR_STD_NOT_FOUND)
296                         tangent = make_float3(0.0f, 0.0f, 0.0f);
297                 else
298                         tangent = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
299         }
300         else {
301                 /* radial */
302                 AttributeElement attr_elem;
303                 int attr_offset = find_attribute(kg, sd, node.z, &attr_elem);
304                 float3 generated;
305
306                 if(attr_offset == ATTR_STD_NOT_FOUND)
307                         generated = sd->P;
308                 else
309                         generated = primitive_attribute_float3(kg, sd, attr_elem, attr_offset, NULL, NULL);
310
311                 if(axis == NODE_TANGENT_AXIS_X)
312                         tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
313                 else if(axis == NODE_TANGENT_AXIS_Y)
314                         tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
315                 else
316                         tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
317         }
318
319         object_normal_transform(kg, sd, &tangent);
320         tangent = cross(sd->N, normalize(cross(tangent, sd->N)));
321         stack_store_float3(stack, tangent_offset, tangent);
322 }
323
324 CCL_NAMESPACE_END
325