Blender V4.3
eevee_world.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2021 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "BKE_lib_id.hh"
10#include "BKE_node.hh"
11#include "BKE_world.h"
12#include "BLI_math_rotation.h"
14#include "NOD_shader.h"
15
16#include "eevee_instance.hh"
17
18namespace blender::eevee {
19
20/* -------------------------------------------------------------------- */
26{
27 bNodeTree *ntree = bke::node_tree_add_tree(nullptr, "World Nodetree", ntreeType_Shader->idname);
28 bNode *background = bke::node_add_static_node(nullptr, ntree, SH_NODE_BACKGROUND);
29 bNode *output = bke::node_add_static_node(nullptr, ntree, SH_NODE_OUTPUT_WORLD);
30 bNodeSocket *background_out = bke::node_find_socket(background, SOCK_OUT, "Background");
31 bNodeSocket *output_in = bke::node_find_socket(output, SOCK_IN, "Surface");
32 bke::node_add_link(ntree, background, background_out, output, output_in);
33 bke::node_set_active(ntree, output);
34
35 color_socket_ =
37 ntree_ = ntree;
38}
39
45
47{
48 /* WARNING: This function is not thread-safe. Which is not a problem for the moment. */
49 copy_v3_fl3(color_socket_->value, wo->horr, wo->horg, wo->horb);
50 return ntree_;
51}
52
55/* -------------------------------------------------------------------- */
60World::~World()
61{
62 if (default_world_ != nullptr) {
63 BKE_id_free(nullptr, default_world_);
64 }
65}
66
67::World *World::default_world_get()
68{
69 if (default_world_ == nullptr) {
70 default_world_ = static_cast<::World *>(BKE_id_new_nomain(ID_WO, "EEVEEE default world"));
71 default_world_->horr = default_world_->horg = default_world_->horb = 0.0f;
72 default_world_->use_nodes = 0;
73 default_world_->nodetree = nullptr;
74 BLI_listbase_clear(&default_world_->gpumaterial);
75 }
76 return default_world_;
77}
78
79::World *World::scene_world_get()
80{
81 return (inst_.scene->world != nullptr) ? inst_.scene->world : default_world_get();
82}
83
85{
86 /* No sun extraction during baking. */
87 if (inst_.is_baking()) {
88 return 0.0;
89 }
90
91 float sun_threshold = scene_world_get()->sun_threshold;
92 if (inst_.use_studio_light()) {
93 /* Do not call `lookdev_world_.intensity_get()` as it might not be initialized yet. */
95 }
96 return sun_threshold;
97}
98
99void World::sync()
100{
101 bool has_update = false;
102
103 WorldHandle wo_handle = {0};
104 if (inst_.scene->world != nullptr) {
105 /* Detect world update before overriding it. */
106 wo_handle = inst_.sync.sync_world(*inst_.scene->world);
107 has_update = wo_handle.recalc != 0;
108 }
109
110 /* Sync volume first since its result can override the surface world. */
111 sync_volume(wo_handle);
112
113 ::World *bl_world;
114 if (inst_.use_studio_light()) {
115 has_update |= lookdev_world_.sync(LookdevParameters(inst_.v3d));
116 bl_world = lookdev_world_.world_get();
117 }
118 else if ((inst_.view_layer->layflag & SCE_LAY_SKY) == 0) {
119 bl_world = default_world_get();
120 }
121 else if (has_volume_absorption_) {
122 bl_world = default_world_get();
123 }
124 else {
125 bl_world = scene_world_get();
126 }
127
128 bNodeTree *ntree = (bl_world->nodetree && bl_world->use_nodes) ?
129 bl_world->nodetree :
130 default_tree.nodetree_get(bl_world);
131
132 {
133 if (has_volume_absorption_) {
134 /* Replace world by black world. */
135 bl_world = default_world_get();
136 }
137 }
138
139 /* We have to manually test here because we have overrides. */
140 ::World *orig_world = (::World *)DEG_get_original_id(&bl_world->id);
141 if (assign_if_different(prev_original_world, orig_world)) {
142 has_update = true;
143 }
144
145 inst_.light_probes.sync_world(bl_world, has_update);
146
147 GPUMaterial *gpumat = inst_.shaders.world_shader_get(bl_world, ntree, MAT_PIPE_DEFERRED);
148
149 inst_.manager->register_layer_attributes(gpumat);
150
151 float opacity = inst_.use_studio_light() ? lookdev_world_.background_opacity_get() :
153 float background_blur = inst_.use_studio_light() ? lookdev_world_.background_blur_get() : 0.0;
154
155 inst_.pipelines.background.sync(gpumat, opacity, background_blur);
156 inst_.pipelines.world.sync(gpumat);
157}
158
159void World::sync_volume(const WorldHandle &world_handle)
160{
161 /* Studio lights have no volume shader. */
162 ::World *world = inst_.use_studio_light() ? nullptr : inst_.scene->world;
163
164 GPUMaterial *gpumat = nullptr;
165
166 /* Only the scene world nodetree can have volume shader. */
167 if (world && world->nodetree && world->use_nodes) {
168 gpumat = inst_.shaders.world_shader_get(world, world->nodetree, MAT_PIPE_VOLUME_MATERIAL);
169 }
170
171 bool had_volume = has_volume_;
172
173 if (gpumat && (GPU_material_status(gpumat) == GPU_MAT_SUCCESS)) {
174 has_volume_ = GPU_material_has_volume_output(gpumat);
175 has_volume_scatter_ = GPU_material_flag_get(gpumat, GPU_MATFLAG_VOLUME_SCATTER);
176 has_volume_absorption_ = GPU_material_flag_get(gpumat, GPU_MATFLAG_VOLUME_ABSORPTION);
177 }
178 else {
179 has_volume_ = has_volume_absorption_ = has_volume_scatter_ = false;
180 }
181
182 /* World volume needs to be always synced for correct clearing of parameter buffers. */
183 inst_.pipelines.world_volume.sync(gpumat);
184
185 if (has_volume_ || had_volume) {
186 inst_.volume.world_sync(world_handle);
187 }
188}
189
192} // namespace blender::eevee
void BKE_id_free(Main *bmain, void *idv)
void * BKE_id_new_nomain(short type, const char *name)
Definition lib_id.cc:1487
#define SH_NODE_OUTPUT_WORLD
Definition BKE_node.hh:914
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
MINLINE void copy_v3_fl3(float v[3], float x, float y, float z)
ID * DEG_get_original_id(ID *id)
@ ID_WO
@ SOCK_OUT
@ SOCK_IN
@ SCE_LAY_SKY
bool GPU_material_flag_get(const GPUMaterial *mat, eGPUMaterialFlag flag)
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat)
@ GPU_MATFLAG_VOLUME_SCATTER
@ GPU_MATFLAG_VOLUME_ABSORPTION
@ GPU_MAT_SUCCESS
bool GPU_material_has_volume_output(GPUMaterial *mat)
#define MEM_SAFE_FREE(v)
struct blender::bke::bNodeTreeType * ntreeType_Shader
void register_layer_attributes(GPUMaterial *material)
void sync(GPUMaterial *gpumat, float background_opacity, float background_blur)
bNodeTree * nodetree_get(::World *world)
float background_opacity_get() const
LightProbeModule light_probes
void sync_world(const ::World *world, bool has_update)
bool sync(const LookdevParameters &new_parameters)
GPUMaterial * world_shader_get(::World *blender_world, bNodeTree *nodetree, eMaterialPipeline pipeline_type)
WorldHandle sync_world(const ::World &world)
Definition eevee_sync.cc:52
void world_sync(const WorldHandle &world_handle)
void sync(GPUMaterial *gpumat)
void node_set_active(bNodeTree *ntree, bNode *node)
Definition node.cc:3896
bNode * node_add_static_node(const bContext *C, bNodeTree *ntree, int type)
Definition node.cc:2642
bNodeLink * node_add_link(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock, bNode *tonode, bNodeSocket *tosock)
Definition node.cc:2912
bNodeTree * node_tree_add_tree(Main *bmain, const char *name, const char *idname)
Definition node.cc:3226
bNodeSocket * node_find_socket(bNode *node, eNodeSocketInOut in_out, StringRef identifier)
Definition node.cc:1829
void node_tree_free_embedded_tree(bNodeTree *ntree)
Definition node.cc:3632
bool assign_if_different(T &old_value, T new_value)
struct World * world
View3DShading shading
struct bNodeTree * nodetree
float horg
short use_nodes
float horb
float sun_threshold
float horr
void * default_value