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