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 | |
39 | class RDShaderFile; |
40 | class 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 | |
238 | public: |
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 | |