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