#include #include #include #include #include #include #include #include #include using namespace faset::render; namespace { std::shared_ptr coarse_mesh() { auto mesh = std::make_shared(); mesh->vertices = { Vertex{{-1, -1, -1}, {-1, -1, -1}}, Vertex{{1, -1, -1}, {1, -1, -1}}, Vertex{{0, 1, 0}, {0, 1, 0}}, Vertex{{0, -1, 1}, {0, -1, 1}}, }; mesh->indices = {0, 2, 1, 0, 1, 3, 1, 2, 3, 2, 0, 3}; return mesh; } VisibilityMode mode_from_argument(std::string_view argument) { if (argument == "direct") return VisibilityMode::Direct; if (argument == "frustum") return VisibilityMode::GpuFrustum; if (argument == "occlusion") return VisibilityMode::GpuOcclusion; throw std::invalid_argument("mode must be direct, frustum, or occlusion"); } } // namespace int main(int argc, char** argv) { try { if (argc > 3) throw std::invalid_argument("usage: faset_p2_visibility_example " "[direct|frustum|occlusion] [capture.ppm]"); RendererConfig config; config.width = 640; config.height = 360; config.headless = true; config.visibility_mode = argc > 1 ? mode_from_argument(argv[1]) : VisibilityMode::GpuOcclusion; config.visibility_diagnostics = true; Renderer renderer(config); Snapshot frame; frame.view_id = "p2-lod-example-camera"; frame.eye = {0, 2, 12}; frame.projection = perspective(.9f, float(config.width) / config.height, .1f, 100); frame.view_projection = multiply(frame.projection, look_at(frame.eye, {0, 0, 0})); const auto prepared_coarse = coarse_mesh(); for (int i = 0; i < 9; ++i) { DrawItem item; item.mesh = cube_mesh(); item.lod_meshes = {prepared_coarse}; item.instance_key = "example/cube/" + std::to_string(i); item.model = transform({float(i - 4) * 1.8f, 0, i % 2 ? -5.f : 0.f}); item.color = {0.28f + .07f * i, .6f, .8f, 1}; item.cast_shadow = false; frame.draws.push_back(std::move(item)); } // The second and later frames have compatible HZB history for this view. for (int i = 0; i < 3; ++i) renderer.render(frame); const auto& stats = renderer.stats(); renderer.capture(argc > 2 ? std::filesystem::path(argv[2]) : std::filesystem::path("p2-visibility.ppm")); std::cout << "GPU path: " << (stats.gpu_visibility_active ? "active" : "unavailable") << ", bins: " << stats.gpu_bins << ", visible: " << stats.gpu_visible_instances << ", LOD0: " << stats.lod_counts[0] << ", LOD1: " << stats.lod_counts[1] << ", validation errors: " << stats.validation_errors << '\n'; return stats.validation_errors ? 1 : 0; } catch (const std::exception& error) { std::cerr << error.what() << '\n'; return 1; } }