Blender V4.3
node_shader_tex_sky.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2005 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "node_shader_util.hh"
6#include "node_util.hh"
7#include "sky_model.h"
8
9#include "BLI_math_rotation.h"
10#include "BLI_task.hh"
11
12#include "BKE_context.hh"
13#include "BKE_scene.hh"
14#include "BKE_texture.h"
15
16#include "RNA_access.hh"
17
18#include "UI_interface.hh"
19#include "UI_resources.hh"
20
22
24
26{
27 b.add_input<decl::Vector>("Vector").hide_value();
28 b.add_output<decl::Color>("Color").no_muted_links();
29}
30
32{
33 uiItemR(layout, ptr, "sky_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
34
35 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_PREETHAM) {
36 uiItemR(layout, ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
37 uiItemR(layout, ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
38 }
39 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_HOSEK) {
40 uiItemR(layout, ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
41 uiItemR(layout, ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
42 uiItemR(layout, ptr, "ground_albedo", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
43 }
44 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NISHITA) {
45 Scene *scene = CTX_data_scene(C);
47 uiItemL(layout, RPT_("Sun disc not available in EEVEE"), ICON_ERROR);
48 }
49 uiItemR(layout, ptr, "sun_disc", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
50
52 if (RNA_boolean_get(ptr, "sun_disc")) {
53 col = uiLayoutColumn(layout, true);
54 uiItemR(col, ptr, "sun_size", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
55 uiItemR(col, ptr, "sun_intensity", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
56 }
57
58 col = uiLayoutColumn(layout, true);
59 uiItemR(col, ptr, "sun_elevation", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
60 uiItemR(col, ptr, "sun_rotation", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
61
62 uiItemR(layout, ptr, "altitude", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
63
64 col = uiLayoutColumn(layout, true);
65 uiItemR(col, ptr, "air_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
66 uiItemR(col, ptr, "dust_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
67 uiItemR(col, ptr, "ozone_density", UI_ITEM_R_SPLIT_EMPTY_NAME, nullptr, ICON_NONE);
68 }
69}
70
71static void node_shader_init_tex_sky(bNodeTree * /*ntree*/, bNode *node)
72{
73 NodeTexSky *tex = MEM_cnew<NodeTexSky>("NodeTexSky");
75 BKE_texture_colormapping_default(&tex->base.color_mapping);
76 tex->sun_direction[0] = 0.0f;
77 tex->sun_direction[1] = 0.0f;
78 tex->sun_direction[2] = 1.0f;
79 tex->turbidity = 2.2f;
80 tex->ground_albedo = 0.3f;
81 tex->sun_disc = true;
82 tex->sun_size = DEG2RADF(0.545f);
83 tex->sun_intensity = 1.0f;
84 tex->sun_elevation = DEG2RADF(15.0f);
85 tex->sun_rotation = 0.0f;
86 tex->altitude = 0.0f;
87 tex->air_density = 1.0f;
88 tex->dust_density = 1.0f;
89 tex->ozone_density = 1.0f;
90 tex->sky_model = SHD_SKY_NISHITA;
91 node->storage = tex;
92}
93
95 float config_Y[5], config_x[5], config_y[5]; /* named after xyY color space */
96 float radiance[3];
97};
98
99static float sky_perez_function(const float *lam, float theta, float gamma)
100{
101 float ctheta = cosf(theta);
102 float cgamma = cosf(gamma);
103
104 return (1.0 + lam[0] * expf(lam[1] / ctheta)) *
105 (1.0 + lam[2] * expf(lam[3] * gamma) + lam[4] * cgamma * cgamma);
106}
107
108static void sky_precompute_old(SkyModelPreetham *sunsky, const float sun_angles[], float turbidity)
109{
110 float theta = sun_angles[0];
111 float theta2 = theta * theta;
112 float theta3 = theta2 * theta;
113 float T = turbidity;
114 float T2 = T * T;
115 float chi = (4.0f / 9.0f - T / 120.0f) * (M_PI - 2.0f * theta);
116
117 sunsky->radiance[0] = (4.0453f * T - 4.9710f) * tanf(chi) - 0.2155f * T + 2.4192f;
118 sunsky->radiance[0] *= 0.06f;
119
120 sunsky->radiance[1] = (0.00166f * theta3 - 0.00375f * theta2 + 0.00209f * theta) * T2 +
121 (-0.02903f * theta3 + 0.06377f * theta2 - 0.03202f * theta + 0.00394f) *
122 T +
123 (0.11693f * theta3 - 0.21196f * theta2 + 0.06052f * theta + 0.25886f);
124
125 sunsky->radiance[2] = (0.00275f * theta3 - 0.00610f * theta2 + 0.00317f * theta) * T2 +
126 (-0.04214f * theta3 + 0.08970f * theta2 - 0.04153f * theta + 0.00516f) *
127 T +
128 (0.15346f * theta3 - 0.26756f * theta2 + 0.06670f * theta + 0.26688f);
129
130 sunsky->config_Y[0] = (0.1787f * T - 1.4630f);
131 sunsky->config_Y[1] = (-0.3554f * T + 0.4275f);
132 sunsky->config_Y[2] = (-0.0227f * T + 5.3251f);
133 sunsky->config_Y[3] = (0.1206f * T - 2.5771f);
134 sunsky->config_Y[4] = (-0.0670f * T + 0.3703f);
135
136 sunsky->config_x[0] = (-0.0193f * T - 0.2592f);
137 sunsky->config_x[1] = (-0.0665f * T + 0.0008f);
138 sunsky->config_x[2] = (-0.0004f * T + 0.2125f);
139 sunsky->config_x[3] = (-0.0641f * T - 0.8989f);
140 sunsky->config_x[4] = (-0.0033f * T + 0.0452f);
141
142 sunsky->config_y[0] = (-0.0167f * T - 0.2608f);
143 sunsky->config_y[1] = (-0.0950f * T + 0.0092f);
144 sunsky->config_y[2] = (-0.0079f * T + 0.2102f);
145 sunsky->config_y[3] = (-0.0441f * T - 1.6537f);
146 sunsky->config_y[4] = (-0.0109f * T + 0.0529f);
147
148 sunsky->radiance[0] /= sky_perez_function(sunsky->config_Y, 0, theta);
149 sunsky->radiance[1] /= sky_perez_function(sunsky->config_x, 0, theta);
150 sunsky->radiance[2] /= sky_perez_function(sunsky->config_y, 0, theta);
151}
152
154 bNode *node,
155 bNodeExecData * /*execdata*/,
156 GPUNodeStack *in,
157 GPUNodeStack *out)
158{
159 node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
160 node_shader_gpu_tex_mapping(mat, node, in, out);
161 NodeTexSky *tex = (NodeTexSky *)node->storage;
162 float sun_angles[2]; /* [0]=theta=zenith angle [1]=phi=azimuth */
163 sun_angles[0] = acosf(tex->sun_direction[2]);
164 sun_angles[1] = atan2f(tex->sun_direction[0], tex->sun_direction[1]);
165
166 if (tex->sky_model == 0) {
167 /* Preetham */
168 SkyModelPreetham sunsky;
169 sky_precompute_old(&sunsky, sun_angles, tex->turbidity);
172 return GPU_stack_link(mat,
173 node,
174 "node_tex_sky_preetham",
175 in,
176 out,
177 /* Pass config_Y/x/y as 3x(vec4+float) */
178 GPU_uniform(&sunsky.config_Y[0]),
179 GPU_uniform(&sunsky.config_Y[4]),
180 GPU_uniform(&sunsky.config_x[0]),
181 GPU_uniform(&sunsky.config_x[4]),
182 GPU_uniform(&sunsky.config_y[0]),
183 GPU_uniform(&sunsky.config_y[4]),
184 GPU_uniform(sun_angles),
185 GPU_uniform(sunsky.radiance),
189 }
190 else if (tex->sky_model == 1) {
191 /* Hosek / Wilkie */
192 sun_angles[0] = fmin(M_PI_2, sun_angles[0]); /* clamp to horizon */
194 tex->turbidity, tex->ground_albedo, fmax(0.0, M_PI_2 - sun_angles[0]));
195 /* Pass sky_state->configs[3][9] as 3*(vec4+vec4)+vec3 */
196 float config_x07[8], config_y07[8], config_z07[8], config_xyz8[3];
197 for (int i = 0; i < 8; ++i) {
198 config_x07[i] = float(sky_state->configs[0][i]);
199 config_y07[i] = float(sky_state->configs[1][i]);
200 config_z07[i] = float(sky_state->configs[2][i]);
201 }
202 for (int i = 0; i < 3; ++i) {
203 config_xyz8[i] = float(sky_state->configs[i][8]);
204 }
205 float radiance[3];
206 for (int i = 0; i < 3; i++) {
207 radiance[i] = sky_state->radiances[i] * (2 * M_PI / 683);
208 }
212 return GPU_stack_link(mat,
213 node,
214 "node_tex_sky_hosekwilkie",
215 in,
216 out,
217 GPU_uniform(&config_x07[0]),
218 GPU_uniform(&config_x07[4]),
219 GPU_uniform(&config_y07[0]),
220 GPU_uniform(&config_y07[4]),
221 GPU_uniform(&config_z07[0]),
222 GPU_uniform(&config_z07[4]),
223 GPU_uniform(config_xyz8),
224 GPU_uniform(sun_angles),
225 GPU_uniform(radiance),
229 }
230 else {
231 /* Nishita */
232
234
237 4,
238 range.first(),
239 range.one_after_last(),
242 tex->sun_elevation,
243 tex->altitude,
244 tex->air_density,
245 tex->dust_density,
246 tex->ozone_density);
247 });
248
249 float sun_rotation = fmodf(tex->sun_rotation, 2.0f * M_PI);
250 if (sun_rotation < 0.0f) {
251 sun_rotation += 2.0f * M_PI;
252 }
253 sun_rotation = 2.0f * M_PI - sun_rotation;
254
257
258 /* To fix pole issue we clamp the v coordinate. */
262 float layer;
263 GPUNodeLink *sky_texture = GPU_image_sky(
264 mat, GPU_SKY_WIDTH, GPU_SKY_HEIGHT, pixels.data(), &layer, sampler);
265 return GPU_stack_link(mat,
266 node,
267 "node_tex_sky_nishita",
268 in,
269 out,
270 GPU_constant(&sun_rotation),
274 sky_texture,
275 GPU_constant(&layer));
276 }
277}
278
279static void node_shader_update_sky(bNodeTree *ntree, bNode *node)
280{
281 bNodeSocket *sockVector = bke::node_find_socket(node, SOCK_IN, "Vector");
282
283 NodeTexSky *tex = (NodeTexSky *)node->storage;
285 ntree, sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1));
286}
287
289{
290 const NodeDeclaration &declaration = *params.node_type().static_declaration;
291 if (params.in_out() == SOCK_OUT) {
293 return;
294 }
295 if (params.node_tree().typeinfo->validate_link(
296 static_cast<eNodeSocketDatatype>(params.other_socket().type), SOCK_FLOAT))
297 {
298 params.add_item(IFACE_("Vector"), [](LinkSearchOpParams &params) {
299 bNode &node = params.add_node("ShaderNodeTexSky");
300 NodeTexSky *tex = (NodeTexSky *)node.storage;
301 tex->sun_disc = false;
302 params.update_and_connect_available_socket(node, "Vector");
303 });
304 }
305}
306
307} // namespace blender::nodes::node_shader_tex_sky_cc
308
309/* node type definition */
311{
312 namespace file_ns = blender::nodes::node_shader_tex_sky_cc;
313
314 static blender::bke::bNodeType ntype;
315
317 ntype.declare = file_ns::node_declare;
318 ntype.draw_buttons = file_ns::node_shader_buts_tex_sky;
320 ntype.initfunc = file_ns::node_shader_init_tex_sky;
323 ntype.gpu_fn = file_ns::node_shader_gpu_tex_sky;
324 /* Remove vector input for Nishita sky model. */
325 ntype.updatefunc = file_ns::node_shader_update_sky;
326 ntype.gather_link_search_ops = file_ns::node_gather_link_searches;
327
329}
Scene * CTX_data_scene(const bContext *C)
#define SH_NODE_TEX_SKY
Definition BKE_node.hh:931
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:414
bool BKE_scene_uses_blender_eevee(const Scene *scene)
Definition scene.cc:2771
void BKE_texture_mapping_default(struct TexMapping *texmap, int type)
Definition texture.cc:247
void BKE_texture_colormapping_default(struct ColorMapping *colormap)
Definition texture.cc:350
#define M_PI_2
#define M_PI
#define DEG2RADF(_deg)
#define RPT_(msgid)
#define IFACE_(msgid)
#define GPU_SKY_WIDTH
#define GPU_SKY_HEIGHT
@ SHD_SKY_PREETHAM
@ SHD_SKY_NISHITA
@ SHD_SKY_HOSEK
@ SOCK_OUT
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_FLOAT
@ TEXMAP_TYPE_POINT
bool GPU_stack_link(GPUMaterial *mat, const bNode *node, const char *name, GPUNodeStack *in, GPUNodeStack *out,...)
GPUNodeLink * GPU_constant(const float *num)
GPUNodeLink * GPU_image_sky(GPUMaterial *mat, int width, int height, const float *pixels, float *layer, GPUSamplerState sampler_state)
GPUNodeLink * GPU_uniform(const float *num)
@ GPU_SAMPLER_EXTEND_MODE_REPEAT
@ GPU_SAMPLER_EXTEND_MODE_EXTEND
@ GPU_SAMPLER_FILTERING_LINEAR
void uiItemL(uiLayout *layout, const char *name, int icon)
uiLayout * uiLayoutColumn(uiLayout *layout, bool align)
void uiItemR(uiLayout *layout, PointerRNA *ptr, const char *propname, eUI_Item_Flag flag, const char *name, int icon)
@ UI_ITEM_R_SPLIT_EMPTY_NAME
Vector< SocketDeclaration * > outputs
local_group_size(16, 16) .push_constant(Type local_group_size(16, 16) .push_constant(Type input_tx sampler(1, ImageType::FLOAT_2D, "matte_tx") .image(0
local_group_size(16, 16) .push_constant(Type b
#define cosf(x)
#define expf(x)
#define tanf(x)
#define atan2f(x, y)
#define fmodf(x, y)
#define acosf(x)
draw_view in_light_buf[] float
uint col
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
#define T
#define T2
Definition md5.cpp:19
void node_type_size_preset(bNodeType *ntype, eNodeSizePreset size)
Definition node.cc:4614
void node_set_socket_availability(bNodeTree *ntree, bNodeSocket *sock, bool is_available)
Definition node.cc:3911
void node_type_storage(bNodeType *ntype, const char *storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:4632
void node_register_type(bNodeType *ntype)
Definition node.cc:1708
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
static void node_gather_link_searches(GatherLinkSearchOpParams &params)
static void sky_precompute_old(SkyModelPreetham *sunsky, const float sun_angles[], float turbidity)
static void node_shader_init_tex_sky(bNodeTree *, bNode *node)
static int node_shader_gpu_tex_sky(GPUMaterial *mat, bNode *node, bNodeExecData *, GPUNodeStack *in, GPUNodeStack *out)
static void node_shader_update_sky(bNodeTree *ntree, bNode *node)
static float sky_perez_function(const float *lam, float theta, float gamma)
static void node_declare(NodeDeclarationBuilder &b)
static void node_shader_buts_tex_sky(uiLayout *layout, bContext *C, PointerRNA *ptr)
void search_link_ops_for_declarations(GatherLinkSearchOpParams &params, Span< SocketDeclaration * > declarations)
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
Definition BLI_task.hh:95
color xyz_to_rgb(float x, float y, float z)
Definition node_color.h:73
void register_node_type_sh_tex_sky()
void sh_node_type_base(blender::bke::bNodeType *ntype, int type, const char *name, short nclass)
void node_shader_gpu_tex_mapping(GPUMaterial *mat, bNode *node, GPUNodeStack *in, GPUNodeStack *)
void node_shader_gpu_default_tex_coord(GPUMaterial *mat, bNode *node, GPUNodeLink **link)
void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:46
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:58
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
int RNA_enum_get(PointerRNA *ptr, const char *name)
void SKY_arhosekskymodelstate_free(SKY_ArHosekSkyModelState *state)
SKY_ArHosekSkyModelState * SKY_arhosek_xyz_skymodelstate_alloc_init(const double turbidity, const double albedo, const double elevation)
void SKY_nishita_skymodel_precompute_texture(float *pixels, int stride, int start_y, int end_y, int width, int height, float sun_elevation, float altitude, float air_density, float dust_density, float ozone_density)
SKY_ArHosekSkyModelConfiguration configs[11]
Definition sky_model.h:317
Defines a node type.
Definition BKE_node.hh:218
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:267
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:318
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:238
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:363
NodeDeclareFunction declare
Definition BKE_node.hh:347
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:257
PointerRNA * ptr
Definition wm_files.cc:4126