Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/scene/3d/lightmap_gi.cpp
9896 views
1
/**************************************************************************/
2
/* lightmap_gi.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "lightmap_gi.h"
32
33
#include "core/config/project_settings.h"
34
#include "core/io/config_file.h"
35
#include "core/math/delaunay_3d.h"
36
#include "core/object/object.h"
37
#include "scene/3d/lightmap_probe.h"
38
#include "scene/3d/mesh_instance_3d.h"
39
#include "scene/resources/camera_attributes.h"
40
#include "scene/resources/environment.h"
41
#include "scene/resources/image_texture.h"
42
#include "scene/resources/sky.h"
43
44
#include "modules/modules_enabled.gen.h" // For lightmapper_rd.
45
46
void LightmapGIData::add_user(const NodePath &p_path, const Rect2 &p_uv_scale, int p_slice_index, int32_t p_sub_instance) {
47
User user;
48
user.path = p_path;
49
user.uv_scale = p_uv_scale;
50
user.slice_index = p_slice_index;
51
user.sub_instance = p_sub_instance;
52
users.push_back(user);
53
}
54
55
int LightmapGIData::get_user_count() const {
56
return users.size();
57
}
58
59
NodePath LightmapGIData::get_user_path(int p_user) const {
60
ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
61
return users[p_user].path;
62
}
63
64
int32_t LightmapGIData::get_user_sub_instance(int p_user) const {
65
ERR_FAIL_INDEX_V(p_user, users.size(), -1);
66
return users[p_user].sub_instance;
67
}
68
69
Rect2 LightmapGIData::get_user_lightmap_uv_scale(int p_user) const {
70
ERR_FAIL_INDEX_V(p_user, users.size(), Rect2());
71
return users[p_user].uv_scale;
72
}
73
74
int LightmapGIData::get_user_lightmap_slice_index(int p_user) const {
75
ERR_FAIL_INDEX_V(p_user, users.size(), -1);
76
return users[p_user].slice_index;
77
}
78
79
void LightmapGIData::clear_users() {
80
users.clear();
81
}
82
83
void LightmapGIData::_set_user_data(const Array &p_data) {
84
ERR_FAIL_COND((p_data.size() % 4) != 0);
85
users.clear();
86
for (int i = 0; i < p_data.size(); i += 4) {
87
add_user(p_data[i + 0], p_data[i + 1], p_data[i + 2], p_data[i + 3]);
88
}
89
}
90
91
Array LightmapGIData::_get_user_data() const {
92
Array ret;
93
for (int i = 0; i < users.size(); i++) {
94
ret.push_back(users[i].path);
95
ret.push_back(users[i].uv_scale);
96
ret.push_back(users[i].slice_index);
97
ret.push_back(users[i].sub_instance);
98
}
99
return ret;
100
}
101
102
void LightmapGIData::set_lightmap_textures(const TypedArray<TextureLayered> &p_data) {
103
storage_light_textures = p_data;
104
if (p_data.is_empty()) {
105
combined_light_texture = Ref<TextureLayered>();
106
_reset_lightmap_textures();
107
return;
108
}
109
110
if (p_data.size() == 1) {
111
combined_light_texture = p_data[0];
112
} else {
113
Vector<Ref<Image>> images;
114
for (int i = 0; i < p_data.size(); i++) {
115
Ref<TextureLayered> texture = p_data[i];
116
ERR_FAIL_COND_MSG(texture.is_null(), vformat("Invalid TextureLayered at index %d.", i));
117
for (int j = 0; j < texture->get_layers(); j++) {
118
images.push_back(texture->get_layer_data(j));
119
}
120
}
121
122
Ref<Texture2DArray> combined_texture;
123
combined_texture.instantiate();
124
125
combined_texture->create_from_images(images);
126
combined_light_texture = combined_texture;
127
}
128
_reset_lightmap_textures();
129
}
130
131
TypedArray<TextureLayered> LightmapGIData::get_lightmap_textures() const {
132
return storage_light_textures;
133
}
134
135
void LightmapGIData::set_shadowmask_textures(const TypedArray<TextureLayered> &p_data) {
136
storage_shadowmask_textures = p_data;
137
138
if (p_data.is_empty()) {
139
combined_shadowmask_texture = Ref<TextureLayered>();
140
_reset_shadowmask_textures();
141
return;
142
}
143
144
if (p_data.size() == 1) {
145
combined_shadowmask_texture = p_data[0];
146
147
} else {
148
Vector<Ref<Image>> images;
149
for (int i = 0; i < p_data.size(); i++) {
150
Ref<TextureLayered> texture = p_data[i];
151
ERR_FAIL_COND_MSG(texture.is_null(), vformat("Invalid TextureLayered at index %d.", i));
152
for (int j = 0; j < texture->get_layers(); j++) {
153
images.push_back(texture->get_layer_data(j));
154
}
155
}
156
157
Ref<Texture2DArray> combined_texture;
158
combined_texture.instantiate();
159
160
combined_texture->create_from_images(images);
161
combined_shadowmask_texture = combined_texture;
162
}
163
164
_reset_shadowmask_textures();
165
}
166
167
TypedArray<TextureLayered> LightmapGIData::get_shadowmask_textures() const {
168
return storage_shadowmask_textures;
169
}
170
171
void LightmapGIData::clear_shadowmask_textures() {
172
RS::get_singleton()->lightmap_set_shadowmask_textures(lightmap, RID());
173
storage_shadowmask_textures.clear();
174
combined_shadowmask_texture.unref();
175
}
176
177
bool LightmapGIData::has_shadowmask_textures() {
178
return !storage_shadowmask_textures.is_empty() && combined_shadowmask_texture.is_valid();
179
}
180
181
RID LightmapGIData::get_rid() const {
182
return lightmap;
183
}
184
185
void LightmapGIData::clear() {
186
users.clear();
187
}
188
189
void LightmapGIData::_reset_lightmap_textures() {
190
RS::get_singleton()->lightmap_set_textures(lightmap, combined_light_texture.is_valid() ? combined_light_texture->get_rid() : RID(), uses_spherical_harmonics);
191
}
192
193
void LightmapGIData::_reset_shadowmask_textures() {
194
RS::get_singleton()->lightmap_set_shadowmask_textures(lightmap, combined_shadowmask_texture.is_valid() ? combined_shadowmask_texture->get_rid() : RID());
195
}
196
197
void LightmapGIData::set_uses_spherical_harmonics(bool p_enable) {
198
uses_spherical_harmonics = p_enable;
199
_reset_lightmap_textures();
200
}
201
202
bool LightmapGIData::is_using_spherical_harmonics() const {
203
return uses_spherical_harmonics;
204
}
205
206
void LightmapGIData::_set_uses_packed_directional(bool p_enable) {
207
_uses_packed_directional = p_enable;
208
}
209
210
bool LightmapGIData::_is_using_packed_directional() const {
211
return _uses_packed_directional;
212
}
213
214
void LightmapGIData::update_shadowmask_mode(ShadowmaskMode p_mode) {
215
RS::get_singleton()->lightmap_set_shadowmask_mode(lightmap, (RS::ShadowmaskMode)p_mode);
216
}
217
218
LightmapGIData::ShadowmaskMode LightmapGIData::get_shadowmask_mode() const {
219
return (ShadowmaskMode)RS::get_singleton()->lightmap_get_shadowmask_mode(lightmap);
220
}
221
222
void LightmapGIData::set_capture_data(const AABB &p_bounds, bool p_interior, const PackedVector3Array &p_points, const PackedColorArray &p_point_sh, const PackedInt32Array &p_tetrahedra, const PackedInt32Array &p_bsp_tree, float p_baked_exposure) {
223
if (p_points.size()) {
224
int pc = p_points.size();
225
ERR_FAIL_COND(pc * 9 != p_point_sh.size());
226
ERR_FAIL_COND((p_tetrahedra.size() % 4) != 0);
227
ERR_FAIL_COND((p_bsp_tree.size() % 6) != 0);
228
RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, p_points, p_point_sh, p_tetrahedra, p_bsp_tree);
229
RS::get_singleton()->lightmap_set_probe_bounds(lightmap, p_bounds);
230
RS::get_singleton()->lightmap_set_probe_interior(lightmap, p_interior);
231
} else {
232
RS::get_singleton()->lightmap_set_probe_capture_data(lightmap, PackedVector3Array(), PackedColorArray(), PackedInt32Array(), PackedInt32Array());
233
RS::get_singleton()->lightmap_set_probe_bounds(lightmap, AABB());
234
RS::get_singleton()->lightmap_set_probe_interior(lightmap, false);
235
}
236
RS::get_singleton()->lightmap_set_baked_exposure_normalization(lightmap, p_baked_exposure);
237
baked_exposure = p_baked_exposure;
238
interior = p_interior;
239
bounds = p_bounds;
240
}
241
242
PackedVector3Array LightmapGIData::get_capture_points() const {
243
return RS::get_singleton()->lightmap_get_probe_capture_points(lightmap);
244
}
245
246
PackedColorArray LightmapGIData::get_capture_sh() const {
247
return RS::get_singleton()->lightmap_get_probe_capture_sh(lightmap);
248
}
249
250
PackedInt32Array LightmapGIData::get_capture_tetrahedra() const {
251
return RS::get_singleton()->lightmap_get_probe_capture_tetrahedra(lightmap);
252
}
253
254
PackedInt32Array LightmapGIData::get_capture_bsp_tree() const {
255
return RS::get_singleton()->lightmap_get_probe_capture_bsp_tree(lightmap);
256
}
257
258
AABB LightmapGIData::get_capture_bounds() const {
259
return bounds;
260
}
261
262
bool LightmapGIData::is_interior() const {
263
return interior;
264
}
265
266
float LightmapGIData::get_baked_exposure() const {
267
return baked_exposure;
268
}
269
270
void LightmapGIData::_set_probe_data(const Dictionary &p_data) {
271
ERR_FAIL_COND(!p_data.has("bounds"));
272
ERR_FAIL_COND(!p_data.has("points"));
273
ERR_FAIL_COND(!p_data.has("tetrahedra"));
274
ERR_FAIL_COND(!p_data.has("bsp"));
275
ERR_FAIL_COND(!p_data.has("sh"));
276
ERR_FAIL_COND(!p_data.has("interior"));
277
ERR_FAIL_COND(!p_data.has("baked_exposure"));
278
set_capture_data(p_data["bounds"], p_data["interior"], p_data["points"], p_data["sh"], p_data["tetrahedra"], p_data["bsp"], p_data["baked_exposure"]);
279
}
280
281
Dictionary LightmapGIData::_get_probe_data() const {
282
Dictionary d;
283
d["bounds"] = get_capture_bounds();
284
d["points"] = get_capture_points();
285
d["tetrahedra"] = get_capture_tetrahedra();
286
d["bsp"] = get_capture_bsp_tree();
287
d["sh"] = get_capture_sh();
288
d["interior"] = is_interior();
289
d["baked_exposure"] = get_baked_exposure();
290
return d;
291
}
292
293
#ifndef DISABLE_DEPRECATED
294
void LightmapGIData::set_light_texture(const Ref<TextureLayered> &p_light_texture) {
295
TypedArray<TextureLayered> arr = { p_light_texture };
296
set_lightmap_textures(arr);
297
}
298
299
Ref<TextureLayered> LightmapGIData::get_light_texture() const {
300
if (storage_light_textures.is_empty()) {
301
return Ref<TextureLayered>();
302
}
303
return storage_light_textures.get(0);
304
}
305
306
void LightmapGIData::_set_light_textures_data(const Array &p_data) {
307
set_lightmap_textures(p_data);
308
}
309
310
Array LightmapGIData::_get_light_textures_data() const {
311
return Array(storage_light_textures);
312
}
313
#endif
314
315
void LightmapGIData::_bind_methods() {
316
ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &LightmapGIData::_set_user_data);
317
ClassDB::bind_method(D_METHOD("_get_user_data"), &LightmapGIData::_get_user_data);
318
319
ClassDB::bind_method(D_METHOD("set_lightmap_textures", "light_textures"), &LightmapGIData::set_lightmap_textures);
320
ClassDB::bind_method(D_METHOD("get_lightmap_textures"), &LightmapGIData::get_lightmap_textures);
321
322
ClassDB::bind_method(D_METHOD("set_shadowmask_textures", "shadowmask_textures"), &LightmapGIData::set_shadowmask_textures);
323
ClassDB::bind_method(D_METHOD("get_shadowmask_textures"), &LightmapGIData::get_shadowmask_textures);
324
325
ClassDB::bind_method(D_METHOD("set_uses_spherical_harmonics", "uses_spherical_harmonics"), &LightmapGIData::set_uses_spherical_harmonics);
326
ClassDB::bind_method(D_METHOD("is_using_spherical_harmonics"), &LightmapGIData::is_using_spherical_harmonics);
327
328
ClassDB::bind_method(D_METHOD("_set_uses_packed_directional", "_uses_packed_directional"), &LightmapGIData::_set_uses_packed_directional);
329
ClassDB::bind_method(D_METHOD("_is_using_packed_directional"), &LightmapGIData::_is_using_packed_directional);
330
331
ClassDB::bind_method(D_METHOD("add_user", "path", "uv_scale", "slice_index", "sub_instance"), &LightmapGIData::add_user);
332
ClassDB::bind_method(D_METHOD("get_user_count"), &LightmapGIData::get_user_count);
333
ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &LightmapGIData::get_user_path);
334
ClassDB::bind_method(D_METHOD("clear_users"), &LightmapGIData::clear_users);
335
336
ClassDB::bind_method(D_METHOD("_set_probe_data", "data"), &LightmapGIData::_set_probe_data);
337
ClassDB::bind_method(D_METHOD("_get_probe_data"), &LightmapGIData::_get_probe_data);
338
339
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "lightmap_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_lightmap_textures", "get_lightmap_textures");
340
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "shadowmask_textures", PROPERTY_HINT_ARRAY_TYPE, "TextureLayered", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_READ_ONLY), "set_shadowmask_textures", "get_shadowmask_textures");
341
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "uses_spherical_harmonics", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "set_uses_spherical_harmonics", "is_using_spherical_harmonics");
342
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
343
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "probe_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_probe_data", "_get_probe_data");
344
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "_uses_packed_directional", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NO_EDITOR | PROPERTY_USAGE_INTERNAL), "_set_uses_packed_directional", "_is_using_packed_directional");
345
346
#ifndef DISABLE_DEPRECATED
347
ClassDB::bind_method(D_METHOD("set_light_texture", "light_texture"), &LightmapGIData::set_light_texture);
348
ClassDB::bind_method(D_METHOD("get_light_texture"), &LightmapGIData::get_light_texture);
349
350
ClassDB::bind_method(D_METHOD("_set_light_textures_data", "data"), &LightmapGIData::_set_light_textures_data);
351
ClassDB::bind_method(D_METHOD("_get_light_textures_data"), &LightmapGIData::_get_light_textures_data);
352
353
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_texture", PROPERTY_HINT_RESOURCE_TYPE, "TextureLayered", PROPERTY_USAGE_NONE), "set_light_texture", "get_light_texture");
354
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "light_textures", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "_set_light_textures_data", "_get_light_textures_data");
355
#endif
356
357
BIND_ENUM_CONSTANT(SHADOWMASK_MODE_NONE);
358
BIND_ENUM_CONSTANT(SHADOWMASK_MODE_REPLACE);
359
BIND_ENUM_CONSTANT(SHADOWMASK_MODE_OVERLAY);
360
}
361
362
LightmapGIData::LightmapGIData() {
363
lightmap = RS::get_singleton()->lightmap_create();
364
}
365
366
LightmapGIData::~LightmapGIData() {
367
ERR_FAIL_NULL(RenderingServer::get_singleton());
368
RS::get_singleton()->free(lightmap);
369
}
370
371
///////////////////////////
372
373
void LightmapGI::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights, Vector<Vector3> &probes) {
374
MeshInstance3D *mi = Object::cast_to<MeshInstance3D>(p_at_node);
375
if (mi && mi->get_gi_mode() == GeometryInstance3D::GI_MODE_STATIC && mi->is_visible_in_tree()) {
376
Ref<Mesh> mesh = mi->get_mesh();
377
if (mesh.is_valid()) {
378
bool all_have_uv2_and_normal = true;
379
bool surfaces_found = false;
380
for (int i = 0; i < mesh->get_surface_count(); i++) {
381
if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
382
continue;
383
}
384
if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) {
385
all_have_uv2_and_normal = false;
386
break;
387
}
388
if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) {
389
all_have_uv2_and_normal = false;
390
break;
391
}
392
surfaces_found = true;
393
}
394
395
if (surfaces_found && all_have_uv2_and_normal) {
396
//READY TO BAKE! size hint could be computed if not found, actually..
397
398
MeshesFound mf;
399
mf.xform = get_global_transform().affine_inverse() * mi->get_global_transform();
400
mf.node_path = get_path_to(mi);
401
mf.subindex = -1;
402
mf.mesh = mesh;
403
mf.lightmap_scale = mi->get_lightmap_texel_scale();
404
405
Ref<Material> all_override = mi->get_material_override();
406
for (int i = 0; i < mesh->get_surface_count(); i++) {
407
if (all_override.is_valid()) {
408
mf.overrides.push_back(all_override);
409
} else {
410
mf.overrides.push_back(mi->get_surface_override_material(i));
411
}
412
}
413
414
meshes.push_back(mf);
415
}
416
}
417
}
418
419
Node3D *s = Object::cast_to<Node3D>(p_at_node);
420
421
if (!mi && s) {
422
Array bmeshes = p_at_node->call("get_bake_meshes");
423
if (bmeshes.size() && (bmeshes.size() & 1) == 0) {
424
Transform3D xf = get_global_transform().affine_inverse() * s->get_global_transform();
425
for (int i = 0; i < bmeshes.size(); i += 2) {
426
Ref<Mesh> mesh = bmeshes[i];
427
if (mesh.is_null()) {
428
continue;
429
}
430
431
MeshesFound mf;
432
433
Transform3D mesh_xf = bmeshes[i + 1];
434
mf.xform = xf * mesh_xf;
435
mf.node_path = get_path_to(s);
436
mf.subindex = i / 2;
437
mf.lightmap_scale = 1.0;
438
mf.mesh = mesh;
439
440
meshes.push_back(mf);
441
}
442
}
443
}
444
445
Light3D *light = Object::cast_to<Light3D>(p_at_node);
446
447
if (light && light->get_bake_mode() != Light3D::BAKE_DISABLED) {
448
LightsFound lf;
449
lf.xform = get_global_transform().affine_inverse() * light->get_global_transform();
450
lf.light = light;
451
lights.push_back(lf);
452
}
453
454
LightmapProbe *probe = Object::cast_to<LightmapProbe>(p_at_node);
455
456
if (probe) {
457
Transform3D xf = get_global_transform().affine_inverse() * probe->get_global_transform();
458
probes.push_back(xf.origin);
459
}
460
461
for (int i = 0; i < p_at_node->get_child_count(); i++) {
462
Node *child = p_at_node->get_child(i);
463
if (!child->get_owner()) {
464
continue; //maybe a helper
465
}
466
467
_find_meshes_and_lights(child, meshes, lights, probes);
468
}
469
}
470
471
int LightmapGI::_bsp_get_simplex_side(const Vector<Vector3> &p_points, const LocalVector<BSPSimplex> &p_simplices, const Plane &p_plane, uint32_t p_simplex) const {
472
int over = 0;
473
int under = 0;
474
const BSPSimplex &s = p_simplices[p_simplex];
475
for (int i = 0; i < 4; i++) {
476
const Vector3 v = p_points[s.vertices[i]];
477
// The tolerance used here comes from experiments on scenes up to
478
// 1000x1000x100 meters. If it's any smaller, some simplices will
479
// appear to self-intersect due to a lack of precision in Plane.
480
if (p_plane.has_point(v, 1.0 / (1 << 13))) {
481
// Coplanar.
482
} else if (p_plane.is_point_over(v)) {
483
over++;
484
} else {
485
under++;
486
}
487
}
488
489
ERR_FAIL_COND_V(under == 0 && over == 0, -2); //should never happen, we discarded flat simplices before, but in any case drop it from the bsp tree and throw an error
490
if (under == 0) {
491
return 1; // all over
492
} else if (over == 0) {
493
return -1; // all under
494
} else {
495
return 0; // crossing
496
}
497
}
498
499
//#define DEBUG_BSP
500
501
int32_t LightmapGI::_compute_bsp_tree(const Vector<Vector3> &p_points, const LocalVector<Plane> &p_planes, LocalVector<int32_t> &planes_tested, const LocalVector<BSPSimplex> &p_simplices, const LocalVector<int32_t> &p_simplex_indices, LocalVector<BSPNode> &bsp_nodes) {
502
ERR_FAIL_COND_V(p_simplex_indices.size() < 2, -1);
503
504
int32_t node_index = (int32_t)bsp_nodes.size();
505
bsp_nodes.push_back(BSPNode());
506
507
//test with all the simplex planes
508
Plane best_plane;
509
float best_plane_score = -1.0;
510
511
for (const int idx : p_simplex_indices) {
512
const BSPSimplex &s = p_simplices[idx];
513
for (int j = 0; j < 4; j++) {
514
uint32_t plane_index = s.planes[j];
515
if (planes_tested[plane_index] == node_index) {
516
continue; //tested this plane already
517
}
518
519
planes_tested[plane_index] = node_index;
520
521
static const int face_order[4][3] = {
522
{ 0, 1, 2 },
523
{ 0, 2, 3 },
524
{ 0, 1, 3 },
525
{ 1, 2, 3 }
526
};
527
528
// despite getting rid of plane duplicates, we should still use here the actual plane to avoid numerical error
529
// from thinking this same simplex is intersecting rather than on a side
530
Vector3 v0 = p_points[s.vertices[face_order[j][0]]];
531
Vector3 v1 = p_points[s.vertices[face_order[j][1]]];
532
Vector3 v2 = p_points[s.vertices[face_order[j][2]]];
533
534
Plane plane(v0, v1, v2);
535
536
//test with all the simplices
537
int over_count = 0;
538
int under_count = 0;
539
540
for (const int &index : p_simplex_indices) {
541
int side = _bsp_get_simplex_side(p_points, p_simplices, plane, index);
542
if (side == -2) {
543
continue; //this simplex is invalid, skip for now
544
} else if (side < 0) {
545
under_count++;
546
} else if (side > 0) {
547
over_count++;
548
}
549
}
550
551
if (under_count == 0 && over_count == 0) {
552
continue; //most likely precision issue with a flat simplex, do not try this plane
553
}
554
555
if (under_count > over_count) { //make sure under is always less than over, so we can compute the same ratio
556
SWAP(under_count, over_count);
557
}
558
559
float score = 0; //by default, score is 0 (worst)
560
if (over_count > 0) {
561
// Simplices that are intersected by the plane are moved into both the over
562
// and under subtrees which makes the entire tree deeper, so the best plane
563
// will have the least intersections while separating the simplices evenly.
564
float balance = float(under_count) / over_count;
565
float separation = float(over_count + under_count) / p_simplex_indices.size();
566
score = balance * separation * separation;
567
}
568
569
if (score > best_plane_score) {
570
best_plane = plane;
571
best_plane_score = score;
572
}
573
}
574
}
575
576
// We often end up with two (or on rare occasions, three) simplices that are
577
// either disjoint or share one vertex and don't have a separating plane
578
// among their faces. The fallback is to loop through new planes created
579
// with one vertex of the first simplex and two vertices of the second until
580
// we find a winner.
581
if (best_plane_score == 0) {
582
const BSPSimplex &simplex0 = p_simplices[p_simplex_indices[0]];
583
const BSPSimplex &simplex1 = p_simplices[p_simplex_indices[1]];
584
585
for (uint32_t i = 0; i < 4 && !best_plane_score; i++) {
586
Vector3 v0 = p_points[simplex0.vertices[i]];
587
for (uint32_t j = 0; j < 3 && !best_plane_score; j++) {
588
if (simplex0.vertices[i] == simplex1.vertices[j]) {
589
break;
590
}
591
Vector3 v1 = p_points[simplex1.vertices[j]];
592
for (uint32_t k = j + 1; k < 4; k++) {
593
if (simplex0.vertices[i] == simplex1.vertices[k]) {
594
break;
595
}
596
Vector3 v2 = p_points[simplex1.vertices[k]];
597
598
Plane plane = Plane(v0, v1, v2);
599
if (plane == Plane()) { // When v0, v1, and v2 are collinear, they can't form a plane.
600
continue;
601
}
602
int32_t side0 = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[0]);
603
int32_t side1 = _bsp_get_simplex_side(p_points, p_simplices, plane, p_simplex_indices[1]);
604
if ((side0 == 1 && side1 == -1) || (side0 == -1 && side1 == 1)) {
605
best_plane = plane;
606
best_plane_score = 1.0;
607
break;
608
}
609
}
610
}
611
}
612
}
613
614
LocalVector<int32_t> indices_over;
615
LocalVector<int32_t> indices_under;
616
617
//split again, but add to list
618
for (const uint32_t index : p_simplex_indices) {
619
int side = _bsp_get_simplex_side(p_points, p_simplices, best_plane, index);
620
621
if (side == -2) {
622
continue; //simplex sits on the plane, does not make sense to use it
623
}
624
if (side <= 0) {
625
indices_under.push_back(index);
626
}
627
628
if (side >= 0) {
629
indices_over.push_back(index);
630
}
631
}
632
633
#ifdef DEBUG_BSP
634
print_line("node " + itos(node_index) + " found plane: " + best_plane + " score:" + rtos(best_plane_score) + " - over " + itos(indices_over.size()) + " under " + itos(indices_under.size()) + " intersecting " + itos(intersecting));
635
#endif
636
637
if (best_plane_score < 0.0 || indices_over.size() == p_simplex_indices.size() || indices_under.size() == p_simplex_indices.size()) {
638
// Failed to separate the tetrahedrons using planes
639
// this means Delaunay broke at some point.
640
// Luckily, because we are using tetrahedrons, we can resort to
641
// less precise but still working ways to generate the separating plane
642
// this will most likely look bad when interpolating, but at least it will not crash.
643
// and the artifact will most likely also be very small, so too difficult to notice.
644
645
//find the longest axis
646
647
WARN_PRINT("Inconsistency found in triangulation while building BSP, probe interpolation quality may degrade a bit.");
648
649
LocalVector<Vector3> centers;
650
AABB bounds_all;
651
for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
652
AABB bounds;
653
for (uint32_t j = 0; j < 4; j++) {
654
Vector3 p = p_points[p_simplices[p_simplex_indices[i]].vertices[j]];
655
if (j == 0) {
656
bounds.position = p;
657
} else {
658
bounds.expand_to(p);
659
}
660
}
661
if (i == 0) {
662
centers.push_back(bounds.get_center());
663
} else {
664
bounds_all.merge_with(bounds);
665
}
666
}
667
Vector3::Axis longest_axis = Vector3::Axis(bounds_all.get_longest_axis_index());
668
669
//find the simplex that will go under
670
uint32_t min_d_idx = 0xFFFFFFFF;
671
float min_d_dist = 1e20;
672
673
for (uint32_t i = 0; i < centers.size(); i++) {
674
if (centers[i][longest_axis] < min_d_dist) {
675
min_d_idx = i;
676
min_d_dist = centers[i][longest_axis];
677
}
678
}
679
//rebuild best_plane and over/under arrays
680
best_plane = Plane();
681
best_plane.normal[longest_axis] = 1.0;
682
best_plane.d = min_d_dist;
683
684
indices_under.clear();
685
indices_under.push_back(min_d_idx);
686
687
indices_over.clear();
688
689
for (uint32_t i = 0; i < p_simplex_indices.size(); i++) {
690
if (i == min_d_idx) {
691
continue;
692
}
693
indices_over.push_back(p_simplex_indices[i]);
694
}
695
}
696
697
BSPNode node;
698
node.plane = best_plane;
699
700
if (indices_under.is_empty()) {
701
//nothing to do here
702
node.under = BSPNode::EMPTY_LEAF;
703
} else if (indices_under.size() == 1) {
704
node.under = -(indices_under[0] + 1);
705
} else {
706
node.under = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_under, bsp_nodes);
707
}
708
709
if (indices_over.is_empty()) {
710
//nothing to do here
711
node.over = BSPNode::EMPTY_LEAF;
712
} else if (indices_over.size() == 1) {
713
node.over = -(indices_over[0] + 1);
714
} else {
715
node.over = _compute_bsp_tree(p_points, p_planes, planes_tested, p_simplices, indices_over, bsp_nodes);
716
}
717
718
bsp_nodes[node_index] = node;
719
720
return node_index;
721
}
722
723
bool LightmapGI::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) {
724
BakeStepUD *bsud = (BakeStepUD *)ud;
725
bool ret = false;
726
if (bsud->func) {
727
ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh);
728
}
729
return ret;
730
}
731
732
void LightmapGI::_plot_triangle_into_octree(GenProbesOctree *p_cell, float p_cell_size, const Vector3 *p_triangle) {
733
for (int i = 0; i < 8; i++) {
734
Vector3i pos = p_cell->offset;
735
uint32_t half_size = p_cell->size / 2;
736
if (i & 1) {
737
pos.x += half_size;
738
}
739
if (i & 2) {
740
pos.y += half_size;
741
}
742
if (i & 4) {
743
pos.z += half_size;
744
}
745
746
AABB subcell;
747
subcell.position = Vector3(pos) * p_cell_size;
748
subcell.size = Vector3(half_size, half_size, half_size) * p_cell_size;
749
750
if (!Geometry3D::triangle_box_overlap(subcell.get_center(), subcell.size * 0.5, p_triangle)) {
751
continue;
752
}
753
754
if (p_cell->children[i] == nullptr) {
755
GenProbesOctree *child = memnew(GenProbesOctree);
756
child->offset = pos;
757
child->size = half_size;
758
p_cell->children[i] = child;
759
}
760
761
if (half_size > 1) {
762
//still levels missing
763
_plot_triangle_into_octree(p_cell->children[i], p_cell_size, p_triangle);
764
}
765
}
766
}
767
768
void LightmapGI::_gen_new_positions_from_octree(const GenProbesOctree *p_cell, float p_cell_size, const Vector<Vector3> &probe_positions, LocalVector<Vector3> &new_probe_positions, HashMap<Vector3i, bool> &positions_used, const AABB &p_bounds) {
769
for (int i = 0; i < 8; i++) {
770
Vector3i pos = p_cell->offset;
771
if (i & 1) {
772
pos.x += p_cell->size;
773
}
774
if (i & 2) {
775
pos.y += p_cell->size;
776
}
777
if (i & 4) {
778
pos.z += p_cell->size;
779
}
780
781
if (p_cell->size == 1 && !positions_used.has(pos)) {
782
//new position to insert!
783
Vector3 real_pos = p_bounds.position + Vector3(pos) * p_cell_size;
784
//see if a user submitted probe is too close
785
int ppcount = probe_positions.size();
786
const Vector3 *pp = probe_positions.ptr();
787
bool exists = false;
788
for (int j = 0; j < ppcount; j++) {
789
if (pp[j].distance_to(real_pos) < (p_cell_size * 0.5f)) {
790
exists = true;
791
break;
792
}
793
}
794
795
if (!exists) {
796
new_probe_positions.push_back(real_pos);
797
}
798
799
positions_used[pos] = true;
800
}
801
802
if (p_cell->children[i] != nullptr) {
803
_gen_new_positions_from_octree(p_cell->children[i], p_cell_size, probe_positions, new_probe_positions, positions_used, p_bounds);
804
}
805
}
806
}
807
808
LightmapGI::BakeError LightmapGI::_save_and_reimport_atlas_textures(const Ref<Lightmapper> p_lightmapper, const String &p_base_name, TypedArray<TextureLayered> &r_textures, bool p_is_shadowmask) const {
809
Vector<Ref<Image>> images;
810
images.resize(p_is_shadowmask ? p_lightmapper->get_shadowmask_texture_count() : p_lightmapper->get_bake_texture_count());
811
812
for (int i = 0; i < images.size(); i++) {
813
images.set(i, p_is_shadowmask ? p_lightmapper->get_shadowmask_texture(i) : p_lightmapper->get_bake_texture(i));
814
}
815
816
const int slice_count = images.size();
817
const int slice_width = images[0]->get_width();
818
const int slice_height = images[0]->get_height();
819
820
const int slices_per_texture = Image::MAX_HEIGHT / slice_height;
821
const int texture_count = Math::ceil(slice_count / (float)slices_per_texture);
822
const int last_count = slice_count % slices_per_texture;
823
824
r_textures.resize(texture_count);
825
826
for (int i = 0; i < texture_count; i++) {
827
const int texture_slice_count = (i == texture_count - 1 && last_count != 0) ? last_count : slices_per_texture;
828
829
Ref<Image> texture_image = Image::create_empty(slice_width, slice_height * texture_slice_count, false, images[0]->get_format());
830
831
for (int j = 0; j < texture_slice_count; j++) {
832
texture_image->blit_rect(images[i * slices_per_texture + j], Rect2i(0, 0, slice_width, slice_height), Point2i(0, slice_height * j));
833
}
834
835
const String atlas_path = (texture_count > 1 ? p_base_name + "_" + itos(i) : p_base_name) + (p_is_shadowmask ? ".png" : ".exr");
836
const String config_path = atlas_path + ".import";
837
838
Ref<ConfigFile> config;
839
config.instantiate();
840
841
// Load an import configuration if present.
842
if (FileAccess::exists(config_path)) {
843
config->load(config_path);
844
}
845
846
config->set_value("remap", "importer", "2d_array_texture");
847
config->set_value("remap", "type", "CompressedTexture2DArray");
848
if (!config->has_section_key("params", "compress/mode")) {
849
// Do not override an existing compression mode.
850
config->set_value("params", "compress/mode", 2);
851
}
852
config->set_value("params", "compress/channel_pack", 1);
853
config->set_value("params", "mipmaps/generate", false);
854
config->set_value("params", "slices/horizontal", 1);
855
config->set_value("params", "slices/vertical", texture_slice_count);
856
857
config->save(config_path);
858
859
if (supersampling_enabled) {
860
texture_image->resize(texture_image->get_width() / supersampling_factor, texture_image->get_height() / supersampling_factor, Image::INTERPOLATE_TRILINEAR);
861
}
862
863
// Save the file.
864
Error save_err;
865
if (p_is_shadowmask) {
866
save_err = texture_image->save_png(atlas_path);
867
} else {
868
save_err = texture_image->save_exr(atlas_path, false);
869
}
870
871
ERR_FAIL_COND_V(save_err, LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE);
872
873
// Reimport the file.
874
ResourceLoader::import(atlas_path);
875
Ref<TextureLayered> t = ResourceLoader::load(atlas_path); // If already loaded, it will be updated on refocus?
876
ERR_FAIL_COND_V(t.is_null(), LightmapGI::BAKE_ERROR_CANT_CREATE_IMAGE);
877
878
// Store the atlas in the array.
879
r_textures[i] = t;
880
}
881
882
return LightmapGI::BAKE_ERROR_OK;
883
}
884
885
LightmapGI::BakeError LightmapGI::bake(Node *p_from_node, String p_image_data_path, Lightmapper::BakeStepFunc p_bake_step, void *p_bake_userdata) {
886
if (p_image_data_path.is_empty()) {
887
if (get_light_data().is_null()) {
888
return BAKE_ERROR_NO_SAVE_PATH;
889
}
890
891
p_image_data_path = get_light_data()->get_path();
892
if (!p_image_data_path.is_resource_file()) {
893
return BAKE_ERROR_NO_SAVE_PATH;
894
}
895
}
896
897
Ref<Lightmapper> lightmapper = Lightmapper::create();
898
ERR_FAIL_COND_V(lightmapper.is_null(), BAKE_ERROR_NO_LIGHTMAPPER);
899
900
BakeStepUD bsud;
901
bsud.func = p_bake_step;
902
bsud.ud = p_bake_userdata;
903
bsud.from_percent = 0.2;
904
bsud.to_percent = 0.8;
905
906
if (p_bake_step) {
907
p_bake_step(0.0, RTR("Finding meshes, lights and probes"), p_bake_userdata, true);
908
}
909
/* STEP 1, FIND MESHES, LIGHTS AND PROBES */
910
Vector<Lightmapper::MeshData> mesh_data;
911
Vector<LightsFound> lights_found;
912
Vector<Vector3> probes_found;
913
AABB bounds;
914
{
915
Vector<MeshesFound> meshes_found;
916
_find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found, probes_found);
917
918
if (meshes_found.is_empty()) {
919
return BAKE_ERROR_NO_MESHES;
920
}
921
// create mesh data for insert
922
923
//get the base material textures, help compute atlas size and bounds
924
for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
925
if (p_bake_step) {
926
float p = (float)(m_i) / meshes_found.size();
927
p_bake_step(p * 0.1, vformat(RTR("Preparing geometry %d/%d"), m_i, meshes_found.size()), p_bake_userdata, false);
928
}
929
930
MeshesFound &mf = meshes_found.write[m_i];
931
932
Size2i mesh_lightmap_size = mf.mesh->get_lightmap_size_hint();
933
if (mesh_lightmap_size == Size2i(0, 0)) {
934
// TODO we should compute a size if no lightmap hint is set, as we did in 3.x.
935
// For now set to basic size to avoid crash.
936
mesh_lightmap_size = Size2i(64, 64);
937
}
938
// Double lightmap texel density if downsampling is enabled, as the final texture size will be halved before saving lightmaps.
939
Size2i lightmap_size = Size2i(Size2(mesh_lightmap_size) * mf.lightmap_scale * texel_scale) * (supersampling_enabled ? supersampling_factor : 1.0);
940
ERR_FAIL_COND_V(lightmap_size.x == 0 || lightmap_size.y == 0, BAKE_ERROR_LIGHTMAP_TOO_SMALL);
941
942
TypedArray<RID> overrides;
943
overrides.resize(mf.overrides.size());
944
for (int i = 0; i < mf.overrides.size(); i++) {
945
if (mf.overrides[i].is_valid()) {
946
overrides[i] = mf.overrides[i]->get_rid();
947
}
948
}
949
TypedArray<Image> images = RS::get_singleton()->bake_render_uv2(mf.mesh->get_rid(), overrides, lightmap_size);
950
951
ERR_FAIL_COND_V(images.is_empty(), BAKE_ERROR_CANT_CREATE_IMAGE);
952
953
Ref<Image> albedo = images[RS::BAKE_CHANNEL_ALBEDO_ALPHA];
954
Ref<Image> orm = images[RS::BAKE_CHANNEL_ORM];
955
956
//multiply albedo by metal
957
958
Lightmapper::MeshData md;
959
960
{
961
Dictionary d;
962
d["path"] = mf.node_path;
963
if (mf.subindex >= 0) {
964
d["subindex"] = mf.subindex;
965
}
966
md.userdata = d;
967
}
968
969
{
970
if (albedo->get_format() != Image::FORMAT_RGBA8) {
971
albedo->convert(Image::FORMAT_RGBA8);
972
}
973
if (orm->get_format() != Image::FORMAT_RGBA8) {
974
orm->convert(Image::FORMAT_RGBA8);
975
}
976
Vector<uint8_t> albedo_alpha = albedo->get_data();
977
Vector<uint8_t> orm_data = orm->get_data();
978
979
Vector<uint8_t> albedom;
980
uint32_t len = albedo_alpha.size();
981
albedom.resize(len);
982
const uint8_t *r_aa = albedo_alpha.ptr();
983
const uint8_t *r_orm = orm_data.ptr();
984
uint8_t *w_albedo = albedom.ptrw();
985
986
for (uint32_t i = 0; i < len; i += 4) {
987
w_albedo[i + 0] = uint8_t(CLAMP(float(r_aa[i + 0]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
988
w_albedo[i + 1] = uint8_t(CLAMP(float(r_aa[i + 1]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
989
w_albedo[i + 2] = uint8_t(CLAMP(float(r_aa[i + 2]) * (1.0 - float(r_orm[i + 2] / 255.0)), 0, 255));
990
w_albedo[i + 3] = r_aa[i + 3];
991
}
992
993
md.albedo_on_uv2.instantiate();
994
md.albedo_on_uv2->set_data(lightmap_size.width, lightmap_size.height, false, Image::FORMAT_RGBA8, albedom);
995
}
996
997
md.emission_on_uv2 = images[RS::BAKE_CHANNEL_EMISSION];
998
if (md.emission_on_uv2->get_format() != Image::FORMAT_RGBAH) {
999
md.emission_on_uv2->convert(Image::FORMAT_RGBAH);
1000
}
1001
1002
//get geometry
1003
1004
Basis normal_xform = mf.xform.basis.inverse().transposed();
1005
1006
for (int i = 0; i < mf.mesh->get_surface_count(); i++) {
1007
if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
1008
continue;
1009
}
1010
Array a = mf.mesh->surface_get_arrays(i);
1011
Ref<Material> mat = mf.mesh->surface_get_material(i);
1012
RID mat_rid;
1013
if (mat.is_valid()) {
1014
mat_rid = mat->get_rid();
1015
}
1016
1017
Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
1018
const Vector3 *vr = vertices.ptr();
1019
Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV2];
1020
const Vector2 *uvr = nullptr;
1021
Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
1022
const Vector3 *nr = nullptr;
1023
Vector<int> index = a[Mesh::ARRAY_INDEX];
1024
1025
ERR_CONTINUE(uv.is_empty());
1026
ERR_CONTINUE(normals.is_empty());
1027
1028
uvr = uv.ptr();
1029
nr = normals.ptr();
1030
1031
int facecount;
1032
const int *ir = nullptr;
1033
1034
if (index.size()) {
1035
facecount = index.size() / 3;
1036
ir = index.ptr();
1037
} else {
1038
facecount = vertices.size() / 3;
1039
}
1040
1041
for (int j = 0; j < facecount; j++) {
1042
uint32_t vidx[3];
1043
1044
if (ir) {
1045
for (int k = 0; k < 3; k++) {
1046
vidx[k] = ir[j * 3 + k];
1047
}
1048
} else {
1049
for (int k = 0; k < 3; k++) {
1050
vidx[k] = j * 3 + k;
1051
}
1052
}
1053
1054
for (int k = 0; k < 3; k++) {
1055
Vector3 v = mf.xform.xform(vr[vidx[k]]);
1056
if (bounds == AABB()) {
1057
bounds.position = v;
1058
} else {
1059
bounds.expand_to(v);
1060
}
1061
md.points.push_back(v);
1062
1063
md.uv2.push_back(uvr[vidx[k]]);
1064
md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized());
1065
md.material.push_back(mat_rid);
1066
}
1067
}
1068
}
1069
1070
mesh_data.push_back(md);
1071
}
1072
}
1073
1074
/* STEP 2, CREATE PROBES */
1075
1076
if (p_bake_step) {
1077
p_bake_step(0.3, RTR("Creating probes"), p_bake_userdata, true);
1078
}
1079
1080
//bounds need to include the user probes
1081
for (int i = 0; i < probes_found.size(); i++) {
1082
bounds.expand_to(probes_found[i]);
1083
}
1084
1085
bounds.grow_by(bounds.size.length() * 0.001);
1086
1087
if (gen_probes == GENERATE_PROBES_DISABLED) {
1088
// generate 8 probes on bound endpoints
1089
for (int i = 0; i < 8; i++) {
1090
probes_found.push_back(bounds.get_endpoint(i));
1091
}
1092
} else {
1093
// detect probes from geometry
1094
static const int subdiv_values[6] = { 0, 4, 8, 16, 32 };
1095
int subdiv = subdiv_values[gen_probes];
1096
1097
float subdiv_cell_size;
1098
Vector3i bound_limit;
1099
{
1100
int longest_axis = bounds.get_longest_axis_index();
1101
subdiv_cell_size = bounds.size[longest_axis] / subdiv;
1102
int axis_n1 = (longest_axis + 1) % 3;
1103
int axis_n2 = (longest_axis + 2) % 3;
1104
1105
bound_limit[longest_axis] = subdiv;
1106
bound_limit[axis_n1] = int(Math::ceil(bounds.size[axis_n1] / subdiv_cell_size));
1107
bound_limit[axis_n2] = int(Math::ceil(bounds.size[axis_n2] / subdiv_cell_size));
1108
//compensate bounds
1109
bounds.size[axis_n1] = bound_limit[axis_n1] * subdiv_cell_size;
1110
bounds.size[axis_n2] = bound_limit[axis_n2] * subdiv_cell_size;
1111
}
1112
1113
GenProbesOctree octree;
1114
octree.size = subdiv;
1115
1116
for (int i = 0; i < mesh_data.size(); i++) {
1117
if (p_bake_step) {
1118
float p = (float)(i) / mesh_data.size();
1119
p_bake_step(0.3 + p * 0.1, vformat(RTR("Creating probes from mesh %d/%d"), i, mesh_data.size()), p_bake_userdata, false);
1120
}
1121
1122
for (int j = 0; j < mesh_data[i].points.size(); j += 3) {
1123
Vector3 points[3] = { mesh_data[i].points[j + 0] - bounds.position, mesh_data[i].points[j + 1] - bounds.position, mesh_data[i].points[j + 2] - bounds.position };
1124
_plot_triangle_into_octree(&octree, subdiv_cell_size, points);
1125
}
1126
}
1127
1128
LocalVector<Vector3> new_probe_positions;
1129
HashMap<Vector3i, bool> positions_used;
1130
for (uint32_t i = 0; i < 8; i++) { //insert bounding endpoints
1131
Vector3i pos;
1132
if (i & 1) {
1133
pos.x += bound_limit.x;
1134
}
1135
if (i & 2) {
1136
pos.y += bound_limit.y;
1137
}
1138
if (i & 4) {
1139
pos.z += bound_limit.z;
1140
}
1141
1142
positions_used[pos] = true;
1143
Vector3 real_pos = bounds.position + Vector3(pos) * subdiv_cell_size; //use same formula for numerical stability
1144
new_probe_positions.push_back(real_pos);
1145
}
1146
//skip first level, since probes are always added at bounds endpoints anyway (code above this)
1147
for (int i = 0; i < 8; i++) {
1148
if (octree.children[i]) {
1149
_gen_new_positions_from_octree(octree.children[i], subdiv_cell_size, probes_found, new_probe_positions, positions_used, bounds);
1150
}
1151
}
1152
1153
for (const Vector3 &position : new_probe_positions) {
1154
probes_found.push_back(position);
1155
}
1156
}
1157
1158
// Add everything to lightmapper
1159
const bool use_physical_light_units = GLOBAL_GET("rendering/lights_and_shadows/use_physical_light_units");
1160
if (p_bake_step) {
1161
p_bake_step(0.4, RTR("Preparing Lightmapper"), p_bake_userdata, true);
1162
}
1163
1164
{
1165
for (int i = 0; i < mesh_data.size(); i++) {
1166
lightmapper->add_mesh(mesh_data[i]);
1167
}
1168
for (int i = 0; i < lights_found.size(); i++) {
1169
Light3D *light = lights_found[i].light;
1170
if (light->is_editor_only()) {
1171
// Don't include editor-only lights in the lightmap bake,
1172
// as this results in inconsistent visuals when running the project.
1173
continue;
1174
}
1175
1176
Transform3D xf = lights_found[i].xform;
1177
1178
// For the lightmapper, the indirect energy represents the multiplier for the indirect bounces caused by the light, so the value is not converted when using physical units.
1179
float indirect_energy = light->get_param(Light3D::PARAM_INDIRECT_ENERGY);
1180
Color linear_color = light->get_color().srgb_to_linear();
1181
float energy = light->get_param(Light3D::PARAM_ENERGY);
1182
if (use_physical_light_units) {
1183
energy *= light->get_param(Light3D::PARAM_INTENSITY);
1184
linear_color *= light->get_correlated_color().srgb_to_linear();
1185
}
1186
1187
if (Object::cast_to<DirectionalLight3D>(light)) {
1188
DirectionalLight3D *l = Object::cast_to<DirectionalLight3D>(light);
1189
if (l->get_sky_mode() != DirectionalLight3D::SKY_MODE_SKY_ONLY) {
1190
lightmapper->add_directional_light(light->get_name(), light->get_bake_mode() == Light3D::BAKE_STATIC, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy, indirect_energy, l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
1191
}
1192
} else if (Object::cast_to<OmniLight3D>(light)) {
1193
OmniLight3D *l = Object::cast_to<OmniLight3D>(light);
1194
if (use_physical_light_units) {
1195
energy *= (1.0 / (Math::PI * 4.0));
1196
}
1197
lightmapper->add_omni_light(light->get_name(), light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, linear_color, energy, indirect_energy, l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
1198
} else if (Object::cast_to<SpotLight3D>(light)) {
1199
SpotLight3D *l = Object::cast_to<SpotLight3D>(light);
1200
if (use_physical_light_units) {
1201
energy *= (1.0 / Math::PI);
1202
}
1203
lightmapper->add_spot_light(light->get_name(), light->get_bake_mode() == Light3D::BAKE_STATIC, xf.origin, -xf.basis.get_column(Vector3::AXIS_Z).normalized(), linear_color, energy, indirect_energy, l->get_param(Light3D::PARAM_RANGE), l->get_param(Light3D::PARAM_ATTENUATION), l->get_param(Light3D::PARAM_SPOT_ANGLE), l->get_param(Light3D::PARAM_SPOT_ATTENUATION), l->get_param(Light3D::PARAM_SIZE), l->get_param(Light3D::PARAM_SHADOW_BLUR));
1204
}
1205
}
1206
for (int i = 0; i < probes_found.size(); i++) {
1207
lightmapper->add_probe(probes_found[i]);
1208
}
1209
}
1210
1211
Ref<Image> environment_image;
1212
Basis environment_transform;
1213
1214
// Add everything to lightmapper
1215
if (environment_mode != ENVIRONMENT_MODE_DISABLED) {
1216
if (p_bake_step) {
1217
p_bake_step(4.1, RTR("Preparing Environment"), p_bake_userdata, true);
1218
}
1219
1220
environment_transform = get_global_transform().basis;
1221
1222
switch (environment_mode) {
1223
case ENVIRONMENT_MODE_DISABLED: {
1224
//nothing
1225
} break;
1226
case ENVIRONMENT_MODE_SCENE: {
1227
Ref<World3D> world = get_world_3d();
1228
if (world.is_valid()) {
1229
Ref<Environment> env = world->get_environment();
1230
if (env.is_null()) {
1231
env = world->get_fallback_environment();
1232
}
1233
1234
if (env.is_valid()) {
1235
environment_image = RS::get_singleton()->environment_bake_panorama(env->get_rid(), true, Size2i(128, 64));
1236
environment_transform = Basis::from_euler(env->get_sky_rotation()).inverse();
1237
}
1238
}
1239
} break;
1240
case ENVIRONMENT_MODE_CUSTOM_SKY: {
1241
if (environment_custom_sky.is_valid()) {
1242
environment_image = RS::get_singleton()->sky_bake_panorama(environment_custom_sky->get_rid(), environment_custom_energy, true, Size2i(128, 64));
1243
}
1244
1245
} break;
1246
case ENVIRONMENT_MODE_CUSTOM_COLOR: {
1247
environment_image.instantiate();
1248
environment_image->initialize_data(128, 64, false, Image::FORMAT_RGBAF);
1249
Color c = environment_custom_color;
1250
c.r *= environment_custom_energy;
1251
c.g *= environment_custom_energy;
1252
c.b *= environment_custom_energy;
1253
environment_image->fill(c);
1254
1255
} break;
1256
}
1257
}
1258
1259
float exposure_normalization = 1.0;
1260
if (camera_attributes.is_valid()) {
1261
exposure_normalization = camera_attributes->get_exposure_multiplier();
1262
if (use_physical_light_units) {
1263
exposure_normalization = camera_attributes->calculate_exposure_normalization();
1264
}
1265
}
1266
1267
Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, denoiser_strength, denoiser_range, bounces,
1268
bounce_indirect_energy, bias, max_texture_size, directional, shadowmask_mode != LightmapGIData::SHADOWMASK_MODE_NONE, use_texture_for_bounces,
1269
Lightmapper::GenerateProbes(gen_probes), environment_image, environment_transform, _lightmap_bake_step_function, &bsud, exposure_normalization, (supersampling_enabled ? supersampling_factor : 1));
1270
1271
if (bake_err == Lightmapper::BAKE_ERROR_TEXTURE_EXCEEDS_MAX_SIZE) {
1272
return BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL;
1273
} else if (bake_err == Lightmapper::BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES) {
1274
return BAKE_ERROR_MESHES_INVALID;
1275
} else if (bake_err == Lightmapper::BAKE_ERROR_ATLAS_TOO_SMALL) {
1276
return BAKE_ERROR_ATLAS_TOO_SMALL;
1277
} else if (bake_err == Lightmapper::BAKE_ERROR_USER_ABORTED) {
1278
return BAKE_ERROR_USER_ABORTED;
1279
}
1280
1281
// POSTBAKE: Save Textures.
1282
TypedArray<TextureLayered> lightmap_textures;
1283
TypedArray<TextureLayered> shadowmask_textures;
1284
1285
const String texture_filename = p_image_data_path.get_basename();
1286
const int shadowmask_texture_count = lightmapper->get_shadowmask_texture_count();
1287
const bool save_shadowmask = shadowmask_mode != LightmapGIData::SHADOWMASK_MODE_NONE && shadowmask_texture_count > 0;
1288
1289
// Save the lightmap atlases.
1290
BakeError save_err = _save_and_reimport_atlas_textures(lightmapper, texture_filename, lightmap_textures, false);
1291
ERR_FAIL_COND_V(save_err != BAKE_ERROR_OK, save_err);
1292
1293
if (save_shadowmask) {
1294
// Save the shadowmask atlases.
1295
save_err = _save_and_reimport_atlas_textures(lightmapper, texture_filename + "_shadow", shadowmask_textures, true);
1296
ERR_FAIL_COND_V(save_err != BAKE_ERROR_OK, save_err);
1297
}
1298
1299
// POSTBAKE: Save Light Data.
1300
Ref<LightmapGIData> gi_data;
1301
1302
if (get_light_data().is_valid()) {
1303
gi_data = get_light_data();
1304
set_light_data(Ref<LightmapGIData>()); // Clear.
1305
gi_data->clear();
1306
1307
} else {
1308
gi_data.instantiate();
1309
}
1310
1311
gi_data->set_lightmap_textures(lightmap_textures);
1312
1313
if (save_shadowmask) {
1314
gi_data->set_shadowmask_textures(shadowmask_textures);
1315
} else {
1316
gi_data->clear_shadowmask_textures();
1317
}
1318
1319
gi_data->set_uses_spherical_harmonics(directional);
1320
gi_data->_set_uses_packed_directional(directional); // New SH lightmaps are packed automatically.
1321
1322
for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
1323
Dictionary d = lightmapper->get_bake_mesh_userdata(i);
1324
NodePath np = d["path"];
1325
int32_t subindex = -1;
1326
if (d.has("subindex")) {
1327
subindex = d["subindex"];
1328
}
1329
1330
Rect2 uv_scale = lightmapper->get_bake_mesh_uv_scale(i);
1331
int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
1332
gi_data->add_user(np, uv_scale, slice_index, subindex);
1333
}
1334
1335
{
1336
// Create tetrahedrons.
1337
Vector<Vector3> points;
1338
Vector<Color> sh;
1339
points.resize(lightmapper->get_bake_probe_count());
1340
sh.resize(lightmapper->get_bake_probe_count() * 9);
1341
for (int i = 0; i < lightmapper->get_bake_probe_count(); i++) {
1342
points.write[i] = lightmapper->get_bake_probe_point(i);
1343
Vector<Color> colors = lightmapper->get_bake_probe_sh(i);
1344
ERR_CONTINUE(colors.size() != 9);
1345
for (int j = 0; j < 9; j++) {
1346
sh.write[i * 9 + j] = colors[j];
1347
}
1348
}
1349
1350
// Obtain solved simplices.
1351
if (p_bake_step) {
1352
p_bake_step(0.8, RTR("Generating Probe Volumes"), p_bake_userdata, true);
1353
}
1354
1355
Vector<Delaunay3D::OutputSimplex> solved_simplices = Delaunay3D::tetrahedralize(points);
1356
1357
LocalVector<BSPSimplex> bsp_simplices;
1358
LocalVector<Plane> bsp_planes;
1359
LocalVector<int32_t> bsp_simplex_indices;
1360
PackedInt32Array tetrahedrons;
1361
1362
for (int i = 0; i < solved_simplices.size(); i++) {
1363
//Prepare a special representation of the simplex, which uses a BSP Tree
1364
BSPSimplex bsp_simplex;
1365
for (int j = 0; j < 4; j++) {
1366
bsp_simplex.vertices[j] = solved_simplices[i].points[j];
1367
}
1368
for (int j = 0; j < 4; j++) {
1369
static const int face_order[4][3] = {
1370
{ 0, 1, 2 },
1371
{ 0, 2, 3 },
1372
{ 0, 1, 3 },
1373
{ 1, 2, 3 }
1374
};
1375
Vector3 a = points[solved_simplices[i].points[face_order[j][0]]];
1376
Vector3 b = points[solved_simplices[i].points[face_order[j][1]]];
1377
Vector3 c = points[solved_simplices[i].points[face_order[j][2]]];
1378
1379
//store planes in an array, but ensure they are reused, to speed up processing
1380
1381
Plane p(a, b, c);
1382
int plane_index = -1;
1383
for (uint32_t k = 0; k < bsp_planes.size(); k++) {
1384
if (bsp_planes[k].is_equal_approx_any_side(p)) {
1385
plane_index = k;
1386
break;
1387
}
1388
}
1389
1390
if (plane_index == -1) {
1391
plane_index = bsp_planes.size();
1392
bsp_planes.push_back(p);
1393
}
1394
1395
bsp_simplex.planes[j] = plane_index;
1396
1397
//also fill simplex array
1398
tetrahedrons.push_back(solved_simplices[i].points[j]);
1399
}
1400
1401
bsp_simplex_indices.push_back(bsp_simplices.size());
1402
bsp_simplices.push_back(bsp_simplex);
1403
}
1404
1405
//#define DEBUG_SIMPLICES_AS_OBJ_FILE
1406
#ifdef DEBUG_SIMPLICES_AS_OBJ_FILE
1407
{
1408
Ref<FileAccess> f = FileAccess::open("res://bsp.obj", FileAccess::WRITE);
1409
for (uint32_t i = 0; i < bsp_simplices.size(); i++) {
1410
f->store_line("o Simplex" + itos(i));
1411
for (int j = 0; j < 4; j++) {
1412
f->store_line(vformat("v %f %f %f", points[bsp_simplices[i].vertices[j]].x, points[bsp_simplices[i].vertices[j]].y, points[bsp_simplices[i].vertices[j]].z));
1413
}
1414
static const int face_order[4][3] = {
1415
{ 1, 2, 3 },
1416
{ 1, 3, 4 },
1417
{ 1, 2, 4 },
1418
{ 2, 3, 4 }
1419
};
1420
1421
for (int j = 0; j < 4; j++) {
1422
f->store_line(vformat("f %d %d %d", 4 * i + face_order[j][0], 4 * i + face_order[j][1], 4 * i + face_order[j][2]));
1423
}
1424
}
1425
}
1426
#endif
1427
1428
LocalVector<BSPNode> bsp_nodes;
1429
LocalVector<int32_t> planes_tested;
1430
planes_tested.resize(bsp_planes.size());
1431
for (int &index : planes_tested) {
1432
index = 0x7FFFFFFF;
1433
}
1434
1435
if (p_bake_step) {
1436
p_bake_step(0.9, RTR("Generating Probe Acceleration Structures"), p_bake_userdata, true);
1437
}
1438
1439
_compute_bsp_tree(points, bsp_planes, planes_tested, bsp_simplices, bsp_simplex_indices, bsp_nodes);
1440
1441
PackedInt32Array bsp_array;
1442
bsp_array.resize(bsp_nodes.size() * 6); // six 32 bits values used for each BSP node
1443
{
1444
float *fptr = (float *)bsp_array.ptrw();
1445
int32_t *iptr = (int32_t *)bsp_array.ptrw();
1446
for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
1447
fptr[i * 6 + 0] = bsp_nodes[i].plane.normal.x;
1448
fptr[i * 6 + 1] = bsp_nodes[i].plane.normal.y;
1449
fptr[i * 6 + 2] = bsp_nodes[i].plane.normal.z;
1450
fptr[i * 6 + 3] = bsp_nodes[i].plane.d;
1451
iptr[i * 6 + 4] = bsp_nodes[i].over;
1452
iptr[i * 6 + 5] = bsp_nodes[i].under;
1453
}
1454
//#define DEBUG_BSP_TREE
1455
#ifdef DEBUG_BSP_TREE
1456
Ref<FileAccess> f = FileAccess::open("res://bsp.txt", FileAccess::WRITE);
1457
for (uint32_t i = 0; i < bsp_nodes.size(); i++) {
1458
f->store_line(itos(i) + " - plane: " + bsp_nodes[i].plane + " over: " + itos(bsp_nodes[i].over) + " under: " + itos(bsp_nodes[i].under));
1459
}
1460
#endif
1461
}
1462
1463
/* Obtain the colors from the images, they will be re-created as cubemaps on the server, depending on the driver */
1464
1465
gi_data->set_capture_data(bounds, interior, points, sh, tetrahedrons, bsp_array, exposure_normalization);
1466
/* Compute a BSP tree of the simplices, so it's easy to find the exact one */
1467
}
1468
1469
gi_data->set_path(p_image_data_path, true);
1470
Error err = ResourceSaver::save(gi_data);
1471
1472
if (err != OK) {
1473
return BAKE_ERROR_CANT_CREATE_IMAGE;
1474
}
1475
1476
set_light_data(gi_data);
1477
update_configuration_warnings();
1478
1479
return BAKE_ERROR_OK;
1480
}
1481
1482
void LightmapGI::_notification(int p_what) {
1483
switch (p_what) {
1484
case NOTIFICATION_POST_ENTER_TREE: {
1485
if (light_data.is_valid()) {
1486
ERR_FAIL_COND_MSG(
1487
light_data->is_using_spherical_harmonics() && !light_data->_is_using_packed_directional(),
1488
vformat(
1489
"%s (%s): The directional lightmap textures are stored in a format that isn't supported anymore. Please bake lightmaps again to make lightmaps display from this node again.",
1490
get_light_data()->get_path(), get_name()));
1491
1492
if (last_owner && last_owner != get_owner()) {
1493
light_data->clear_users();
1494
}
1495
1496
_assign_lightmaps();
1497
}
1498
} break;
1499
1500
case NOTIFICATION_EXIT_TREE: {
1501
last_owner = get_owner();
1502
1503
if (light_data.is_valid()) {
1504
_clear_lightmaps();
1505
}
1506
} break;
1507
}
1508
}
1509
1510
void LightmapGI::_assign_lightmaps() {
1511
ERR_FAIL_COND(light_data.is_null());
1512
1513
Vector<String> missing_node_paths;
1514
1515
for (int i = 0; i < light_data->get_user_count(); i++) {
1516
NodePath user_path = light_data->get_user_path(i);
1517
Node *node = get_node_or_null(user_path);
1518
if (!node) {
1519
missing_node_paths.push_back(String(user_path));
1520
continue;
1521
}
1522
int instance_idx = light_data->get_user_sub_instance(i);
1523
if (instance_idx >= 0) {
1524
RID instance_id = node->call("get_bake_mesh_instance", instance_idx);
1525
if (instance_id.is_valid()) {
1526
RS::get_singleton()->instance_geometry_set_lightmap(instance_id, get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
1527
}
1528
} else {
1529
VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
1530
ERR_CONTINUE(!vi);
1531
RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), get_instance(), light_data->get_user_lightmap_uv_scale(i), light_data->get_user_lightmap_slice_index(i));
1532
}
1533
}
1534
1535
if (!missing_node_paths.is_empty()) {
1536
String missing_paths_text;
1537
if (missing_node_paths.size() <= 3) {
1538
missing_paths_text = String(", ").join(missing_node_paths);
1539
} else {
1540
missing_paths_text = vformat("%s and %d more", String(", ").join(missing_node_paths.slice(0, 3)), missing_node_paths.size() - 3);
1541
}
1542
WARN_PRINT(vformat("%s couldn't find previously baked nodes and needs a rebake (missing nodes: %s).", get_name(), missing_paths_text));
1543
}
1544
}
1545
1546
void LightmapGI::_clear_lightmaps() {
1547
ERR_FAIL_COND(light_data.is_null());
1548
for (int i = 0; i < light_data->get_user_count(); i++) {
1549
Node *node = get_node_or_null(light_data->get_user_path(i));
1550
if (!node) {
1551
continue;
1552
}
1553
int instance_idx = light_data->get_user_sub_instance(i);
1554
if (instance_idx >= 0) {
1555
RID instance_id = node->call("get_bake_mesh_instance", instance_idx);
1556
if (instance_id.is_valid()) {
1557
RS::get_singleton()->instance_geometry_set_lightmap(instance_id, RID(), Rect2(), 0);
1558
}
1559
} else {
1560
VisualInstance3D *vi = Object::cast_to<VisualInstance3D>(node);
1561
ERR_CONTINUE(!vi);
1562
RS::get_singleton()->instance_geometry_set_lightmap(vi->get_instance(), RID(), Rect2(), 0);
1563
}
1564
}
1565
}
1566
1567
void LightmapGI::set_light_data(const Ref<LightmapGIData> &p_data) {
1568
if (light_data.is_valid()) {
1569
if (is_inside_tree()) {
1570
_clear_lightmaps();
1571
}
1572
set_base(RID());
1573
}
1574
light_data = p_data;
1575
1576
if (light_data.is_valid()) {
1577
set_base(light_data->get_rid());
1578
if (is_inside_tree()) {
1579
_assign_lightmaps();
1580
}
1581
light_data->update_shadowmask_mode(shadowmask_mode);
1582
}
1583
1584
update_gizmos();
1585
}
1586
1587
Ref<LightmapGIData> LightmapGI::get_light_data() const {
1588
return light_data;
1589
}
1590
1591
void LightmapGI::set_bake_quality(BakeQuality p_quality) {
1592
bake_quality = p_quality;
1593
}
1594
1595
LightmapGI::BakeQuality LightmapGI::get_bake_quality() const {
1596
return bake_quality;
1597
}
1598
1599
AABB LightmapGI::get_aabb() const {
1600
return AABB();
1601
}
1602
1603
void LightmapGI::set_use_denoiser(bool p_enable) {
1604
use_denoiser = p_enable;
1605
notify_property_list_changed();
1606
}
1607
1608
bool LightmapGI::is_using_denoiser() const {
1609
return use_denoiser;
1610
}
1611
1612
void LightmapGI::set_denoiser_strength(float p_denoiser_strength) {
1613
denoiser_strength = p_denoiser_strength;
1614
}
1615
1616
float LightmapGI::get_denoiser_strength() const {
1617
return denoiser_strength;
1618
}
1619
1620
void LightmapGI::set_denoiser_range(int p_denoiser_range) {
1621
denoiser_range = p_denoiser_range;
1622
}
1623
1624
int LightmapGI::get_denoiser_range() const {
1625
return denoiser_range;
1626
}
1627
1628
void LightmapGI::set_directional(bool p_enable) {
1629
directional = p_enable;
1630
}
1631
1632
bool LightmapGI::is_directional() const {
1633
return directional;
1634
}
1635
1636
void LightmapGI::set_shadowmask_mode(LightmapGIData::ShadowmaskMode p_mode) {
1637
shadowmask_mode = p_mode;
1638
if (light_data.is_valid()) {
1639
light_data->update_shadowmask_mode(p_mode);
1640
}
1641
1642
update_configuration_warnings();
1643
}
1644
1645
LightmapGIData::ShadowmaskMode LightmapGI::get_shadowmask_mode() const {
1646
return shadowmask_mode;
1647
}
1648
1649
void LightmapGI::set_use_texture_for_bounces(bool p_enable) {
1650
use_texture_for_bounces = p_enable;
1651
}
1652
1653
bool LightmapGI::is_using_texture_for_bounces() const {
1654
return use_texture_for_bounces;
1655
}
1656
1657
void LightmapGI::set_interior(bool p_enable) {
1658
interior = p_enable;
1659
}
1660
1661
bool LightmapGI::is_interior() const {
1662
return interior;
1663
}
1664
1665
void LightmapGI::set_environment_mode(EnvironmentMode p_mode) {
1666
environment_mode = p_mode;
1667
notify_property_list_changed();
1668
}
1669
1670
LightmapGI::EnvironmentMode LightmapGI::get_environment_mode() const {
1671
return environment_mode;
1672
}
1673
1674
void LightmapGI::set_environment_custom_sky(const Ref<Sky> &p_sky) {
1675
environment_custom_sky = p_sky;
1676
}
1677
1678
Ref<Sky> LightmapGI::get_environment_custom_sky() const {
1679
return environment_custom_sky;
1680
}
1681
1682
void LightmapGI::set_environment_custom_color(const Color &p_color) {
1683
environment_custom_color = p_color;
1684
}
1685
1686
Color LightmapGI::get_environment_custom_color() const {
1687
return environment_custom_color;
1688
}
1689
1690
void LightmapGI::set_environment_custom_energy(float p_energy) {
1691
environment_custom_energy = p_energy;
1692
}
1693
1694
float LightmapGI::get_environment_custom_energy() const {
1695
return environment_custom_energy;
1696
}
1697
1698
void LightmapGI::set_bounces(int p_bounces) {
1699
ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16);
1700
bounces = p_bounces;
1701
}
1702
1703
int LightmapGI::get_bounces() const {
1704
return bounces;
1705
}
1706
1707
void LightmapGI::set_bounce_indirect_energy(float p_indirect_energy) {
1708
ERR_FAIL_COND(p_indirect_energy < 0.0);
1709
bounce_indirect_energy = p_indirect_energy;
1710
}
1711
1712
float LightmapGI::get_bounce_indirect_energy() const {
1713
return bounce_indirect_energy;
1714
}
1715
1716
void LightmapGI::set_bias(float p_bias) {
1717
ERR_FAIL_COND(p_bias < 0.00001);
1718
bias = p_bias;
1719
}
1720
1721
float LightmapGI::get_bias() const {
1722
return bias;
1723
}
1724
1725
void LightmapGI::set_texel_scale(float p_multiplier) {
1726
ERR_FAIL_COND(p_multiplier < (0.01 - CMP_EPSILON));
1727
texel_scale = p_multiplier;
1728
}
1729
1730
float LightmapGI::get_texel_scale() const {
1731
return texel_scale;
1732
}
1733
1734
void LightmapGI::set_max_texture_size(int p_size) {
1735
ERR_FAIL_COND_MSG(p_size < 2048, vformat("The LightmapGI maximum texture size supplied (%d) is too small. The minimum allowed value is 2048.", p_size));
1736
ERR_FAIL_COND_MSG(p_size > 16384, vformat("The LightmapGI maximum texture size supplied (%d) is too large. The maximum allowed value is 16384.", p_size));
1737
max_texture_size = p_size;
1738
}
1739
1740
int LightmapGI::get_max_texture_size() const {
1741
return max_texture_size;
1742
}
1743
1744
void LightmapGI::set_supersampling_enabled(bool p_enable) {
1745
supersampling_enabled = p_enable;
1746
1747
notify_property_list_changed();
1748
}
1749
1750
bool LightmapGI::is_supersampling_enabled() const {
1751
return supersampling_enabled;
1752
}
1753
1754
void LightmapGI::set_supersampling_factor(float p_factor) {
1755
ERR_FAIL_COND(p_factor < 1);
1756
1757
supersampling_factor = p_factor;
1758
}
1759
1760
float LightmapGI::get_supersampling_factor() const {
1761
return supersampling_factor;
1762
}
1763
1764
void LightmapGI::set_generate_probes(GenerateProbes p_generate_probes) {
1765
gen_probes = p_generate_probes;
1766
}
1767
1768
LightmapGI::GenerateProbes LightmapGI::get_generate_probes() const {
1769
return gen_probes;
1770
}
1771
1772
void LightmapGI::set_camera_attributes(const Ref<CameraAttributes> &p_camera_attributes) {
1773
camera_attributes = p_camera_attributes;
1774
}
1775
1776
Ref<CameraAttributes> LightmapGI::get_camera_attributes() const {
1777
return camera_attributes;
1778
}
1779
1780
PackedStringArray LightmapGI::get_configuration_warnings() const {
1781
PackedStringArray warnings = VisualInstance3D::get_configuration_warnings();
1782
1783
#ifdef MODULE_LIGHTMAPPER_RD_ENABLED
1784
if (!DisplayServer::get_singleton()->can_create_rendering_device()) {
1785
warnings.push_back(vformat(RTR("Lightmaps can only be baked from a GPU that supports the RenderingDevice backends.\nYour GPU (%s) does not support RenderingDevice, as it does not support Vulkan, Direct3D 12, or Metal.\nLightmap baking will not be available on this device, although rendering existing baked lightmaps will work."), RenderingServer::get_singleton()->get_video_adapter_name()));
1786
return warnings;
1787
}
1788
1789
if (shadowmask_mode != LightmapGIData::SHADOWMASK_MODE_NONE && light_data.is_valid() && !light_data->has_shadowmask_textures()) {
1790
warnings.push_back(RTR("The lightmap has no baked shadowmask textures. Please rebake with the Shadowmask Mode set to anything other than None."));
1791
}
1792
1793
#elif defined(ANDROID_ENABLED) || defined(APPLE_EMBEDDED_ENABLED)
1794
warnings.push_back(vformat(RTR("Lightmaps cannot be baked on %s. Rendering existing baked lightmaps will still work."), OS::get_singleton()->get_name()));
1795
#else
1796
warnings.push_back(RTR("Lightmaps cannot be baked, as the `lightmapper_rd` module was disabled at compile-time. Rendering existing baked lightmaps will still work."));
1797
#endif
1798
1799
return warnings;
1800
}
1801
1802
void LightmapGI::_validate_property(PropertyInfo &p_property) const {
1803
if (!Engine::get_singleton()->is_editor_hint()) {
1804
return;
1805
}
1806
if (p_property.name == "supersampling_factor" && !supersampling_enabled) {
1807
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1808
}
1809
if (p_property.name == "environment_custom_sky" && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
1810
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1811
}
1812
if (p_property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
1813
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1814
}
1815
if (p_property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
1816
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1817
}
1818
if (p_property.name == "denoiser_strength" && !use_denoiser) {
1819
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1820
}
1821
if (p_property.name == "denoiser_range" && !use_denoiser) {
1822
p_property.usage = PROPERTY_USAGE_NO_EDITOR;
1823
}
1824
}
1825
1826
void LightmapGI::_bind_methods() {
1827
ClassDB::bind_method(D_METHOD("set_light_data", "data"), &LightmapGI::set_light_data);
1828
ClassDB::bind_method(D_METHOD("get_light_data"), &LightmapGI::get_light_data);
1829
1830
ClassDB::bind_method(D_METHOD("set_bake_quality", "bake_quality"), &LightmapGI::set_bake_quality);
1831
ClassDB::bind_method(D_METHOD("get_bake_quality"), &LightmapGI::get_bake_quality);
1832
1833
ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &LightmapGI::set_bounces);
1834
ClassDB::bind_method(D_METHOD("get_bounces"), &LightmapGI::get_bounces);
1835
1836
ClassDB::bind_method(D_METHOD("set_bounce_indirect_energy", "bounce_indirect_energy"), &LightmapGI::set_bounce_indirect_energy);
1837
ClassDB::bind_method(D_METHOD("get_bounce_indirect_energy"), &LightmapGI::get_bounce_indirect_energy);
1838
1839
ClassDB::bind_method(D_METHOD("set_generate_probes", "subdivision"), &LightmapGI::set_generate_probes);
1840
ClassDB::bind_method(D_METHOD("get_generate_probes"), &LightmapGI::get_generate_probes);
1841
1842
ClassDB::bind_method(D_METHOD("set_bias", "bias"), &LightmapGI::set_bias);
1843
ClassDB::bind_method(D_METHOD("get_bias"), &LightmapGI::get_bias);
1844
1845
ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &LightmapGI::set_environment_mode);
1846
ClassDB::bind_method(D_METHOD("get_environment_mode"), &LightmapGI::get_environment_mode);
1847
1848
ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &LightmapGI::set_environment_custom_sky);
1849
ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &LightmapGI::get_environment_custom_sky);
1850
1851
ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &LightmapGI::set_environment_custom_color);
1852
ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &LightmapGI::get_environment_custom_color);
1853
1854
ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &LightmapGI::set_environment_custom_energy);
1855
ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &LightmapGI::get_environment_custom_energy);
1856
1857
ClassDB::bind_method(D_METHOD("set_texel_scale", "texel_scale"), &LightmapGI::set_texel_scale);
1858
ClassDB::bind_method(D_METHOD("get_texel_scale"), &LightmapGI::get_texel_scale);
1859
1860
ClassDB::bind_method(D_METHOD("set_max_texture_size", "max_texture_size"), &LightmapGI::set_max_texture_size);
1861
ClassDB::bind_method(D_METHOD("get_max_texture_size"), &LightmapGI::get_max_texture_size);
1862
1863
ClassDB::bind_method(D_METHOD("set_supersampling_enabled", "enable"), &LightmapGI::set_supersampling_enabled);
1864
ClassDB::bind_method(D_METHOD("is_supersampling_enabled"), &LightmapGI::is_supersampling_enabled);
1865
1866
ClassDB::bind_method(D_METHOD("set_supersampling_factor", "factor"), &LightmapGI::set_supersampling_factor);
1867
ClassDB::bind_method(D_METHOD("get_supersampling_factor"), &LightmapGI::get_supersampling_factor);
1868
1869
ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &LightmapGI::set_use_denoiser);
1870
ClassDB::bind_method(D_METHOD("is_using_denoiser"), &LightmapGI::is_using_denoiser);
1871
1872
ClassDB::bind_method(D_METHOD("set_denoiser_strength", "denoiser_strength"), &LightmapGI::set_denoiser_strength);
1873
ClassDB::bind_method(D_METHOD("get_denoiser_strength"), &LightmapGI::get_denoiser_strength);
1874
1875
ClassDB::bind_method(D_METHOD("set_denoiser_range", "denoiser_range"), &LightmapGI::set_denoiser_range);
1876
ClassDB::bind_method(D_METHOD("get_denoiser_range"), &LightmapGI::get_denoiser_range);
1877
1878
ClassDB::bind_method(D_METHOD("set_interior", "enable"), &LightmapGI::set_interior);
1879
ClassDB::bind_method(D_METHOD("is_interior"), &LightmapGI::is_interior);
1880
1881
ClassDB::bind_method(D_METHOD("set_directional", "directional"), &LightmapGI::set_directional);
1882
ClassDB::bind_method(D_METHOD("is_directional"), &LightmapGI::is_directional);
1883
1884
ClassDB::bind_method(D_METHOD("set_shadowmask_mode", "mode"), &LightmapGI::set_shadowmask_mode);
1885
ClassDB::bind_method(D_METHOD("get_shadowmask_mode"), &LightmapGI::get_shadowmask_mode);
1886
1887
ClassDB::bind_method(D_METHOD("set_use_texture_for_bounces", "use_texture_for_bounces"), &LightmapGI::set_use_texture_for_bounces);
1888
ClassDB::bind_method(D_METHOD("is_using_texture_for_bounces"), &LightmapGI::is_using_texture_for_bounces);
1889
1890
ClassDB::bind_method(D_METHOD("set_camera_attributes", "camera_attributes"), &LightmapGI::set_camera_attributes);
1891
ClassDB::bind_method(D_METHOD("get_camera_attributes"), &LightmapGI::get_camera_attributes);
1892
1893
// ClassDB::bind_method(D_METHOD("bake", "from_node"), &LightmapGI::bake, DEFVAL(Variant()));
1894
1895
ADD_GROUP("Tweaks", "");
1896
ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality");
1897
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "supersampling"), "set_supersampling_enabled", "is_supersampling_enabled");
1898
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "supersampling_factor", PROPERTY_HINT_RANGE, "1,8,1"), "set_supersampling_factor", "get_supersampling_factor");
1899
ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,6,1,or_greater"), "set_bounces", "get_bounces");
1900
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bounce_indirect_energy", PROPERTY_HINT_RANGE, "0,2,0.01"), "set_bounce_indirect_energy", "get_bounce_indirect_energy");
1901
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "directional"), "set_directional", "is_directional");
1902
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadowmask_mode", PROPERTY_HINT_ENUM, "None,Replace,Overlay"), "set_shadowmask_mode", "get_shadowmask_mode");
1903
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_texture_for_bounces"), "set_use_texture_for_bounces", "is_using_texture_for_bounces");
1904
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
1905
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
1906
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "denoiser_strength", PROPERTY_HINT_RANGE, "0.001,0.2,0.001,or_greater"), "set_denoiser_strength", "get_denoiser_strength");
1907
ADD_PROPERTY(PropertyInfo(Variant::INT, "denoiser_range", PROPERTY_HINT_RANGE, "1,20"), "set_denoiser_range", "get_denoiser_range");
1908
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
1909
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "texel_scale", PROPERTY_HINT_RANGE, "0.01,100.0,0.01"), "set_texel_scale", "get_texel_scale");
1910
ADD_PROPERTY(PropertyInfo(Variant::INT, "max_texture_size", PROPERTY_HINT_RANGE, "2048,16384,1"), "set_max_texture_size", "get_max_texture_size");
1911
ADD_GROUP("Environment", "environment_");
1912
ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
1913
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
1914
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
1915
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
1916
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "camera_attributes", PROPERTY_HINT_RESOURCE_TYPE, "CameraAttributesPractical,CameraAttributesPhysical"), "set_camera_attributes", "get_camera_attributes");
1917
ADD_GROUP("Gen Probes", "generate_probes_");
1918
ADD_PROPERTY(PropertyInfo(Variant::INT, "generate_probes_subdiv", PROPERTY_HINT_ENUM, "Disabled,4,8,16,32"), "set_generate_probes", "get_generate_probes");
1919
ADD_GROUP("Data", "");
1920
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "LightmapGIData"), "set_light_data", "get_light_data");
1921
1922
BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
1923
BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
1924
BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
1925
BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA);
1926
1927
BIND_ENUM_CONSTANT(GENERATE_PROBES_DISABLED);
1928
BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_4);
1929
BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_8);
1930
BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_16);
1931
BIND_ENUM_CONSTANT(GENERATE_PROBES_SUBDIV_32);
1932
1933
BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
1934
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SCENE_ROOT);
1935
BIND_ENUM_CONSTANT(BAKE_ERROR_FOREIGN_DATA);
1936
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
1937
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
1938
BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
1939
BIND_ENUM_CONSTANT(BAKE_ERROR_MESHES_INVALID);
1940
BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE);
1941
BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED);
1942
BIND_ENUM_CONSTANT(BAKE_ERROR_TEXTURE_SIZE_TOO_SMALL);
1943
BIND_ENUM_CONSTANT(BAKE_ERROR_LIGHTMAP_TOO_SMALL);
1944
BIND_ENUM_CONSTANT(BAKE_ERROR_ATLAS_TOO_SMALL);
1945
1946
BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED);
1947
BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE);
1948
BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY);
1949
BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR);
1950
}
1951
1952
LightmapGI::LightmapGI() {
1953
}
1954
1955