Blender V4.5
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 layout->prop(ptr, "sky_type", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
34
35 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_PREETHAM) {
36 layout->prop(ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
37 layout->prop(ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
38 }
39 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_HOSEK) {
40 layout->prop(ptr, "sun_direction", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE);
41 layout->prop(ptr, "turbidity", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
42 layout->prop(ptr, "ground_albedo", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
43 }
44 if (RNA_enum_get(ptr, "sky_type") == SHD_SKY_NISHITA) {
45 Scene *scene = CTX_data_scene(C);
47 layout->label(RPT_("Sun disc not available in EEVEE"), ICON_ERROR);
48 }
49 layout->prop(ptr, "sun_disc", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
50
52 if (RNA_boolean_get(ptr, "sun_disc")) {
53 col = &layout->column(true);
54 col->prop(ptr, "sun_size", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
55 col->prop(ptr, "sun_intensity", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
56 }
57
58 col = &layout->column(true);
59 col->prop(ptr, "sun_elevation", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
60 col->prop(ptr, "sun_rotation", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
61
62 layout->prop(ptr, "altitude", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
63
64 col = &layout->column(true);
65 col->prop(ptr, "air_density", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
66 col->prop(ptr, "dust_density", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
67 col->prop(ptr, "ozone_density", UI_ITEM_R_SPLIT_EMPTY_NAME, std::nullopt, ICON_NONE);
68 }
69}
70
71static void node_shader_init_tex_sky(bNodeTree * /*ntree*/, bNode *node)
72{
73 NodeTexSky *tex = MEM_callocN<NodeTexSky>("NodeTexSky");
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;
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*/,
158{
159 node_shader_gpu_default_tex_coord(mat, node, &in[0].link);
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 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
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
278static void node_shader_update_sky(bNodeTree *ntree, bNode *node)
279{
280 bNodeSocket *sockVector = bke::node_find_socket(*node, SOCK_IN, "Vector");
281
282 NodeTexSky *tex = (NodeTexSky *)node->storage;
284 *ntree, *sockVector, !(tex->sky_model == 2 && tex->sun_disc == 1));
285}
286
288{
289 const NodeDeclaration &declaration = *params.node_type().static_declaration;
290 if (params.in_out() == SOCK_OUT) {
292 return;
293 }
294 if (params.node_tree().typeinfo->validate_link(eNodeSocketDatatype(params.other_socket().type),
295 SOCK_FLOAT))
296 {
297 params.add_item(IFACE_("Vector"), [](LinkSearchOpParams &params) {
298 bNode &node = params.add_node("ShaderNodeTexSky");
299 NodeTexSky *tex = (NodeTexSky *)node.storage;
300 tex->sun_disc = false;
301 params.update_and_connect_available_socket(node, "Vector");
302 });
303 }
304}
305
306} // namespace blender::nodes::node_shader_tex_sky_cc
307
308/* node type definition */
310{
311 namespace file_ns = blender::nodes::node_shader_tex_sky_cc;
312
313 static blender::bke::bNodeType ntype;
314
315 sh_node_type_base(&ntype, "ShaderNodeTexSky", SH_NODE_TEX_SKY);
316 ntype.ui_name = "Sky Texture";
317 ntype.ui_description = "Generate a procedural sky texture";
318 ntype.enum_name_legacy = "TEX_SKY";
320 ntype.declare = file_ns::node_declare;
321 ntype.draw_buttons = file_ns::node_shader_buts_tex_sky;
323 ntype.initfunc = file_ns::node_shader_init_tex_sky;
326 ntype.gpu_fn = file_ns::node_shader_gpu_tex_sky;
327 /* Remove vector input for Nishita sky model. */
328 ntype.updatefunc = file_ns::node_shader_update_sky;
329 ntype.gather_link_search_ops = file_ns::node_gather_link_searches;
330
332}
Scene * CTX_data_scene(const bContext *C)
#define NODE_CLASS_TEXTURE
Definition BKE_node.hh:443
#define SH_NODE_TEX_SKY
bool BKE_scene_uses_blender_eevee(const Scene *scene)
Definition scene.cc:2821
void BKE_texture_mapping_default(struct TexMapping *texmap, int type)
Definition texture.cc:238
void BKE_texture_colormapping_default(struct ColorMapping *colormap)
Definition texture.cc:341
#define DEG2RADF(_deg)
#define M_PI_2
#define M_PI
#define RPT_(msgid)
#define IFACE_(msgid)
@ SOCK_OUT
@ SOCK_IN
eNodeSocketDatatype
@ SOCK_FLOAT
@ SHD_SKY_PREETHAM
@ SHD_SKY_NISHITA
@ SHD_SKY_HOSEK
@ 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
#define C
Definition RandGen.cpp:29
@ UI_ITEM_R_SPLIT_EMPTY_NAME
const T * data() const
Definition BLI_array.hh:301
constexpr int64_t first() const
constexpr int64_t one_after_last() const
Vector< SocketDeclaration * > outputs
#define cosf(x)
#define expf(x)
#define tanf(x)
#define atan2f(x, y)
#define fmodf(x, y)
#define acosf(x)
uint col
#define in
#define out
#define GPU_SKY_WIDTH
#define GPU_SKY_HEIGHT
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
#define T
#define T2
Definition md5.cpp:20
bNodeSocket * node_find_socket(bNode &node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:2864
void node_register_type(bNodeType &ntype)
Definition node.cc:2748
void node_set_socket_availability(bNodeTree &ntree, bNodeSocket &sock, bool is_available)
Definition node.cc:5011
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
Definition node.cc:5603
void node_type_size_preset(bNodeType &ntype, eNodeSizePreset size)
Definition node.cc:5585
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:93
color xyz_to_rgb(float x, float y, float z)
Definition node_color.h:73
void register_node_type_sh_tex_sky()
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 sh_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void get_XYZ_to_RGB_for_gpu(XYZ_to_RGB *data)
void node_free_standard_storage(bNode *node)
Definition node_util.cc:42
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
Definition node_util.cc:54
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)
TexMapping tex_mapping
ColorMapping color_mapping
NodeTexBase base
float sun_direction[3]
SKY_ArHosekSkyModelConfiguration configs[11]
Definition sky_model.h:317
void * storage
Defines a node type.
Definition BKE_node.hh:226
std::string ui_description
Definition BKE_node.hh:232
void(* initfunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:277
NodeGPUExecFunction gpu_fn
Definition BKE_node.hh:330
const char * enum_name_legacy
Definition BKE_node.hh:235
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
Definition BKE_node.hh:247
NodeGatherSocketLinkOperationsFunction gather_link_search_ops
Definition BKE_node.hh:371
NodeDeclareFunction declare
Definition BKE_node.hh:355
void(* updatefunc)(bNodeTree *ntree, bNode *node)
Definition BKE_node.hh:269
void label(blender::StringRef name, int icon)
uiLayout & column(bool align)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)
i
Definition text_draw.cc:230
PointerRNA * ptr
Definition wm_files.cc:4226