ff92920c610feb0cf0e930356f0beb64a5b80b7e
[blender.git] / intern / cycles / kernel / svm / svm_attribute.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 /* Attribute Node */
20
21 ccl_device void svm_node_attr_init(KernelGlobals *kg, ShaderData *sd,
22         uint4 node, NodeAttributeType *type,
23         NodeAttributeType *mesh_type, AttributeElement *elem, int *offset, uint *out_offset)
24 {
25         *out_offset = node.z;
26         *type = (NodeAttributeType)node.w;
27         if(ccl_fetch(sd, object) != OBJECT_NONE) {
28                 /* find attribute by unique id */
29                 uint id = node.y;
30                 uint attr_offset = ccl_fetch(sd, object)*kernel_data.bvh.attributes_map_stride;
31                 attr_offset += attribute_primitive_type(kg, sd);
32                 uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
33                 
34                 while(attr_map.x != id) {
35                         if(UNLIKELY(attr_map.x == ATTR_STD_NONE)) {
36                                 *elem = ATTR_ELEMENT_NONE;
37                                 *offset = 0;
38                                 *mesh_type = (NodeAttributeType)node.w;
39                                 return;
40                         }
41                         attr_offset += ATTR_PRIM_TYPES;
42                         attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
43                 }
44
45                 /* return result */
46                 *elem = (AttributeElement)attr_map.y;
47                 *offset = as_int(attr_map.z);
48                 *mesh_type = (NodeAttributeType)attr_map.w;
49         }
50         else {
51                 /* background */
52                 *elem = ATTR_ELEMENT_NONE;
53                 *offset = 0;
54                 *mesh_type = (NodeAttributeType)node.w;
55         }
56 }
57
58 ccl_device void svm_node_attr(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
59 {
60         NodeAttributeType type, mesh_type;
61         AttributeElement elem;
62         uint out_offset;
63         int offset;
64
65         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
66
67         /* fetch and store attribute */
68         if(type == NODE_ATTR_FLOAT) {
69                 if(mesh_type == NODE_ATTR_FLOAT) {
70                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
71                         stack_store_float(stack, out_offset, f);
72                 }
73                 else {
74                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
75                         stack_store_float(stack, out_offset, average(f));
76                 }
77         }
78         else {
79                 if(mesh_type == NODE_ATTR_FLOAT3) {
80                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, NULL);
81                         stack_store_float3(stack, out_offset, f);
82                 }
83                 else {
84                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, NULL);
85                         stack_store_float3(stack, out_offset, make_float3(f, f, f));
86                 }
87         }
88 }
89
90 ccl_device void svm_node_attr_bump_dx(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
91 {
92         NodeAttributeType type, mesh_type;
93         AttributeElement elem;
94         uint out_offset;
95         int offset;
96
97         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
98
99         /* fetch and store attribute */
100         if(type == NODE_ATTR_FLOAT) {
101                 if(mesh_type == NODE_ATTR_FLOAT) {
102                         float dx;
103                         float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
104                         stack_store_float(stack, out_offset, f+dx);
105                 }
106                 else {
107                         float3 dx;
108                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
109                         stack_store_float(stack, out_offset, average(f+dx));
110                 }
111         }
112         else {
113                 if(mesh_type == NODE_ATTR_FLOAT3) {
114                         float3 dx;
115                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, &dx, NULL);
116                         stack_store_float3(stack, out_offset, f+dx);
117                 }
118                 else {
119                         float dx;
120                         float f = primitive_attribute_float(kg, sd, elem, offset, &dx, NULL);
121                         stack_store_float3(stack, out_offset, make_float3(f+dx, f+dx, f+dx));
122                 }
123         }
124 }
125
126 ccl_device void svm_node_attr_bump_dy(KernelGlobals *kg,
127                                       ShaderData *sd,
128                                       float *stack,
129                                       uint4 node)
130 {
131         NodeAttributeType type, mesh_type;
132         AttributeElement elem;
133         uint out_offset;
134         int offset;
135
136         svm_node_attr_init(kg, sd, node, &type, &mesh_type, &elem, &offset, &out_offset);
137
138         /* fetch and store attribute */
139         if(type == NODE_ATTR_FLOAT) {
140                 if(mesh_type == NODE_ATTR_FLOAT) {
141                         float dy;
142                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
143                         stack_store_float(stack, out_offset, f+dy);
144                 }
145                 else {
146                         float3 dy;
147                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
148                         stack_store_float(stack, out_offset, average(f+dy));
149                 }
150         }
151         else {
152                 if(mesh_type == NODE_ATTR_FLOAT3) {
153                         float3 dy;
154                         float3 f = primitive_attribute_float3(kg, sd, elem, offset, NULL, &dy);
155                         stack_store_float3(stack, out_offset, f+dy);
156                 }
157                 else {
158                         float dy;
159                         float f = primitive_attribute_float(kg, sd, elem, offset, NULL, &dy);
160                         stack_store_float3(stack, out_offset, make_float3(f+dy, f+dy, f+dy));
161                 }
162         }
163 }
164
165 CCL_NAMESPACE_END
166