Blender  V3.3
sky.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
7 
8 /* Sky texture */
9 
10 ccl_device float sky_angle_between(float thetav, float phiv, float theta, float phi)
11 {
12  float cospsi = sinf(thetav) * sinf(theta) * cosf(phi - phiv) + cosf(thetav) * cosf(theta);
13  return safe_acosf(cospsi);
14 }
15 
16 /*
17  * "A Practical Analytic Model for Daylight"
18  * A. J. Preetham, Peter Shirley, Brian Smits
19  */
20 ccl_device float sky_perez_function(ccl_private float *lam, float theta, float gamma)
21 {
22  float ctheta = cosf(theta);
23  float cgamma = cosf(gamma);
24 
25  return (1.0f + lam[0] * expf(lam[1] / ctheta)) *
26  (1.0f + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma);
27 }
28 
30  float3 dir,
31  float sunphi,
32  float suntheta,
33  float radiance_x,
34  float radiance_y,
35  float radiance_z,
36  ccl_private float *config_x,
37  ccl_private float *config_y,
38  ccl_private float *config_z)
39 {
40  /* convert vector to spherical coordinates */
41  float2 spherical = direction_to_spherical(dir);
42  float theta = spherical.x;
43  float phi = spherical.y;
44 
45  /* angle between sun direction and dir */
46  float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
47 
48  /* clamp theta to horizon */
49  theta = min(theta, M_PI_2_F - 0.001f);
50 
51  /* compute xyY color space values */
52  float x = radiance_y * sky_perez_function(config_y, theta, gamma);
53  float y = radiance_z * sky_perez_function(config_z, theta, gamma);
54  float Y = radiance_x * sky_perez_function(config_x, theta, gamma);
55 
56  /* convert to RGB */
57  float3 xyz = xyY_to_xyz(x, y, Y);
58  return xyz_to_rgb_clamped(kg, xyz);
59 }
60 
61 /*
62  * "An Analytic Model for Full Spectral Sky-Dome Radiance"
63  * Lukas Hosek, Alexander Wilkie
64  */
65 ccl_device float sky_radiance_internal(ccl_private float *configuration, float theta, float gamma)
66 {
67  float ctheta = cosf(theta);
68  float cgamma = cosf(gamma);
69 
70  float expM = expf(configuration[4] * gamma);
71  float rayM = cgamma * cgamma;
72  float mieM = (1.0f + rayM) / powf((1.0f + configuration[8] * configuration[8] -
73  2.0f * configuration[8] * cgamma),
74  1.5f);
75  float zenith = sqrtf(ctheta);
76 
77  return (1.0f + configuration[0] * expf(configuration[1] / (ctheta + 0.01f))) *
78  (configuration[2] + configuration[3] * expM + configuration[5] * rayM +
79  configuration[6] * mieM + configuration[7] * zenith);
80 }
81 
83  float3 dir,
84  float sunphi,
85  float suntheta,
86  float radiance_x,
87  float radiance_y,
88  float radiance_z,
89  ccl_private float *config_x,
90  ccl_private float *config_y,
91  ccl_private float *config_z)
92 {
93  /* convert vector to spherical coordinates */
94  float2 spherical = direction_to_spherical(dir);
95  float theta = spherical.x;
96  float phi = spherical.y;
97 
98  /* angle between sun direction and dir */
99  float gamma = sky_angle_between(theta, phi, suntheta, sunphi);
100 
101  /* clamp theta to horizon */
102  theta = min(theta, M_PI_2_F - 0.001f);
103 
104  /* compute xyz color space values */
105  float x = sky_radiance_internal(config_x, theta, gamma) * radiance_x;
106  float y = sky_radiance_internal(config_y, theta, gamma) * radiance_y;
107  float z = sky_radiance_internal(config_z, theta, gamma) * radiance_z;
108 
109  /* convert to RGB and adjust strength */
110  return xyz_to_rgb_clamped(kg, make_float3(x, y, z)) * (M_2PI_F / 683);
111 }
112 
113 /* Nishita improved sky model */
115 {
116  return make_float3(cosf(lat) * cosf(lon), cosf(lat) * sinf(lon), sinf(lat));
117 }
118 
120  float3 dir,
121  float3 pixel_bottom,
122  float3 pixel_top,
123  ccl_private float *nishita_data,
124  uint texture_id)
125 {
126  /* definitions */
127  float sun_elevation = nishita_data[0];
128  float sun_rotation = nishita_data[1];
129  float angular_diameter = nishita_data[2];
130  float sun_intensity = nishita_data[3];
131  bool sun_disc = (angular_diameter >= 0.0f);
132  float3 xyz;
133  /* convert dir to spherical coordinates */
134  float2 direction = direction_to_spherical(dir);
135  /* render above the horizon */
136  if (dir.z >= 0.0f) {
137  /* definitions */
138  float3 sun_dir = geographical_to_direction(sun_elevation, sun_rotation + M_PI_2_F);
139  float sun_dir_angle = precise_angle(dir, sun_dir);
140  float half_angular = angular_diameter / 2.0f;
141  float dir_elevation = M_PI_2_F - direction.x;
142 
143  /* if ray inside sun disc render it, otherwise render sky */
144  if (sun_disc && sun_dir_angle < half_angular) {
145  /* get 2 pixels data */
146  float y;
147 
148  /* sun interpolation */
149  if (sun_elevation - half_angular > 0.0f) {
150  if (sun_elevation + half_angular > 0.0f) {
151  y = ((dir_elevation - sun_elevation) / angular_diameter) + 0.5f;
152  xyz = interp(pixel_bottom, pixel_top, y) * sun_intensity;
153  }
154  }
155  else {
156  if (sun_elevation + half_angular > 0.0f) {
157  y = dir_elevation / (sun_elevation + half_angular);
158  xyz = interp(pixel_bottom, pixel_top, y) * sun_intensity;
159  }
160  }
161  /* limb darkening, coefficient is 0.6f */
162  float limb_darkening = (1.0f -
163  0.6f * (1.0f - sqrtf(1.0f - sqr(sun_dir_angle / half_angular))));
164  xyz *= limb_darkening;
165  }
166  /* sky */
167  else {
168  /* sky interpolation */
169  float x = (direction.y + M_PI_F + sun_rotation) / M_2PI_F;
170  /* more pixels toward horizon compensation */
171  float y = safe_sqrtf(dir_elevation / M_PI_2_F);
172  if (x > 1.0f) {
173  x -= 1.0f;
174  }
175  xyz = float4_to_float3(kernel_tex_image_interp(kg, texture_id, x, y));
176  }
177  }
178  /* ground */
179  else {
180  if (dir.z < -0.4f) {
181  xyz = make_float3(0.0f, 0.0f, 0.0f);
182  }
183  else {
184  /* black ground fade */
185  float fade = 1.0f + dir.z * 2.5f;
186  fade = sqr(fade) * fade;
187  /* interpolation */
188  float x = (direction.y + M_PI_F + sun_rotation) / M_2PI_F;
189  if (x > 1.0f) {
190  x -= 1.0f;
191  }
192  xyz = float4_to_float3(kernel_tex_image_interp(kg, texture_id, x, -0.5)) * fade;
193  }
194  }
195 
196  /* convert to RGB */
197  return xyz_to_rgb_clamped(kg, xyz);
198 }
199 
201  KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, uint4 node, int offset)
202 {
203  /* Load data */
204  uint dir_offset = node.y;
205  uint out_offset = node.z;
206  int sky_model = node.w;
207 
208  float3 dir = stack_load_float3(stack, dir_offset);
209  float3 f;
210 
211  /* Preetham and Hosek share the same data */
212  if (sky_model == 0 || sky_model == 1) {
213  /* Define variables */
214  float sunphi, suntheta, radiance_x, radiance_y, radiance_z;
215  float config_x[9], config_y[9], config_z[9];
216 
218  sunphi = data.x;
219  suntheta = data.y;
220  radiance_x = data.z;
221  radiance_y = data.w;
222 
223  data = read_node_float(kg, &offset);
224  radiance_z = data.x;
225  config_x[0] = data.y;
226  config_x[1] = data.z;
227  config_x[2] = data.w;
228 
229  data = read_node_float(kg, &offset);
230  config_x[3] = data.x;
231  config_x[4] = data.y;
232  config_x[5] = data.z;
233  config_x[6] = data.w;
234 
235  data = read_node_float(kg, &offset);
236  config_x[7] = data.x;
237  config_x[8] = data.y;
238  config_y[0] = data.z;
239  config_y[1] = data.w;
240 
241  data = read_node_float(kg, &offset);
242  config_y[2] = data.x;
243  config_y[3] = data.y;
244  config_y[4] = data.z;
245  config_y[5] = data.w;
246 
247  data = read_node_float(kg, &offset);
248  config_y[6] = data.x;
249  config_y[7] = data.y;
250  config_y[8] = data.z;
251  config_z[0] = data.w;
252 
253  data = read_node_float(kg, &offset);
254  config_z[1] = data.x;
255  config_z[2] = data.y;
256  config_z[3] = data.z;
257  config_z[4] = data.w;
258 
259  data = read_node_float(kg, &offset);
260  config_z[5] = data.x;
261  config_z[6] = data.y;
262  config_z[7] = data.z;
263  config_z[8] = data.w;
264 
265  /* Compute Sky */
266  if (sky_model == 0) {
267  f = sky_radiance_preetham(kg,
268  dir,
269  sunphi,
270  suntheta,
271  radiance_x,
272  radiance_y,
273  radiance_z,
274  config_x,
275  config_y,
276  config_z);
277  }
278  else {
279  f = sky_radiance_hosek(kg,
280  dir,
281  sunphi,
282  suntheta,
283  radiance_x,
284  radiance_y,
285  radiance_z,
286  config_x,
287  config_y,
288  config_z);
289  }
290  }
291  /* Nishita */
292  else {
293  /* Define variables */
294  float nishita_data[4];
295 
297  float3 pixel_bottom = make_float3(data.x, data.y, data.z);
298  float3 pixel_top;
299  pixel_top.x = data.w;
300 
301  data = read_node_float(kg, &offset);
302  pixel_top.y = data.x;
303  pixel_top.z = data.y;
304  nishita_data[0] = data.z;
305  nishita_data[1] = data.w;
306 
307  data = read_node_float(kg, &offset);
308  nishita_data[2] = data.x;
309  nishita_data[3] = data.y;
310  uint texture_id = __float_as_uint(data.z);
311 
312  /* Compute Sky */
313  f = sky_radiance_nishita(kg, dir, pixel_bottom, pixel_top, nishita_data, texture_id);
314  }
315 
316  stack_store_float3(stack, out_offset, f);
317  return offset;
318 }
319 
MINLINE float safe_sqrtf(float a)
MINLINE float safe_acosf(float a)
unsigned int uint
Definition: BLI_sys_types.h:67
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
float float4[4]
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its Y
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define expf(x)
Definition: cuda/compat.h:106
#define ccl_private
Definition: cuda/compat.h:48
#define powf(x, y)
Definition: cuda/compat.h:103
#define ccl_device_noinline
Definition: cuda/compat.h:40
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
CCL_NAMESPACE_BEGIN ccl_device float2 direction_to_spherical(float3 dir)
OperationNode * node
const KernelGlobalsCPU *ccl_restrict KernelGlobals
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
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)
ShaderData
Definition: kernel/types.h:925
ccl_device float3 xyz_to_rgb_clamped(KernelGlobals kg, float3 xyz)
ccl_device_inline float2 interp(const float2 &a, const float2 &b, float t)
Definition: math_float2.h:232
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
ccl_device float4 kernel_tex_image_interp(KernelGlobals kg, int id, float x, float y)
color xyY_to_xyz(float x, float y, float Y)
Definition: node_color.h:46
CCL_NAMESPACE_BEGIN ccl_device float fade(float t)
Definition: noise.h:15
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:82
ccl_device_noinline int svm_node_tex_sky(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, uint4 node, int offset)
Definition: sky.h:200
ccl_device float3 geographical_to_direction(float lat, float lon)
Definition: sky.h:114
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:29
CCL_NAMESPACE_BEGIN ccl_device float sky_angle_between(float thetav, float phiv, float theta, float phi)
Definition: sky.h:10
ccl_device float sky_perez_function(ccl_private float *lam, float theta, float gamma)
Definition: sky.h:20
ccl_device float sky_radiance_internal(ccl_private float *configuration, float theta, float gamma)
Definition: sky.h:65
ccl_device float3 sky_radiance_nishita(KernelGlobals kg, float3 dir, float3 pixel_bottom, float3 pixel_top, ccl_private float *nishita_data, uint texture_id)
Definition: sky.h:119
#define min(a, b)
Definition: sort.c:35
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
ccl_device_inline uint __float_as_uint(float f)
Definition: util/math.h:263
#define M_PI_2_F
Definition: util/math.h:37
ccl_device_inline float sqr(float a)
Definition: util/math.h:746
#define M_2PI_F
Definition: util/math.h:60
ccl_device_inline float precise_angle(float3 a, float3 b)
Definition: util/math.h:927
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline float3 float4_to_float3(const float4 a)
Definition: util/math.h:500