Deferred renderer: sort objects by distance to camera
This commit is contained in:
parent
72e0681521
commit
f4908f2368
1 changed files with 22 additions and 16 deletions
|
|
@ -956,12 +956,18 @@ void main()
|
|||
|
||||
// Sort objects by mask & compute bbox
|
||||
|
||||
std::unordered_map<std::tuple<std::uint32_t, material const *>, std::vector<std::size_t>> sorted_objects;
|
||||
struct objects_bucket
|
||||
{
|
||||
std::vector<std::size_t> objects;
|
||||
std::size_t first_visible;
|
||||
};
|
||||
|
||||
std::unordered_map<std::tuple<std::uint32_t, material const *>, objects_bucket> buckets;
|
||||
|
||||
geom::box<float, 3> lit_bbox;
|
||||
geom::box<float, 3> casts_shadow_bbox;
|
||||
|
||||
std::vector<bool> clipped_by_camera(objects.size());
|
||||
std::vector<float> camera_distance(objects.size());
|
||||
|
||||
for (std::size_t i = 0; i < objects.size(); ++i)
|
||||
{
|
||||
|
|
@ -977,29 +983,31 @@ void main()
|
|||
if (o.mat->casts_shadow && o.mat->transparent)
|
||||
throw std::runtime_error("Transparent objects cannot cast shadow");
|
||||
|
||||
sorted_objects[std::tuple{mask(o), o.mat}].push_back(i);
|
||||
buckets[std::tuple{mask(o), o.mat}].objects.push_back(i);
|
||||
|
||||
if (o.mat->lit) lit_bbox |= o.bbox;
|
||||
if (o.mat->casts_shadow) casts_shadow_bbox |= o.bbox;
|
||||
|
||||
bool clipped = true;
|
||||
float dist = -std::numeric_limits<float>::infinity();
|
||||
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;
|
||||
}
|
||||
dist = std::max(dist, dot(o.bbox.corner(c & 1, (c & 2) >> 1, (c & 4) >> 1) - camera_position, camera_direction));
|
||||
}
|
||||
|
||||
clipped_by_camera[i] = clipped;
|
||||
camera_distance[i] = dist;
|
||||
}
|
||||
|
||||
for (auto & p : buckets)
|
||||
{
|
||||
std::sort(p.second.objects.begin(), p.second.objects.end(), [&](auto i, auto j){ return camera_distance[i] < camera_distance[j]; });
|
||||
p.second.first_visible = std::partition_point(p.second.objects.begin(), p.second.objects.end(), [&](auto i){ return camera_distance[i] < 0.f; }) - p.second.objects.begin();
|
||||
}
|
||||
|
||||
auto render_all = [&](auto & program, auto && predicate, bool clip_by_camera = false)
|
||||
{
|
||||
for (auto const & p : sorted_objects)
|
||||
for (auto const & p : buckets)
|
||||
{
|
||||
if (p.second.empty()) continue;
|
||||
if (p.second.objects.empty()) continue;
|
||||
|
||||
std::uint32_t mask = std::get<0>(p.first);
|
||||
|
||||
|
|
@ -1020,11 +1028,9 @@ void main()
|
|||
|
||||
program["u_material"] = geom::vector<float, 2>{mat->specular.intensity, mat->specular.shininess};
|
||||
|
||||
for (std::size_t i : p.second)
|
||||
for (std::size_t i = (clip_by_camera ? p.second.first_visible : 0); i < p.second.objects.size(); ++i)
|
||||
{
|
||||
auto const & o = objects[i];
|
||||
|
||||
if (clip_by_camera && clipped_by_camera[i]) continue;
|
||||
auto const & o = objects[p.second.objects[i]];
|
||||
|
||||
if (mask & O_PRE_TRANSFORM)
|
||||
program["u_pre_transform"] = *o.pre_transform;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue