Merged changes in the trunk up to revision 51448.
[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_inline float3 svm_tangent_from_generated(float3 P)
24 {
25         float length = len(P);
26
27         if(length == 0.0f)
28                 return make_float3(0.0f, 0.0f, 0.0f);
29
30         float u = 0.0f;
31         if(!(P.x == 0.0f && P.y == 0.0f))
32                 u = (1.0f - atan2f(P.x, P.y))/(2.0f*M_PI_F);
33         
34         float v = 1.0f - acosf(clamp(P.z/length, -1.0f, 1.0f))/M_PI_F;
35
36         return make_float3(u, v, 0.0f);
37 }
38
39 __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
40 {
41         float3 data;
42
43         switch(type) {
44                 case NODE_GEOM_P: data = sd->P; break;
45                 case NODE_GEOM_N: data = sd->N; break;
46 #ifdef __DPDU__
47                 case NODE_GEOM_T: {
48                         if(sd->object != ~0) {
49                                 int attr_offset = find_attribute(kg, sd, ATTR_STD_TANGENT);
50
51                                 if(attr_offset != ATTR_STD_NOT_FOUND) {
52                                         data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
53                                         object_normal_transform(kg, sd, &data);
54                                 }
55                                 else {
56                                         attr_offset = find_attribute(kg, sd, ATTR_STD_GENERATED);
57
58                                         if(attr_offset != ATTR_STD_NOT_FOUND) {
59                                                 data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL);
60                                                 svm_tangent_from_generated(data);
61                                                 object_normal_transform(kg, sd, &data);
62                                         }
63                                         else
64                                                 data = normalize(sd->dPdu);
65                                 }
66                         }
67                         else
68                                 data = normalize(sd->dPdu);
69
70                         break;
71                 }
72 #endif
73                 case NODE_GEOM_I: data = sd->I; break;
74                 case NODE_GEOM_Ng: data = sd->Ng; break;
75 #ifdef __UV__
76                 case NODE_GEOM_uv: data = make_float3(sd->u, sd->v, 0.0f); break;
77 #endif
78         }
79
80         stack_store_float3(stack, out_offset, data);
81 }
82
83 __device void svm_node_geometry_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
84 {
85 #ifdef __RAY_DIFFERENTIALS__
86         float3 data;
87
88         switch(type) {
89                 case NODE_GEOM_P: data = sd->P + sd->dP.dx; break;
90                 case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dx, sd->v + sd->dv.dx, 0.0f); break;
91                 default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
92         }
93
94         stack_store_float3(stack, out_offset, data);
95 #else
96         svm_node_geometry(kg, sd, stack, type, out_offset);
97 #endif
98 }
99
100 __device void svm_node_geometry_bump_dy(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
101 {
102 #ifdef __RAY_DIFFERENTIALS__
103         float3 data;
104
105         switch(type) {
106                 case NODE_GEOM_P: data = sd->P + sd->dP.dy; break;
107                 case NODE_GEOM_uv: data = make_float3(sd->u + sd->du.dy, sd->v + sd->dv.dy, 0.0f); break;
108                 default: svm_node_geometry(kg, sd, stack, type, out_offset); return;
109         }
110
111         stack_store_float3(stack, out_offset, data);
112 #else
113         svm_node_geometry(kg, sd, stack, type, out_offset);
114 #endif
115 }
116
117 /* Object Info */
118
119 __device void svm_node_object_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
120 {
121         float data;
122
123         switch(type) {
124                 case NODE_INFO_OB_LOCATION: {
125                         stack_store_float3(stack, out_offset, object_location(kg, sd));
126                         return;
127                 }
128                 case NODE_INFO_OB_INDEX: data = object_pass_id(kg, sd->object); break;
129                 case NODE_INFO_MAT_INDEX: data = shader_pass_id(kg, sd); break;
130                 case NODE_INFO_OB_RANDOM: data = object_random_number(kg, sd->object); break;
131                 default: data = 0.0f; break;
132         }
133
134         stack_store_float(stack, out_offset, data);
135 }
136
137 /* Particle Info */
138
139 __device void svm_node_particle_info(KernelGlobals *kg, ShaderData *sd, float *stack, uint type, uint out_offset)
140 {
141         switch(type) {
142                 case NODE_INFO_PAR_INDEX: {
143                         uint particle_id = object_particle_id(kg, sd->object);
144                         stack_store_float(stack, out_offset, particle_index(kg, particle_id));
145                         break;
146                 }
147                 case NODE_INFO_PAR_AGE: {
148                         uint particle_id = object_particle_id(kg, sd->object);
149                         stack_store_float(stack, out_offset, particle_age(kg, particle_id));
150                         break;
151                 }
152                 case NODE_INFO_PAR_LIFETIME: {
153                         uint particle_id = object_particle_id(kg, sd->object);
154                         stack_store_float(stack, out_offset, particle_lifetime(kg, particle_id));
155                         break;
156                 }
157                 case NODE_INFO_PAR_LOCATION: {
158                         uint particle_id = object_particle_id(kg, sd->object);
159                         stack_store_float3(stack, out_offset, particle_location(kg, particle_id));
160                         break;
161                 }
162                 #if 0   /* XXX float4 currently not supported in SVM stack */
163                 case NODE_INFO_PAR_ROTATION: {
164                         uint particle_id = object_particle_id(kg, sd->object);
165                         stack_store_float4(stack, out_offset, particle_rotation(kg, particle_id));
166                         break;
167                 }
168                 #endif
169                 case NODE_INFO_PAR_SIZE: {
170                         uint particle_id = object_particle_id(kg, sd->object);
171                         stack_store_float(stack, out_offset, particle_size(kg, particle_id));
172                         break;
173                 }
174                 case NODE_INFO_PAR_VELOCITY: {
175                         uint particle_id = object_particle_id(kg, sd->object);
176                         stack_store_float3(stack, out_offset, particle_velocity(kg, particle_id));
177                         break;
178                 }
179                 case NODE_INFO_PAR_ANGULAR_VELOCITY: {
180                         uint particle_id = object_particle_id(kg, sd->object);
181                         stack_store_float3(stack, out_offset, particle_angular_velocity(kg, particle_id));
182                         break;
183                 }
184         }
185 }
186
187 CCL_NAMESPACE_END
188