Unravel Engine C++ Reference
Loading...
Searching...
No Matches
batch_key.cpp
Go to the documentation of this file.
1#include "batch_key.h"
2#include "mesh.h"
3#include "material.h"
4#include <base/hash.hpp>
5#include <cmath>
6#include <compare>
7#include <sstream>
8
9namespace unravel
10{
11
12batch_key::batch_key(std::shared_ptr<mesh> mesh_ptr,
13 std::shared_ptr<material> material_ptr,
14 uint32_t lod_index,
15 uint32_t submesh_index)
16 : mesh_ptr(std::move(mesh_ptr))
17 , material_ptr(std::move(material_ptr))
18 , lod_index(lod_index)
19 , submesh_index(submesh_index)
20{
21}
22
24 const asset_handle<material>& material_handle,
25 uint32_t lod_index,
26 uint32_t submesh_index)
27 : mesh_ptr(mesh_handle.get())
28 , material_ptr(material_handle.get())
29 , lod_index(lod_index)
30 , submesh_index(submesh_index)
31{
32}
33
34auto batch_key::hash() const noexcept -> size_t
35{
36 // Use hash_combine utility to combine all key components
37 size_t seed = 0;
38 utils::hash_combine(seed, mesh_ptr.get());
42
43 return seed;
44}
45
46auto batch_key::is_valid() const -> bool
47{
48 return mesh_ptr && material_ptr;
49}
50
51auto batch_key::to_string() const -> std::string
52{
53 std::ostringstream oss;
54 oss << "batch_key{";
55 oss << "mesh=" << static_cast<const void*>(mesh_ptr.get());
56 oss << ", material=" << static_cast<const void*>(material_ptr.get());
57 oss << ", lod=" << lod_index;
58 oss << ", submesh=" << submesh_index;
59 oss << "}";
60 return oss.str();
61}
62
64 uint32_t lod,
65 uint32_t submesh,
67 std::optional<shadow_cutout_state> cutout_state)
68 : mesh_ptr(std::move(mesh))
69 , lod_index(lod)
70 , submesh_index(submesh)
71 , cull(cull_type)
72 , cutout(std::move(cutout_state))
73{
74}
75
76namespace
77{
78auto compare_float(float lhs, float rhs) -> std::strong_ordering
79{
80 if(lhs < rhs)
81 {
82 return std::strong_ordering::less;
83 }
84 if(lhs > rhs)
85 {
86 return std::strong_ordering::greater;
87 }
88 return std::strong_ordering::equal;
89}
90
91auto compare_shadow_cutout(const std::optional<shadow_cutout_state>& a,
92 const std::optional<shadow_cutout_state>& b) -> std::strong_ordering
93{
94 if(a.has_value() != b.has_value())
95 {
96 return a.has_value() ? std::strong_ordering::greater : std::strong_ordering::less;
97 }
98 if(!a.has_value())
99 {
100 return std::strong_ordering::equal;
101 }
102
103 const shadow_cutout_state& lhs = *a;
104 const shadow_cutout_state& rhs = *b;
105 if(lhs.color_map.get() != rhs.color_map.get())
106 {
107 return lhs.color_map.get() < rhs.color_map.get() ? std::strong_ordering::less
108 : std::strong_ordering::greater;
109 }
110 if(const auto cmp = compare_float(lhs.alpha_test_value, rhs.alpha_test_value); cmp != 0)
111 {
112 return cmp;
113 }
114 if(const auto cmp = compare_float(lhs.base_color.value.r, rhs.base_color.value.r); cmp != 0)
115 {
116 return cmp;
117 }
118 if(const auto cmp = compare_float(lhs.base_color.value.g, rhs.base_color.value.g); cmp != 0)
119 {
120 return cmp;
121 }
122 if(const auto cmp = compare_float(lhs.base_color.value.b, rhs.base_color.value.b); cmp != 0)
123 {
124 return cmp;
125 }
126 if(const auto cmp = compare_float(lhs.base_color.value.a, rhs.base_color.value.a); cmp != 0)
127 {
128 return cmp;
129 }
130 if(const auto cmp = compare_float(lhs.tiling.x, rhs.tiling.x); cmp != 0)
131 {
132 return cmp;
133 }
134 return compare_float(lhs.tiling.y, rhs.tiling.y);
135}
136} // namespace
137
138auto shadow_batch_key::operator<=>(const shadow_batch_key& other) const -> std::strong_ordering
139{
140 if(mesh_ptr.get() != other.mesh_ptr.get())
141 {
142 return mesh_ptr.get() < other.mesh_ptr.get() ? std::strong_ordering::less : std::strong_ordering::greater;
143 }
144 if(lod_index != other.lod_index)
145 {
146 return lod_index < other.lod_index ? std::strong_ordering::less : std::strong_ordering::greater;
147 }
148 if(submesh_index != other.submesh_index)
149 {
150 return submesh_index < other.submesh_index ? std::strong_ordering::less : std::strong_ordering::greater;
151 }
152 if(cull != other.cull)
153 {
154 return cull < other.cull ? std::strong_ordering::less : std::strong_ordering::greater;
155 }
156 return compare_shadow_cutout(cutout, other.cutout);
157}
158
159auto shadow_batch_key::operator==(const shadow_batch_key& other) const -> bool
160{
161 return (*this <=> other) == 0;
162}
163
164auto shadow_batch_key::hash() const noexcept -> size_t
165{
166 size_t seed = 0;
167 utils::hash_combine(seed, mesh_ptr.get());
170 utils::hash_combine(seed, static_cast<std::uint8_t>(cull));
171 utils::hash_combine(seed, cutout.has_value());
172 if(cutout.has_value())
173 {
174 utils::hash_combine(seed, cutout->color_map.get());
175 utils::hash_combine(seed, cutout->alpha_test_value);
176 utils::hash_combine(seed, cutout->base_color.value.r);
177 utils::hash_combine(seed, cutout->base_color.value.g);
178 utils::hash_combine(seed, cutout->base_color.value.b);
179 utils::hash_combine(seed, cutout->base_color.value.a);
180 utils::hash_combine(seed, cutout->tiling.x);
181 utils::hash_combine(seed, cutout->tiling.y);
182 }
183 return seed;
184}
185
186auto shadow_batch_key::is_valid() const -> bool
187{
188 return static_cast<bool>(mesh_ptr);
189}
190
192{
193 return cutout.has_value();
194}
195
196auto shadow_batch_key::to_string() const -> std::string
197{
198 std::ostringstream oss;
199 oss << "shadow_batch_key{mesh=" << static_cast<const void*>(mesh_ptr.get());
200 oss << ", lod=" << lod_index << ", submesh=" << submesh_index;
201 oss << ", cutout=" << (cutout.has_value() ? "yes" : "no") << "}";
202 return oss.str();
203}
204
205auto make_shadow_batch_key(const std::shared_ptr<mesh>& mesh_ptr,
206 uint32_t lod_index,
207 uint32_t submesh_index,
208 const std::shared_ptr<material>& material_ptr) -> shadow_batch_key
209{
211 std::optional<shadow_cutout_state> cutout;
212 if(material_ptr)
213 {
214 cull = material_ptr->get_cull_type();
215 if(material_ptr->is<pbr_material>())
216 {
217 const auto& pbr = static_cast<const pbr_material&>(*material_ptr);
218 if(!pbr.casts_shadow())
219 {
220 return {};
221 }
222 if(pbr.uses_alpha_cutout())
223 {
224 cutout = pbr.make_shadow_cutout_state();
225 }
226 }
227 }
228 return shadow_batch_key(mesh_ptr, lod_index, submesh_index, cull, cutout);
229}
230
231} // namespace unravel
entt::handle b
entt::handle a
Main class representing a 3D mesh with support for different LODs, submeshes, and skinning.
Definition mesh.h:323
Class for physically-based rendering (PBR) materials.
Definition material.h:112
Hash specialization for batch_key to enable use in std::unordered_map.
auto make_shadow_batch_key(const std::shared_ptr< mesh > &mesh_ptr, uint32_t lod_index, uint32_t submesh_index, const std::shared_ptr< material > &material_ptr) -> shadow_batch_key
Build a shadow batch key from mesh geometry and optional material cutout metadata.
cull_type
Enum representing the type of culling to be used.
Definition material.h:25
@ counter_clockwise
Cull counter-clockwise faces.
void hash_combine(std::size_t &seed, const T &v)
Definition hash.hpp:8
Thread-safe handle to an asset.
batch_key()=default
Default constructor.
auto hash() const noexcept -> size_t
Generate hash value for this batch key.
Definition batch_key.cpp:34
auto to_string() const -> std::string
Convert batch key to string for debugging.
Definition batch_key.cpp:51
auto is_valid() const -> bool
Check if this batch key is valid.
Definition batch_key.cpp:46
std::shared_ptr< material > material_ptr
Shared pointer to the material.
Definition batch_key.h:33
uint32_t lod_index
Level of detail index.
Definition batch_key.h:36
std::shared_ptr< mesh > mesh_ptr
Shared pointer to the mesh geometry.
Definition batch_key.h:30
uint32_t submesh_index
Submesh index within the mesh.
Definition batch_key.h:39
Batch key for shadow depth passes — geometry-first, optional cutout bucket.
Definition batch_key.h:119
auto hash() const noexcept -> size_t
std::shared_ptr< mesh > mesh_ptr
Definition batch_key.h:120
auto is_valid() const -> bool
std::optional< shadow_cutout_state > cutout
Definition batch_key.h:124
auto uses_alpha_cutout() const -> bool
auto operator==(const shadow_batch_key &other) const -> bool
auto to_string() const -> std::string
auto operator<=>(const shadow_batch_key &other) const -> std::strong_ordering