Merged changes in the trunk up to revision 51985.
[blender.git] / intern / cycles / kernel / svm / svm_geometry.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 CCL_NAMESPACE_BEGIN
20
21 /* Geometry Node */
22
23 __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
24 {
25         float3 data;
26
27         switch(type) {
28                 case NODE_GEOM_P: data = sd->P; break;
29                 case NODE_GEOM_N: data = sd->N; break;
30 #ifdef __DPDU__
31                 case NODE_GEOM_T: {
32                         /* try to create spherical tangent from generated coordinates */
33                         int attr_offset = (sd->object != ~0)? find_attribute(kg, sd, ATTR_STD_GENERATED): ATTR_STD_NOT_FOUND;
34
35                         if(attr_offset != ATTR_STD_NOT_FOUND) {
36                                 data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
37                                 data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f);
38                                 object_normal_transform(kg, sd, &data);
39                                 data = cross(sd->N, normalize(cross(data, sd->N)));;
40                         }
41                         else {
42                                 /* otherwise use surface derivatives */
43                                 data = normalize(sd->dPdu);
44                         }
45
46                         break;
47                 }
48 #endif
49                 case NODE_GEOM_I: data = sd->I; break;
50                 case NODE_GEOM_Ng: data = sd->Ng; break;
51 #ifdef __UV__
52                 case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break;
53 #endif
54         }
55
56         stack_store_float3(stack, out_offset, data);
57 }
58
59 __device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
60 {
61 #ifdef __RAY_DIFFERENTIALS__
62         float3 data;
63
64         switch(type) {
65                 case NODE_GEOM_P: data = sd->P + sd->dP.dx; break;
66                 case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break;
67                 default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
68         }
69
70         stack_store_float3(stack, out_offset, data);
71 #else
72         svm_node_geometry(kg, sd, stack, type, out_offset);
73 #endif
74 }
75
76 __device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
77 {
78 #ifdef __RAY_DIFFERENTIALS__
79         float3 data;
80
81         switch(type) {
82                 case NODE_GEOM_P: data = sd->P + sd->dP.dy; break;
83                 case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break;
84                 default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
85         }
86
87         stack_store_float3(stack, out_offset, data);
88 #else
89         svm_node_geometry(kg, sd, stack, type, out_offset);
90 #endif
91 }
92
93 /* Object Info */
94
95 __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
96 {
97         float data;
98
99         switch(type) {
100                 case NODE_INFO_OB_LOCATION: {
101                         stack_store_float3(stack, out_offset, object_location(kg, sd));
102                         return;
103                 }
104                 case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
105                 case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
106                 case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
107                 default: data = 0.0f; break;
108         }
109
110         stack_store_float(stack, out_offset, data);
111 }
112
113 /* Particle Info */
114
115 __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
116 {
117         switch(type) {
118                 case NODE_INFO_PAR_INDEX: {
119                         uint particle_id = object_particle_id(kg, sd->object);
120                         stack_store_float(stack, out_offset, particle_index(kg, particle_id));
121                         break;
122                 }
123                 case NODE_INFO_PAR_AGE: {
124                         uint particle_id = object_particle_id(kg, sd->object);
125                         stack_store_float(stack, out_offset, particle_age(kg, particle_id));
126                         break;
127                 }
128                 case NODE_INFO_PAR_LIFETIME: {
129                         uint particle_id = object_particle_id(kg, sd->object);
130                         stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
131                         break;
132                 }
133                 case NODE_INFO_PAR_LOCATION: {
134                         uint particle_id = object_particle_id(kg, sd->object);
135                         stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
136                         break;
137                 }
138                 #if 0   /* XXX float4 currently not supported in SVM stack */
139                 case NODE_INFO_PAR_ROTATION: {
140                         uint particle_id = object_particle_id(kg, sd->object);
141                         stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
142                         break;
143                 }
144                 #endif
145                 case NODE_INFO_PAR_SIZE: {
146                         uint particle_id = object_particle_id(kg, sd->object);
147                         stack_store_float(stack, out_offset, particle_size(kg, particle_id));
148                         break;
149                 }
150                 case NODE_INFO_PAR_VELOCITY: {
151                         uint particle_id = object_particle_id(kg, sd->object);
152                         stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
153                         break;
154                 }
155                 case NODE_INFO_PAR_ANGULAR_VELOCITY: {
156                         uint particle_id = object_particle_id(kg, sd->object);
157                         stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
158                         break;
159                 }
160         }
161 }
162
163 CCL_NAMESPACE_END
164