Path: blob/master/modules/lightmapper_rd/lightmapper_rd.cpp
20941 views
/**************************************************************************/1/* lightmapper_rd.cpp */2/**************************************************************************/3/* This file is part of: */4/* GODOT ENGINE */5/* https://godotengine.org */6/**************************************************************************/7/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */8/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */9/* */10/* Permission is hereby granted, free of charge, to any person obtaining */11/* a copy of this software and associated documentation files (the */12/* "Software"), to deal in the Software without restriction, including */13/* without limitation the rights to use, copy, modify, merge, publish, */14/* distribute, sublicense, and/or sell copies of the Software, and to */15/* permit persons to whom the Software is furnished to do so, subject to */16/* the following conditions: */17/* */18/* The above copyright notice and this permission notice shall be */19/* included in all copies or substantial portions of the Software. */20/* */21/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */22/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */23/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */24/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */25/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */26/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */27/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */28/**************************************************************************/2930#include "lightmapper_rd.h"3132#include "core/string/print_string.h"33#include "lm_blendseams.glsl.gen.h"34#include "lm_compute.glsl.gen.h"35#include "lm_raster.glsl.gen.h"3637#include "core/config/project_settings.h"38#include "core/io/dir_access.h"39#include "core/math/geometry_2d.h"40#include "core/math/geometry_3d.h"41#include "editor/file_system/editor_paths.h"42#include "editor/settings/editor_settings.h"43#include "servers/rendering/rendering_device_binds.h"44#include "servers/rendering/rendering_server_globals.h"4546#if defined(VULKAN_ENABLED)47#include "drivers/vulkan/rendering_context_driver_vulkan.h"48#endif49#if defined(METAL_ENABLED)50#include "drivers/metal/rendering_context_driver_metal.h"51#endif5253//uncomment this if you want to see textures from all the process saved54//#define DEBUG_TEXTURES5556void LightmapperRD::add_mesh(const MeshData &p_mesh) {57ERR_FAIL_COND(p_mesh.albedo_on_uv2.is_null() || p_mesh.albedo_on_uv2->is_empty());58ERR_FAIL_COND(p_mesh.emission_on_uv2.is_null() || p_mesh.emission_on_uv2->is_empty());59ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_width() != p_mesh.emission_on_uv2->get_width());60ERR_FAIL_COND(p_mesh.albedo_on_uv2->get_height() != p_mesh.emission_on_uv2->get_height());61ERR_FAIL_COND(p_mesh.points.is_empty());62MeshInstance mi;63mi.data = p_mesh;64mesh_instances.push_back(mi);65}6667void LightmapperRD::add_directional_light(const String &p_name, bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_angular_distance, float p_shadow_blur) {68Light l;69l.type = LIGHT_TYPE_DIRECTIONAL;70l.direction[0] = p_direction.x;71l.direction[1] = p_direction.y;72l.direction[2] = p_direction.z;73l.color[0] = p_color.r;74l.color[1] = p_color.g;75l.color[2] = p_color.b;76l.energy = p_energy;77l.indirect_energy = p_indirect_energy;78l.static_bake = p_static;79l.size = Math::tan(Math::deg_to_rad(p_angular_distance));80l.shadow_blur = p_shadow_blur;81lights.push_back(l);8283LightMetadata md;84md.name = p_name;85md.type = LIGHT_TYPE_DIRECTIONAL;86light_metadata.push_back(md);87}8889void LightmapperRD::add_omni_light(const String &p_name, bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) {90Light l;91l.type = LIGHT_TYPE_OMNI;92l.position[0] = p_position.x;93l.position[1] = p_position.y;94l.position[2] = p_position.z;95l.range = p_range;96l.attenuation = p_attenuation;97l.color[0] = p_color.r;98l.color[1] = p_color.g;99l.color[2] = p_color.b;100l.energy = p_energy;101l.indirect_energy = p_indirect_energy;102l.static_bake = p_static;103l.size = p_size;104l.shadow_blur = p_shadow_blur;105lights.push_back(l);106107LightMetadata md;108md.name = p_name;109md.type = LIGHT_TYPE_OMNI;110light_metadata.push_back(md);111}112113void LightmapperRD::add_spot_light(const String &p_name, bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_indirect_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) {114Light l;115l.type = LIGHT_TYPE_SPOT;116l.position[0] = p_position.x;117l.position[1] = p_position.y;118l.position[2] = p_position.z;119l.direction[0] = p_direction.x;120l.direction[1] = p_direction.y;121l.direction[2] = p_direction.z;122l.range = p_range;123l.attenuation = p_attenuation;124l.cos_spot_angle = Math::cos(Math::deg_to_rad(p_spot_angle));125l.inv_spot_attenuation = 1.0f / p_spot_attenuation;126l.color[0] = p_color.r;127l.color[1] = p_color.g;128l.color[2] = p_color.b;129l.energy = p_energy;130l.indirect_energy = p_indirect_energy;131l.static_bake = p_static;132l.size = p_size;133l.shadow_blur = p_shadow_blur;134lights.push_back(l);135136LightMetadata md;137md.name = p_name;138md.type = LIGHT_TYPE_SPOT;139light_metadata.push_back(md);140}141142void LightmapperRD::add_probe(const Vector3 &p_position) {143Probe probe;144probe.position[0] = p_position.x;145probe.position[1] = p_position.y;146probe.position[2] = p_position.z;147probe.position[3] = 0;148probe_positions.push_back(probe);149}150151void LightmapperRD::_plot_triangle_into_triangle_index_list(int p_size, const Vector3i &p_ofs, const AABB &p_bounds, const Vector3 p_points[3], uint32_t p_triangle_index, LocalVector<TriangleSort> &p_triangles_sort, uint32_t p_grid_size) {152int half_size = p_size / 2;153154for (int i = 0; i < 8; i++) {155AABB aabb = p_bounds;156aabb.size *= 0.5;157Vector3i n = p_ofs;158159if (i & 1) {160aabb.position.x += aabb.size.x;161n.x += half_size;162}163if (i & 2) {164aabb.position.y += aabb.size.y;165n.y += half_size;166}167if (i & 4) {168aabb.position.z += aabb.size.z;169n.z += half_size;170}171172{173Vector3 qsize = aabb.size * 0.5; //quarter size, for fast aabb test174175if (!Geometry3D::triangle_box_overlap(aabb.position + qsize, qsize, p_points)) {176//does not fit in child, go on177continue;178}179}180181if (half_size == 1) {182//got to the end183TriangleSort ts;184ts.cell_index = n.x + (n.y * p_grid_size) + (n.z * p_grid_size * p_grid_size);185ts.triangle_index = p_triangle_index;186ts.triangle_aabb.position = p_points[0];187ts.triangle_aabb.size = Vector3();188ts.triangle_aabb.expand_to(p_points[1]);189ts.triangle_aabb.expand_to(p_points[2]);190p_triangles_sort.push_back(ts);191} else {192_plot_triangle_into_triangle_index_list(half_size, n, aabb, p_points, p_triangle_index, p_triangles_sort, p_grid_size);193}194}195}196197void LightmapperRD::_sort_triangle_clusters(uint32_t p_cluster_size, uint32_t p_cluster_index, uint32_t p_index_start, uint32_t p_count, LocalVector<TriangleSort> &p_triangle_sort, LocalVector<ClusterAABB> &p_cluster_aabb) {198if (p_count == 0) {199return;200}201202// Compute AABB for all triangles in the range.203SortArray<TriangleSort, TriangleSortAxis<0>> triangle_sorter_x;204SortArray<TriangleSort, TriangleSortAxis<1>> triangle_sorter_y;205SortArray<TriangleSort, TriangleSortAxis<2>> triangle_sorter_z;206AABB cluster_aabb = p_triangle_sort[p_index_start].triangle_aabb;207for (uint32_t i = 1; i < p_count; i++) {208cluster_aabb.merge_with(p_triangle_sort[p_index_start + i].triangle_aabb);209}210211if (p_count > p_cluster_size) {212int longest_axis_index = cluster_aabb.get_longest_axis_index();213switch (longest_axis_index) {214case 0:215triangle_sorter_x.sort(&p_triangle_sort[p_index_start], p_count);216break;217case 1:218triangle_sorter_y.sort(&p_triangle_sort[p_index_start], p_count);219break;220case 2:221triangle_sorter_z.sort(&p_triangle_sort[p_index_start], p_count);222break;223default:224DEV_ASSERT(false && "Invalid axis returned by AABB.");225break;226}227228uint32_t left_cluster_count = next_power_of_2(p_count / 2);229left_cluster_count = MAX(left_cluster_count, p_cluster_size);230left_cluster_count = MIN(left_cluster_count, p_count);231_sort_triangle_clusters(p_cluster_size, p_cluster_index, p_index_start, left_cluster_count, p_triangle_sort, p_cluster_aabb);232233if (left_cluster_count < p_count) {234uint32_t cluster_index_right = p_cluster_index + (left_cluster_count / p_cluster_size);235_sort_triangle_clusters(p_cluster_size, cluster_index_right, p_index_start + left_cluster_count, p_count - left_cluster_count, p_triangle_sort, p_cluster_aabb);236}237} else {238ClusterAABB &aabb = p_cluster_aabb[p_cluster_index];239Vector3 aabb_end = cluster_aabb.get_end();240aabb.min_bounds[0] = cluster_aabb.position.x;241aabb.min_bounds[1] = cluster_aabb.position.y;242aabb.min_bounds[2] = cluster_aabb.position.z;243aabb.max_bounds[0] = aabb_end.x;244aabb.max_bounds[1] = aabb_end.y;245aabb.max_bounds[2] = aabb_end.z;246}247}248249Lightmapper::BakeError LightmapperRD::_blit_meshes_into_atlas(int p_max_texture_size, int p_denoiser_range, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, float p_supersampling_factor, BakeStepFunc p_step_function, void *p_bake_userdata) {250Vector<Size2i> sizes;251252for (int m_i = 0; m_i < mesh_instances.size(); m_i++) {253MeshInstance &mi = mesh_instances.write[m_i];254Size2i s = Size2i(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height());255sizes.push_back(s);256atlas_size = atlas_size.max(s + Size2i(2, 2).maxi(p_denoiser_range) * p_supersampling_factor);257}258259int max = nearest_power_of_2_templated(atlas_size.width);260max = MAX(max, nearest_power_of_2_templated(atlas_size.height));261262if (max > p_max_texture_size) {263return BAKE_ERROR_TEXTURE_EXCEEDS_MAX_SIZE;264}265266if (p_step_function) {267if (p_step_function(0.1, RTR("Determining optimal atlas size"), p_bake_userdata, true)) {268return BAKE_ERROR_USER_ABORTED;269}270}271272atlas_size = Size2i(max, max);273274Size2i best_atlas_size;275int best_atlas_slices = 0;276int best_atlas_memory = 0x7FFFFFFF;277Vector<Vector3i> best_atlas_offsets;278279// Determine best texture array atlas size by bruteforce fitting.280while (atlas_size.x <= p_max_texture_size && atlas_size.y <= p_max_texture_size) {281Vector<Vector2i> source_sizes;282Vector<int> source_indices;283source_sizes.resize(sizes.size());284source_indices.resize(sizes.size());285for (int i = 0; i < source_indices.size(); i++) {286// Add padding between lightmaps.287// Scale the padding if the lightmap will be downsampled at the end of the baking process288// Otherwise the padding would be insufficient.289source_sizes.write[i] = sizes[i] + Vector2i(2, 2).maxi(p_denoiser_range) * p_supersampling_factor;290source_indices.write[i] = i;291}292Vector<Vector3i> atlas_offsets;293atlas_offsets.resize(source_sizes.size());294295// Ensure the sizes can all fit into a single atlas layer.296// This should always happen, and this check is only in place to prevent an infinite loop.297for (int i = 0; i < source_sizes.size(); i++) {298if (source_sizes[i] > atlas_size) {299return BAKE_ERROR_ATLAS_TOO_SMALL;300}301}302303int slices = 0;304305while (source_sizes.size() > 0) {306Vector<Vector3i> offsets = Geometry2D::partial_pack_rects(source_sizes, atlas_size);307Vector<int> new_indices;308Vector<Vector2i> new_sources;309for (int i = 0; i < offsets.size(); i++) {310Vector3i ofs = offsets[i];311int sidx = source_indices[i];312if (ofs.z > 0) {313//valid314ofs.z = slices;315atlas_offsets.write[sidx] = ofs + Vector3i(1, 1, 0); // Center lightmap in the reserved oversized region316} else {317new_indices.push_back(sidx);318new_sources.push_back(source_sizes[i]);319}320}321322source_sizes = new_sources;323source_indices = new_indices;324slices++;325}326327int mem_used = atlas_size.x * atlas_size.y * slices;328if (mem_used < best_atlas_memory) {329best_atlas_size = atlas_size;330best_atlas_offsets = atlas_offsets;331best_atlas_slices = slices;332best_atlas_memory = mem_used;333}334335if (atlas_size.width == atlas_size.height) {336atlas_size.width *= 2;337} else {338atlas_size.height *= 2;339}340}341atlas_size = best_atlas_size;342atlas_slices = best_atlas_slices;343344// apply the offsets and slice to all images, and also blit albedo and emission345albedo_images.resize(atlas_slices);346emission_images.resize(atlas_slices);347348if (p_step_function) {349if (p_step_function(0.2, RTR("Blitting albedo and emission"), p_bake_userdata, true)) {350return BAKE_ERROR_USER_ABORTED;351}352}353354for (int i = 0; i < atlas_slices; i++) {355Ref<Image> albedo = Image::create_empty(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8);356albedo->set_as_black();357albedo_images.write[i] = albedo;358359Ref<Image> emission = Image::create_empty(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH);360emission->set_as_black();361emission_images.write[i] = emission;362}363364//assign uv positions365366for (int m_i = 0; m_i < mesh_instances.size(); m_i++) {367MeshInstance &mi = mesh_instances.write[m_i];368mi.offset.x = best_atlas_offsets[m_i].x;369mi.offset.y = best_atlas_offsets[m_i].y;370mi.slice = best_atlas_offsets[m_i].z;371albedo_images.write[mi.slice]->blit_rect(mi.data.albedo_on_uv2, Rect2i(Vector2i(), mi.data.albedo_on_uv2->get_size()), mi.offset);372emission_images.write[mi.slice]->blit_rect(mi.data.emission_on_uv2, Rect2(Vector2i(), mi.data.emission_on_uv2->get_size()), mi.offset);373}374375return BAKE_OK;376}377378void LightmapperRD::_create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, uint32_t p_cluster_size, Vector<Probe> &p_probe_positions, GenerateProbes p_generate_probes, Vector<int> &slice_triangle_count, Vector<int> &slice_seam_count, RID &vertex_buffer, RID &triangle_buffer, RID &lights_buffer, RID &r_triangle_indices_buffer, RID &r_cluster_indices_buffer, RID &r_cluster_aabbs_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata) {379HashMap<Vertex, uint32_t, VertexHash> vertex_map;380381//fill triangles array and vertex array382LocalVector<Triangle> triangles;383LocalVector<Vertex> vertex_array;384LocalVector<Seam> seams;385386slice_triangle_count.resize(atlas_slices);387slice_seam_count.resize(atlas_slices);388389for (int i = 0; i < atlas_slices; i++) {390slice_triangle_count.write[i] = 0;391slice_seam_count.write[i] = 0;392}393394bounds = AABB();395396for (int m_i = 0; m_i < mesh_instances.size(); m_i++) {397if (p_step_function) {398float p = float(m_i + 1) / MAX(1, mesh_instances.size()) * 0.1;399p_step_function(0.3 + p, vformat(RTR("Plotting mesh into acceleration structure %d/%d"), m_i + 1, mesh_instances.size()), p_bake_userdata, false);400}401402HashMap<Edge, EdgeUV2, EdgeHash> edges;403404MeshInstance &mi = mesh_instances.write[m_i];405406Vector2 uv_scale = Vector2(mi.data.albedo_on_uv2->get_width(), mi.data.albedo_on_uv2->get_height()) / Vector2(atlas_size);407Vector2 uv_offset = Vector2(mi.offset) / Vector2(atlas_size);408if (m_i == 0) {409bounds.position = mi.data.points[0];410}411412for (int i = 0; i < mi.data.points.size(); i += 3) {413Vector3 vtxs[3] = { mi.data.points[i + 0], mi.data.points[i + 1], mi.data.points[i + 2] };414Vector2 uvs[3] = { mi.data.uv2[i + 0] * uv_scale + uv_offset, mi.data.uv2[i + 1] * uv_scale + uv_offset, mi.data.uv2[i + 2] * uv_scale + uv_offset };415Vector3 normal[3] = { mi.data.normal[i + 0], mi.data.normal[i + 1], mi.data.normal[i + 2] };416417AABB taabb;418Triangle t;419t.slice = mi.slice;420for (int k = 0; k < 3; k++) {421bounds.expand_to(vtxs[k]);422423Vertex v;424v.position[0] = vtxs[k].x;425v.position[1] = vtxs[k].y;426v.position[2] = vtxs[k].z;427v.uv[0] = uvs[k].x;428v.uv[1] = uvs[k].y;429v.normal_xy[0] = normal[k].x;430v.normal_xy[1] = normal[k].y;431v.normal_z = normal[k].z;432433uint32_t *indexptr = vertex_map.getptr(v);434435if (indexptr) {436t.indices[k] = *indexptr;437} else {438uint32_t new_index = vertex_map.size();439t.indices[k] = new_index;440vertex_map[v] = new_index;441vertex_array.push_back(v);442}443444if (k == 0) {445taabb.position = vtxs[k];446} else {447taabb.expand_to(vtxs[k]);448}449}450451//compute seams that will need to be blended later452for (int k = 0; k < 3; k++) {453int n = (k + 1) % 3;454455Edge edge(vtxs[k], vtxs[n], normal[k], normal[n]);456Vector2i edge_indices(t.indices[k], t.indices[n]);457EdgeUV2 uv2(uvs[k], uvs[n], edge_indices);458459if (edge.b == edge.a) {460continue; //degenerate, somehow461}462if (edge.b < edge.a) {463SWAP(edge.a, edge.b);464SWAP(edge.na, edge.nb);465SWAP(uv2.a, uv2.b);466SWAP(uv2.indices.x, uv2.indices.y);467SWAP(edge_indices.x, edge_indices.y);468}469470EdgeUV2 *euv2 = edges.getptr(edge);471if (!euv2) {472edges[edge] = uv2;473} else {474if (*euv2 == uv2) {475continue; // seam shared UV space, no need to blend476}477if (euv2->seam_found) {478continue; //bad geometry479}480481Seam seam;482seam.a = edge_indices;483seam.b = euv2->indices;484seam.slice = mi.slice;485seams.push_back(seam);486slice_seam_count.write[mi.slice]++;487euv2->seam_found = true;488}489}490491t.min_bounds[0] = taabb.position.x;492t.min_bounds[1] = taabb.position.y;493t.min_bounds[2] = taabb.position.z;494t.max_bounds[0] = taabb.position.x + MAX(taabb.size.x, 0.0001);495t.max_bounds[1] = taabb.position.y + MAX(taabb.size.y, 0.0001);496t.max_bounds[2] = taabb.position.z + MAX(taabb.size.z, 0.0001);497498t.cull_mode = RS::CULL_MODE_BACK;499500RID material = mi.data.material[i];501if (material.is_valid()) {502t.cull_mode = RSG::material_storage->material_get_cull_mode(material);503}504t.pad1 = 0; //make valgrind not complain505triangles.push_back(t);506slice_triangle_count.write[t.slice]++;507}508}509510//also consider probe positions for bounds511for (int i = 0; i < p_probe_positions.size(); i++) {512Vector3 pp(p_probe_positions[i].position[0], p_probe_positions[i].position[1], p_probe_positions[i].position[2]);513bounds.expand_to(pp);514}515bounds.grow_by(0.1); //grow a bit to avoid numerical error516517triangles.sort(); //sort by slice518seams.sort();519520if (p_step_function) {521p_step_function(0.4, RTR("Optimizing acceleration structure"), p_bake_userdata, true);522}523524//fill list of triangles in grid525LocalVector<TriangleSort> triangle_sort;526for (uint32_t i = 0; i < triangles.size(); i++) {527const Triangle &t = triangles[i];528Vector3 face[3] = {529Vector3(vertex_array[t.indices[0]].position[0], vertex_array[t.indices[0]].position[1], vertex_array[t.indices[0]].position[2]),530Vector3(vertex_array[t.indices[1]].position[0], vertex_array[t.indices[1]].position[1], vertex_array[t.indices[1]].position[2]),531Vector3(vertex_array[t.indices[2]].position[0], vertex_array[t.indices[2]].position[1], vertex_array[t.indices[2]].position[2])532};533_plot_triangle_into_triangle_index_list(grid_size, Vector3i(), bounds, face, i, triangle_sort, grid_size);534}535//sort it536triangle_sort.sort();537538LocalVector<uint32_t> cluster_indices;539LocalVector<ClusterAABB> cluster_aabbs;540Vector<uint32_t> triangle_indices;541triangle_indices.resize(triangle_sort.size());542Vector<uint32_t> grid_indices;543grid_indices.resize(grid_size * grid_size * grid_size * 2);544memset(grid_indices.ptrw(), 0, grid_indices.size() * sizeof(uint32_t));545546{547// Fill grid with cell indices.548uint32_t last_cell = 0xFFFFFFFF;549uint32_t *giw = grid_indices.ptrw();550uint32_t cluster_count = 0;551uint32_t solid_cell_count = 0;552for (uint32_t i = 0; i < triangle_sort.size(); i++) {553uint32_t cell = triangle_sort[i].cell_index;554if (cell != last_cell) {555giw[cell * 2 + 1] = solid_cell_count;556solid_cell_count++;557}558559if ((giw[cell * 2] % p_cluster_size) == 0) {560// Add an extra cluster every time the triangle counter reaches a multiple of the cluster size.561cluster_count++;562}563564giw[cell * 2]++;565last_cell = cell;566}567568// Build fixed-size triangle clusters for all the cells to speed up the traversal. A cell can hold multiple clusters that each contain a fixed569// amount of triangles and an AABB. The tracer will check against the AABBs first to know whether it needs to visit the cell's triangles.570//571// The building algorithm will divide the triangles recursively contained inside each cell, sorting by the longest axis of the AABB on each step.572//573// - If the amount of triangles is less or equal to the cluster size, the AABB will be stored and the algorithm stops.574//575// - The division by two is increased to the next power of two of half the amount of triangles (with cluster size as the minimum value) to576// ensure the first half always fills the cluster.577578cluster_indices.resize(solid_cell_count * 2);579cluster_aabbs.resize(cluster_count);580581uint32_t i = 0;582uint32_t cluster_index = 0;583uint32_t solid_cell_index = 0;584uint32_t *tiw = triangle_indices.ptrw();585while (i < triangle_sort.size()) {586cluster_indices[solid_cell_index * 2] = cluster_index;587cluster_indices[solid_cell_index * 2 + 1] = i;588589uint32_t cell = triangle_sort[i].cell_index;590uint32_t triangle_count = giw[cell * 2];591uint32_t cell_cluster_count = (triangle_count + p_cluster_size - 1) / p_cluster_size;592_sort_triangle_clusters(p_cluster_size, cluster_index, i, triangle_count, triangle_sort, cluster_aabbs);593594for (uint32_t j = 0; j < triangle_count; j++) {595tiw[i + j] = triangle_sort[i + j].triangle_index;596}597598i += triangle_count;599cluster_index += cell_cluster_count;600solid_cell_index++;601}602}603#if 0604for (int i = 0; i < grid_size; i++) {605for (int j = 0; j < grid_size; j++) {606for (int k = 0; k < grid_size; k++) {607uint32_t index = i * (grid_size * grid_size) + j * grid_size + k;608grid_indices.write[index * 2] = float(i) / grid_size * 255;609grid_indices.write[index * 2 + 1] = float(j) / grid_size * 255;610}611}612}613#endif614615#if 0616for (int i = 0; i < grid_size; i++) {617Vector<uint8_t> grid_usage;618grid_usage.resize(grid_size * grid_size);619for (int j = 0; j < grid_usage.size(); j++) {620uint32_t ofs = i * grid_size * grid_size + j;621uint32_t count = grid_indices[ofs * 2];622grid_usage.write[j] = count > 0 ? 255 : 0;623}624625Ref<Image> img = Image::create_from_data(grid_size, grid_size, false, Image::FORMAT_L8, grid_usage);626img->save_png("res://grid_layer_" + itos(1000 + i).substr(1, 3) + ".png");627}628#endif629630/*****************************/631/*** CREATE GPU STRUCTURES ***/632/*****************************/633634lights.sort();635light_metadata.sort();636637Vector<Vector2i> seam_buffer_vec;638seam_buffer_vec.resize(seams.size() * 2);639for (uint32_t i = 0; i < seams.size(); i++) {640seam_buffer_vec.write[i * 2 + 0] = seams[i].a;641seam_buffer_vec.write[i * 2 + 1] = seams[i].b;642}643644{ //buffers645vertex_buffer = rd->storage_buffer_create(vertex_array.size() * sizeof(Vertex), vertex_array.span().reinterpret<uint8_t>());646647triangle_buffer = rd->storage_buffer_create(triangles.size() * sizeof(Triangle), triangles.span().reinterpret<uint8_t>());648649r_triangle_indices_buffer = rd->storage_buffer_create(triangle_indices.size() * sizeof(uint32_t), triangle_indices.span().reinterpret<uint8_t>());650651r_cluster_indices_buffer = rd->storage_buffer_create(cluster_indices.size() * sizeof(uint32_t), cluster_indices.span().reinterpret<uint8_t>());652653r_cluster_aabbs_buffer = rd->storage_buffer_create(cluster_aabbs.size() * sizeof(ClusterAABB), cluster_aabbs.span().reinterpret<uint8_t>());654655// Even when there are no lights, the buffer must exist.656static const Light empty_lights[1];657Span<uint8_t> lb = (lights.is_empty() ? Span(empty_lights) : lights.span()).reinterpret<uint8_t>();658lights_buffer = rd->storage_buffer_create(lb.size(), lb);659660// Even when there are no seams, the buffer must exist.661static const Vector2i empty_seams[2];662Span<uint8_t> sb = (seam_buffer_vec.is_empty() ? Span(empty_seams) : seam_buffer_vec.span()).reinterpret<uint8_t>();663seams_buffer = rd->storage_buffer_create(sb.size(), sb);664665// Even when there are no probes, the buffer must exist.666static const Probe empty_probes[1];667Span<uint8_t> pb = (p_probe_positions.is_empty() ? Span(empty_probes) : p_probe_positions.span()).reinterpret<uint8_t>();668probe_positions_buffer = rd->storage_buffer_create(pb.size(), pb);669}670671{ //grid672673RD::TextureFormat tf;674tf.width = grid_size;675tf.height = grid_size;676tf.depth = grid_size;677tf.texture_type = RD::TEXTURE_TYPE_3D;678tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;679680Vector<Vector<uint8_t>> texdata;681texdata.resize(1);682//grid and indices683tf.format = RD::DATA_FORMAT_R32G32_UINT;684texdata.write[0] = grid_indices.to_byte_array();685grid_texture = rd->texture_create(tf, RD::TextureView(), texdata);686}687}688689void LightmapperRD::_raster_geometry(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, int grid_size, AABB bounds, float p_bias, Vector<int> slice_triangle_count, RID position_tex, RID unocclude_tex, RID normal_tex, RID raster_depth_buffer, RID rasterize_shader, RID raster_base_uniform) {690Vector<RID> framebuffers;691692for (int i = 0; i < atlas_slices; i++) {693RID slice_pos_tex = rd->texture_create_shared_from_slice(RD::TextureView(), position_tex, i, 0);694RID slice_unoc_tex = rd->texture_create_shared_from_slice(RD::TextureView(), unocclude_tex, i, 0);695RID slice_norm_tex = rd->texture_create_shared_from_slice(RD::TextureView(), normal_tex, i, 0);696Vector<RID> fb;697fb.push_back(slice_pos_tex);698fb.push_back(slice_norm_tex);699fb.push_back(slice_unoc_tex);700fb.push_back(raster_depth_buffer);701framebuffers.push_back(rd->framebuffer_create(fb));702}703704RD::PipelineDepthStencilState ds;705ds.enable_depth_test = true;706ds.enable_depth_write = true;707ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does render same pixel twice708709RID raster_pipeline = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0);710RID raster_pipeline_wire;711{712RD::PipelineRasterizationState rw;713rw.wireframe = true;714raster_pipeline_wire = rd->render_pipeline_create(rasterize_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, rw, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(3), 0);715}716717uint32_t triangle_offset = 0;718Vector<Color> clear_colors;719clear_colors.push_back(Color(0, 0, 0, 0));720clear_colors.push_back(Color(0, 0, 0, 0));721clear_colors.push_back(Color(0, 0, 0, 0));722723for (int i = 0; i < atlas_slices; i++) {724RasterPushConstant raster_push_constant;725raster_push_constant.atlas_size[0] = atlas_size.x;726raster_push_constant.atlas_size[1] = atlas_size.y;727raster_push_constant.base_triangle = triangle_offset;728raster_push_constant.to_cell_offset[0] = bounds.position.x;729raster_push_constant.to_cell_offset[1] = bounds.position.y;730raster_push_constant.to_cell_offset[2] = bounds.position.z;731raster_push_constant.bias = p_bias;732raster_push_constant.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size);733raster_push_constant.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size);734raster_push_constant.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size);735raster_push_constant.grid_size[0] = grid_size;736raster_push_constant.grid_size[1] = grid_size;737raster_push_constant.grid_size[2] = grid_size;738739// Half pixel offset is required so the rasterizer doesn't output face edges directly aligned into pixels.740// This fixes artifacts where the pixel would be traced from the edge of a face, causing half the rays to741// be outside of the boundaries of the geometry. See <https://github.com/godotengine/godot/issues/69126>.742raster_push_constant.uv_offset[0] = -0.5f / float(atlas_size.x);743raster_push_constant.uv_offset[1] = -0.5f / float(atlas_size.y);744745RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i], RD::DRAW_CLEAR_ALL, clear_colors, 1.0f, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS);746//draw opaque747rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline);748rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0);749rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant));750rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3);751//draw wire752rd->draw_list_bind_render_pipeline(draw_list, raster_pipeline_wire);753rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0);754rd->draw_list_set_push_constant(draw_list, &raster_push_constant, sizeof(RasterPushConstant));755rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3);756757rd->draw_list_end();758759triangle_offset += slice_triangle_count[i];760}761}762763static Vector<RD::Uniform> dilate_or_denoise_common_uniforms(RID &p_source_light_tex, RID &p_dest_light_tex) {764Vector<RD::Uniform> uniforms;765{766RD::Uniform u;767u.uniform_type = RD::UNIFORM_TYPE_IMAGE;768u.binding = 0;769u.append_id(p_dest_light_tex);770uniforms.push_back(u);771}772{773RD::Uniform u;774u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;775u.binding = 1;776u.append_id(p_source_light_tex);777uniforms.push_back(u);778}779780return uniforms;781}782783LightmapperRD::BakeError LightmapperRD::_dilate(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices) {784Vector<RD::Uniform> uniforms = dilate_or_denoise_common_uniforms(source_light_tex, dest_light_tex);785786RID compute_shader_dilate = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("dilate"));787ERR_FAIL_COND_V(compute_shader_dilate.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen788RID compute_shader_dilate_pipeline = rd->compute_pipeline_create(compute_shader_dilate);789790RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_dilate, 1);791792RD::ComputeListID compute_list = rd->compute_list_begin();793rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_dilate_pipeline);794rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);795rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1);796push_constant.region_ofs[0] = 0;797push_constant.region_ofs[1] = 0;798Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1); //restore group size799800for (int i = 0; i < atlas_slices; i++) {801push_constant.atlas_slice = i;802rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));803rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z);804//no barrier, let them run all together805}806rd->compute_list_end();807rd->free_rid(compute_shader_dilate);808809#ifdef DEBUG_TEXTURES810for (int i = 0; i < atlas_slices; i++) {811Vector<uint8_t> s = rd->texture_get_data(source_light_tex, i);812Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);813img->convert(Image::FORMAT_RGBA8);814img->save_png("res://5_dilated_" + itos(i) + ".png");815}816#endif817return BAKE_OK;818}819820LightmapperRD::BakeError LightmapperRD::_pack_l1(RenderingDevice *rd, Ref<RDShaderFile> &compute_shader, RID &compute_base_uniform_set, PushConstant &push_constant, RID &source_light_tex, RID &dest_light_tex, const Size2i &atlas_size, int atlas_slices) {821Vector<RD::Uniform> uniforms = dilate_or_denoise_common_uniforms(source_light_tex, dest_light_tex);822823RID compute_shader_pack = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("pack_coeffs"));824ERR_FAIL_COND_V(compute_shader_pack.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen825RID compute_shader_pack_pipeline = rd->compute_pipeline_create(compute_shader_pack);826827RID dilate_uniform_set = rd->uniform_set_create(uniforms, compute_shader_pack, 1);828829RD::ComputeListID compute_list = rd->compute_list_begin();830rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_pack_pipeline);831rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);832rd->compute_list_bind_uniform_set(compute_list, dilate_uniform_set, 1);833push_constant.region_ofs[0] = 0;834push_constant.region_ofs[1] = 0;835Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1); //restore group size836837for (int i = 0; i < atlas_slices; i++) {838push_constant.atlas_slice = i;839rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));840rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z);841//no barrier, let them run all together842}843rd->compute_list_end();844rd->free_rid(compute_shader_pack);845846return BAKE_OK;847}848849Error LightmapperRD::_store_pfm(RenderingDevice *p_rd, RID p_atlas_tex, int p_index, const Size2i &p_atlas_size, const String &p_name, bool p_shadowmask) {850Vector<uint8_t> data = p_rd->texture_get_data(p_atlas_tex, p_index);851Ref<Image> img = Image::create_from_data(p_atlas_size.width, p_atlas_size.height, false, p_shadowmask ? Image::FORMAT_RGBA8 : Image::FORMAT_RGBAH, data);852img->convert(Image::FORMAT_RGBF);853Vector<uint8_t> data_float = img->get_data();854855Error err = OK;856Ref<FileAccess> file = FileAccess::open(p_name, FileAccess::WRITE, &err);857ERR_FAIL_COND_V_MSG(err, err, vformat("Can't save PFN at path: '%s'.", p_name));858file->store_line("PF");859file->store_line(vformat("%d %d", img->get_width(), img->get_height()));860#ifdef BIG_ENDIAN_ENABLED861file->store_line("1.0");862#else863file->store_line("-1.0");864#endif865file->store_buffer(data_float);866file->close();867868return OK;869}870871Ref<Image> LightmapperRD::_read_pfm(const String &p_name, bool p_shadowmask) {872Error err = OK;873Ref<FileAccess> file = FileAccess::open(p_name, FileAccess::READ, &err);874ERR_FAIL_COND_V_MSG(err, Ref<Image>(), vformat("Can't load PFM at path: '%s'.", p_name));875ERR_FAIL_COND_V(file->get_line() != "PF", Ref<Image>());876877Vector<String> new_size = file->get_line().split(" ");878ERR_FAIL_COND_V(new_size.size() != 2, Ref<Image>());879int new_width = new_size[0].to_int();880int new_height = new_size[1].to_int();881882float endian = file->get_line().to_float();883Vector<uint8_t> new_data = file->get_buffer(file->get_length() - file->get_position());884file->close();885886#ifdef BIG_ENDIAN_ENABLED887if (unlikely(endian < 0.0)) {888uint32_t count = new_data.size() / 4;889uint16_t *dst = (uint16_t *)new_data.ptrw();890for (uint32_t j = 0; j < count; j++) {891dst[j * 4] = BSWAP32(dst[j * 4]);892}893}894#else895if (unlikely(endian > 0.0)) {896uint32_t count = new_data.size() / 4;897uint16_t *dst = (uint16_t *)new_data.ptrw();898for (uint32_t j = 0; j < count; j++) {899dst[j * 4] = BSWAP32(dst[j * 4]);900}901}902#endif903Ref<Image> img = Image::create_from_data(new_width, new_height, false, Image::FORMAT_RGBF, new_data);904img->convert(p_shadowmask ? Image::FORMAT_RGBA8 : Image::FORMAT_RGBAH);905return img;906}907908LightmapperRD::BakeError LightmapperRD::_denoise_oidn(RenderingDevice *p_rd, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, bool p_shadowmask, const String &p_exe) {909Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);910911for (int i = 0; i < p_atlas_slices; i++) {912String fname_norm_in = EditorPaths::get_singleton()->get_cache_dir().path_join(vformat("temp_norm_%d.pfm", i));913_store_pfm(p_rd, p_source_normal_tex, i, p_atlas_size, fname_norm_in, false);914915for (int j = 0; j < (p_bake_sh ? 4 : 1); j++) {916int index = i * (p_bake_sh ? 4 : 1) + j;917String fname_light_in = EditorPaths::get_singleton()->get_cache_dir().path_join(vformat("temp_light_%d.pfm", index));918String fname_out = EditorPaths::get_singleton()->get_cache_dir().path_join(vformat("temp_denoised_%d.pfm", index));919920_store_pfm(p_rd, p_source_light_tex, index, p_atlas_size, fname_light_in, p_shadowmask);921922List<String> args;923args.push_back("--device");924args.push_back("default");925926args.push_back("--filter");927args.push_back("RTLightmap");928929args.push_back(p_shadowmask ? "--ldr" : "--hdr");930args.push_back(fname_light_in);931932args.push_back("--nrm");933args.push_back(fname_norm_in);934935args.push_back("--output");936args.push_back(fname_out);937938String str;939int exitcode = 0;940941Error err = OS::get_singleton()->execute(p_exe, args, &str, &exitcode, true);942943da->remove(fname_light_in);944945if (err != OK || exitcode != 0) {946da->remove(fname_out);947print_verbose(str);948ERR_FAIL_V_MSG(BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, vformat("OIDN denoiser failed, return code: %d", exitcode));949}950951Ref<Image> img = _read_pfm(fname_out, p_shadowmask);952da->remove(fname_out);953954ERR_FAIL_COND_V(img.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);955956Vector<uint8_t> old_data = p_rd->texture_get_data(p_source_light_tex, index);957Vector<uint8_t> new_data = img->get_data();958img.unref(); // Avoid copy on write.959960uint32_t count = old_data.size() / 2;961const uint16_t *src = (const uint16_t *)old_data.ptr();962uint16_t *dst = (uint16_t *)new_data.ptrw();963for (uint32_t k = 0; k < count; k += 4) {964dst[k + 3] = src[k + 3];965}966967p_rd->texture_update(p_dest_light_tex, index, new_data);968}969da->remove(fname_norm_in);970}971return BAKE_OK;972}973974LightmapperRD::BakeError LightmapperRD::_denoise(RenderingDevice *p_rd, Ref<RDShaderFile> &p_compute_shader, const RID &p_compute_base_uniform_set, PushConstant &p_push_constant, RID p_source_light_tex, RID p_source_normal_tex, RID p_dest_light_tex, RID p_unocclude_tex, float p_denoiser_strength, int p_denoiser_range, const Size2i &p_atlas_size, int p_atlas_slices, bool p_bake_sh, BakeStepFunc p_step_function, void *p_bake_userdata) {975RID denoise_params_buffer = p_rd->uniform_buffer_create(sizeof(DenoiseParams));976DenoiseParams denoise_params;977denoise_params.spatial_bandwidth = 5.0f;978denoise_params.light_bandwidth = p_denoiser_strength;979denoise_params.albedo_bandwidth = 1.0f;980denoise_params.normal_bandwidth = 0.1f;981denoise_params.filter_strength = 10.0f;982denoise_params.half_search_window = p_denoiser_range;983denoise_params.slice_count = p_bake_sh ? 4 : 1;984p_rd->buffer_update(denoise_params_buffer, 0, sizeof(DenoiseParams), &denoise_params);985986Vector<RD::Uniform> uniforms = dilate_or_denoise_common_uniforms(p_source_light_tex, p_dest_light_tex);987{988RD::Uniform u;989u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;990u.binding = 2;991u.append_id(p_source_normal_tex);992uniforms.push_back(u);993}994{995RD::Uniform u;996u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;997u.binding = 3;998u.append_id(p_unocclude_tex);999uniforms.push_back(u);1000}1001{1002RD::Uniform u;1003u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;1004u.binding = 4;1005u.append_id(denoise_params_buffer);1006uniforms.push_back(u);1007}10081009RID compute_shader_denoise = p_rd->shader_create_from_spirv(p_compute_shader->get_spirv_stages("denoise"));1010ERR_FAIL_COND_V(compute_shader_denoise.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);10111012RID compute_shader_denoise_pipeline = p_rd->compute_pipeline_create(compute_shader_denoise);1013RID denoise_uniform_set = p_rd->uniform_set_create(uniforms, compute_shader_denoise, 1);10141015// We denoise in fixed size regions and synchronize execution to avoid GPU timeouts.1016// We use a region with 1/4 the amount of pixels if we're denoising SH lightmaps, as1017// all four of them are denoised in the shader in one dispatch.1018const int user_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size")));1019const int max_region_size = p_bake_sh ? user_region_size / 2 : user_region_size;1020int x_regions = Math::division_round_up(p_atlas_size.width, max_region_size);1021int y_regions = Math::division_round_up(p_atlas_size.height, max_region_size);1022for (int s = 0; s < p_atlas_slices; s++) {1023p_push_constant.atlas_slice = s;10241025for (int i = 0; i < x_regions; i++) {1026for (int j = 0; j < y_regions; j++) {1027int x = i * max_region_size;1028int y = j * max_region_size;1029int w = MIN((i + 1) * max_region_size, p_atlas_size.width) - x;1030int h = MIN((j + 1) * max_region_size, p_atlas_size.height) - y;1031p_push_constant.region_ofs[0] = x;1032p_push_constant.region_ofs[1] = y;10331034RD::ComputeListID compute_list = p_rd->compute_list_begin();1035p_rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_denoise_pipeline);1036p_rd->compute_list_bind_uniform_set(compute_list, p_compute_base_uniform_set, 0);1037p_rd->compute_list_bind_uniform_set(compute_list, denoise_uniform_set, 1);1038p_rd->compute_list_set_push_constant(compute_list, &p_push_constant, sizeof(PushConstant));1039p_rd->compute_list_dispatch(compute_list, Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1);1040p_rd->compute_list_end();10411042p_rd->submit();1043p_rd->sync();1044}1045}1046if (p_step_function) {1047int percent = (s + 1) * 100 / p_atlas_slices;1048float p = float(s) / p_atlas_slices * 0.1;1049if (p_step_function(0.8 + p, vformat(RTR("Denoising %d%%"), percent), p_bake_userdata, false)) {1050return BAKE_ERROR_USER_ABORTED;1051}1052}1053}10541055p_rd->free_rid(compute_shader_denoise);1056p_rd->free_rid(denoise_params_buffer);10571058return BAKE_OK;1059}10601061LightmapperRD::BakeError LightmapperRD::bake(BakeQuality p_quality, bool p_use_denoiser, float p_denoiser_strength, int p_denoiser_range, int p_bounces, float p_bounce_indirect_energy, float p_bias, int p_max_texture_size, bool p_bake_sh, bool p_bake_shadowmask, bool p_texture_for_bounces, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function, void *p_bake_userdata, float p_exposure_normalization, float p_supersampling_factor) {1062int denoiser = GLOBAL_GET("rendering/lightmapping/denoising/denoiser");1063String oidn_path = EDITOR_GET("filesystem/tools/oidn/oidn_denoise_path");10641065if (p_use_denoiser && denoiser == 1) {1066// OIDN (external).1067Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);10681069if (da->dir_exists(oidn_path)) {1070if (OS::get_singleton()->get_name() == "Windows") {1071oidn_path = oidn_path.path_join("oidnDenoise.exe");1072} else {1073oidn_path = oidn_path.path_join("oidnDenoise");1074}1075}1076ERR_FAIL_COND_V_MSG(oidn_path.is_empty() || !da->file_exists(oidn_path), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES, "OIDN denoiser is selected in the project settings, but no or invalid OIDN executable path is configured in the editor settings.");1077}10781079if (p_step_function) {1080p_step_function(0.0, RTR("Begin Bake"), p_bake_userdata, true);1081}1082lightmap_textures.clear();1083shadowmask_textures.clear();1084int grid_size = 128;10851086/* STEP 1: Fetch material textures and compute the bounds */10871088AABB bounds;1089Size2i atlas_size;1090int atlas_slices;1091Vector<Ref<Image>> albedo_images;1092Vector<Ref<Image>> emission_images;10931094BakeError bake_error = _blit_meshes_into_atlas(p_max_texture_size, p_denoiser_range, albedo_images, emission_images, bounds, atlas_size, atlas_slices, p_supersampling_factor, p_step_function, p_bake_userdata);1095if (bake_error != BAKE_OK) {1096return bake_error;1097}10981099// Find any directional light suitable for shadowmasking.1100if (p_bake_shadowmask) {1101bool found = false;1102for (int i = 0; i < lights.size(); i++) {1103if (lights[i].type == LightType::LIGHT_TYPE_DIRECTIONAL && !lights[i].static_bake) {1104found = true;1105break;1106}1107}11081109if (!found) {1110p_bake_shadowmask = false;1111WARN_PRINT("Shadowmask disabled: no directional light with their bake mode set to dynamic exists.");1112}1113}11141115#ifdef DEBUG_TEXTURES1116for (int i = 0; i < atlas_slices; i++) {1117albedo_images[i]->save_png("res://0_albedo_" + itos(i) + ".png");1118emission_images[i]->save_png("res://0_emission_" + itos(i) + ".png");1119}1120#endif11211122// Attempt to create a local device by requesting it from rendering server first.1123// If that fails because the current renderer is not implemented on top of RD, we fall back to creating1124// a local rendering device manually depending on the current platform.1125Error err;1126RenderingContextDriver *rcd = nullptr;1127RenderingDevice *rd = RenderingServer::get_singleton()->create_local_rendering_device();1128if (rd == nullptr) {1129#if defined(RD_ENABLED)1130#if defined(METAL_ENABLED)1131rcd = memnew(RenderingContextDriverMetal);1132rd = memnew(RenderingDevice);1133#endif1134#if defined(VULKAN_ENABLED)1135if (rcd == nullptr) {1136rcd = memnew(RenderingContextDriverVulkan);1137rd = memnew(RenderingDevice);1138}1139#endif1140#endif1141if (rcd != nullptr && rd != nullptr) {1142err = rcd->initialize();1143if (err == OK) {1144err = rd->initialize(rcd);1145}11461147if (err != OK) {1148memdelete(rd);1149memdelete(rcd);1150rd = nullptr;1151rcd = nullptr;1152}1153}1154}11551156ERR_FAIL_NULL_V(rd, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);11571158RID albedo_array_tex;1159RID emission_array_tex;1160RID normal_tex;1161RID position_tex;1162RID unocclude_tex;1163RID light_source_tex;1164RID light_dest_tex;1165RID light_accum_tex;1166RID light_accum_tex2;1167RID light_environment_tex;1168RID shadowmask_tex;1169RID shadowmask_tex2;11701171#define FREE_TEXTURES \1172rd->free_rid(albedo_array_tex); \1173rd->free_rid(emission_array_tex); \1174rd->free_rid(normal_tex); \1175rd->free_rid(position_tex); \1176rd->free_rid(unocclude_tex); \1177rd->free_rid(light_source_tex); \1178rd->free_rid(light_accum_tex2); \1179rd->free_rid(light_accum_tex); \1180rd->free_rid(light_environment_tex); \1181if (p_bake_shadowmask) { \1182rd->free_rid(shadowmask_tex); \1183rd->free_rid(shadowmask_tex2); \1184}11851186{ // create all textures11871188Vector<Vector<uint8_t>> albedo_data;1189Vector<Vector<uint8_t>> emission_data;1190for (int i = 0; i < atlas_slices; i++) {1191albedo_data.push_back(albedo_images[i]->get_data());1192emission_data.push_back(emission_images[i]->get_data());1193}11941195RD::TextureFormat tf;1196tf.width = atlas_size.width;1197tf.height = atlas_size.height;1198tf.array_layers = atlas_slices;1199tf.texture_type = RD::TEXTURE_TYPE_2D_ARRAY;1200tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;1201tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;12021203albedo_array_tex = rd->texture_create(tf, RD::TextureView(), albedo_data);12041205tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;12061207emission_array_tex = rd->texture_create(tf, RD::TextureView(), emission_data);12081209//this will be rastered to1210tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;1211normal_tex = rd->texture_create(tf, RD::TextureView());1212tf.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;1213position_tex = rd->texture_create(tf, RD::TextureView());1214unocclude_tex = rd->texture_create(tf, RD::TextureView());12151216tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;12171218// shadowmask1219if (p_bake_shadowmask) {1220tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM;12211222shadowmask_tex = rd->texture_create(tf, RD::TextureView());1223rd->texture_clear(shadowmask_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices);12241225shadowmask_tex2 = rd->texture_create(tf, RD::TextureView());1226rd->texture_clear(shadowmask_tex2, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices);1227}12281229// lightmap1230tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT;12311232light_source_tex = rd->texture_create(tf, RD::TextureView());1233rd->texture_clear(light_source_tex, Color(0, 0, 0, 0), 0, 1, 0, atlas_slices);12341235if (p_bake_sh) {1236tf.array_layers *= 4;1237}1238light_accum_tex = rd->texture_create(tf, RD::TextureView());1239rd->texture_clear(light_accum_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers);1240light_dest_tex = rd->texture_create(tf, RD::TextureView());1241rd->texture_clear(light_dest_tex, Color(0, 0, 0, 0), 0, 1, 0, tf.array_layers);1242light_accum_tex2 = light_dest_tex;12431244//env1245{1246Ref<Image> panorama_tex;1247if (p_environment_panorama.is_valid()) {1248panorama_tex = p_environment_panorama;1249panorama_tex->convert(Image::FORMAT_RGBAF);1250} else {1251panorama_tex.instantiate();1252panorama_tex->initialize_data(8, 8, false, Image::FORMAT_RGBAF);1253panorama_tex->fill(Color(0, 0, 0, 1));1254}12551256RD::TextureFormat tfp;1257tfp.width = panorama_tex->get_width();1258tfp.height = panorama_tex->get_height();1259tfp.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT;1260tfp.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT;12611262Vector<Vector<uint8_t>> tdata;1263tdata.push_back(panorama_tex->get_data());1264light_environment_tex = rd->texture_create(tfp, RD::TextureView(), tdata);12651266#ifdef DEBUG_TEXTURES1267panorama_tex->save_exr("res://0_panorama.exr", false);1268#endif1269}1270}12711272/* STEP 2: create the acceleration structure for the GPU*/12731274Vector<int> slice_triangle_count;1275RID bake_parameters_buffer;1276RID vertex_buffer;1277RID triangle_buffer;1278RID lights_buffer;1279RID triangle_indices_buffer;1280RID cluster_indices_buffer;1281RID cluster_aabbs_buffer;1282RID grid_texture;1283RID seams_buffer;1284RID probe_positions_buffer;12851286Vector<int> slice_seam_count;12871288#define FREE_BUFFERS \1289rd->free_rid(bake_parameters_buffer); \1290rd->free_rid(vertex_buffer); \1291rd->free_rid(triangle_buffer); \1292rd->free_rid(lights_buffer); \1293rd->free_rid(triangle_indices_buffer); \1294rd->free_rid(cluster_indices_buffer); \1295rd->free_rid(cluster_aabbs_buffer); \1296rd->free_rid(grid_texture); \1297rd->free_rid(seams_buffer); \1298rd->free_rid(probe_positions_buffer);12991300const uint32_t cluster_size = 16;1301_create_acceleration_structures(rd, atlas_size, atlas_slices, bounds, grid_size, cluster_size, probe_positions, p_generate_probes, slice_triangle_count, slice_seam_count, vertex_buffer, triangle_buffer, lights_buffer, triangle_indices_buffer, cluster_indices_buffer, cluster_aabbs_buffer, probe_positions_buffer, grid_texture, seams_buffer, p_step_function, p_bake_userdata);13021303// The index of the directional light used for shadowmasking.1304int shadowmask_light_idx = -1;13051306// Find the directional light index in the sorted lights array.1307if (p_bake_shadowmask) {1308int shadowmask_lights_count = 0;13091310for (int i = 0; i < lights.size(); i++) {1311if (lights[i].type == LightType::LIGHT_TYPE_DIRECTIONAL && !lights[i].static_bake) {1312if (shadowmask_light_idx < 0) {1313shadowmask_light_idx = i;1314}1315shadowmask_lights_count += 1;1316}1317}13181319if (shadowmask_lights_count > 1) {1320WARN_PRINT(1321vformat("%d directional lights detected for shadowmask baking. Only %s will be used.",1322shadowmask_lights_count, light_metadata[shadowmask_light_idx].name));1323}1324}13251326// Create global bake parameters buffer.1327BakeParameters bake_parameters;1328bake_parameters.world_size[0] = bounds.size.x;1329bake_parameters.world_size[1] = bounds.size.y;1330bake_parameters.world_size[2] = bounds.size.z;1331bake_parameters.bias = p_bias;1332bake_parameters.to_cell_offset[0] = bounds.position.x;1333bake_parameters.to_cell_offset[1] = bounds.position.y;1334bake_parameters.to_cell_offset[2] = bounds.position.z;1335bake_parameters.grid_size = grid_size;1336bake_parameters.to_cell_size[0] = (1.0 / bounds.size.x) * float(grid_size);1337bake_parameters.to_cell_size[1] = (1.0 / bounds.size.y) * float(grid_size);1338bake_parameters.to_cell_size[2] = (1.0 / bounds.size.z) * float(grid_size);1339bake_parameters.light_count = lights.size();1340bake_parameters.env_transform[0] = p_environment_transform.rows[0][0];1341bake_parameters.env_transform[1] = p_environment_transform.rows[1][0];1342bake_parameters.env_transform[2] = p_environment_transform.rows[2][0];1343bake_parameters.env_transform[3] = 0.0f;1344bake_parameters.env_transform[4] = p_environment_transform.rows[0][1];1345bake_parameters.env_transform[5] = p_environment_transform.rows[1][1];1346bake_parameters.env_transform[6] = p_environment_transform.rows[2][1];1347bake_parameters.env_transform[7] = 0.0f;1348bake_parameters.env_transform[8] = p_environment_transform.rows[0][2];1349bake_parameters.env_transform[9] = p_environment_transform.rows[1][2];1350bake_parameters.env_transform[10] = p_environment_transform.rows[2][2];1351bake_parameters.env_transform[11] = 0.0f;1352bake_parameters.atlas_size[0] = atlas_size.width;1353bake_parameters.atlas_size[1] = atlas_size.height;1354bake_parameters.exposure_normalization = p_exposure_normalization;1355bake_parameters.bounces = p_bounces;1356bake_parameters.bounce_indirect_energy = p_bounce_indirect_energy;1357bake_parameters.shadowmask_light_idx = shadowmask_light_idx;1358// Same number of rays for transparency regardless of quality (it's more of a retry rather than shooting new ones).1359bake_parameters.transparency_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_transparency_rays");1360bake_parameters.supersampling_factor = p_supersampling_factor;13611362bake_parameters_buffer = rd->uniform_buffer_create(sizeof(BakeParameters));1363rd->buffer_update(bake_parameters_buffer, 0, sizeof(BakeParameters), &bake_parameters);13641365if (p_step_function) {1366if (p_step_function(0.47, RTR("Preparing shaders"), p_bake_userdata, true)) {1367FREE_TEXTURES1368FREE_BUFFERS1369memdelete(rd);1370if (rcd != nullptr) {1371memdelete(rcd);1372}1373return BAKE_ERROR_USER_ABORTED;1374}1375}13761377//shaders1378Ref<RDShaderFile> raster_shader;1379raster_shader.instantiate();1380err = raster_shader->parse_versions_from_text(lm_raster_shader_glsl);1381if (err != OK) {1382raster_shader->print_errors("raster_shader");13831384FREE_TEXTURES1385FREE_BUFFERS13861387memdelete(rd);13881389if (rcd != nullptr) {1390memdelete(rcd);1391}1392}1393ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);13941395RID rasterize_shader = rd->shader_create_from_spirv(raster_shader->get_spirv_stages());13961397ERR_FAIL_COND_V(rasterize_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //this is a bug check, though, should not happen13981399RID sampler;1400{1401RD::SamplerState s;1402s.mag_filter = RD::SAMPLER_FILTER_LINEAR;1403s.min_filter = RD::SAMPLER_FILTER_LINEAR;1404s.max_lod = 0;14051406sampler = rd->sampler_create(s);1407}14081409Vector<RD::Uniform> base_uniforms;1410{1411{1412RD::Uniform u;1413u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER;1414u.binding = 0;1415u.append_id(bake_parameters_buffer);1416base_uniforms.push_back(u);1417}1418{1419RD::Uniform u;1420u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1421u.binding = 1;1422u.append_id(vertex_buffer);1423base_uniforms.push_back(u);1424}1425{1426RD::Uniform u;1427u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1428u.binding = 2;1429u.append_id(triangle_buffer);1430base_uniforms.push_back(u);1431}1432{1433RD::Uniform u;1434u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1435u.binding = 3;1436u.append_id(triangle_indices_buffer);1437base_uniforms.push_back(u);1438}1439{1440RD::Uniform u;1441u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1442u.binding = 4;1443u.append_id(lights_buffer);1444base_uniforms.push_back(u);1445}1446{1447RD::Uniform u;1448u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1449u.binding = 5;1450u.append_id(seams_buffer);1451base_uniforms.push_back(u);1452}1453{1454RD::Uniform u;1455u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1456u.binding = 6;1457u.append_id(probe_positions_buffer);1458base_uniforms.push_back(u);1459}1460{1461RD::Uniform u;1462u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1463u.binding = 7;1464u.append_id(grid_texture);1465base_uniforms.push_back(u);1466}1467{1468RD::Uniform u;1469u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1470u.binding = 8;1471u.append_id(albedo_array_tex);1472base_uniforms.push_back(u);1473}1474{1475RD::Uniform u;1476u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1477u.binding = 9;1478u.append_id(emission_array_tex);1479base_uniforms.push_back(u);1480}1481{1482RD::Uniform u;1483u.uniform_type = RD::UNIFORM_TYPE_SAMPLER;1484u.binding = 10;1485u.append_id(sampler);1486base_uniforms.push_back(u);1487}1488{1489RD::Uniform u;1490u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1491u.binding = 11;1492u.append_id(cluster_indices_buffer);1493base_uniforms.push_back(u);1494}1495{1496RD::Uniform u;1497u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1498u.binding = 12;1499u.append_id(cluster_aabbs_buffer);1500base_uniforms.push_back(u);1501}1502}15031504RID raster_base_uniform = rd->uniform_set_create(base_uniforms, rasterize_shader, 0);1505RID raster_depth_buffer;1506{1507RD::TextureFormat tf;1508tf.width = atlas_size.width;1509tf.height = atlas_size.height;1510tf.depth = 1;1511tf.texture_type = RD::TEXTURE_TYPE_2D;1512tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;1513tf.format = RD::DATA_FORMAT_D32_SFLOAT;1514tf.is_discardable = true;15151516raster_depth_buffer = rd->texture_create(tf, RD::TextureView());1517}15181519rd->submit();1520rd->sync();15211522/* STEP 3: Raster the geometry to UV2 coords in the atlas textures GPU*/15231524_raster_geometry(rd, atlas_size, atlas_slices, grid_size, bounds, p_bias, slice_triangle_count, position_tex, unocclude_tex, normal_tex, raster_depth_buffer, rasterize_shader, raster_base_uniform);15251526#ifdef DEBUG_TEXTURES15271528for (int i = 0; i < atlas_slices; i++) {1529Vector<uint8_t> s = rd->texture_get_data(position_tex, i);1530Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s);1531img->save_exr("res://1_position_" + itos(i) + ".exr", false);15321533s = rd->texture_get_data(normal_tex, i);1534img->set_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);1535img->save_exr("res://1_normal_" + itos(i) + ".exr", false);1536}1537#endif15381539#define FREE_RASTER_RESOURCES \1540rd->free_rid(rasterize_shader); \1541rd->free_rid(sampler); \1542rd->free_rid(raster_depth_buffer);15431544/* Plot direct light */15451546Ref<RDShaderFile> compute_shader;1547String defines = "";1548defines += "\n#define CLUSTER_SIZE " + uitos(cluster_size) + "\n";15491550if (p_bake_sh) {1551defines += "\n#define USE_SH_LIGHTMAPS\n";1552}15531554if (p_texture_for_bounces) {1555defines += "\n#define USE_LIGHT_TEXTURE_FOR_BOUNCES\n";1556}15571558if (p_bake_shadowmask) {1559defines += "\n#define USE_SHADOWMASK\n";1560}15611562compute_shader.instantiate();1563err = compute_shader->parse_versions_from_text(lm_compute_shader_glsl, defines);1564if (err != OK) {1565FREE_TEXTURES1566FREE_BUFFERS1567FREE_RASTER_RESOURCES1568memdelete(rd);15691570if (rcd != nullptr) {1571memdelete(rcd);1572}15731574compute_shader->print_errors("compute_shader");1575}1576ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);15771578// Unoccluder1579RID compute_shader_unocclude = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("unocclude"));1580ERR_FAIL_COND_V(compute_shader_unocclude.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen1581RID compute_shader_unocclude_pipeline = rd->compute_pipeline_create(compute_shader_unocclude);15821583// Direct light1584RID compute_shader_primary = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("primary"));1585ERR_FAIL_COND_V(compute_shader_primary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); // internal check, should not happen1586RID compute_shader_primary_pipeline = rd->compute_pipeline_create(compute_shader_primary);15871588// Indirect light1589RID compute_shader_secondary = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("secondary"));1590ERR_FAIL_COND_V(compute_shader_secondary.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen1591RID compute_shader_secondary_pipeline = rd->compute_pipeline_create(compute_shader_secondary);15921593// Light probes1594RID compute_shader_light_probes = rd->shader_create_from_spirv(compute_shader->get_spirv_stages("light_probes"));1595ERR_FAIL_COND_V(compute_shader_light_probes.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES); //internal check, should not happen1596RID compute_shader_light_probes_pipeline = rd->compute_pipeline_create(compute_shader_light_probes);15971598RID compute_base_uniform_set = rd->uniform_set_create(base_uniforms, compute_shader_primary, 0);15991600#define FREE_COMPUTE_RESOURCES \1601rd->free_rid(compute_shader_unocclude); \1602rd->free_rid(compute_shader_primary); \1603rd->free_rid(compute_shader_secondary); \1604rd->free_rid(compute_shader_light_probes);16051606Vector3i group_size(Math::division_round_up(atlas_size.x, 8), Math::division_round_up(atlas_size.y, 8), 1);1607rd->submit();1608rd->sync();16091610if (p_step_function) {1611if (p_step_function(0.49, RTR("Un-occluding geometry"), p_bake_userdata, true)) {1612FREE_TEXTURES1613FREE_BUFFERS1614FREE_RASTER_RESOURCES1615FREE_COMPUTE_RESOURCES1616memdelete(rd);1617if (rcd != nullptr) {1618memdelete(rcd);1619}1620return BAKE_ERROR_USER_ABORTED;1621}1622}16231624PushConstant push_constant;1625push_constant.denoiser_range = p_use_denoiser ? p_denoiser_range : 1.0;16261627/* UNOCCLUDE */1628{1629Vector<RD::Uniform> uniforms;1630{1631{1632RD::Uniform u;1633u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1634u.binding = 0;1635u.append_id(position_tex);1636uniforms.push_back(u);1637}1638{1639RD::Uniform u;1640u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1641u.binding = 1;1642u.append_id(unocclude_tex);1643uniforms.push_back(u);1644}1645}16461647RID unocclude_uniform_set = rd->uniform_set_create(uniforms, compute_shader_unocclude, 1);16481649RD::ComputeListID compute_list = rd->compute_list_begin();1650rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_unocclude_pipeline);1651rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);1652rd->compute_list_bind_uniform_set(compute_list, unocclude_uniform_set, 1);16531654for (int i = 0; i < atlas_slices; i++) {1655push_constant.atlas_slice = i;1656rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));1657rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z);1658//no barrier, let them run all together1659}1660rd->compute_list_end(); //done1661}16621663#ifdef DEBUG_TEXTURES1664for (int i = 0; i < atlas_slices; i++) {1665Vector<uint8_t> s = rd->texture_get_data(unocclude_tex, i);1666Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAF, s);1667img->save_exr("res://1_unocclude_" + itos(i) + ".exr", false);1668}1669#endif16701671if (p_step_function) {1672if (p_step_function(0.5, RTR("Plot direct lighting"), p_bake_userdata, true)) {1673FREE_TEXTURES1674FREE_BUFFERS1675FREE_RASTER_RESOURCES1676FREE_COMPUTE_RESOURCES1677memdelete(rd);1678if (rcd != nullptr) {1679memdelete(rcd);1680}1681return BAKE_ERROR_USER_ABORTED;1682}1683}16841685const int max_region_size = nearest_power_of_2_templated(int(GLOBAL_GET("rendering/lightmapping/bake_performance/region_size")));1686const int x_regions = Math::division_round_up(atlas_size.width, max_region_size);1687const int y_regions = Math::division_round_up(atlas_size.height, max_region_size);16881689// Set ray count to the quality used for direct light and bounces.1690switch (p_quality) {1691case BAKE_QUALITY_LOW: {1692push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/low_quality_ray_count");1693} break;1694case BAKE_QUALITY_MEDIUM: {1695push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/medium_quality_ray_count");1696} break;1697case BAKE_QUALITY_HIGH: {1698push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/high_quality_ray_count");1699} break;1700case BAKE_QUALITY_ULTRA: {1701push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/ultra_quality_ray_count");1702} break;1703}17041705push_constant.ray_count = CLAMP(push_constant.ray_count, 16u, 8192u);17061707/* PRIMARY (direct) LIGHT PASS */1708{1709Vector<RD::Uniform> uniforms;1710{1711{1712RD::Uniform u;1713u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1714u.binding = 0;1715u.append_id(light_source_tex);1716uniforms.push_back(u);1717}1718{1719RD::Uniform u;1720u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1721u.binding = 1;1722u.append_id(light_dest_tex); //will be unused1723uniforms.push_back(u);1724}1725{1726RD::Uniform u;1727u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1728u.binding = 2;1729u.append_id(position_tex);1730uniforms.push_back(u);1731}1732{1733RD::Uniform u;1734u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1735u.binding = 3;1736u.append_id(normal_tex);1737uniforms.push_back(u);1738}1739{1740RD::Uniform u;1741u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1742u.binding = 4;1743u.append_id(light_accum_tex);1744uniforms.push_back(u);1745}17461747if (p_bake_shadowmask) {1748RD::Uniform u;1749u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1750u.binding = 5;1751u.append_id(shadowmask_tex);1752uniforms.push_back(u);1753}1754}17551756RID light_uniform_set = rd->uniform_set_create(uniforms, compute_shader_primary, 1);17571758int count = 0;1759for (int s = 0; s < atlas_slices; s++) {1760push_constant.atlas_slice = s;17611762for (int i = 0; i < x_regions; i++) {1763for (int j = 0; j < y_regions; j++) {1764int x = i * max_region_size;1765int y = j * max_region_size;1766int w = MIN((i + 1) * max_region_size, atlas_size.width) - x;1767int h = MIN((j + 1) * max_region_size, atlas_size.height) - y;17681769push_constant.region_ofs[0] = x;1770push_constant.region_ofs[1] = y;17711772group_size = Vector3i(Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1);1773RD::ComputeListID compute_list = rd->compute_list_begin();1774rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_primary_pipeline);1775rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);1776rd->compute_list_bind_uniform_set(compute_list, light_uniform_set, 1);1777rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));1778rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z);1779rd->compute_list_end();17801781rd->submit();1782rd->sync();17831784count++;1785if (p_step_function) {1786int total = (atlas_slices * x_regions * y_regions);1787int percent = count * 100 / total;1788float p = float(count) / total * 0.1;1789if (p_step_function(0.5 + p, vformat(RTR("Plot direct lighting %d%%"), percent), p_bake_userdata, false)) {1790FREE_TEXTURES1791FREE_BUFFERS1792FREE_RASTER_RESOURCES1793FREE_COMPUTE_RESOURCES1794memdelete(rd);1795if (rcd != nullptr) {1796memdelete(rcd);1797}1798return BAKE_ERROR_USER_ABORTED;1799}1800}1801}1802}1803}1804}18051806#ifdef DEBUG_TEXTURES18071808for (int i = 0; i < atlas_slices; i++) {1809Vector<uint8_t> s = rd->texture_get_data(light_source_tex, i);1810Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);1811img->save_exr("res://2_light_primary_" + itos(i) + ".exr", false);1812}18131814if (p_bake_sh) {1815for (int i = 0; i < atlas_slices * 4; i++) {1816Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);1817Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);1818img->save_exr("res://2_light_primary_accum_" + itos(i) + ".exr", false);1819}1820}1821#endif18221823/* SECONDARY (indirect) LIGHT PASS(ES) */18241825if (p_bounces > 0) {1826Vector<RD::Uniform> uniforms;1827{1828{1829// Unused.1830RD::Uniform u;1831u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1832u.binding = 0;1833u.append_id(light_dest_tex);1834uniforms.push_back(u);1835}1836{1837RD::Uniform u;1838u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1839u.binding = 1;1840u.append_id(light_source_tex);1841uniforms.push_back(u);1842}1843{1844RD::Uniform u;1845u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1846u.binding = 2;1847u.append_id(position_tex);1848uniforms.push_back(u);1849}1850{1851RD::Uniform u;1852u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1853u.binding = 3;1854u.append_id(normal_tex);1855uniforms.push_back(u);1856}1857{1858RD::Uniform u;1859u.uniform_type = RD::UNIFORM_TYPE_IMAGE;1860u.binding = 4;1861u.append_id(light_accum_tex);1862uniforms.push_back(u);1863}1864{1865RD::Uniform u;1866u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1867u.binding = 5;1868u.append_id(light_environment_tex);1869uniforms.push_back(u);1870}1871}18721873RID secondary_uniform_set;1874secondary_uniform_set = rd->uniform_set_create(uniforms, compute_shader_secondary, 1);18751876const int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_pass");1877int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays);18781879if (p_step_function) {1880if (p_step_function(0.6, RTR("Integrate indirect lighting"), p_bake_userdata, true)) {1881FREE_TEXTURES1882FREE_BUFFERS1883FREE_RASTER_RESOURCES1884FREE_COMPUTE_RESOURCES1885memdelete(rd);1886if (rcd != nullptr) {1887memdelete(rcd);1888}1889return BAKE_ERROR_USER_ABORTED;1890}1891}18921893int count = 0;1894for (int s = 0; s < atlas_slices; s++) {1895push_constant.atlas_slice = s;18961897for (int i = 0; i < x_regions; i++) {1898for (int j = 0; j < y_regions; j++) {1899int x = i * max_region_size;1900int y = j * max_region_size;1901int w = MIN((i + 1) * max_region_size, atlas_size.width) - x;1902int h = MIN((j + 1) * max_region_size, atlas_size.height) - y;19031904push_constant.region_ofs[0] = x;1905push_constant.region_ofs[1] = y;19061907group_size = Vector3i(Math::division_round_up(w, 8), Math::division_round_up(h, 8), 1);19081909for (int k = 0; k < ray_iterations; k++) {1910RD::ComputeListID compute_list = rd->compute_list_begin();1911rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_secondary_pipeline);1912rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);1913rd->compute_list_bind_uniform_set(compute_list, secondary_uniform_set, 1);19141915push_constant.ray_from = k * max_rays;1916push_constant.ray_to = MIN((k + 1) * max_rays, int32_t(push_constant.ray_count));1917rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));1918rd->compute_list_dispatch(compute_list, group_size.x, group_size.y, group_size.z);19191920rd->compute_list_end();1921rd->submit();1922rd->sync();19231924count++;1925if (p_step_function) {1926int total = (atlas_slices * x_regions * y_regions * ray_iterations);1927int percent = count * 100 / total;1928float p = float(count) / total * 0.1;1929if (p_step_function(0.6 + p, vformat(RTR("Integrate indirect lighting %d%%"), percent), p_bake_userdata, false)) {1930FREE_TEXTURES1931FREE_BUFFERS1932FREE_RASTER_RESOURCES1933FREE_COMPUTE_RESOURCES1934memdelete(rd);1935if (rcd != nullptr) {1936memdelete(rcd);1937}1938return BAKE_ERROR_USER_ABORTED;1939}1940}1941}1942}1943}1944}1945}19461947/* LIGHTPROBES */19481949RID light_probe_buffer;19501951if (probe_positions.size()) {1952light_probe_buffer = rd->storage_buffer_create(sizeof(float) * 4 * 9 * probe_positions.size());19531954if (p_step_function) {1955if (p_step_function(0.7, RTR("Baking light probes"), p_bake_userdata, true)) {1956FREE_TEXTURES1957FREE_BUFFERS1958FREE_RASTER_RESOURCES1959FREE_COMPUTE_RESOURCES1960if (probe_positions.size() > 0) {1961rd->free_rid(light_probe_buffer);1962}1963memdelete(rd);1964if (rcd != nullptr) {1965memdelete(rcd);1966}1967return BAKE_ERROR_USER_ABORTED;1968}1969}19701971Vector<RD::Uniform> uniforms;1972{1973{1974RD::Uniform u;1975u.uniform_type = RD::UNIFORM_TYPE_STORAGE_BUFFER;1976u.binding = 0;1977u.append_id(light_probe_buffer);1978uniforms.push_back(u);1979}1980{1981RD::Uniform u;1982u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1983u.binding = 1;1984u.append_id(light_source_tex);1985uniforms.push_back(u);1986}1987{1988RD::Uniform u;1989u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;1990u.binding = 2;1991u.append_id(light_environment_tex);1992uniforms.push_back(u);1993}1994}1995RID light_probe_uniform_set = rd->uniform_set_create(uniforms, compute_shader_light_probes, 1);19961997switch (p_quality) {1998case BAKE_QUALITY_LOW: {1999push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/low_quality_probe_ray_count");2000} break;2001case BAKE_QUALITY_MEDIUM: {2002push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/medium_quality_probe_ray_count");2003} break;2004case BAKE_QUALITY_HIGH: {2005push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/high_quality_probe_ray_count");2006} break;2007case BAKE_QUALITY_ULTRA: {2008push_constant.ray_count = GLOBAL_GET("rendering/lightmapping/bake_quality/ultra_quality_probe_ray_count");2009} break;2010}20112012push_constant.ray_count = CLAMP(push_constant.ray_count, 16u, 8192u);2013push_constant.probe_count = probe_positions.size();20142015int max_rays = GLOBAL_GET("rendering/lightmapping/bake_performance/max_rays_per_probe_pass");2016int ray_iterations = Math::division_round_up((int32_t)push_constant.ray_count, max_rays);20172018for (int i = 0; i < ray_iterations; i++) {2019RD::ComputeListID compute_list = rd->compute_list_begin();2020rd->compute_list_bind_compute_pipeline(compute_list, compute_shader_light_probes_pipeline);2021rd->compute_list_bind_uniform_set(compute_list, compute_base_uniform_set, 0);2022rd->compute_list_bind_uniform_set(compute_list, light_probe_uniform_set, 1);20232024push_constant.ray_from = i * max_rays;2025push_constant.ray_to = MIN((i + 1) * max_rays, int32_t(push_constant.ray_count));2026rd->compute_list_set_push_constant(compute_list, &push_constant, sizeof(PushConstant));2027rd->compute_list_dispatch(compute_list, Math::division_round_up((int)probe_positions.size(), 64), 1, 1);20282029rd->compute_list_end(); //done2030rd->submit();2031rd->sync();20322033if (p_step_function) {2034int percent = i * 100 / ray_iterations;2035float p = float(i) / ray_iterations * 0.1;2036if (p_step_function(0.7 + p, vformat(RTR("Integrating light probes %d%%"), percent), p_bake_userdata, false)) {2037FREE_TEXTURES2038FREE_BUFFERS2039FREE_RASTER_RESOURCES2040FREE_COMPUTE_RESOURCES2041if (probe_positions.size() > 0) {2042rd->free_rid(light_probe_buffer);2043}2044memdelete(rd);2045if (rcd != nullptr) {2046memdelete(rcd);2047}2048return BAKE_ERROR_USER_ABORTED;2049}2050}2051}2052}20532054#if 02055for (int i = 0; i < probe_positions.size(); i++) {2056Ref<Image> img = Image::create_empty(6, 4, false, Image::FORMAT_RGB8);2057for (int j = 0; j < 6; j++) {2058Vector<uint8_t> s = rd->texture_get_data(lightprobe_tex, i * 6 + j);2059Ref<Image> img2 = Image::create_from_data(2, 2, false, Image::FORMAT_RGBAF, s);2060img2->convert(Image::FORMAT_RGB8);2061img->blit_rect(img2, Rect2i(0, 0, 2, 2), Point2i((j % 3) * 2, (j / 3) * 2));2062}2063img->save_png("res://3_light_probe_" + itos(i) + ".png");2064}2065#endif20662067/* DENOISE */20682069if (p_bake_sh) {2070SWAP(light_accum_tex, light_accum_tex2);2071BakeError error = _pack_l1(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices);2072if (unlikely(error != BAKE_OK)) {2073return error;2074}2075}20762077if (p_use_denoiser) {2078if (p_step_function) {2079if (p_step_function(0.8, RTR("Denoising"), p_bake_userdata, true)) {2080FREE_TEXTURES2081FREE_BUFFERS2082FREE_RASTER_RESOURCES2083FREE_COMPUTE_RESOURCES2084if (probe_positions.size() > 0) {2085rd->free_rid(light_probe_buffer);2086}2087memdelete(rd);2088if (rcd != nullptr) {2089memdelete(rcd);2090}2091return BAKE_ERROR_USER_ABORTED;2092}2093}20942095{2096BakeError error;2097if (denoiser == 1) {2098// OIDN (external).2099error = _denoise_oidn(rd, light_accum_tex, normal_tex, light_accum_tex, atlas_size, atlas_slices, p_bake_sh, false, oidn_path);2100} else {2101// JNLM (built-in).2102SWAP(light_accum_tex, light_accum_tex2);2103error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, normal_tex, light_accum_tex, unocclude_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, p_bake_sh, p_step_function, p_bake_userdata);2104}2105if (unlikely(error != BAKE_OK)) {2106return error;2107}2108}21092110if (p_bake_shadowmask) {2111BakeError error;2112if (denoiser == 1) {2113// OIDN (external).2114error = _denoise_oidn(rd, shadowmask_tex, normal_tex, shadowmask_tex, atlas_size, atlas_slices, false, true, oidn_path);2115} else {2116// JNLM (built-in).2117SWAP(shadowmask_tex, shadowmask_tex2);2118error = _denoise(rd, compute_shader, compute_base_uniform_set, push_constant, shadowmask_tex2, normal_tex, shadowmask_tex, unocclude_tex, p_denoiser_strength, p_denoiser_range, atlas_size, atlas_slices, false, p_step_function, p_bake_userdata);2119}2120if (unlikely(error != BAKE_OK)) {2121return error;2122}2123}2124}21252126/* DILATE */21272128{2129SWAP(light_accum_tex, light_accum_tex2);2130BakeError error = _dilate(rd, compute_shader, compute_base_uniform_set, push_constant, light_accum_tex2, light_accum_tex, atlas_size, atlas_slices * (p_bake_sh ? 4 : 1));2131if (unlikely(error != BAKE_OK)) {2132return error;2133}21342135if (p_bake_shadowmask) {2136SWAP(shadowmask_tex, shadowmask_tex2);2137error = _dilate(rd, compute_shader, compute_base_uniform_set, push_constant, shadowmask_tex2, shadowmask_tex, atlas_size, atlas_slices);2138if (unlikely(error != BAKE_OK)) {2139return error;2140}2141}2142}21432144#ifdef DEBUG_TEXTURES21452146for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) {2147Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);2148Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);2149img->save_exr("res://4_light_secondary_" + itos(i) + ".exr", false);2150}2151#endif21522153/* BLEND SEAMS */2154//shaders2155Ref<RDShaderFile> blendseams_shader;2156blendseams_shader.instantiate();2157err = blendseams_shader->parse_versions_from_text(lm_blendseams_shader_glsl);2158if (err != OK) {2159FREE_TEXTURES2160FREE_BUFFERS2161FREE_RASTER_RESOURCES2162FREE_COMPUTE_RESOURCES2163memdelete(rd);21642165if (rcd != nullptr) {2166memdelete(rcd);2167}21682169blendseams_shader->print_errors("blendseams_shader");2170}2171ERR_FAIL_COND_V(err != OK, BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);21722173RID blendseams_line_raster_shader = rd->shader_create_from_spirv(blendseams_shader->get_spirv_stages("lines"));21742175ERR_FAIL_COND_V(blendseams_line_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);21762177RID blendseams_triangle_raster_shader = rd->shader_create_from_spirv(blendseams_shader->get_spirv_stages("triangles"));21782179ERR_FAIL_COND_V(blendseams_triangle_raster_shader.is_null(), BAKE_ERROR_LIGHTMAP_CANT_PRE_BAKE_MESHES);21802181#define FREE_BLENDSEAMS_RESOURCES \2182rd->free_rid(blendseams_line_raster_shader); \2183rd->free_rid(blendseams_triangle_raster_shader);21842185{2186//pre copy2187for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) {2188rd->texture_copy(light_accum_tex, light_accum_tex2, Vector3(), Vector3(), Vector3(atlas_size.width, atlas_size.height, 1), 0, 0, i, i);2189}21902191Vector<RID> framebuffers;2192for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) {2193RID slice_tex = rd->texture_create_shared_from_slice(RD::TextureView(), light_accum_tex, i, 0);2194Vector<RID> fb;2195fb.push_back(slice_tex);2196fb.push_back(raster_depth_buffer);2197framebuffers.push_back(rd->framebuffer_create(fb));2198}21992200Vector<RD::Uniform> uniforms;2201{2202{2203RD::Uniform u;2204u.uniform_type = RD::UNIFORM_TYPE_TEXTURE;2205u.binding = 0;2206u.append_id(light_accum_tex2);2207uniforms.push_back(u);2208}2209}22102211RID blendseams_raster_uniform = rd->uniform_set_create(uniforms, blendseams_line_raster_shader, 1);22122213bool debug = false;2214RD::PipelineColorBlendState bs = RD::PipelineColorBlendState::create_blend(1);2215bs.attachments.write[0].src_alpha_blend_factor = RD::BLEND_FACTOR_ZERO;2216bs.attachments.write[0].dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE;22172218RD::PipelineDepthStencilState ds;2219ds.enable_depth_test = true;2220ds.enable_depth_write = true;2221ds.depth_compare_operator = RD::COMPARE_OP_LESS; //so it does not render same pixel twice, this avoids wrong blending22222223RID blendseams_line_raster_pipeline = rd->render_pipeline_create(blendseams_line_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_LINES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0);2224RID blendseams_triangle_raster_pipeline = rd->render_pipeline_create(blendseams_triangle_raster_shader, rd->framebuffer_get_format(framebuffers[0]), RD::INVALID_FORMAT_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), ds, bs, 0);22252226uint32_t seam_offset = 0;2227uint32_t triangle_offset = 0;22282229for (int i = 0; i < atlas_slices; i++) {2230int subslices = (p_bake_sh ? 4 : 1);22312232if (slice_seam_count[i] == 0) {2233continue;2234}22352236for (int k = 0; k < subslices; k++) {2237RasterSeamsPushConstant seams_push_constant;2238seams_push_constant.slice = uint32_t(i * subslices + k);2239seams_push_constant.debug = debug;22402241// Store the current subslice in the breadcrumb.2242RD::DrawListID draw_list = rd->draw_list_begin(framebuffers[i * subslices + k], RD::DRAW_CLEAR_DEPTH, Vector<Color>(), 1.0f, 0, Rect2(), RDD::BreadcrumbMarker::LIGHTMAPPER_PASS | seams_push_constant.slice);22432244rd->draw_list_bind_uniform_set(draw_list, raster_base_uniform, 0);2245rd->draw_list_bind_uniform_set(draw_list, blendseams_raster_uniform, 1);22462247const int uv_offset_count = 9;2248static const Vector3 uv_offsets[uv_offset_count] = {2249Vector3(0, 0, 0.5), //using zbuffer, so go inwards-outwards2250Vector3(0, 1, 0.2),2251Vector3(0, -1, 0.2),2252Vector3(1, 0, 0.2),2253Vector3(-1, 0, 0.2),2254Vector3(-1, -1, 0.1),2255Vector3(1, -1, 0.1),2256Vector3(1, 1, 0.1),2257Vector3(-1, 1, 0.1),2258};22592260/* step 1 use lines to blend the edges */2261{2262seams_push_constant.base_index = seam_offset;2263rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline);2264seams_push_constant.uv_offset[0] = (uv_offsets[0].x - 0.5f) / float(atlas_size.width);2265seams_push_constant.uv_offset[1] = (uv_offsets[0].y - 0.5f) / float(atlas_size.height);2266seams_push_constant.blend = uv_offsets[0].z;22672268rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));2269rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4);2270}22712272/* step 2 use triangles to mask the interior */22732274{2275seams_push_constant.base_index = triangle_offset;2276rd->draw_list_bind_render_pipeline(draw_list, blendseams_triangle_raster_pipeline);2277seams_push_constant.blend = 0; //do not draw them, just fill the z-buffer so its used as a mask22782279rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));2280rd->draw_list_draw(draw_list, false, 1, slice_triangle_count[i] * 3);2281}2282/* step 3 blend around the triangle */22832284rd->draw_list_bind_render_pipeline(draw_list, blendseams_line_raster_pipeline);22852286for (int j = 1; j < uv_offset_count; j++) {2287seams_push_constant.base_index = seam_offset;2288seams_push_constant.uv_offset[0] = (uv_offsets[j].x - 0.5f) / float(atlas_size.width);2289seams_push_constant.uv_offset[1] = (uv_offsets[j].y - 0.5f) / float(atlas_size.height);2290seams_push_constant.blend = uv_offsets[0].z;22912292rd->draw_list_set_push_constant(draw_list, &seams_push_constant, sizeof(RasterSeamsPushConstant));2293rd->draw_list_draw(draw_list, false, 1, slice_seam_count[i] * 4);2294}2295rd->draw_list_end();2296}2297seam_offset += slice_seam_count[i];2298triangle_offset += slice_triangle_count[i];2299}2300}23012302#ifdef DEBUG_TEXTURES23032304for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) {2305Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);2306Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);2307img->save_exr("res://5_blendseams" + itos(i) + ".exr", false);2308}2309#endif23102311if (p_step_function) {2312p_step_function(0.9, RTR("Retrieving textures"), p_bake_userdata, true);2313}23142315for (int i = 0; i < atlas_slices * (p_bake_sh ? 4 : 1); i++) {2316Vector<uint8_t> s = rd->texture_get_data(light_accum_tex, i);2317Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBAH, s);2318img->convert(Image::FORMAT_RGBH); //remove alpha2319lightmap_textures.push_back(img);2320}23212322if (p_bake_shadowmask) {2323for (int i = 0; i < atlas_slices; i++) {2324Vector<uint8_t> s = rd->texture_get_data(shadowmask_tex, i);2325Ref<Image> img = Image::create_from_data(atlas_size.width, atlas_size.height, false, Image::FORMAT_RGBA8, s);2326img->convert(Image::FORMAT_R8);2327shadowmask_textures.push_back(img);2328}2329}23302331if (probe_positions.size() > 0) {2332probe_values.resize(probe_positions.size() * 9);2333Vector<uint8_t> probe_data = rd->buffer_get_data(light_probe_buffer);2334memcpy(probe_values.ptrw(), probe_data.ptr(), probe_data.size());2335rd->free_rid(light_probe_buffer);23362337#ifdef DEBUG_TEXTURES2338{2339Ref<Image> img2 = Image::create_from_data(probe_values.size(), 1, false, Image::FORMAT_RGBAF, probe_data);2340img2->save_exr("res://6_lightprobes.exr", false);2341}2342#endif2343}23442345FREE_TEXTURES2346FREE_BUFFERS2347FREE_RASTER_RESOURCES2348FREE_COMPUTE_RESOURCES2349FREE_BLENDSEAMS_RESOURCES23502351memdelete(rd);23522353if (rcd != nullptr) {2354memdelete(rcd);2355}23562357return BAKE_OK;2358}23592360int LightmapperRD::get_bake_texture_count() const {2361return lightmap_textures.size();2362}23632364Ref<Image> LightmapperRD::get_bake_texture(int p_index) const {2365ERR_FAIL_INDEX_V(p_index, lightmap_textures.size(), Ref<Image>());2366return lightmap_textures[p_index];2367}23682369int LightmapperRD::get_shadowmask_texture_count() const {2370return shadowmask_textures.size();2371}23722373Ref<Image> LightmapperRD::get_shadowmask_texture(int p_index) const {2374ERR_FAIL_INDEX_V(p_index, shadowmask_textures.size(), Ref<Image>());2375return shadowmask_textures[p_index];2376}23772378int LightmapperRD::get_bake_mesh_count() const {2379return mesh_instances.size();2380}23812382Variant LightmapperRD::get_bake_mesh_userdata(int p_index) const {2383ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant());2384return mesh_instances[p_index].data.userdata;2385}23862387Rect2 LightmapperRD::get_bake_mesh_uv_scale(int p_index) const {2388ERR_FAIL_COND_V(lightmap_textures.is_empty(), Rect2());2389Rect2 uv_ofs;2390Vector2 atlas_size = Vector2(lightmap_textures[0]->get_width(), lightmap_textures[0]->get_height());2391uv_ofs.position = Vector2(mesh_instances[p_index].offset) / atlas_size;2392uv_ofs.size = Vector2(mesh_instances[p_index].data.albedo_on_uv2->get_width(), mesh_instances[p_index].data.albedo_on_uv2->get_height()) / atlas_size;2393return uv_ofs;2394}23952396int LightmapperRD::get_bake_mesh_texture_slice(int p_index) const {2397ERR_FAIL_INDEX_V(p_index, mesh_instances.size(), Variant());2398return mesh_instances[p_index].slice;2399}24002401int LightmapperRD::get_bake_probe_count() const {2402return probe_positions.size();2403}24042405Vector3 LightmapperRD::get_bake_probe_point(int p_probe) const {2406ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Variant());2407return Vector3(probe_positions[p_probe].position[0], probe_positions[p_probe].position[1], probe_positions[p_probe].position[2]);2408}24092410Vector<Color> LightmapperRD::get_bake_probe_sh(int p_probe) const {2411ERR_FAIL_INDEX_V(p_probe, probe_positions.size(), Vector<Color>());2412Vector<Color> ret;2413ret.resize(9);2414memcpy(ret.ptrw(), &probe_values[p_probe * 9], sizeof(Color) * 9);2415return ret;2416}24172418LightmapperRD::LightmapperRD() {2419}242024212422