Blender V5.0
sky.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
7#include "kernel/image.h"
8
9#include "kernel/svm/types.h"
10#include "kernel/svm/util.h"
11
13
14#include "util/color.h"
15
17
18/* Sky texture */
19
20ccl_device float sky_angle_between(const float thetav,
21 const float phiv,
22 const float theta,
23 const float phi)
24{
25 const float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta);
26 return safe_acosf(cospsi);
27}
28
29/*
30 * "A Practical Analytic Model for Daylight"
31 * A. J. Preetham, Peter Shirley, Brian Smits
32 */
34 const float theta,
35 const float gamma)
36{
37 const float ctheta = cosf(theta);
38 const float cgamma = cosf(gamma);
39
40 return (1.0f + lam[0] * expf(lam[1] / ctheta)) *
41 (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma);
42}
43
45 const float3 dir,
46 const float sunphi,
47 const float suntheta,
48 const float radiance_x,
49 const float radiance_y,
50 const float radiance_z,
51 ccl_private float *config_x,
52 ccl_private float *config_y,
53 ccl_private float *config_z)
54{
55 /* convert vector to spherical coordinates */
56 const float2 spherical = direction_to_spherical(dir);
57 float theta = spherical.x;
58 const float phi = -spherical.y + M_PI_2_F;
59
60 /* angle between sun direction and dir */
61 const float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
62
63 /* clamp theta to horizon */
64 theta = min(theta, M_PI_2_F - 0.001f);
65
66 /* compute xyY color space values */
67 const float x = radiance_y * sky_perez_function(config_y, theta, gamma);
68 const float y = radiance_z * sky_perez_function(config_z, theta, gamma);
69 const float Y = radiance_x * sky_perez_function(config_x, theta, gamma);
70
71 /* convert to RGB */
72 const float3 xyz = xyY_to_xyz(x, y, Y);
73 return xyz_to_rgb_clamped(kg, xyz);
74}
75
76/*
77 * "An Analytic Model for Full Spectral Sky-Dome Radiance"
78 * Lukas Hosek, Alexander Wilkie
79 */
80ccl_device float sky_radiance_internal(const ccl_private float *configuration,
81 const float theta,
82 const float gamma)
83{
84 const float ctheta = cosf(theta);
85 const float cgamma = cosf(gamma);
86
87 const float expM = expf(configuration[4] * gamma);
88 const float rayM = cgamma * cgamma;
89 const float mieM = (1.0f + rayM) / powf((1.0f + configuration[8] * configuration[8] -
90 2.0f * configuration[8] * cgamma),
91 1.5f);
92 const float zenith = sqrtf(ctheta);
93
94 return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) *
95 (configuration[2] + configuration[3] * expM + configuration[5] * rayM +
96 configuration[6] * mieM + configuration[7] * zenith);
97}
98
100 const float3 dir,
101 const float sunphi,
102 const float suntheta,
103 const float radiance_x,
104 const float radiance_y,
105 const float radiance_z,
106 ccl_private float *config_x,
107 ccl_private float *config_y,
108 ccl_private float *config_z)
109{
110 /* convert vector to spherical coordinates */
111 const float2 spherical = direction_to_spherical(dir);
112 float theta = spherical.x;
113 const float phi = -spherical.y + M_PI_2_F;
114
115 /* angle between sun direction and dir */
116 const float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
117
118 /* clamp theta to horizon */
119 theta = min(theta, M_PI_2_F - 0.001f);
120
121 /* compute xyz color space values */
122 const float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x;
123 const float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y;
124 const float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z;
125
126 /* convert to RGB and adjust strength */
127 return xyz_to_rgb_clamped(kg, make_float3(x, y, z)) * (M_2PI_F / 683);
128}
129
130/* Nishita improved sky model */
131ccl_device float3 geographical_to_direction(const float lat, const float lon)
132{
133 return spherical_to_direction(lat - M_PI_2_F, lon - M_PI_2_F);
134}
135
137 const float3 dir,
138 const uint32_t path_flag,
139 const float3 pixel_bottom,
140 const float3 pixel_top,
141 const ccl_private float *sky_data,
142 const uint texture_id)
143{
144 /* Definitions */
145 const float sun_elevation = sky_data[0];
146 const float sun_rotation = sky_data[1];
147 const float angular_diameter = sky_data[2];
148 const float sun_intensity = sky_data[3];
149 const float earth_intersection_angle = sky_data[4];
150 const bool sun_disc = (angular_diameter >= 0.0f);
151 float3 xyz = zero_float3();
152 const float2 direction = direction_to_spherical(dir);
153 const float3 sun_dir = spherical_to_direction(sun_elevation - M_PI_2_F, sun_rotation - M_PI_2_F);
154 const float sun_dir_angle = precise_angle(dir, sun_dir);
155 const float half_angular = angular_diameter * 0.5f;
156 const float dir_elevation = M_PI_2_F - direction.x;
157
158 /* If the ray is inside the Sun disc, render it, otherwise render the sky.
159 * Alternatively, ignore the Sun if we're evaluating the background texture. */
160 if (sun_disc && sun_dir_angle < half_angular && dir_elevation > earth_intersection_angle &&
161 !((path_flag & PATH_RAY_IMPORTANCE_BAKE) && kernel_data.background.use_sun_guiding))
162 {
163 /* Sun interpolation */
164 const float y = ((dir_elevation - sun_elevation) / angular_diameter) + 0.5f;
165 /* Limb darkening, coefficient is 0.6f */
166 const float limb_darkening = (1.0f -
167 0.6f * (1.0f - sqrtf(1.0f - sqr(sun_dir_angle / half_angular))));
168 xyz = mix(pixel_bottom, pixel_top, y) * sun_intensity * limb_darkening;
169 }
170
171 /* Sky */
172 const float x = fractf((-direction.y - M_PI_2_F + sun_rotation) * M_1_2PI_F);
173 /* Undo the non-linear transformation from the sky LUT */
174 const float y = copysignf(sqrtf(fabsf(dir_elevation) * M_2_PI_F), dir_elevation) * 0.5f + 0.5f;
175 xyz += make_float3(kernel_tex_image_interp(kg, texture_id, x, y));
176
177 /* Convert to RGB */
178 return xyz_to_rgb_clamped(kg, xyz);
179}
180
182 const uint32_t path_flag,
183 ccl_private float *stack,
184 const uint4 node,
185 int offset)
186{
187 /* Load data */
188 const uint dir_offset = node.y;
189 const uint out_offset = node.z;
190 const NodeSkyType sky_type = NodeSkyType(node.w);
191
192 const float3 dir = stack_load_float3(stack, dir_offset);
193 float3 rgb;
194
195 /* Preetham and Hosek share the same data */
196 if (sky_type == NODE_SKY_PREETHAM || sky_type == NODE_SKY_HOSEK) {
197 /* Define variables */
198 float sunphi;
199 float suntheta;
200 float radiance_x;
201 float radiance_y;
202 float radiance_z;
203 float config_x[9];
204 float config_y[9];
205 float config_z[9];
206
207 float4 data = read_node_float(kg, &offset);
208 sunphi = data.x;
209 suntheta = data.y;
210 radiance_x = data.z;
211 radiance_y = data.w;
212
213 data = read_node_float(kg, &offset);
214 radiance_z = data.x;
215 config_x[0] = data.y;
216 config_x[1] = data.z;
217 config_x[2] = data.w;
218
219 data = read_node_float(kg, &offset);
220 config_x[3] = data.x;
221 config_x[4] = data.y;
222 config_x[5] = data.z;
223 config_x[6] = data.w;
224
225 data = read_node_float(kg, &offset);
226 config_x[7] = data.x;
227 config_x[8] = data.y;
228 config_y[0] = data.z;
229 config_y[1] = data.w;
230
231 data = read_node_float(kg, &offset);
232 config_y[2] = data.x;
233 config_y[3] = data.y;
234 config_y[4] = data.z;
235 config_y[5] = data.w;
236
237 data = read_node_float(kg, &offset);
238 config_y[6] = data.x;
239 config_y[7] = data.y;
240 config_y[8] = data.z;
241 config_z[0] = data.w;
242
243 data = read_node_float(kg, &offset);
244 config_z[1] = data.x;
245 config_z[2] = data.y;
246 config_z[3] = data.z;
247 config_z[4] = data.w;
248
249 data = read_node_float(kg, &offset);
250 config_z[5] = data.x;
251 config_z[6] = data.y;
252 config_z[7] = data.z;
253 config_z[8] = data.w;
254
255 /* Compute Sky */
256 if (sky_type == NODE_SKY_PREETHAM) {
257 rgb = sky_radiance_preetham(kg,
258 dir,
259 sunphi,
260 suntheta,
261 radiance_x,
262 radiance_y,
263 radiance_z,
264 config_x,
265 config_y,
266 config_z);
267 }
268 else {
269 rgb = sky_radiance_hosek(kg,
270 dir,
271 sunphi,
272 suntheta,
273 radiance_x,
274 radiance_y,
275 radiance_z,
276 config_x,
277 config_y,
278 config_z);
279 }
280 }
281 /* Nishita */
282 else {
283 float4 data = read_node_float(kg, &offset);
284 const float3 pixel_bottom = make_float3(data.x, data.y, data.z);
285 float3 pixel_top;
286 pixel_top.x = data.w;
287
288 float sky_data[5];
289 data = read_node_float(kg, &offset);
290 pixel_top.y = data.x;
291 pixel_top.z = data.y;
292 sky_data[0] = data.z;
293 sky_data[1] = data.w;
294
295 data = read_node_float(kg, &offset);
296 sky_data[2] = data.x;
297 sky_data[3] = data.y;
298 sky_data[4] = data.z;
299 const uint texture_id = __float_as_uint(data.w);
300
301 /* Compute Sky */
302 rgb = sky_radiance_nishita(kg, dir, path_flag, pixel_bottom, pixel_top, sky_data, texture_id);
303 }
304
305 stack_store_float3(stack, out_offset, rgb);
306 return offset;
307}
308
MINLINE float safe_acosf(float a)
unsigned int uint
#define Y
BMesh const char void * data
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, const int id, const float x, float y)
ccl_device_inline float4 read_node_float(KernelGlobals kg, ccl_private int *const offset)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
CCL_NAMESPACE_BEGIN ccl_device float2 direction_to_spherical(const float3 dir)
ccl_device float3 spherical_to_direction(const float theta, const float phi)
#define kernel_data
#define M_2_PI_F
#define M_PI_2_F
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define M_1_2PI_F
#define ccl_device_noinline
#define expf(x)
#define powf(x, y)
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define copysignf(x, y)
#define __float_as_uint(x)
NodeSkyType
@ NODE_SKY_PREETHAM
@ NODE_SKY_HOSEK
@ PATH_RAY_IMPORTANCE_BAKE
ccl_device float3 xyz_to_rgb_clamped(KernelGlobals kg, const float3 xyz)
ccl_device_inline float precise_angle(const float3 a, const float3 b)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
color xyY_to_xyz(float x, float y, float Y)
Definition node_color.h:52
#define mix
#define sqr
#define fabsf
#define sqrtf
#define ccl_device
#define M_2PI_F
#define sinf
#define fractf
#define cosf
ccl_device float3 geographical_to_direction(const float lat, const float lon)
Definition sky.h:131
ccl_device float sky_perez_function(const ccl_private float *lam, const float theta, const float gamma)
Definition sky.h:33
CCL_NAMESPACE_BEGIN ccl_device float sky_angle_between(const float thetav, const float phiv, const float theta, const float phi)
Definition sky.h:20
ccl_device float3 sky_radiance_hosek(KernelGlobals kg, const float3 dir, const float sunphi, const float suntheta, const float radiance_x, const float radiance_y, const float radiance_z, ccl_private float *config_x, ccl_private float *config_y, ccl_private float *config_z)
Definition sky.h:99
ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg, const uint32_t path_flag, ccl_private float *stack, const uint4 node, int offset)
Definition sky.h:181
ccl_device float3 sky_radiance_preetham(KernelGlobals kg, const float3 dir, const float sunphi, const float suntheta, const float radiance_x, const float radiance_y, const float radiance_z, ccl_private float *config_x, ccl_private float *config_y, ccl_private float *config_z)
Definition sky.h:44
ccl_device float sky_radiance_internal(const ccl_private float *configuration, const float theta, const float gamma)
Definition sky.h:80
ccl_device float3 sky_radiance_nishita(KernelGlobals kg, const float3 dir, const uint32_t path_flag, const float3 pixel_bottom, const float3 pixel_top, const ccl_private float *sky_data, const uint texture_id)
Definition sky.h:136
#define min(a, b)
Definition sort.cc:36
float x
float y
float z
Definition sky_math.h:136
float y
Definition sky_math.h:136
float x
Definition sky_math.h:136
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13