12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637 |
- /*************************************************************************/
- /* baked_lightmap.cpp */
- /*************************************************************************/
- /* This file is part of: */
- /* GODOT ENGINE */
- /* https://godotengine.org */
- /*************************************************************************/
- /* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */
- /* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */
- /* */
- /* Permission is hereby granted, free of charge, to any person obtaining */
- /* a copy of this software and associated documentation files (the */
- /* "Software"), to deal in the Software without restriction, including */
- /* without limitation the rights to use, copy, modify, merge, publish, */
- /* distribute, sublicense, and/or sell copies of the Software, and to */
- /* permit persons to whom the Software is furnished to do so, subject to */
- /* the following conditions: */
- /* */
- /* The above copyright notice and this permission notice shall be */
- /* included in all copies or substantial portions of the Software. */
- /* */
- /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
- /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
- /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
- /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
- /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
- /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
- /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
- /*************************************************************************/
- #include "baked_lightmap.h"
- #include "core/io/config_file.h"
- #include "core/io/resource_saver.h"
- #include "core/math/math_defs.h"
- #include "core/os/dir_access.h"
- #include "core/os/os.h"
- #include "voxel_light_baker.h"
- void BakedLightmapData::set_bounds(const AABB &p_bounds) {
- bounds = p_bounds;
- VS::get_singleton()->lightmap_capture_set_bounds(baked_light, p_bounds);
- }
- AABB BakedLightmapData::get_bounds() const {
- return bounds;
- }
- void BakedLightmapData::set_octree(const PoolVector<uint8_t> &p_octree) {
- VS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree);
- }
- PoolVector<uint8_t> BakedLightmapData::get_octree() const {
- return VS::get_singleton()->lightmap_capture_get_octree(baked_light);
- }
- void BakedLightmapData::set_cell_space_transform(const Transform &p_xform) {
- cell_space_xform = p_xform;
- VS::get_singleton()->lightmap_capture_set_octree_cell_transform(baked_light, p_xform);
- }
- Transform BakedLightmapData::get_cell_space_transform() const {
- return cell_space_xform;
- }
- void BakedLightmapData::set_cell_subdiv(int p_cell_subdiv) {
- cell_subdiv = p_cell_subdiv;
- VS::get_singleton()->lightmap_capture_set_octree_cell_subdiv(baked_light, p_cell_subdiv);
- }
- int BakedLightmapData::get_cell_subdiv() const {
- return cell_subdiv;
- }
- void BakedLightmapData::set_energy(float p_energy) {
- energy = p_energy;
- VS::get_singleton()->lightmap_capture_set_energy(baked_light, energy);
- }
- float BakedLightmapData::get_energy() const {
- return energy;
- }
- void BakedLightmapData::set_interior(bool p_interior) {
- interior = p_interior;
- VS::get_singleton()->lightmap_capture_set_interior(baked_light, interior);
- }
- bool BakedLightmapData::is_interior() const {
- return interior;
- }
- void BakedLightmapData::add_user(const NodePath &p_path, const Ref<Resource> &p_lightmap, int p_lightmap_slice, const Rect2 &p_lightmap_uv_rect, int p_instance) {
- ERR_FAIL_COND_MSG(p_lightmap.is_null(), "It's not a reference to a valid Texture object.");
- ERR_FAIL_COND(p_lightmap_slice == -1 && !Object::cast_to<Texture>(p_lightmap.ptr()));
- ERR_FAIL_COND(p_lightmap_slice != -1 && !Object::cast_to<TextureLayered>(p_lightmap.ptr()));
- User user;
- user.path = p_path;
- if (p_lightmap_slice == -1) {
- user.lightmap.single = p_lightmap;
- } else {
- user.lightmap.layered = p_lightmap;
- }
- user.lightmap_slice = p_lightmap_slice;
- user.lightmap_uv_rect = p_lightmap_uv_rect;
- user.instance_index = p_instance;
- users.push_back(user);
- }
- int BakedLightmapData::get_user_count() const {
- return users.size();
- }
- NodePath BakedLightmapData::get_user_path(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), NodePath());
- return users[p_user].path;
- }
- Ref<Resource> BakedLightmapData::get_user_lightmap(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), Ref<Resource>());
- if (users[p_user].lightmap_slice == -1) {
- return users[p_user].lightmap.single;
- } else {
- return users[p_user].lightmap.layered;
- }
- }
- int BakedLightmapData::get_user_lightmap_slice(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), -1);
- return users[p_user].lightmap_slice;
- }
- Rect2 BakedLightmapData::get_user_lightmap_uv_rect(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), Rect2(0, 0, 1, 1));
- return users[p_user].lightmap_uv_rect;
- }
- int BakedLightmapData::get_user_instance(int p_user) const {
- ERR_FAIL_INDEX_V(p_user, users.size(), -1);
- return users[p_user].instance_index;
- }
- void BakedLightmapData::clear_users() {
- users.clear();
- }
- void BakedLightmapData::clear_data() {
- clear_users();
- if (baked_light.is_valid()) {
- VS::get_singleton()->free(baked_light);
- }
- baked_light = VS::get_singleton()->lightmap_capture_create();
- }
- void BakedLightmapData::_set_user_data(const Array &p_data) {
- ERR_FAIL_COND(p_data.size() <= 0);
- // Detect old lightmapper format
- if (p_data.size() % 3 == 0) {
- bool is_old_format = true;
- for (int i = 0; i < p_data.size(); i += 3) {
- is_old_format = is_old_format && p_data[i + 0].get_type() == Variant::NODE_PATH;
- is_old_format = is_old_format && p_data[i + 1].is_ref();
- is_old_format = is_old_format && p_data[i + 2].get_type() == Variant::INT;
- if (!is_old_format) {
- break;
- }
- }
- if (is_old_format) {
- #ifdef DEBUG_ENABLED
- WARN_PRINT("Geometry at path " + String(p_data[0]) + " is using old lightmapper data. Please re-bake.");
- #endif
- Array adapted_data;
- adapted_data.resize((p_data.size() / 3) * 5);
- for (int i = 0; i < p_data.size() / 3; i++) {
- adapted_data[i * 5 + 0] = p_data[i * 3 + 0];
- adapted_data[i * 5 + 1] = p_data[i * 3 + 1];
- adapted_data[i * 5 + 2] = -1;
- adapted_data[i * 5 + 3] = Rect2(0, 0, 1, 1);
- adapted_data[i * 5 + 4] = p_data[i * 3 + 2];
- }
- _set_user_data(adapted_data);
- return;
- }
- }
- ERR_FAIL_COND((p_data.size() % 5) != 0);
- for (int i = 0; i < p_data.size(); i += 5) {
- add_user(p_data[i], p_data[i + 1], p_data[i + 2], p_data[i + 3], p_data[i + 4]);
- }
- }
- Array BakedLightmapData::_get_user_data() const {
- Array ret;
- for (int i = 0; i < users.size(); i++) {
- ret.push_back(users[i].path);
- ret.push_back(users[i].lightmap_slice == -1 ? Ref<Resource>(users[i].lightmap.single) : Ref<Resource>(users[i].lightmap.layered));
- ret.push_back(users[i].lightmap_slice);
- ret.push_back(users[i].lightmap_uv_rect);
- ret.push_back(users[i].instance_index);
- }
- return ret;
- }
- RID BakedLightmapData::get_rid() const {
- return baked_light;
- }
- void BakedLightmapData::_bind_methods() {
- ClassDB::bind_method(D_METHOD("_set_user_data", "data"), &BakedLightmapData::_set_user_data);
- ClassDB::bind_method(D_METHOD("_get_user_data"), &BakedLightmapData::_get_user_data);
- ClassDB::bind_method(D_METHOD("set_bounds", "bounds"), &BakedLightmapData::set_bounds);
- ClassDB::bind_method(D_METHOD("get_bounds"), &BakedLightmapData::get_bounds);
- ClassDB::bind_method(D_METHOD("set_cell_space_transform", "xform"), &BakedLightmapData::set_cell_space_transform);
- ClassDB::bind_method(D_METHOD("get_cell_space_transform"), &BakedLightmapData::get_cell_space_transform);
- ClassDB::bind_method(D_METHOD("set_cell_subdiv", "cell_subdiv"), &BakedLightmapData::set_cell_subdiv);
- ClassDB::bind_method(D_METHOD("get_cell_subdiv"), &BakedLightmapData::get_cell_subdiv);
- ClassDB::bind_method(D_METHOD("set_octree", "octree"), &BakedLightmapData::set_octree);
- ClassDB::bind_method(D_METHOD("get_octree"), &BakedLightmapData::get_octree);
- ClassDB::bind_method(D_METHOD("set_energy", "energy"), &BakedLightmapData::set_energy);
- ClassDB::bind_method(D_METHOD("get_energy"), &BakedLightmapData::get_energy);
- ClassDB::bind_method(D_METHOD("set_interior", "interior"), &BakedLightmapData::set_interior);
- ClassDB::bind_method(D_METHOD("is_interior"), &BakedLightmapData::is_interior);
- ClassDB::bind_method(D_METHOD("add_user", "path", "lightmap", "lightmap_slice", "lightmap_uv_rect", "instance"), &BakedLightmapData::add_user);
- ClassDB::bind_method(D_METHOD("get_user_count"), &BakedLightmapData::get_user_count);
- ClassDB::bind_method(D_METHOD("get_user_path", "user_idx"), &BakedLightmapData::get_user_path);
- ClassDB::bind_method(D_METHOD("get_user_lightmap", "user_idx"), &BakedLightmapData::get_user_lightmap);
- ClassDB::bind_method(D_METHOD("clear_users"), &BakedLightmapData::clear_users);
- ClassDB::bind_method(D_METHOD("clear_data"), &BakedLightmapData::clear_data);
- ADD_PROPERTY(PropertyInfo(Variant::AABB, "bounds", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_bounds", "get_bounds");
- ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "cell_space_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_space_transform", "get_cell_space_transform");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "cell_subdiv", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_cell_subdiv", "get_cell_subdiv");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "energy", PROPERTY_HINT_RANGE, "0,16,0.01,or_greater"), "set_energy", "get_energy");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "interior"), "set_interior", "is_interior");
- ADD_PROPERTY(PropertyInfo(Variant::POOL_BYTE_ARRAY, "octree", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_octree", "get_octree");
- ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "user_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_user_data", "_get_user_data");
- }
- BakedLightmapData::BakedLightmapData() {
- baked_light = VS::get_singleton()->lightmap_capture_create();
- energy = 1;
- cell_subdiv = 1;
- interior = false;
- }
- BakedLightmapData::~BakedLightmapData() {
- VS::get_singleton()->free(baked_light);
- }
- ///////////////////////////
- Lightmapper::BakeStepFunc BakedLightmap::bake_step_function;
- Lightmapper::BakeStepFunc BakedLightmap::bake_substep_function;
- Lightmapper::BakeEndFunc BakedLightmap::bake_end_function;
- Size2i BakedLightmap::_compute_lightmap_size(const MeshesFound &p_mesh) {
- double area = 0;
- double uv_area = 0;
- for (int i = 0; i < p_mesh.mesh->get_surface_count(); i++) {
- Array arrays = p_mesh.mesh->surface_get_arrays(i);
- PoolVector<Vector3> vertices = arrays[Mesh::ARRAY_VERTEX];
- PoolVector<Vector2> uv2 = arrays[Mesh::ARRAY_TEX_UV2];
- PoolVector<int> indices = arrays[Mesh::ARRAY_INDEX];
- ERR_FAIL_COND_V(vertices.size() == 0, Vector2());
- ERR_FAIL_COND_V(uv2.size() == 0, Vector2());
- int vc = vertices.size();
- PoolVector<Vector3>::Read vr = vertices.read();
- PoolVector<Vector2>::Read u2r = uv2.read();
- PoolVector<int>::Read ir;
- int ic = 0;
- if (indices.size()) {
- ic = indices.size();
- ir = indices.read();
- }
- int faces = ic ? ic / 3 : vc / 3;
- for (int j = 0; j < faces; j++) {
- Vector3 vertex[3];
- Vector2 uv[3];
- for (int k = 0; k < 3; k++) {
- int idx = ic ? ir[j * 3 + k] : j * 3 + k;
- vertex[k] = p_mesh.xform.xform(vr[idx]);
- uv[k] = u2r[idx];
- }
- Vector3 p1 = vertex[0];
- Vector3 p2 = vertex[1];
- Vector3 p3 = vertex[2];
- double a = p1.distance_to(p2);
- double b = p2.distance_to(p3);
- double c = p3.distance_to(p1);
- double halfPerimeter = (a + b + c) / 2.0;
- area += sqrt(halfPerimeter * (halfPerimeter - a) * (halfPerimeter - b) * (halfPerimeter - c));
- Vector2 uv_p1 = uv[0];
- Vector2 uv_p2 = uv[1];
- Vector2 uv_p3 = uv[2];
- double uv_a = uv_p1.distance_to(uv_p2);
- double uv_b = uv_p2.distance_to(uv_p3);
- double uv_c = uv_p3.distance_to(uv_p1);
- double uv_halfPerimeter = (uv_a + uv_b + uv_c) / 2.0;
- uv_area += sqrt(
- uv_halfPerimeter * (uv_halfPerimeter - uv_a) * (uv_halfPerimeter - uv_b) * (uv_halfPerimeter - uv_c));
- }
- }
- if (uv_area < 0.0001f) {
- uv_area = 1.0;
- }
- int pixels = Math::round(ceil((1.0 / sqrt(uv_area)) * sqrt(area * default_texels_per_unit)));
- int size = CLAMP(pixels, 2, 4096);
- return Vector2i(size, size);
- }
- void BakedLightmap::_find_meshes_and_lights(Node *p_at_node, Vector<MeshesFound> &meshes, Vector<LightsFound> &lights) {
- AABB bounds = AABB(-extents, extents * 2.0);
- MeshInstance *mi = Object::cast_to<MeshInstance>(p_at_node);
- if (mi && mi->get_flag(GeometryInstance::FLAG_USE_BAKED_LIGHT) && mi->is_visible_in_tree()) {
- Ref<Mesh> mesh = mi->get_mesh();
- if (mesh.is_valid()) {
- bool all_have_uv2_and_normal = true;
- bool surfaces_found = false;
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- if (mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
- continue;
- }
- if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_TEX_UV2)) {
- all_have_uv2_and_normal = false;
- break;
- }
- if (!(mesh->surface_get_format(i) & Mesh::ARRAY_FORMAT_NORMAL)) {
- all_have_uv2_and_normal = false;
- break;
- }
- surfaces_found = true;
- }
- if (surfaces_found && all_have_uv2_and_normal) {
- Transform mesh_xform = get_global_transform().affine_inverse() * mi->get_global_transform();
- AABB aabb = mesh_xform.xform(mesh->get_aabb());
- if (bounds.intersects(aabb)) {
- MeshesFound mf;
- mf.cast_shadows = mi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
- mf.generate_lightmap = mi->get_generate_lightmap();
- mf.xform = mesh_xform;
- mf.node_path = get_path_to(mi);
- mf.subindex = -1;
- mf.mesh = mesh;
- static const int lightmap_scale[4] = { 1, 2, 4, 8 }; //GeometryInstance3D::LIGHTMAP_SCALE_MAX = { 1, 2, 4, 8 };
- mf.lightmap_scale = lightmap_scale[mi->get_lightmap_scale()];
- Ref<Material> all_override = mi->get_material_override();
- for (int i = 0; i < mesh->get_surface_count(); i++) {
- if (all_override.is_valid()) {
- mf.overrides.push_back(all_override);
- } else {
- mf.overrides.push_back(mi->get_surface_material(i));
- }
- }
- meshes.push_back(mf);
- }
- }
- }
- }
- Spatial *s = Object::cast_to<Spatial>(p_at_node);
- if (!mi && s) {
- Array bmeshes = p_at_node->call("get_bake_meshes");
- if (bmeshes.size() && (bmeshes.size() & 1) == 0) {
- Transform xf = get_global_transform().affine_inverse() * s->get_global_transform();
- Ref<Material> all_override;
- GeometryInstance *gi = Object::cast_to<GeometryInstance>(p_at_node);
- if (gi) {
- all_override = gi->get_material_override();
- }
- for (int i = 0; i < bmeshes.size(); i += 2) {
- Ref<Mesh> mesh = bmeshes[i];
- if (!mesh.is_valid()) {
- continue;
- }
- Transform mesh_xform = xf * bmeshes[i + 1];
- AABB aabb = mesh_xform.xform(mesh->get_aabb());
- if (!bounds.intersects(aabb)) {
- continue;
- }
- MeshesFound mf;
- mf.xform = mesh_xform;
- mf.node_path = get_path_to(s);
- mf.subindex = i / 2;
- mf.lightmap_scale = 1;
- mf.mesh = mesh;
- if (gi) {
- mf.cast_shadows = gi->get_cast_shadows_setting() != GeometryInstance::SHADOW_CASTING_SETTING_OFF;
- mf.generate_lightmap = gi->get_generate_lightmap();
- } else {
- mf.cast_shadows = true;
- mf.generate_lightmap = true;
- }
- for (int j = 0; j < mesh->get_surface_count(); j++) {
- mf.overrides.push_back(all_override);
- }
- meshes.push_back(mf);
- }
- }
- }
- Light *light = Object::cast_to<Light>(p_at_node);
- if (light && light->get_bake_mode() != Light::BAKE_DISABLED) {
- LightsFound lf;
- lf.xform = get_global_transform().affine_inverse() * light->get_global_transform();
- lf.light = light;
- lights.push_back(lf);
- }
- for (int i = 0; i < p_at_node->get_child_count(); i++) {
- Node *child = p_at_node->get_child(i);
- if (!child->get_owner()) {
- continue; //maybe a helper
- }
- _find_meshes_and_lights(child, meshes, lights);
- }
- }
- void BakedLightmap::_get_material_images(const MeshesFound &p_found_mesh, Lightmapper::MeshData &r_mesh_data, Vector<Ref<Texture>> &r_albedo_textures, Vector<Ref<Texture>> &r_emission_textures) {
- for (int i = 0; i < p_found_mesh.mesh->get_surface_count(); ++i) {
- Ref<SpatialMaterial> mat = p_found_mesh.overrides[i];
- if (mat.is_null()) {
- mat = p_found_mesh.mesh->surface_get_material(i);
- }
- Ref<Texture> albedo_texture;
- Color albedo_add = Color(1, 1, 1, 1);
- Color albedo_mul = Color(1, 1, 1, 1);
- Ref<Texture> emission_texture;
- Color emission_add = Color(0, 0, 0, 0);
- Color emission_mul = Color(1, 1, 1, 1);
- if (mat.is_valid()) {
- albedo_texture = mat->get_texture(SpatialMaterial::TEXTURE_ALBEDO);
- if (albedo_texture.is_valid()) {
- albedo_mul = mat->get_albedo();
- albedo_add = Color(0, 0, 0, 0);
- } else {
- albedo_add = mat->get_albedo();
- }
- emission_texture = mat->get_texture(SpatialMaterial::TEXTURE_EMISSION);
- Color emission_color = mat->get_emission();
- float emission_energy = mat->get_emission_energy();
- if (mat->get_emission_operator() == SpatialMaterial::EMISSION_OP_ADD) {
- emission_mul = Color(1, 1, 1) * emission_energy;
- emission_add = emission_color * emission_energy;
- } else {
- emission_mul = emission_color * emission_energy;
- emission_add = Color(0, 0, 0);
- }
- }
- Lightmapper::MeshData::TextureDef albedo;
- albedo.mul = albedo_mul;
- albedo.add = albedo_add;
- if (albedo_texture.is_valid()) {
- albedo.tex_rid = albedo_texture->get_rid();
- r_albedo_textures.push_back(albedo_texture);
- }
- r_mesh_data.albedo.push_back(albedo);
- Lightmapper::MeshData::TextureDef emission;
- emission.mul = emission_mul;
- emission.add = emission_add;
- if (emission_texture.is_valid()) {
- emission.tex_rid = emission_texture->get_rid();
- r_emission_textures.push_back(emission_texture);
- }
- r_mesh_data.emission.push_back(emission);
- }
- }
- void BakedLightmap::_save_image(String &r_base_path, Ref<Image> r_img, bool p_use_srgb) {
- if (use_hdr) {
- r_base_path += ".exr";
- } else {
- r_base_path += ".png";
- }
- String relative_path = r_base_path;
- if (relative_path.begins_with("res://")) {
- relative_path = relative_path.substr(6, relative_path.length());
- }
- bool hdr_grayscale = use_hdr && !use_color;
- r_img->lock();
- for (int i = 0; i < r_img->get_height(); i++) {
- for (int j = 0; j < r_img->get_width(); j++) {
- Color c = r_img->get_pixel(j, i);
- c.r = MAX(c.r, environment_min_light.r);
- c.g = MAX(c.g, environment_min_light.g);
- c.b = MAX(c.b, environment_min_light.b);
- if (hdr_grayscale) {
- c = Color(c.get_v(), 0.0f, 0.0f);
- }
- if (p_use_srgb) {
- c = c.to_srgb();
- }
- r_img->set_pixel(j, i, c);
- }
- }
- r_img->unlock();
- if (!use_color) {
- if (use_hdr) {
- r_img->convert(Image::FORMAT_RH);
- } else {
- r_img->convert(Image::FORMAT_L8);
- }
- }
- if (use_hdr) {
- r_img->save_exr(relative_path, !use_color);
- } else {
- r_img->save_png(relative_path);
- }
- }
- bool BakedLightmap::_lightmap_bake_step_function(float p_completion, const String &p_text, void *ud, bool p_refresh) {
- BakeStepUD *bsud = (BakeStepUD *)ud;
- bool ret = false;
- if (bsud->func) {
- ret = bsud->func(bsud->from_percent + p_completion * (bsud->to_percent - bsud->from_percent), p_text, bsud->ud, p_refresh);
- }
- return ret;
- }
- BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, String p_data_save_path) {
- if (!p_from_node && !get_parent()) {
- return BAKE_ERROR_NO_ROOT;
- }
- bool no_save_path = false;
- if (p_data_save_path == "" && (get_light_data().is_null() || !get_light_data()->get_path().is_resource_file())) {
- no_save_path = true;
- }
- if (p_data_save_path == "") {
- if (get_light_data().is_null()) {
- no_save_path = true;
- } else {
- p_data_save_path = get_light_data()->get_path();
- if (!p_data_save_path.is_resource_file()) {
- no_save_path = true;
- }
- }
- }
- if (no_save_path) {
- if (image_path == "") {
- return BAKE_ERROR_NO_SAVE_PATH;
- } else {
- p_data_save_path = image_path;
- }
- WARN_PRINT("Using the deprecated property \"image_path\" as a save path, consider providing a better save path via the \"data_save_path\" parameter");
- p_data_save_path = image_path.plus_file("BakedLightmap.lmbake");
- }
- {
- //check for valid save path
- DirAccessRef d = DirAccess::open(p_data_save_path.get_base_dir());
- if (!d) {
- ERR_FAIL_V_MSG(BAKE_ERROR_NO_SAVE_PATH, "Invalid save path '" + p_data_save_path + "'.");
- }
- }
- uint32_t time_started = OS::get_singleton()->get_ticks_msec();
- if (bake_step_function) {
- bool cancelled = bake_step_function(0.0, TTR("Finding meshes and lights"), nullptr, true);
- if (cancelled) {
- bake_end_function(time_started);
- return BAKE_ERROR_USER_ABORTED;
- }
- }
- Ref<Lightmapper> lightmapper = Lightmapper::create();
- if (lightmapper.is_null()) {
- bake_end_function(time_started);
- return BAKE_ERROR_NO_LIGHTMAPPER;
- }
- Vector<LightsFound> lights_found;
- Vector<MeshesFound> meshes_found;
- _find_meshes_and_lights(p_from_node ? p_from_node : get_parent(), meshes_found, lights_found);
- if (meshes_found.size() == 0) {
- bake_end_function(time_started);
- return BAKE_ERROR_NO_MESHES;
- }
- for (int m_i = 0; m_i < meshes_found.size(); m_i++) {
- if (bake_step_function) {
- float p = (float)(m_i) / meshes_found.size();
- bool cancelled = bake_step_function(p * 0.05, vformat(TTR("Preparing geometry (%d/%d)"), m_i + 1, meshes_found.size()), nullptr, false);
- if (cancelled) {
- bake_end_function(time_started);
- return BAKE_ERROR_USER_ABORTED;
- }
- }
- MeshesFound &mf = meshes_found.write[m_i];
- Size2i lightmap_size = mf.mesh->get_lightmap_size_hint();
- if (lightmap_size == Vector2i(0, 0)) {
- lightmap_size = _compute_lightmap_size(mf);
- }
- lightmap_size *= mf.lightmap_scale;
- Lightmapper::MeshData md;
- {
- Dictionary d;
- d["path"] = mf.node_path;
- if (mf.subindex >= 0) {
- d["subindex"] = mf.subindex;
- }
- d["cast_shadows"] = mf.cast_shadows;
- d["generate_lightmap"] = mf.generate_lightmap;
- d["node_name"] = mf.node_path.get_name(mf.node_path.get_name_count() - 1);
- md.userdata = d;
- }
- Basis normal_xform = mf.xform.basis.inverse().transposed();
- for (int i = 0; i < mf.mesh->get_surface_count(); i++) {
- if (mf.mesh->surface_get_primitive_type(i) != Mesh::PRIMITIVE_TRIANGLES) {
- continue;
- }
- Array a = mf.mesh->surface_get_arrays(i);
- Vector<Vector3> vertices = a[Mesh::ARRAY_VERTEX];
- const Vector3 *vr = vertices.ptr();
- Vector<Vector2> uv2 = a[Mesh::ARRAY_TEX_UV2];
- const Vector2 *uv2r = nullptr;
- Vector<Vector2> uv = a[Mesh::ARRAY_TEX_UV];
- const Vector2 *uvr = nullptr;
- Vector<Vector3> normals = a[Mesh::ARRAY_NORMAL];
- const Vector3 *nr = nullptr;
- Vector<int> index = a[Mesh::ARRAY_INDEX];
- ERR_CONTINUE(uv2.size() == 0);
- ERR_CONTINUE(normals.size() == 0);
- if (!uv.empty()) {
- uvr = uv.ptr();
- }
- uv2r = uv2.ptr();
- nr = normals.ptr();
- int facecount;
- const int *ir = nullptr;
- if (index.size()) {
- facecount = index.size() / 3;
- ir = index.ptr();
- } else {
- facecount = vertices.size() / 3;
- }
- md.surface_facecounts.push_back(facecount);
- for (int j = 0; j < facecount; j++) {
- uint32_t vidx[3];
- if (ir) {
- for (int k = 0; k < 3; k++) {
- vidx[k] = ir[j * 3 + k];
- }
- } else {
- for (int k = 0; k < 3; k++) {
- vidx[k] = j * 3 + k;
- }
- }
- for (int k = 0; k < 3; k++) {
- Vector3 v = mf.xform.xform(vr[vidx[k]]);
- md.points.push_back(v);
- md.uv2.push_back(uv2r[vidx[k]]);
- md.normal.push_back(normal_xform.xform(nr[vidx[k]]).normalized());
- if (uvr != nullptr) {
- md.uv.push_back(uvr[vidx[k]]);
- }
- }
- }
- }
- Vector<Ref<Texture>> albedo_textures;
- Vector<Ref<Texture>> emission_textures;
- _get_material_images(mf, md, albedo_textures, emission_textures);
- for (int j = 0; j < albedo_textures.size(); j++) {
- lightmapper->add_albedo_texture(albedo_textures[j]);
- }
- for (int j = 0; j < emission_textures.size(); j++) {
- lightmapper->add_emission_texture(emission_textures[j]);
- }
- lightmapper->add_mesh(md, lightmap_size);
- }
- for (int i = 0; i < lights_found.size(); i++) {
- Light *light = lights_found[i].light;
- Transform xf = lights_found[i].xform;
- if (Object::cast_to<DirectionalLight>(light)) {
- DirectionalLight *l = Object::cast_to<DirectionalLight>(light);
- lightmapper->add_directional_light(light->get_bake_mode() == Light::BAKE_ALL, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_SIZE));
- } else if (Object::cast_to<OmniLight>(light)) {
- OmniLight *l = Object::cast_to<OmniLight>(light);
- lightmapper->add_omni_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SIZE));
- } else if (Object::cast_to<SpotLight>(light)) {
- SpotLight *l = Object::cast_to<SpotLight>(light);
- lightmapper->add_spot_light(light->get_bake_mode() == Light::BAKE_ALL, xf.origin, -xf.basis.get_axis(Vector3::AXIS_Z).normalized(), l->get_color(), l->get_param(Light::PARAM_ENERGY), l->get_param(Light::PARAM_INDIRECT_ENERGY), l->get_param(Light::PARAM_RANGE), l->get_param(Light::PARAM_ATTENUATION), l->get_param(Light::PARAM_SPOT_ANGLE), l->get_param(Light::PARAM_SPOT_ATTENUATION), l->get_param(Light::PARAM_SIZE));
- }
- }
- Ref<Image> environment_image;
- Basis environment_xform;
- if (environment_mode != ENVIRONMENT_MODE_DISABLED) {
- if (bake_step_function) {
- bake_step_function(0.1, TTR("Preparing environment"), nullptr, true);
- }
- switch (environment_mode) {
- case ENVIRONMENT_MODE_DISABLED: {
- //nothing
- } break;
- case ENVIRONMENT_MODE_SCENE: {
- Ref<World> world = get_world();
- if (world.is_valid()) {
- Ref<Environment> env = world->get_environment();
- if (env.is_null()) {
- env = world->get_fallback_environment();
- }
- if (env.is_valid()) {
- environment_image = _get_irradiance_map(env, Vector2i(128, 64));
- environment_xform = get_global_transform().affine_inverse().basis * env->get_sky_orientation();
- }
- }
- } break;
- case ENVIRONMENT_MODE_CUSTOM_SKY: {
- if (environment_custom_sky.is_valid()) {
- environment_image = _get_irradiance_from_sky(environment_custom_sky, environment_custom_energy, Vector2i(128, 64));
- environment_xform.set_euler(environment_custom_sky_rotation_degrees * Math_PI / 180.0);
- }
- } break;
- case ENVIRONMENT_MODE_CUSTOM_COLOR: {
- environment_image.instance();
- environment_image->create(128, 64, false, Image::FORMAT_RGBF);
- Color c = environment_custom_color;
- c.r *= environment_custom_energy;
- c.g *= environment_custom_energy;
- c.b *= environment_custom_energy;
- environment_image->lock();
- for (int i = 0; i < 128; i++) {
- for (int j = 0; j < 64; j++) {
- environment_image->set_pixel(i, j, c);
- }
- }
- environment_image->unlock();
- } break;
- }
- }
- BakeStepUD bsud;
- bsud.func = bake_step_function;
- bsud.ud = nullptr;
- bsud.from_percent = 0.1;
- bsud.to_percent = 0.9;
- bool gen_atlas = OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2 ? false : generate_atlas;
- Lightmapper::BakeError bake_err = lightmapper->bake(Lightmapper::BakeQuality(bake_quality), use_denoiser, bounces, bounce_indirect_energy, bias, gen_atlas, max_atlas_size, environment_image, environment_xform, _lightmap_bake_step_function, &bsud, bake_substep_function);
- if (bake_err != Lightmapper::BAKE_OK) {
- bake_end_function(time_started);
- switch (bake_err) {
- case Lightmapper::BAKE_ERROR_USER_ABORTED: {
- return BAKE_ERROR_USER_ABORTED;
- }
- case Lightmapper::BAKE_ERROR_LIGHTMAP_TOO_SMALL: {
- return BAKE_ERROR_LIGHTMAP_SIZE;
- }
- case Lightmapper::BAKE_ERROR_NO_MESHES: {
- return BAKE_ERROR_NO_MESHES;
- }
- default: {
- }
- }
- return BAKE_ERROR_NO_LIGHTMAPPER;
- }
- Ref<BakedLightmapData> data;
- if (get_light_data().is_valid()) {
- data = get_light_data();
- set_light_data(Ref<BakedLightmapData>()); //clear
- data->clear_data();
- } else {
- data.instance();
- }
- if (capture_enabled) {
- if (bake_step_function) {
- bool cancelled = bake_step_function(0.85, TTR("Generating capture"), nullptr, true);
- if (cancelled) {
- bake_end_function(time_started);
- return BAKE_ERROR_USER_ABORTED;
- }
- }
- VoxelLightBaker voxel_baker;
- int bake_subdiv;
- int capture_subdiv;
- AABB bake_bounds;
- {
- bake_bounds = AABB(-extents, extents * 2.0);
- int subdiv = nearest_power_of_2_templated(int(bake_bounds.get_longest_axis_size() / capture_cell_size));
- bake_bounds.size[bake_bounds.get_longest_axis_index()] = subdiv * capture_cell_size;
- bake_subdiv = nearest_shift(subdiv) + 1;
- capture_subdiv = bake_subdiv;
- float css = capture_cell_size;
- while (css < capture_cell_size && capture_subdiv > 2) {
- capture_subdiv--;
- css *= 2.0;
- }
- }
- voxel_baker.begin_bake(capture_subdiv + 1, bake_bounds);
- for (int mesh_id = 0; mesh_id < meshes_found.size(); mesh_id++) {
- MeshesFound &mf = meshes_found.write[mesh_id];
- voxel_baker.plot_mesh(mf.xform, mf.mesh, mf.overrides, Ref<Material>());
- }
- VoxelLightBaker::BakeQuality capt_quality = VoxelLightBaker::BakeQuality::BAKE_QUALITY_HIGH;
- if (capture_quality == BakedLightmap::BakeQuality::BAKE_QUALITY_LOW) {
- capt_quality = VoxelLightBaker::BakeQuality::BAKE_QUALITY_LOW;
- } else if (capture_quality == BakedLightmap::BakeQuality::BAKE_QUALITY_MEDIUM) {
- capt_quality = VoxelLightBaker::BakeQuality::BAKE_QUALITY_MEDIUM;
- }
- voxel_baker.begin_bake_light(capt_quality, capture_propagation);
- for (int i = 0; i < lights_found.size(); i++) {
- LightsFound &lf = lights_found.write[i];
- switch (lf.light->get_light_type()) {
- case VS::LIGHT_DIRECTIONAL: {
- voxel_baker.plot_light_directional(-lf.xform.basis.get_axis(2), lf.light->get_color(), lf.light->get_param(Light::PARAM_ENERGY), lf.light->get_param(Light::PARAM_INDIRECT_ENERGY), lf.light->get_bake_mode() == Light::BAKE_ALL);
- } break;
- case VS::LIGHT_OMNI: {
- voxel_baker.plot_light_omni(lf.xform.origin, lf.light->get_color(), lf.light->get_param(Light::PARAM_ENERGY), lf.light->get_param(Light::PARAM_INDIRECT_ENERGY), lf.light->get_param(Light::PARAM_RANGE), lf.light->get_param(Light::PARAM_ATTENUATION), lf.light->get_bake_mode() == Light::BAKE_ALL);
- } break;
- case VS::LIGHT_SPOT: {
- voxel_baker.plot_light_spot(lf.xform.origin, lf.xform.basis.get_axis(2), lf.light->get_color(), lf.light->get_param(Light::PARAM_ENERGY), lf.light->get_param(Light::PARAM_INDIRECT_ENERGY), lf.light->get_param(Light::PARAM_RANGE), lf.light->get_param(Light::PARAM_ATTENUATION), lf.light->get_param(Light::PARAM_SPOT_ANGLE), lf.light->get_param(Light::PARAM_SPOT_ATTENUATION), lf.light->get_bake_mode() == Light::BAKE_ALL);
- } break;
- }
- }
- voxel_baker.end_bake();
- AABB bounds = AABB(-extents, extents * 2);
- data->set_cell_subdiv(capture_subdiv);
- data->set_bounds(bounds);
- data->set_octree(voxel_baker.create_capture_octree(capture_subdiv));
- {
- float bake_bound_size = bake_bounds.get_longest_axis_size();
- Transform to_bounds;
- to_bounds.basis.scale(Vector3(bake_bound_size, bake_bound_size, bake_bound_size));
- to_bounds.origin = bounds.position;
- Transform to_grid;
- to_grid.basis.scale(Vector3(1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1), 1 << (capture_subdiv - 1)));
- Transform to_cell_space = to_grid * to_bounds.affine_inverse();
- data->set_cell_space_transform(to_cell_space);
- }
- }
- if (bake_step_function) {
- bool cancelled = bake_step_function(0.9, TTR("Saving lightmaps"), nullptr, true);
- if (cancelled) {
- bake_end_function(time_started);
- return BAKE_ERROR_USER_ABORTED;
- }
- }
- Vector<Ref<Image>> images;
- for (int i = 0; i < lightmapper->get_bake_texture_count(); i++) {
- images.push_back(lightmapper->get_bake_texture(i));
- }
- bool use_srgb = use_color && !use_hdr;
- if (gen_atlas) {
- Ref<Image> large_image;
- large_image.instance();
- large_image->create(images[0]->get_width(), images[0]->get_height() * images.size(), false, images[0]->get_format());
- for (int i = 0; i < images.size(); i++) {
- large_image->blit_rect(images[i], Rect2(0, 0, images[0]->get_width(), images[0]->get_height()), Point2(0, images[0]->get_height() * i));
- }
- Ref<TextureLayered> texture;
- String base_path = p_data_save_path.get_basename();
- if (ResourceLoader::import) {
- _save_image(base_path, large_image, use_srgb);
- Ref<ConfigFile> config;
- config.instance();
- if (FileAccess::exists(base_path + ".import")) {
- config->load(base_path + ".import");
- } else {
- // Set only if settings don't exist, to keep user choice
- config->set_value("params", "compress/mode", 0);
- }
- config->set_value("remap", "importer", "texture_array");
- config->set_value("remap", "type", "TextureArray");
- config->set_value("params", "detect_3d", false);
- config->set_value("params", "flags/repeat", false);
- config->set_value("params", "flags/filter", true);
- config->set_value("params", "flags/mipmaps", false);
- config->set_value("params", "flags/srgb", use_srgb);
- config->set_value("params", "slices/horizontal", 1);
- config->set_value("params", "slices/vertical", images.size());
- config->save(base_path + ".import");
- ResourceLoader::import(base_path);
- texture = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
- } else {
- base_path += ".texarr";
- Ref<TextureLayered> tex;
- bool set_path = true;
- if (ResourceCache::has(base_path)) {
- tex = Ref<Resource>((Resource *)ResourceCache::get(base_path));
- set_path = false;
- }
- if (!tex.is_valid()) {
- tex.instance();
- }
- tex->create(images[0]->get_width(), images[0]->get_height(), images.size(), images[0]->get_format(), Texture::FLAGS_DEFAULT);
- for (int i = 0; i < images.size(); i++) {
- tex->set_layer_data(images[i], i);
- }
- ResourceSaver::save(base_path, tex, ResourceSaver::FLAG_CHANGE_PATH);
- if (set_path) {
- tex->set_path(base_path);
- }
- texture = tex;
- }
- for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
- if (meshes_found[i].generate_lightmap) {
- Dictionary d = lightmapper->get_bake_mesh_userdata(i);
- NodePath np = d["path"];
- int32_t subindex = -1;
- if (d.has("subindex")) {
- subindex = d["subindex"];
- }
- Rect2 uv_rect = lightmapper->get_bake_mesh_uv_scale(i);
- int slice_index = lightmapper->get_bake_mesh_texture_slice(i);
- data->add_user(np, texture, slice_index, uv_rect, subindex);
- }
- }
- } else {
- for (int i = 0; i < lightmapper->get_bake_mesh_count(); i++) {
- if (!meshes_found[i].generate_lightmap) {
- continue;
- }
- Ref<Texture> texture;
- String base_path = p_data_save_path.get_base_dir().plus_file(images[i]->get_name());
- if (ResourceLoader::import) {
- _save_image(base_path, images[i], use_srgb);
- Ref<ConfigFile> config;
- config.instance();
- if (FileAccess::exists(base_path + ".import")) {
- config->load(base_path + ".import");
- } else {
- // Set only if settings don't exist, to keep user choice
- config->set_value("params", "compress/mode", 0);
- }
- config->set_value("remap", "importer", "texture");
- config->set_value("remap", "type", "StreamTexture");
- config->set_value("params", "detect_3d", false);
- config->set_value("params", "flags/repeat", false);
- config->set_value("params", "flags/filter", true);
- config->set_value("params", "flags/mipmaps", false);
- config->set_value("params", "flags/srgb", use_srgb);
- config->save(base_path + ".import");
- ResourceLoader::import(base_path);
- texture = ResourceLoader::load(base_path); //if already loaded, it will be updated on refocus?
- } else {
- base_path += ".tex";
- Ref<ImageTexture> tex;
- bool set_path = true;
- if (ResourceCache::has(base_path)) {
- tex = Ref<Resource>((Resource *)ResourceCache::get(base_path));
- set_path = false;
- }
- if (!tex.is_valid()) {
- tex.instance();
- }
- tex->create_from_image(images[i], Texture::FLAGS_DEFAULT);
- ResourceSaver::save(base_path, tex, ResourceSaver::FLAG_CHANGE_PATH);
- if (set_path) {
- tex->set_path(base_path);
- }
- texture = tex;
- }
- Dictionary d = lightmapper->get_bake_mesh_userdata(i);
- NodePath np = d["path"];
- int32_t subindex = -1;
- if (d.has("subindex")) {
- subindex = d["subindex"];
- }
- Rect2 uv_rect = Rect2(0, 0, 1, 1);
- int slice_index = -1;
- data->add_user(np, texture, slice_index, uv_rect, subindex);
- }
- }
- if (bake_step_function) {
- bool cancelled = bake_step_function(1.0, TTR("Done"), nullptr, true);
- if (cancelled) {
- bake_end_function(time_started);
- return BAKE_ERROR_USER_ABORTED;
- }
- }
- Error err = ResourceSaver::save(p_data_save_path, data);
- data->set_path(p_data_save_path);
- if (err != OK) {
- bake_end_function(time_started);
- return BAKE_ERROR_CANT_CREATE_IMAGE;
- }
- set_light_data(data);
- bake_end_function(time_started);
- return BAKE_ERROR_OK;
- }
- void BakedLightmap::set_capture_cell_size(float p_cell_size) {
- capture_cell_size = MAX(0.1, p_cell_size);
- }
- float BakedLightmap::get_capture_cell_size() const {
- return capture_cell_size;
- }
- void BakedLightmap::set_extents(const Vector3 &p_extents) {
- extents = p_extents;
- update_gizmo();
- _change_notify("extents");
- }
- Vector3 BakedLightmap::get_extents() const {
- return extents;
- }
- void BakedLightmap::set_default_texels_per_unit(const float &p_bake_texels_per_unit) {
- default_texels_per_unit = MAX(0.0, p_bake_texels_per_unit);
- }
- float BakedLightmap::get_default_texels_per_unit() const {
- return default_texels_per_unit;
- }
- void BakedLightmap::set_capture_enabled(bool p_enable) {
- capture_enabled = p_enable;
- _change_notify();
- }
- bool BakedLightmap::get_capture_enabled() const {
- return capture_enabled;
- }
- void BakedLightmap::_notification(int p_what) {
- if (p_what == NOTIFICATION_READY) {
- if (light_data.is_valid()) {
- _assign_lightmaps();
- }
- request_ready(); //will need ready again if re-enters tree
- }
- if (p_what == NOTIFICATION_EXIT_TREE) {
- if (light_data.is_valid()) {
- _clear_lightmaps();
- }
- }
- }
- void BakedLightmap::_assign_lightmaps() {
- ERR_FAIL_COND(!light_data.is_valid());
- bool atlassed_on_gles2 = false;
- for (int i = 0; i < light_data->get_user_count(); i++) {
- Ref<Resource> lightmap = light_data->get_user_lightmap(i);
- ERR_CONTINUE(!lightmap.is_valid());
- ERR_CONTINUE(!Object::cast_to<Texture>(lightmap.ptr()) && !Object::cast_to<TextureLayered>(lightmap.ptr()));
- Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_instance(i);
- if (instance_idx >= 0) {
- RID instance = node->call("get_bake_mesh_instance", instance_idx);
- if (instance.is_valid()) {
- int slice = light_data->get_user_lightmap_slice(i);
- atlassed_on_gles2 = atlassed_on_gles2 || (slice != -1 && OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2);
- VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid(), slice, light_data->get_user_lightmap_uv_rect(i));
- }
- } else {
- VisualInstance *vi = Object::cast_to<VisualInstance>(node);
- ERR_CONTINUE(!vi);
- int slice = light_data->get_user_lightmap_slice(i);
- atlassed_on_gles2 = atlassed_on_gles2 || (slice != -1 && OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2);
- VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid(), slice, light_data->get_user_lightmap_uv_rect(i));
- }
- }
- if (atlassed_on_gles2) {
- ERR_PRINT("GLES2 doesn't support layered textures, so lightmap atlassing is not supported. Please re-bake the lightmap or switch to GLES3.");
- }
- }
- void BakedLightmap::_clear_lightmaps() {
- ERR_FAIL_COND(!light_data.is_valid());
- for (int i = 0; i < light_data->get_user_count(); i++) {
- Node *node = get_node(light_data->get_user_path(i));
- int instance_idx = light_data->get_user_instance(i);
- if (instance_idx >= 0) {
- RID instance = node->call("get_bake_mesh_instance", instance_idx);
- if (instance.is_valid()) {
- VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID(), -1, Rect2(0, 0, 1, 1));
- }
- } else {
- VisualInstance *vi = Object::cast_to<VisualInstance>(node);
- ERR_CONTINUE(!vi);
- VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID(), -1, Rect2(0, 0, 1, 1));
- }
- }
- }
- Ref<Image> BakedLightmap::_get_irradiance_from_sky(Ref<Sky> p_sky, float p_energy, Vector2i p_size) {
- if (p_sky.is_null()) {
- return Ref<Image>();
- }
- Ref<Image> sky_image;
- Ref<PanoramaSky> panorama = p_sky;
- if (panorama.is_valid()) {
- sky_image = panorama->get_panorama()->get_data();
- }
- Ref<ProceduralSky> procedural = p_sky;
- if (procedural.is_valid()) {
- sky_image = procedural->get_data();
- }
- if (sky_image.is_null()) {
- return Ref<Image>();
- }
- sky_image->convert(Image::FORMAT_RGBF);
- sky_image->resize(p_size.x, p_size.y, Image::INTERPOLATE_CUBIC);
- if (p_energy != 1.0) {
- sky_image->lock();
- for (int i = 0; i < p_size.y; i++) {
- for (int j = 0; j < p_size.x; j++) {
- sky_image->set_pixel(j, i, sky_image->get_pixel(j, i) * p_energy);
- }
- }
- sky_image->unlock();
- }
- return sky_image;
- }
- Ref<Image> BakedLightmap::_get_irradiance_map(Ref<Environment> p_env, Vector2i p_size) {
- Environment::BGMode bg_mode = p_env->get_background();
- switch (bg_mode) {
- case Environment::BG_SKY: {
- return _get_irradiance_from_sky(p_env->get_sky(), p_env->get_bg_energy(), Vector2i(128, 64));
- }
- case Environment::BG_CLEAR_COLOR:
- case Environment::BG_COLOR: {
- Color c = bg_mode == Environment::BG_CLEAR_COLOR ? Color(GLOBAL_GET("rendering/environment/default_clear_color")) : p_env->get_bg_color();
- c.r *= p_env->get_bg_energy();
- c.g *= p_env->get_bg_energy();
- c.b *= p_env->get_bg_energy();
- Ref<Image> ret;
- ret.instance();
- ret->create(p_size.x, p_size.y, false, Image::FORMAT_RGBF);
- ret->fill(c);
- return ret;
- }
- default: {
- }
- }
- return Ref<Image>();
- }
- void BakedLightmap::set_light_data(const Ref<BakedLightmapData> &p_data) {
- if (light_data.is_valid()) {
- if (is_inside_tree()) {
- _clear_lightmaps();
- }
- set_base(RID());
- }
- light_data = p_data;
- _change_notify();
- if (light_data.is_valid()) {
- set_base(light_data->get_rid());
- if (is_inside_tree()) {
- _assign_lightmaps();
- }
- }
- }
- Ref<BakedLightmapData> BakedLightmap::get_light_data() const {
- return light_data;
- }
- void BakedLightmap::set_capture_propagation(float p_propagation) {
- capture_propagation = p_propagation;
- }
- float BakedLightmap::get_capture_propagation() const {
- return capture_propagation;
- }
- void BakedLightmap::set_capture_quality(BakeQuality p_quality) {
- capture_quality = p_quality;
- }
- BakedLightmap::BakeQuality BakedLightmap::get_capture_quality() const {
- return capture_quality;
- }
- void BakedLightmap::set_generate_atlas(bool p_enabled) {
- generate_atlas = p_enabled;
- }
- bool BakedLightmap::is_generate_atlas_enabled() const {
- return generate_atlas;
- }
- void BakedLightmap::set_max_atlas_size(int p_size) {
- ERR_FAIL_COND(p_size < 2048);
- max_atlas_size = p_size;
- }
- int BakedLightmap::get_max_atlas_size() const {
- return max_atlas_size;
- }
- void BakedLightmap::set_bake_quality(BakeQuality p_quality) {
- bake_quality = p_quality;
- _change_notify();
- }
- BakedLightmap::BakeQuality BakedLightmap::get_bake_quality() const {
- return bake_quality;
- }
- #ifndef DISABLE_DEPRECATED
- void BakedLightmap::set_image_path(const String &p_path) {
- image_path = p_path;
- }
- String BakedLightmap::get_image_path() const {
- return image_path;
- }
- #endif
- void BakedLightmap::set_use_denoiser(bool p_enable) {
- use_denoiser = p_enable;
- }
- bool BakedLightmap::is_using_denoiser() const {
- return use_denoiser;
- }
- void BakedLightmap::set_use_hdr(bool p_enable) {
- use_hdr = p_enable;
- }
- bool BakedLightmap::is_using_hdr() const {
- return use_hdr;
- }
- void BakedLightmap::set_use_color(bool p_enable) {
- use_color = p_enable;
- }
- bool BakedLightmap::is_using_color() const {
- return use_color;
- }
- void BakedLightmap::set_environment_mode(EnvironmentMode p_mode) {
- environment_mode = p_mode;
- _change_notify();
- }
- BakedLightmap::EnvironmentMode BakedLightmap::get_environment_mode() const {
- return environment_mode;
- }
- void BakedLightmap::set_environment_custom_sky(const Ref<Sky> &p_sky) {
- environment_custom_sky = p_sky;
- }
- Ref<Sky> BakedLightmap::get_environment_custom_sky() const {
- return environment_custom_sky;
- }
- void BakedLightmap::set_environment_custom_sky_rotation_degrees(const Vector3 &p_rotation) {
- environment_custom_sky_rotation_degrees = p_rotation;
- }
- Vector3 BakedLightmap::get_environment_custom_sky_rotation_degrees() const {
- return environment_custom_sky_rotation_degrees;
- }
- void BakedLightmap::set_environment_custom_color(const Color &p_color) {
- environment_custom_color = p_color;
- }
- Color BakedLightmap::get_environment_custom_color() const {
- return environment_custom_color;
- }
- void BakedLightmap::set_environment_custom_energy(float p_energy) {
- environment_custom_energy = p_energy;
- }
- float BakedLightmap::get_environment_custom_energy() const {
- return environment_custom_energy;
- }
- void BakedLightmap::set_environment_min_light(Color p_min_light) {
- environment_min_light = p_min_light;
- }
- Color BakedLightmap::get_environment_min_light() const {
- return environment_min_light;
- }
- void BakedLightmap::set_bounces(int p_bounces) {
- ERR_FAIL_COND(p_bounces < 0 || p_bounces > 16);
- bounces = p_bounces;
- }
- int BakedLightmap::get_bounces() const {
- return bounces;
- }
- void BakedLightmap::set_bounce_indirect_energy(float p_indirect_energy) {
- ERR_FAIL_COND(p_indirect_energy < 0.0);
- bounce_indirect_energy = p_indirect_energy;
- }
- float BakedLightmap::get_bounce_indirect_energy() const {
- return bounce_indirect_energy;
- }
- void BakedLightmap::set_bias(float p_bias) {
- ERR_FAIL_COND(p_bias < 0.00001f);
- bias = p_bias;
- }
- float BakedLightmap::get_bias() const {
- return bias;
- }
- AABB BakedLightmap::get_aabb() const {
- return AABB(-extents, extents * 2);
- }
- PoolVector<Face3> BakedLightmap::get_faces(uint32_t p_usage_flags) const {
- return PoolVector<Face3>();
- }
- void BakedLightmap::_validate_property(PropertyInfo &property) const {
- if (property.name.begins_with("environment_custom_sky") && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
- }
- if (property.name == "environment_custom_color" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR) {
- property.usage = 0;
- }
- if (property.name == "environment_custom_energy" && environment_mode != ENVIRONMENT_MODE_CUSTOM_COLOR && environment_mode != ENVIRONMENT_MODE_CUSTOM_SKY) {
- property.usage = 0;
- }
- if (property.name.begins_with("atlas") && OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
- property.usage = PROPERTY_USAGE_NOEDITOR;
- }
- if (property.name.begins_with("capture") && property.name != "capture_enabled" && !capture_enabled) {
- property.usage = 0;
- }
- }
- void BakedLightmap::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_light_data", "data"), &BakedLightmap::set_light_data);
- ClassDB::bind_method(D_METHOD("get_light_data"), &BakedLightmap::get_light_data);
- ClassDB::bind_method(D_METHOD("set_bake_quality", "quality"), &BakedLightmap::set_bake_quality);
- ClassDB::bind_method(D_METHOD("get_bake_quality"), &BakedLightmap::get_bake_quality);
- ClassDB::bind_method(D_METHOD("set_bounces", "bounces"), &BakedLightmap::set_bounces);
- ClassDB::bind_method(D_METHOD("get_bounces"), &BakedLightmap::get_bounces);
- ClassDB::bind_method(D_METHOD("set_bounce_indirect_energy", "bounce_indirect_energy"), &BakedLightmap::set_bounce_indirect_energy);
- ClassDB::bind_method(D_METHOD("get_bounce_indirect_energy"), &BakedLightmap::get_bounce_indirect_energy);
- ClassDB::bind_method(D_METHOD("set_bias", "bias"), &BakedLightmap::set_bias);
- ClassDB::bind_method(D_METHOD("get_bias"), &BakedLightmap::get_bias);
- ClassDB::bind_method(D_METHOD("set_environment_mode", "mode"), &BakedLightmap::set_environment_mode);
- ClassDB::bind_method(D_METHOD("get_environment_mode"), &BakedLightmap::get_environment_mode);
- ClassDB::bind_method(D_METHOD("set_environment_custom_sky", "sky"), &BakedLightmap::set_environment_custom_sky);
- ClassDB::bind_method(D_METHOD("get_environment_custom_sky"), &BakedLightmap::get_environment_custom_sky);
- ClassDB::bind_method(D_METHOD("set_environment_custom_sky_rotation_degrees", "rotation"), &BakedLightmap::set_environment_custom_sky_rotation_degrees);
- ClassDB::bind_method(D_METHOD("get_environment_custom_sky_rotation_degrees"), &BakedLightmap::get_environment_custom_sky_rotation_degrees);
- ClassDB::bind_method(D_METHOD("set_environment_custom_color", "color"), &BakedLightmap::set_environment_custom_color);
- ClassDB::bind_method(D_METHOD("get_environment_custom_color"), &BakedLightmap::get_environment_custom_color);
- ClassDB::bind_method(D_METHOD("set_environment_custom_energy", "energy"), &BakedLightmap::set_environment_custom_energy);
- ClassDB::bind_method(D_METHOD("get_environment_custom_energy"), &BakedLightmap::get_environment_custom_energy);
- ClassDB::bind_method(D_METHOD("set_environment_min_light", "min_light"), &BakedLightmap::set_environment_min_light);
- ClassDB::bind_method(D_METHOD("get_environment_min_light"), &BakedLightmap::get_environment_min_light);
- ClassDB::bind_method(D_METHOD("set_use_denoiser", "use_denoiser"), &BakedLightmap::set_use_denoiser);
- ClassDB::bind_method(D_METHOD("is_using_denoiser"), &BakedLightmap::is_using_denoiser);
- ClassDB::bind_method(D_METHOD("set_use_hdr", "use_denoiser"), &BakedLightmap::set_use_hdr);
- ClassDB::bind_method(D_METHOD("is_using_hdr"), &BakedLightmap::is_using_hdr);
- ClassDB::bind_method(D_METHOD("set_use_color", "use_denoiser"), &BakedLightmap::set_use_color);
- ClassDB::bind_method(D_METHOD("is_using_color"), &BakedLightmap::is_using_color);
- ClassDB::bind_method(D_METHOD("set_generate_atlas", "enabled"), &BakedLightmap::set_generate_atlas);
- ClassDB::bind_method(D_METHOD("is_generate_atlas_enabled"), &BakedLightmap::is_generate_atlas_enabled);
- ClassDB::bind_method(D_METHOD("set_max_atlas_size", "max_atlas_size"), &BakedLightmap::set_max_atlas_size);
- ClassDB::bind_method(D_METHOD("get_max_atlas_size"), &BakedLightmap::get_max_atlas_size);
- ClassDB::bind_method(D_METHOD("set_capture_quality", "capture_quality"), &BakedLightmap::set_capture_quality);
- ClassDB::bind_method(D_METHOD("get_capture_quality"), &BakedLightmap::get_capture_quality);
- ClassDB::bind_method(D_METHOD("set_extents", "extents"), &BakedLightmap::set_extents);
- ClassDB::bind_method(D_METHOD("get_extents"), &BakedLightmap::get_extents);
- ClassDB::bind_method(D_METHOD("set_default_texels_per_unit", "texels"), &BakedLightmap::set_default_texels_per_unit);
- ClassDB::bind_method(D_METHOD("get_default_texels_per_unit"), &BakedLightmap::get_default_texels_per_unit);
- ClassDB::bind_method(D_METHOD("set_capture_propagation", "propagation"), &BakedLightmap::set_capture_propagation);
- ClassDB::bind_method(D_METHOD("get_capture_propagation"), &BakedLightmap::get_capture_propagation);
- ClassDB::bind_method(D_METHOD("set_capture_enabled", "enabled"), &BakedLightmap::set_capture_enabled);
- ClassDB::bind_method(D_METHOD("get_capture_enabled"), &BakedLightmap::get_capture_enabled);
- ClassDB::bind_method(D_METHOD("set_capture_cell_size", "capture_cell_size"), &BakedLightmap::set_capture_cell_size);
- ClassDB::bind_method(D_METHOD("get_capture_cell_size"), &BakedLightmap::get_capture_cell_size);
- #ifndef DISABLE_DEPRECATED
- ClassDB::bind_method(D_METHOD("set_image_path", "image_path"), &BakedLightmap::set_image_path);
- ClassDB::bind_method(D_METHOD("get_image_path"), &BakedLightmap::get_image_path);
- #endif
- ClassDB::bind_method(D_METHOD("bake", "from_node", "data_save_path"), &BakedLightmap::bake, DEFVAL(Variant()), DEFVAL(""));
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "extents"), "set_extents", "get_extents");
- ADD_GROUP("Tweaks", "");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "quality", PROPERTY_HINT_ENUM, "Low,Medium,High,Ultra"), "set_bake_quality", "get_bake_quality");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "bounces", PROPERTY_HINT_RANGE, "0,16,1"), "set_bounces", "get_bounces");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bounce_indirect_energy", PROPERTY_HINT_RANGE, "0,16,0.01"), "set_bounce_indirect_energy", "get_bounce_indirect_energy");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_denoiser"), "set_use_denoiser", "is_using_denoiser");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_hdr"), "set_use_hdr", "is_using_hdr");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_color"), "set_use_color", "is_using_color");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "bias", PROPERTY_HINT_RANGE, "0.00001,0.1,0.00001,or_greater"), "set_bias", "get_bias");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "default_texels_per_unit", PROPERTY_HINT_RANGE, "0.0,64.0,0.01,or_greater"), "set_default_texels_per_unit", "get_default_texels_per_unit");
- ADD_GROUP("Atlas", "atlas_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "atlas_generate"), "set_generate_atlas", "is_generate_atlas_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "atlas_max_size"), "set_max_atlas_size", "get_max_atlas_size");
- ADD_GROUP("Environment", "environment_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "environment_mode", PROPERTY_HINT_ENUM, "Disabled,Scene,Custom Sky,Custom Color"), "set_environment_mode", "get_environment_mode");
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "environment_custom_sky", PROPERTY_HINT_RESOURCE_TYPE, "Sky"), "set_environment_custom_sky", "get_environment_custom_sky");
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "environment_custom_sky_rotation_degrees", PROPERTY_HINT_NONE), "set_environment_custom_sky_rotation_degrees", "get_environment_custom_sky_rotation_degrees");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_custom_color", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_custom_color", "get_environment_custom_color");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "environment_custom_energy", PROPERTY_HINT_RANGE, "0,64,0.01"), "set_environment_custom_energy", "get_environment_custom_energy");
- ADD_PROPERTY(PropertyInfo(Variant::COLOR, "environment_min_light", PROPERTY_HINT_COLOR_NO_ALPHA), "set_environment_min_light", "get_environment_min_light");
- ADD_GROUP("Capture", "capture_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "capture_enabled"), "set_capture_enabled", "get_capture_enabled");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_cell_size", PROPERTY_HINT_RANGE, "0.25,2.0,0.05,or_greater"), "set_capture_cell_size", "get_capture_cell_size");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "capture_quality", PROPERTY_HINT_ENUM, "Low,Medium,High"), "set_capture_quality", "get_capture_quality");
- ADD_PROPERTY(PropertyInfo(Variant::REAL, "capture_propagation", PROPERTY_HINT_RANGE, "0,1,0.01"), "set_capture_propagation", "get_capture_propagation");
- ADD_GROUP("Data", "");
- #ifndef DISABLE_DEPRECATED
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "image_path", PROPERTY_HINT_DIR, "", 0), "set_image_path", "get_image_path");
- #endif
- ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "light_data", PROPERTY_HINT_RESOURCE_TYPE, "BakedLightmapData"), "set_light_data", "get_light_data");
- BIND_ENUM_CONSTANT(BAKE_QUALITY_LOW);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_MEDIUM);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_HIGH);
- BIND_ENUM_CONSTANT(BAKE_QUALITY_ULTRA);
- BIND_ENUM_CONSTANT(BAKE_ERROR_OK);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_SAVE_PATH);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_MESHES);
- BIND_ENUM_CONSTANT(BAKE_ERROR_CANT_CREATE_IMAGE);
- BIND_ENUM_CONSTANT(BAKE_ERROR_LIGHTMAP_SIZE);
- BIND_ENUM_CONSTANT(BAKE_ERROR_INVALID_MESH);
- BIND_ENUM_CONSTANT(BAKE_ERROR_USER_ABORTED);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_LIGHTMAPPER);
- BIND_ENUM_CONSTANT(BAKE_ERROR_NO_ROOT);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_DISABLED);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_SCENE);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_SKY);
- BIND_ENUM_CONSTANT(ENVIRONMENT_MODE_CUSTOM_COLOR);
- }
- BakedLightmap::BakedLightmap() {
- extents = Vector3(10, 10, 10);
- default_texels_per_unit = 16.0f;
- bake_quality = BAKE_QUALITY_MEDIUM;
- capture_quality = BAKE_QUALITY_MEDIUM;
- capture_propagation = 1;
- capture_enabled = true;
- bounces = 3;
- bounce_indirect_energy = 1.0;
- image_path = "";
- set_disable_scale(true);
- capture_cell_size = 0.5;
- environment_mode = ENVIRONMENT_MODE_DISABLED;
- environment_custom_color = Color(0.2, 0.7, 1.0);
- environment_custom_energy = 1.0;
- environment_min_light = Color(0.0, 0.0, 0.0);
- use_denoiser = true;
- use_hdr = true;
- use_color = true;
- bias = 0.005;
- generate_atlas = true;
- max_atlas_size = 4096;
- }
|