Cycles Hair: refactoring to support generic attributes for hair curves. There
[blender.git] / intern / cycles / kernel / kernel_curve.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 #ifdef __HAIR__
22
23 /* curve attributes */
24
25 __device float curve_attribute_float(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float *dx, float *dy)
26 {
27         if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
28 #ifdef __RAY_DIFFERENTIALS__
29                 if(dx) *dx = 0.0f;
30                 if(dy) *dy = 0.0f;
31 #endif
32
33                 return kernel_tex_fetch(__attributes_float, offset + sd->curve_seg);
34         }
35         else if(elem == ATTR_ELEMENT_CURVE_KEY) {
36                 float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
37
38                 float f0 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.x));
39                 float f1 = kernel_tex_fetch(__attributes_float, offset + __float_as_int(segment.y));
40
41 #ifdef __RAY_DIFFERENTIALS__
42                 if(dx) *dx = sd->du.dx*(f1 - f0);
43                 if(dy) *dy = 0.0f;
44 #endif
45
46                 return (1.0f - sd->u)*f0 + sd->u*f1;
47         }
48         else {
49 #ifdef __RAY_DIFFERENTIALS__
50                 if(dx) *dx = 0.0f;
51                 if(dy) *dy = 0.0f;
52 #endif
53
54                 return 0.0f;
55         }
56 }
57
58 __device float3 curve_attribute_float3(KernelGlobals *kg, const ShaderData *sd, AttributeElement elem, int offset, float3 *dx, float3 *dy)
59 {
60         if(elem == ATTR_ELEMENT_CURVE_SEGMENT) {
61                 /* idea: we can't derive any useful differentials here, but for tiled
62                  * mipmap image caching it would be useful to avoid reading the highest
63                  * detail level always. maybe a derivative based on the hair density
64                  * could be computed somehow? */
65 #ifdef __RAY_DIFFERENTIALS__
66                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
67                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
68 #endif
69
70                 return float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + sd->curve_seg));
71         }
72         else if(elem == ATTR_ELEMENT_CURVE_KEY) {
73                 float4 segment = kernel_tex_fetch(__curve_segments, sd->curve_seg);
74
75                 float3 f0 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.x)));
76                 float3 f1 = float4_to_float3(kernel_tex_fetch(__attributes_float3, offset + __float_as_int(segment.y)));
77
78 #ifdef __RAY_DIFFERENTIALS__
79                 if(dx) *dx = sd->du.dx*(f1 - f0);
80                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
81 #endif
82
83                 return (1.0f - sd->u)*f0 + sd->u*f1;
84         }
85         else {
86 #ifdef __RAY_DIFFERENTIALS__
87                 if(dx) *dx = make_float3(0.0f, 0.0f, 0.0f);
88                 if(dy) *dy = make_float3(0.0f, 0.0f, 0.0f);
89 #endif
90
91                 return make_float3(0.0f, 0.0f, 0.0f);
92         }
93 }
94
95 /* hair info node functions */
96
97 __device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
98 {
99         int prim = sd->curve_seg;
100         float u = sd->u;
101         float r = 0.0f;
102
103         if(prim != -1) {
104                 float4 v00 = kernel_tex_fetch(__curve_segments, prim);
105
106                 int v1 = __float_as_int(v00.x);
107                 int v2 = __float_as_int(v00.y);
108
109                 float4 P1 = kernel_tex_fetch(__curve_keys, v1);
110                 float4 P2 = kernel_tex_fetch(__curve_keys, v2);
111                 r = (P2.w - P1.w) * u + P1.w;
112         }
113
114         return r*2.0f;
115 }
116
117 __device float3 curve_tangent_normal(KernelGlobals *kg, ShaderData *sd)
118 {       
119         float3 tgN = make_float3(0.0f,0.0f,0.0f);
120
121         if(sd->curve_seg != ~0) {
122                 float normalmix = kernel_data.curve_kernel_data.normalmix;
123
124                 tgN = -(-sd->I - sd->dPdu * (dot(sd->dPdu,-sd->I) * normalmix / len_squared(sd->dPdu)));
125                 tgN = normalize(tgN);
126
127                 /* need to find suitable scaled gd for corrected normal */
128 #if 0
129                 if (kernel_data.curve_kernel_data.use_tangent_normal_correction)
130                         tgN = normalize(tgN - gd * sd->dPdu);
131 #endif
132         }
133
134         return tgN;
135 }
136
137 #endif
138
139 CCL_NAMESPACE_END
140