1/**************************************************************************/
2/* lightmapper_rd.h */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#ifndef LIGHTMAPPER_RD_H
32#define LIGHTMAPPER_RD_H
33
34#include "core/templates/local_vector.h"
35#include "scene/3d/lightmapper.h"
36#include "scene/resources/mesh.h"
37#include "servers/rendering/rendering_device.h"
38
39class RDShaderFile;
40class LightmapperRD : public Lightmapper {
41 GDCLASS(LightmapperRD, Lightmapper)
42
43 struct MeshInstance {
44 MeshData data;
45 int slice = 0;
46 Vector2i offset;
47 };
48
49 struct Light {
50 float position[3] = {};
51 uint32_t type = LIGHT_TYPE_DIRECTIONAL;
52 float direction[3] = {};
53 float energy = 0.0;
54 float color[3] = {};
55 float size = 0.0;
56 float range = 0.0;
57 float attenuation = 0.0;
58 float cos_spot_angle = 0.0;
59 float inv_spot_attenuation = 0.0;
60 float shadow_blur = 0.0;
61 uint32_t static_bake = 0;
62 uint32_t pad[2] = {};
63
64 bool operator<(const Light &p_light) const {
65 return type < p_light.type;
66 }
67 };
68
69 struct Vertex {
70 float position[3] = {};
71 float normal_z = 0.0;
72 float uv[2] = {};
73 float normal_xy[2] = {};
74
75 bool operator==(const Vertex &p_vtx) const {
76 return (position[0] == p_vtx.position[0]) &&
77 (position[1] == p_vtx.position[1]) &&
78 (position[2] == p_vtx.position[2]) &&
79 (uv[0] == p_vtx.uv[0]) &&
80 (uv[1] == p_vtx.uv[1]) &&
81 (normal_xy[0] == p_vtx.normal_xy[0]) &&
82 (normal_xy[1] == p_vtx.normal_xy[1]) &&
83 (normal_z == p_vtx.normal_z);
84 }
85 };
86
87 struct Edge {
88 Vector3 a;
89 Vector3 b;
90 Vector3 na;
91 Vector3 nb;
92 bool operator==(const Edge &p_seam) const {
93 return a == p_seam.a && b == p_seam.b && na == p_seam.na && nb == p_seam.nb;
94 }
95 Edge() {
96 }
97
98 Edge(const Vector3 &p_a, const Vector3 &p_b, const Vector3 &p_na, const Vector3 &p_nb) {
99 a = p_a;
100 b = p_b;
101 na = p_na;
102 nb = p_nb;
103 }
104 };
105
106 struct Probe {
107 float position[4] = {};
108 };
109
110 Vector<Probe> probe_positions;
111
112 struct EdgeHash {
113 _FORCE_INLINE_ static uint32_t hash(const Edge &p_edge) {
114 uint32_t h = hash_murmur3_one_float(p_edge.a.x);
115 h = hash_murmur3_one_float(p_edge.a.y, h);
116 h = hash_murmur3_one_float(p_edge.a.z, h);
117 h = hash_murmur3_one_float(p_edge.b.x, h);
118 h = hash_murmur3_one_float(p_edge.b.y, h);
119 h = hash_murmur3_one_float(p_edge.b.z, h);
120 return h;
121 }
122 };
123 struct EdgeUV2 {
124 Vector2 a;
125 Vector2 b;
126 Vector2i indices;
127 bool operator==(const EdgeUV2 &p_uv2) const {
128 return a == p_uv2.a && b == p_uv2.b;
129 }
130 bool seam_found = false;
131 EdgeUV2(Vector2 p_a, Vector2 p_b, Vector2i p_indices) {
132 a = p_a;
133 b = p_b;
134 indices = p_indices;
135 }
136 EdgeUV2() {}
137 };
138
139 struct Seam {
140 Vector2i a;
141 Vector2i b;
142 uint32_t slice;
143 bool operator<(const Seam &p_seam) const {
144 return slice < p_seam.slice;
145 }
146 };
147
148 struct VertexHash {
149 _FORCE_INLINE_ static uint32_t hash(const Vertex &p_vtx) {
150 uint32_t h = hash_murmur3_one_float(p_vtx.position[0]);
151 h = hash_murmur3_one_float(p_vtx.position[1], h);
152 h = hash_murmur3_one_float(p_vtx.position[2], h);
153 h = hash_murmur3_one_float(p_vtx.uv[0], h);
154 h = hash_murmur3_one_float(p_vtx.uv[1], h);
155 h = hash_murmur3_one_float(p_vtx.normal_xy[0], h);
156 h = hash_murmur3_one_float(p_vtx.normal_xy[1], h);
157 h = hash_murmur3_one_float(p_vtx.normal_z, h);
158 return hash_fmix32(h);
159 }
160 };
161
162 struct Triangle {
163 uint32_t indices[3] = {};
164 uint32_t slice = 0;
165 float min_bounds[3] = {};
166 float pad0 = 0.0;
167 float max_bounds[3] = {};
168 float pad1 = 0.0;
169 bool operator<(const Triangle &p_triangle) const {
170 return slice < p_triangle.slice;
171 }
172 };
173
174 Vector<MeshInstance> mesh_instances;
175
176 Vector<Light> lights;
177
178 struct TriangleSort {
179 uint32_t cell_index = 0;
180 uint32_t triangle_index = 0;
181 bool operator<(const TriangleSort &p_triangle_sort) const {
182 return cell_index < p_triangle_sort.cell_index; //sorting by triangle index in this case makes no sense
183 }
184 };
185
186 void _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> &triangles, uint32_t p_grid_size);
187
188 struct RasterPushConstant {
189 float atlas_size[2] = {};
190 float uv_offset[2] = {};
191 float to_cell_size[3] = {};
192 uint32_t base_triangle = 0;
193 float to_cell_offset[3] = {};
194 float bias = 0.0;
195 int32_t grid_size[3] = {};
196 uint32_t pad2 = 0;
197 };
198
199 struct RasterSeamsPushConstant {
200 uint32_t base_index = 0;
201 uint32_t slice = 0;
202 float uv_offset[2] = {};
203 uint32_t debug = 0;
204 float blend = 0.0;
205 uint32_t pad[2] = {};
206 };
207
208 struct PushConstant {
209 int32_t atlas_size[2] = {};
210 uint32_t ray_count = 0;
211 uint32_t ray_to = 0;
212
213 float world_size[3] = {};
214 float bias = 0.0;
215
216 float to_cell_offset[3] = {};
217 uint32_t ray_from = 0;
218
219 float to_cell_size[3] = {};
220 uint32_t light_count = 0;
221
222 int32_t grid_size = 0;
223 int32_t atlas_slice = 0;
224 int32_t region_ofs[2] = {};
225
226 float environment_xform[12] = {};
227 };
228
229 Vector<Ref<Image>> bake_textures;
230 Vector<Color> probe_values;
231
232 BakeError _blit_meshes_into_atlas(int p_max_texture_size, Vector<Ref<Image>> &albedo_images, Vector<Ref<Image>> &emission_images, AABB &bounds, Size2i &atlas_size, int &atlas_slices, BakeStepFunc p_step_function, void *p_bake_userdata);
233 void _create_acceleration_structures(RenderingDevice *rd, Size2i atlas_size, int atlas_slices, AABB &bounds, int grid_size, Vector<Probe> &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 &triangle_cell_indices_buffer, RID &probe_positions_buffer, RID &grid_texture, RID &seams_buffer, BakeStepFunc p_step_function, void *p_bake_userdata);
234 void _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);
235
236 BakeError _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);
237
238public:
239 virtual void add_mesh(const MeshData &p_mesh) override;
240 virtual void add_directional_light(bool p_static, const Vector3 &p_direction, const Color &p_color, float p_energy, float p_angular_distance, float p_shadow_blur) override;
241 virtual void add_omni_light(bool p_static, const Vector3 &p_position, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_size, float p_shadow_blur) override;
242 virtual void add_spot_light(bool p_static, const Vector3 &p_position, const Vector3 p_direction, const Color &p_color, float p_energy, float p_range, float p_attenuation, float p_spot_angle, float p_spot_attenuation, float p_size, float p_shadow_blur) override;
243 virtual void add_probe(const Vector3 &p_position) override;
244 virtual BakeError bake(BakeQuality p_quality, bool p_use_denoiser, int p_bounces, float p_bias, int p_max_texture_size, bool p_bake_sh, GenerateProbes p_generate_probes, const Ref<Image> &p_environment_panorama, const Basis &p_environment_transform, BakeStepFunc p_step_function = nullptr, void *p_bake_userdata = nullptr, float p_exposure_normalization = 1.0) override;
245
246 int get_bake_texture_count() const override;
247 Ref<Image> get_bake_texture(int p_index) const override;
248 int get_bake_mesh_count() const override;
249 Variant get_bake_mesh_userdata(int p_index) const override;
250 Rect2 get_bake_mesh_uv_scale(int p_index) const override;
251 int get_bake_mesh_texture_slice(int p_index) const override;
252 int get_bake_probe_count() const override;
253 Vector3 get_bake_probe_point(int p_probe) const override;
254 Vector<Color> get_bake_probe_sh(int p_probe) const override;
255
256 LightmapperRD();
257};
258
259#endif // LIGHTMAPPER_RD_H
260