c0b01262212ed9480c9a381f0f41e7d7b73aa821
[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,
22                                    ShaderData *sd,
23                                    int path_flag,
24                                    float *stack,
25                                    uint4 node,
26                                    int *offset)
27 {
28         float3 data;
29         uint type = node.y;
30         uint out_offset = node.z;
31
32         switch(type) {
33                 case NODE_TEXCO_OBJECT: {
34                         data = ccl_fetch(sd, P);
35                         if(node.w == 0) {
36                                 if(ccl_fetch(sd, object) != OBJECT_NONE) {
37                                         object_inverse_position_transform(kg, sd, &data);
38                                 }
39                         }
40                         else {
41                                 Transform tfm;
42                                 tfm.x = read_node_float(kg, offset);
43                                 tfm.y = read_node_float(kg, offset);
44                                 tfm.z = read_node_float(kg, offset);
45                                 tfm.w = read_node_float(kg, offset);
46                                 data = transform_point(&tfm, data);
47                         }
48                         break;
49                 }
50                 case NODE_TEXCO_NORMAL: {
51                         data = ccl_fetch(sd, N);
52                         object_inverse_normal_transform(kg, sd, &data);
53                         break;
54                 }
55                 case NODE_TEXCO_CAMERA: {
56                         Transform tfm = kernel_data.cam.worldtocamera;
57
58                         if(ccl_fetch(sd, object) != OBJECT_NONE)
59                                 data = transform_point(&tfm, ccl_fetch(sd, P));
60                         else
61                                 data = transform_point(&tfm, ccl_fetch(sd, P) + camera_position(kg));
62                         break;
63                 }
64                 case NODE_TEXCO_WINDOW: {
65                         if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
66                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P));
67                         else
68                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P));
69                         data.z = 0.0f;
70                         break;
71                 }
72                 case NODE_TEXCO_REFLECTION: {
73                         if(ccl_fetch(sd, object) != OBJECT_NONE)
74                                 data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
75                         else
76                                 data = ccl_fetch(sd, I);
77                         break;
78                 }
79                 case NODE_TEXCO_DUPLI_GENERATED: {
80                         data = object_dupli_generated(kg, ccl_fetch(sd, object));
81                         break;
82                 }
83                 case NODE_TEXCO_DUPLI_UV: {
84                         data = object_dupli_uv(kg, ccl_fetch(sd, object));
85                         break;
86                 }
87                 case NODE_TEXCO_VOLUME_GENERATED: {
88                         data = ccl_fetch(sd, P);
89
90 #ifdef __VOLUME__
91                         if(ccl_fetch(sd, object) != OBJECT_NONE)
92                                 data = volume_normalized_position(kg, sd, data);
93 #endif
94                         break;
95                 }
96         }
97
98         stack_store_float3(stack, out_offset, data);
99 }
100
101 ccl_device void svm_node_tex_coord_bump_dx(KernelGlobals *kg,
102                                            ShaderData *sd,
103                                            int path_flag,
104                                            float *stack,
105                                            uint4 node,
106                                            int *offset)
107 {
108 #ifdef __RAY_DIFFERENTIALS__
109         float3 data;
110         uint type = node.y;
111         uint out_offset = node.z;
112
113         switch(type) {
114                 case NODE_TEXCO_OBJECT: {
115                         data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
116                         if(node.w == 0) {
117                                 if(ccl_fetch(sd, object) != OBJECT_NONE) {
118                                         object_inverse_position_transform(kg, sd, &data);
119                                 }
120                         }
121                         else {
122                                 Transform tfm;
123                                 tfm.x = read_node_float(kg, offset);
124                                 tfm.y = read_node_float(kg, offset);
125                                 tfm.z = read_node_float(kg, offset);
126                                 tfm.w = read_node_float(kg, offset);
127                                 data = transform_point(&tfm, data);
128                         }
129                         break;
130                 }
131                 case NODE_TEXCO_NORMAL: {
132                         data = ccl_fetch(sd, N);
133                         object_inverse_normal_transform(kg, sd, &data);
134                         break;
135                 }
136                 case NODE_TEXCO_CAMERA: {
137                         Transform tfm = kernel_data.cam.worldtocamera;
138
139                         if(ccl_fetch(sd, object) != OBJECT_NONE)
140                                 data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
141                         else
142                                 data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx + camera_position(kg));
143                         break;
144                 }
145                 case NODE_TEXCO_WINDOW: {
146                         if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
147                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dx);
148                         else
149                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx);
150                         data.z = 0.0f;
151                         break;
152                 }
153                 case NODE_TEXCO_REFLECTION: {
154                         if(ccl_fetch(sd, object) != OBJECT_NONE)
155                                 data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
156                         else
157                                 data = ccl_fetch(sd, I);
158                         break;
159                 }
160                 case NODE_TEXCO_DUPLI_GENERATED: {
161                         data = object_dupli_generated(kg, ccl_fetch(sd, object));
162                         break;
163                 }
164                 case NODE_TEXCO_DUPLI_UV: {
165                         data = object_dupli_uv(kg, ccl_fetch(sd, object));
166                         break;
167                 }
168                 case NODE_TEXCO_VOLUME_GENERATED: {
169                         data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dx;
170
171 #ifdef __VOLUME__
172                         if(ccl_fetch(sd, object) != OBJECT_NONE)
173                                 data = volume_normalized_position(kg, sd, data);
174 #endif
175                         break;
176                 }
177         }
178
179         stack_store_float3(stack, out_offset, data);
180 #else
181         svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
182 #endif
183 }
184
185 ccl_device void svm_node_tex_coord_bump_dy(KernelGlobals *kg,
186                                            ShaderData *sd,
187                                            int path_flag,
188                                            float *stack,
189                                            uint4 node,
190                                            int *offset)
191 {
192 #ifdef __RAY_DIFFERENTIALS__
193         float3 data;
194         uint type = node.y;
195         uint out_offset = node.z;
196
197         switch(type) {
198                 case NODE_TEXCO_OBJECT: {
199                         data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
200                         if(node.w == 0) {
201                                 if(ccl_fetch(sd, object) != OBJECT_NONE) {
202                                         object_inverse_position_transform(kg, sd, &data);
203                                 }
204                         }
205                         else {
206                                 Transform tfm;
207                                 tfm.x = read_node_float(kg, offset);
208                                 tfm.y = read_node_float(kg, offset);
209                                 tfm.z = read_node_float(kg, offset);
210                                 tfm.w = read_node_float(kg, offset);
211                                 data = transform_point(&tfm, data);
212                         }
213                         break;
214                 }
215                 case NODE_TEXCO_NORMAL: {
216                         data = ccl_fetch(sd, N);
217                         object_inverse_normal_transform(kg, sd, &data);
218                         break;
219                 }
220                 case NODE_TEXCO_CAMERA: {
221                         Transform tfm = kernel_data.cam.worldtocamera;
222
223                         if(ccl_fetch(sd, object) != OBJECT_NONE)
224                                 data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
225                         else
226                                 data = transform_point(&tfm, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy + camera_position(kg));
227                         break;
228                 }
229                 case NODE_TEXCO_WINDOW: {
230                         if((path_flag & PATH_RAY_CAMERA) && ccl_fetch(sd, object) == OBJECT_NONE && kernel_data.cam.type == CAMERA_ORTHOGRAPHIC)
231                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, ray_P) + ccl_fetch(sd, ray_dP).dy);
232                         else
233                                 data = camera_world_to_ndc(kg, sd, ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy);
234                         data.z = 0.0f;
235                         break;
236                 }
237                 case NODE_TEXCO_REFLECTION: {
238                         if(ccl_fetch(sd, object) != OBJECT_NONE)
239                                 data = 2.0f*dot(ccl_fetch(sd, N), ccl_fetch(sd, I))*ccl_fetch(sd, N) - ccl_fetch(sd, I);
240                         else
241                                 data = ccl_fetch(sd, I);
242                         break;
243                 }
244                 case NODE_TEXCO_DUPLI_GENERATED: {
245                         data = object_dupli_generated(kg, ccl_fetch(sd, object));
246                         break;
247                 }
248                 case NODE_TEXCO_DUPLI_UV: {
249                         data = object_dupli_uv(kg, ccl_fetch(sd, object));
250                         break;
251                 }
252                 case NODE_TEXCO_VOLUME_GENERATED: {
253                         data = ccl_fetch(sd, P) + ccl_fetch(sd, dP).dy;
254
255 #ifdef __VOLUME__
256                         if(ccl_fetch(sd, object) != OBJECT_NONE)
257                                 data = volume_normalized_position(kg, sd, data);
258 #endif
259                         break;
260                 }
261         }
262
263         stack_store_float3(stack, out_offset, data);
264 #else
265         svm_node_tex_coord(kg, sd, path_flag, stack, node, offset);
266 #endif
267 }
268
269 ccl_device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
270 {
271         uint color_offset, strength_offset, normal_offset, space;
272         decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space);
273
274         float3 color = stack_load_float3(stack, color_offset);
275         color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f);
276
277         bool is_backfacing = (ccl_fetch(sd, flag) & SD_BACKFACING) != 0;
278         float3 N;
279
280         if(space == NODE_NORMAL_MAP_TANGENT) {
281                 /* tangent space */
282                 if(ccl_fetch(sd, object) == OBJECT_NONE) {
283                         stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
284                         return;
285                 }
286
287                 /* first try to get tangent attribute */
288                 const AttributeDescriptor attr = find_attribute(kg, sd, node.z);
289                 const AttributeDescriptor attr_sign = find_attribute(kg, sd, node.w);
290                 const AttributeDescriptor attr_normal = find_attribute(kg, sd, ATTR_STD_VERTEX_NORMAL);
291
292                 if(attr.offset == ATTR_STD_NOT_FOUND || attr_sign.offset == ATTR_STD_NOT_FOUND || attr_normal.offset == ATTR_STD_NOT_FOUND) {
293                         stack_store_float3(stack, normal_offset, make_float3(0.0f, 0.0f, 0.0f));
294                         return;
295                 }
296
297                 /* get _unnormalized_ interpolated normal and tangent */
298                 float3 tangent = primitive_attribute_float3(kg, sd, attr, NULL, NULL);
299                 float sign = primitive_attribute_float(kg, sd, attr_sign, NULL, NULL);
300                 float3 normal;
301
302                 if(ccl_fetch(sd, shader) & SHADER_SMOOTH_NORMAL) {
303                         normal = primitive_attribute_float3(kg, sd, attr_normal, NULL, NULL);
304                 }
305                 else {
306                         normal = ccl_fetch(sd, Ng);
307
308                         /* the normal is already inverted, which is too soon for the math here */
309                         if(is_backfacing) {
310                                 normal = -normal;
311                         }
312
313                         object_inverse_normal_transform(kg, sd, &normal);
314                 }
315
316                 /* apply normal map */
317                 float3 B = sign * cross(normal, tangent);
318                 N = safe_normalize(color.x * tangent + color.y * B + color.z * normal);
319
320                 /* transform to world space */
321                 object_normal_transform(kg, sd, &N);
322         }
323         else {
324                 /* strange blender convention */
325                 if(space == NODE_NORMAL_MAP_BLENDER_OBJECT || space == NODE_NORMAL_MAP_BLENDER_WORLD) {
326                         color.y = -color.y;
327                         color.z = -color.z;
328                 }
329         
330                 /* object, world space */
331                 N = color;
332
333                 if(space == NODE_NORMAL_MAP_OBJECT || space == NODE_NORMAL_MAP_BLENDER_OBJECT)
334                         object_normal_transform(kg, sd, &N);
335                 else
336                         N = safe_normalize(N);
337         }
338
339         /* invert normal for backfacing polygons */
340         if(is_backfacing) {
341                 N = -N;
342         }
343
344         float strength = stack_load_float(stack, strength_offset);
345
346         if(strength != 1.0f) {
347                 strength = max(strength, 0.0f);
348                 N = safe_normalize(ccl_fetch(sd, N) + (N - ccl_fetch(sd, N))*strength);
349         }
350
351         if(is_zero(N)) {
352                 N = ccl_fetch(sd, N);
353         }
354
355         stack_store_float3(stack, normal_offset, N);
356 }
357
358 ccl_device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
359 {
360         uint tangent_offset, direction_type, axis;
361         decode_node_uchar4(node.y, &tangent_offset, &direction_type, &axis, NULL);
362
363         float3 tangent;
364
365         if(direction_type == NODE_TANGENT_UVMAP) {
366                 /* UV map */
367                 const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
368
369                 if(desc.offset == ATTR_STD_NOT_FOUND)
370                         tangent = make_float3(0.0f, 0.0f, 0.0f);
371                 else
372                         tangent = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
373         }
374         else {
375                 /* radial */
376                 const AttributeDescriptor desc = find_attribute(kg, sd, node.z);
377                 float3 generated;
378
379                 if(desc.offset == ATTR_STD_NOT_FOUND)
380                         generated = ccl_fetch(sd, P);
381                 else
382                         generated = primitive_attribute_float3(kg, sd, desc, NULL, NULL);
383
384                 if(axis == NODE_TANGENT_AXIS_X)
385                         tangent = make_float3(0.0f, -(generated.z - 0.5f), (generated.y - 0.5f));
386                 else if(axis == NODE_TANGENT_AXIS_Y)
387                         tangent = make_float3(-(generated.z - 0.5f), 0.0f, (generated.x - 0.5f));
388                 else
389                         tangent = make_float3(-(generated.y - 0.5f), (generated.x - 0.5f), 0.0f);
390         }
391
392         object_normal_transform(kg, sd, &tangent);
393         tangent = cross(ccl_fetch(sd, N), normalize(cross(tangent, ccl_fetch(sd, N))));
394         stack_store_float3(stack, tangent_offset, tangent);
395 }
396
397 CCL_NAMESPACE_END
398