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>
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
|
|
@ -914,11 +956,13 @@ void main()
|
|||
|
||||
// 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> casts_shadow_bbox;
|
||||
|
||||
std::vector<bool> clipped_by_camera(objects.size());
|
||||
|
||||
for (std::size_t i = 0; i < objects.size(); ++i)
|
||||
{
|
||||
auto const & o = objects[i];
|
||||
|
|
@ -933,51 +977,54 @@ void main()
|
|||
if (o.mat->casts_shadow && o.mat->transparent)
|
||||
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->casts_shadow) casts_shadow_bbox |= o.bbox;
|
||||
|
||||
bool clipped = true;
|
||||
for (int c = 0; c < 8; ++c)
|
||||
{
|
||||
if (dot(o.bbox.corner(c & 1, (c & 2) >> 1, (c & 4) >> 1) - camera_position, camera_direction) > 0.f)
|
||||
{
|
||||
clipped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
clipped_by_camera[i] = clipped;
|
||||
}
|
||||
|
||||
auto render_all = [&](auto & program, auto && predicate, bool clip_by_camera = false)
|
||||
{
|
||||
for (auto const & p : objects_by_mask)
|
||||
for (auto const & p : sorted_objects)
|
||||
{
|
||||
std::uint32_t mask = p.first;
|
||||
if (p.second.empty()) continue;
|
||||
|
||||
std::uint32_t mask = std::get<0>(p.first);
|
||||
|
||||
if (!predicate(mask)) continue;
|
||||
|
||||
if (p.second.empty()) continue;
|
||||
material const * mat = std::get<1>(p.first);
|
||||
|
||||
program["u_flag_mask"] = mask;
|
||||
|
||||
if (mask & O_UNIFORM_COLOR)
|
||||
program["u_color"] = *(mat->color);
|
||||
|
||||
if (mask & O_TEXTURE_COLOR)
|
||||
{
|
||||
gl::ActiveTexture(gl::TEXTURE0);
|
||||
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)
|
||||
{
|
||||
bool clipped = true;
|
||||
for (int c = 0; c < 8; ++c)
|
||||
{
|
||||
if (dot(o.bbox.corner(c & 1, (c & 2) >> 1, (c & 4) >> 1) - camera_position, camera_direction) > 0.f)
|
||||
{
|
||||
clipped = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (clipped)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mask & O_UNIFORM_COLOR)
|
||||
program["u_color"] = *o.mat->color;
|
||||
|
||||
if (mask & O_TEXTURE_COLOR)
|
||||
{
|
||||
gl::ActiveTexture(gl::TEXTURE0);
|
||||
o.mat->texture->bind();
|
||||
}
|
||||
if (clip_by_camera && clipped_by_camera[i]) continue;
|
||||
|
||||
if (mask & O_PRE_TRANSFORM)
|
||||
program["u_pre_transform"] = *o.pre_transform;
|
||||
|
|
@ -985,8 +1032,6 @@ void main()
|
|||
if (mask & 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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue