svn merge -r41655:41715 ^/trunk/blender --- this is the real cycles merge, needs...
[blender.git] / intern / cycles / kernel / svm / svm_sky.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 __device float3 xyY_to_xyz(float x, float y, float Y)
22 {
23         float X, Z;
24
25         if(y != 0.0f) X = (x / y) * Y;
26         else X = 0.0f;
27
28         if(y != 0.0f && Y != 0.0f) Z = (1.0f - x - y) / y * Y;
29         else Z = 0.0f;
30
31         return make_float3(X, Y, Z);
32 }
33
34 __device float3 xyz_to_rgb(float x, float y, float z)
35 {
36         return make_float3(3.240479f * x + -1.537150f * y + -0.498535f * z,
37                                           -0.969256f * x +  1.875991f * y +  0.041556f * z,
38                                            0.055648f * x + -0.204043f * y +  1.057311f * z);
39 }
40
41 /*
42  * "A Practical Analytic Model for Daylight"
43  * A. J. Preetham, Peter Shirley, Brian Smits
44  */
45
46 __device float sky_angle_between(float thetav, float phiv, float theta, float phi)
47 {
48         float cospsi = sinf(thetav)*sinf(theta)*cosf(phi - phiv) + cosf(thetav)*cosf(theta);
49         return safe_acosf(cospsi);
50 }
51
52 __device float sky_perez_function(__constant float *lam, float theta, float gamma)
53 {
54         float ctheta = cosf(theta);
55         float cgamma = cosf(gamma);
56
57         return (1.0f + lam[0]*expf(lam[1]/ctheta)) * (1.0f + lam[2]*expf(lam[3]*gamma)  + lam[4]*cgamma*cgamma);
58 }
59
60 __device float3 sky_radiance(KernelGlobals *kg, float3 dir)
61 {
62         /* convert vector to spherical coordinates */
63         float2 spherical = direction_to_spherical(dir);
64         float theta = spherical.x;
65         float phi = spherical.y;
66
67         /* angle between sun direction and dir */
68         float gamma = sky_angle_between(theta, phi, kernel_data.sunsky.theta, kernel_data.sunsky.phi);
69
70         /* clamp theta to horizon */
71         theta = min(theta, M_PI_2_F - 0.001f);
72
73         /* compute xyY color space values */
74         float x = kernel_data.sunsky.zenith_x * sky_perez_function(kernel_data.sunsky.perez_x, theta, gamma);
75         float y = kernel_data.sunsky.zenith_y * sky_perez_function(kernel_data.sunsky.perez_y, theta, gamma);
76         float Y = kernel_data.sunsky.zenith_Y * sky_perez_function(kernel_data.sunsky.perez_Y, theta, gamma);
77
78         /* convert to RGB */
79         float3 xyz = xyY_to_xyz(x, y, Y);
80         return xyz_to_rgb(xyz.x, xyz.y, xyz.z);
81 }
82
83 __device void svm_node_tex_sky(KernelGlobals *kg, ShaderData *sd, float *stack, uint dir_offset, uint out_offset)
84 {
85         float3 dir = stack_load_float3(stack, dir_offset);
86         float3 f = sky_radiance(kg, dir);
87
88         stack_store_float3(stack, out_offset, f);
89 }
90
91 CCL_NAMESPACE_END
92