Deferred renderer: bucket objects by material
This commit is contained in:
parent
82817304e2
commit
72e0681521
1 changed files with 75 additions and 30 deletions
|
|
@ -23,6 +23,48 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
void hash_combine(std::size_t & seed, std::size_t value)
|
||||||
|
{
|
||||||
|
seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T1, typename T2>
|
||||||
|
struct hash<std::tuple<T1, T2>>
|
||||||
|
{
|
||||||
|
std::hash<T1> h1;
|
||||||
|
std::hash<T2> h2;
|
||||||
|
|
||||||
|
std::size_t operator() (std::tuple<T1, T2> const & t) const
|
||||||
|
{
|
||||||
|
std::size_t h = 0;
|
||||||
|
hash_combine(h, h1(std::get<0>(t)));
|
||||||
|
hash_combine(h, h2(std::get<1>(t)));
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T1, typename T2, typename T3>
|
||||||
|
struct hash<std::tuple<T1, T2, T3>>
|
||||||
|
{
|
||||||
|
std::hash<T1> h1;
|
||||||
|
std::hash<T2> h2;
|
||||||
|
std::hash<T3> h3;
|
||||||
|
|
||||||
|
std::size_t operator() (std::tuple<T1, T2, T3> const & t) const
|
||||||
|
{
|
||||||
|
std::size_t h = 0;
|
||||||
|
hash_combine(h, h1(std::get<0>(t)));
|
||||||
|
hash_combine(h, h2(std::get<1>(t)));
|
||||||
|
hash_combine(h, h3(std::get<2>(t)));
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace psemek::gfx
|
namespace psemek::gfx
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
@ -914,11 +956,13 @@ void main()
|
||||||
|
|
||||||
// Sort objects by mask & compute bbox
|
// Sort objects by mask & compute bbox
|
||||||
|
|
||||||
std::unordered_map<std::uint32_t, std::vector<std::size_t>> objects_by_mask;
|
std::unordered_map<std::tuple<std::uint32_t, material const *>, std::vector<std::size_t>> sorted_objects;
|
||||||
|
|
||||||
geom::box<float, 3> lit_bbox;
|
geom::box<float, 3> lit_bbox;
|
||||||
geom::box<float, 3> casts_shadow_bbox;
|
geom::box<float, 3> casts_shadow_bbox;
|
||||||
|
|
||||||
|
std::vector<bool> clipped_by_camera(objects.size());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < objects.size(); ++i)
|
for (std::size_t i = 0; i < objects.size(); ++i)
|
||||||
{
|
{
|
||||||
auto const & o = objects[i];
|
auto const & o = objects[i];
|
||||||
|
|
@ -933,30 +977,11 @@ void main()
|
||||||
if (o.mat->casts_shadow && o.mat->transparent)
|
if (o.mat->casts_shadow && o.mat->transparent)
|
||||||
throw std::runtime_error("Transparent objects cannot cast shadow");
|
throw std::runtime_error("Transparent objects cannot cast shadow");
|
||||||
|
|
||||||
objects_by_mask[mask(objects[i])].push_back(i);
|
sorted_objects[std::tuple{mask(o), o.mat}].push_back(i);
|
||||||
|
|
||||||
if (o.mat->lit) lit_bbox |= o.bbox;
|
if (o.mat->lit) lit_bbox |= o.bbox;
|
||||||
if (o.mat->casts_shadow) casts_shadow_bbox |= o.bbox;
|
if (o.mat->casts_shadow) casts_shadow_bbox |= o.bbox;
|
||||||
}
|
|
||||||
|
|
||||||
auto render_all = [&](auto & program, auto && predicate, bool clip_by_camera = false)
|
|
||||||
{
|
|
||||||
for (auto const & p : objects_by_mask)
|
|
||||||
{
|
|
||||||
std::uint32_t mask = p.first;
|
|
||||||
|
|
||||||
if (!predicate(mask)) continue;
|
|
||||||
|
|
||||||
if (p.second.empty()) continue;
|
|
||||||
|
|
||||||
program["u_flag_mask"] = mask;
|
|
||||||
|
|
||||||
for (std::size_t i : p.second)
|
|
||||||
{
|
|
||||||
auto const & o = objects[i];
|
|
||||||
|
|
||||||
if (clip_by_camera)
|
|
||||||
{
|
|
||||||
bool clipped = true;
|
bool clipped = true;
|
||||||
for (int c = 0; c < 8; ++c)
|
for (int c = 0; c < 8; ++c)
|
||||||
{
|
{
|
||||||
|
|
@ -966,27 +991,47 @@ void main()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (clipped)
|
|
||||||
continue;
|
clipped_by_camera[i] = clipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto render_all = [&](auto & program, auto && predicate, bool clip_by_camera = false)
|
||||||
|
{
|
||||||
|
for (auto const & p : sorted_objects)
|
||||||
|
{
|
||||||
|
if (p.second.empty()) continue;
|
||||||
|
|
||||||
|
std::uint32_t mask = std::get<0>(p.first);
|
||||||
|
|
||||||
|
if (!predicate(mask)) continue;
|
||||||
|
|
||||||
|
material const * mat = std::get<1>(p.first);
|
||||||
|
|
||||||
|
program["u_flag_mask"] = mask;
|
||||||
|
|
||||||
if (mask & O_UNIFORM_COLOR)
|
if (mask & O_UNIFORM_COLOR)
|
||||||
program["u_color"] = *o.mat->color;
|
program["u_color"] = *(mat->color);
|
||||||
|
|
||||||
if (mask & O_TEXTURE_COLOR)
|
if (mask & O_TEXTURE_COLOR)
|
||||||
{
|
{
|
||||||
gl::ActiveTexture(gl::TEXTURE0);
|
gl::ActiveTexture(gl::TEXTURE0);
|
||||||
o.mat->texture->bind();
|
mat->texture->bind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program["u_material"] = geom::vector<float, 2>{mat->specular.intensity, mat->specular.shininess};
|
||||||
|
|
||||||
|
for (std::size_t i : p.second)
|
||||||
|
{
|
||||||
|
auto const & o = objects[i];
|
||||||
|
|
||||||
|
if (clip_by_camera && clipped_by_camera[i]) continue;
|
||||||
|
|
||||||
if (mask & O_PRE_TRANSFORM)
|
if (mask & O_PRE_TRANSFORM)
|
||||||
program["u_pre_transform"] = *o.pre_transform;
|
program["u_pre_transform"] = *o.pre_transform;
|
||||||
|
|
||||||
if (mask & O_POST_TRANSFORM)
|
if (mask & O_POST_TRANSFORM)
|
||||||
program["u_post_transform"] = *o.post_transform;
|
program["u_post_transform"] = *o.post_transform;
|
||||||
|
|
||||||
program["u_material"] = geom::vector<float, 2>{o.mat->specular.intensity, o.mat->specular.shininess};
|
|
||||||
|
|
||||||
o.mesh->draw();
|
o.mesh->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue