656357be52d474560d9db17e6c5776659bd6e085
[blender.git] / intern / cycles / kernel / svm / svm_displace.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 /* Bump Node */
20
21 ccl_device void svm_node_set_bump(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node)
22 {
23 #ifdef __RAY_DIFFERENTIALS__
24         /* get normal input */
25         uint normal_offset, distance_offset, invert, use_object_space;
26         decode_node_uchar4(node.y, &normal_offset, &distance_offset, &invert, &use_object_space);
27
28         float3 normal_in = stack_valid(normal_offset)? stack_load_float3(stack, normal_offset): sd->N;
29
30         float3 dPdx = sd->dP.dx;
31         float3 dPdy = sd->dP.dy;
32
33         if(use_object_space) {
34                 object_inverse_normal_transform(kg, sd, &normal_in);
35                 object_inverse_dir_transform(kg, sd, &dPdx);
36                 object_inverse_dir_transform(kg, sd, &dPdy);
37         }
38
39         /* get surface tangents from normal */
40         float3 Rx = cross(dPdy, normal_in);
41         float3 Ry = cross(normal_in, dPdx);
42
43         /* get bump values */
44         uint c_offset, x_offset, y_offset, strength_offset;
45         decode_node_uchar4(node.z, &c_offset, &x_offset, &y_offset, &strength_offset);
46
47         float h_c = stack_load_float(stack, c_offset);
48         float h_x = stack_load_float(stack, x_offset);
49         float h_y = stack_load_float(stack, y_offset);
50
51         /* compute surface gradient and determinant */
52         float det = dot(dPdx, Rx);
53         float3 surfgrad = (h_x - h_c)*Rx + (h_y - h_c)*Ry;
54
55         float absdet = fabsf(det);
56
57         float strength = stack_load_float(stack, strength_offset);
58         float distance = stack_load_float(stack, distance_offset);
59
60         if(invert)
61                 distance *= -1.0f;
62
63         strength = max(strength, 0.0f);
64
65         /* compute and output perturbed normal */
66         float3 normal_out = safe_normalize(absdet*normal_in - distance*signf(det)*surfgrad);
67         if(is_zero(normal_out)) {
68                 normal_out = normal_in;
69         }
70         else {
71                 normal_out = normalize(strength*normal_out + (1.0f - strength)*normal_in);
72         }
73
74         if(use_object_space) {
75                 object_normal_transform(kg, sd, &normal_out);
76         }
77
78         stack_store_float3(stack, node.w, normal_out);
79 #endif
80 }
81
82 /* Displacement Node */
83
84 ccl_device void svm_node_set_displacement(KernelGlobals *kg, ShaderData *sd, float *stack, uint fac_offset)
85 {
86         float d = stack_load_float(stack, fac_offset);
87
88         float3 dP = sd->N;
89         object_inverse_normal_transform(kg, sd, &dP);
90
91         dP *= d*0.1f; /* todo: get rid of this factor */
92
93         object_dir_transform(kg, sd, &dP);
94
95         sd->P += dP;
96 }
97
98 CCL_NAMESPACE_END
99