Merge branch 'blender-v2.81-release'
[blender.git] / intern / cycles / kernel / svm / svm_sky.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 /* Sky texture */
20
21 ccl_device float sky_angle_between(float thetav, float phiv, float theta, float phi)
22 {
23   float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta);
24   return safe_acosf(cospsi);
25 }
26
27 /*
28  * "A Practical Analytic Model for Daylight"
29  * A. J. Preetham, Peter Shirley, Brian Smits
30  */
31 ccl_device float sky_perez_function(float *lam, float theta, float gamma)
32 {
33   float ctheta = cosf(theta);
34   float cgamma = cosf(gamma);
35
36   return (1.0f + lam[0] * expf(lam[1] / ctheta)) *
37          (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma);
38 }
39
40 ccl_device float3 sky_radiance_old(KernelGlobals *kg,
41                                    float3 dir,
42                                    float sunphi,
43                                    float suntheta,
44                                    float radiance_x,
45                                    float radiance_y,
46                                    float radiance_z,
47                                    float *config_x,
48                                    float *config_y,
49                                    float *config_z)
50 {
51   /* convert vector to spherical coordinates */
52   float2 spherical = direction_to_spherical(dir);
53   float theta = spherical.x;
54   float phi = spherical.y;
55
56   /* angle between sun direction and dir */
57   float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
58
59   /* clamp theta to horizon */
60   theta = min(theta, M_PI_2_F - 0.001f);
61
62   /* compute xyY color space values */
63   float x = radiance_y * sky_perez_function(config_y, theta, gamma);
64   float y = radiance_z * sky_perez_function(config_z, theta, gamma);
65   float Y = radiance_x * sky_perez_function(config_x, theta, gamma);
66
67   /* convert to RGB */
68   float3 xyz = xyY_to_xyz(x, y, Y);
69   return xyz_to_rgb(kg, xyz);
70 }
71
72 /*
73  * "An Analytic Model for Full Spectral Sky-Dome Radiance"
74  * Lukas Hosek, Alexander Wilkie
75  */
76 ccl_device float sky_radiance_internal(float *configuration, float theta, float gamma)
77 {
78   float ctheta = cosf(theta);
79   float cgamma = cosf(gamma);
80
81   float expM = expf(configuration[4] * gamma);
82   float rayM = cgamma * cgamma;
83   float mieM = (1.0f + rayM) / powf((1.0f + configuration[8] * configuration[8] -
84                                      2.0f * configuration[8] * cgamma),
85                                     1.5f);
86   float zenith = sqrtf(ctheta);
87
88   return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) *
89          (configuration[2] + configuration[3] * expM + configuration[5] * rayM +
90           configuration[6] * mieM + configuration[7] * zenith);
91 }
92
93 ccl_device float3 sky_radiance_new(KernelGlobals *kg,
94                                    float3 dir,
95                                    float sunphi,
96                                    float suntheta,
97                                    float radiance_x,
98                                    float radiance_y,
99                                    float radiance_z,
100                                    float *config_x,
101                                    float *config_y,
102                                    float *config_z)
103 {
104   /* convert vector to spherical coordinates */
105   float2 spherical = direction_to_spherical(dir);
106   float theta = spherical.x;
107   float phi = spherical.y;
108
109   /* angle between sun direction and dir */
110   float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
111
112   /* clamp theta to horizon */
113   theta = min(theta, M_PI_2_F - 0.001f);
114
115   /* compute xyz color space values */
116   float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x;
117   float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y;
118   float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z;
119
120   /* convert to RGB and adjust strength */
121   return xyz_to_rgb(kg, make_float3(x, y, z)) * (M_2PI_F / 683);
122 }
123
124 ccl_device void svm_node_tex_sky(
125     KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node, int *offset)
126 {
127   /* Define variables */
128   float sunphi, suntheta, radiance_x, radiance_y, radiance_z;
129   float config_x[9], config_y[9], config_z[9];
130
131   /* Load data */
132   uint dir_offset = node.y;
133   uint out_offset = node.z;
134   int sky_model = node.w;
135
136   float4 data = read_node_float(kg, offset);
137   sunphi = data.x;
138   suntheta = data.y;
139   radiance_x = data.z;
140   radiance_y = data.w;
141
142   data = read_node_float(kg, offset);
143   radiance_z = data.x;
144   config_x[0] = data.y;
145   config_x[1] = data.z;
146   config_x[2] = data.w;
147
148   data = read_node_float(kg, offset);
149   config_x[3] = data.x;
150   config_x[4] = data.y;
151   config_x[5] = data.z;
152   config_x[6] = data.w;
153
154   data = read_node_float(kg, offset);
155   config_x[7] = data.x;
156   config_x[8] = data.y;
157   config_y[0] = data.z;
158   config_y[1] = data.w;
159
160   data = read_node_float(kg, offset);
161   config_y[2] = data.x;
162   config_y[3] = data.y;
163   config_y[4] = data.z;
164   config_y[5] = data.w;
165
166   data = read_node_float(kg, offset);
167   config_y[6] = data.x;
168   config_y[7] = data.y;
169   config_y[8] = data.z;
170   config_z[0] = data.w;
171
172   data = read_node_float(kg, offset);
173   config_z[1] = data.x;
174   config_z[2] = data.y;
175   config_z[3] = data.z;
176   config_z[4] = data.w;
177
178   data = read_node_float(kg, offset);
179   config_z[5] = data.x;
180   config_z[6] = data.y;
181   config_z[7] = data.z;
182   config_z[8] = data.w;
183
184   float3 dir = stack_load_float3(stack, dir_offset);
185   float3 f;
186
187   /* Compute Sky */
188   if (sky_model == 0) {
189     f = sky_radiance_old(kg,
190                          dir,
191                          sunphi,
192                          suntheta,
193                          radiance_x,
194                          radiance_y,
195                          radiance_z,
196                          config_x,
197                          config_y,
198                          config_z);
199   }
200   else {
201     f = sky_radiance_new(kg,
202                          dir,
203                          sunphi,
204                          suntheta,
205                          radiance_x,
206                          radiance_y,
207                          radiance_z,
208                          config_x,
209                          config_y,
210                          config_z);
211   }
212
213   stack_store_float3(stack, out_offset, f);
214 }
215
216 CCL_NAMESPACE_END