#define BOOST_TEST_MODULE test_render #include "testHelpers.h" #include "testMainWindow.h" #include "testRenderOutput.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class TestScene : public SceneProvider { RailVehicleClassPtr brush47rvc; std::shared_ptr train1, train2; RailLinks rail; std::shared_ptr gd = std::make_shared(GeoData::createFlat({0, 0}, {1000000, 1000000}, 1)); std::shared_ptr env = std::make_shared(); Terrain terrain {gd}; Water water {gd}; public: TestScene() { gameState->assets = AssetFactory::loadAll(RESDIR); brush47rvc = std::dynamic_pointer_cast(gameState->assets.at("brush-47")); std::random_device randomdev {}; std::uniform_real_distribution rotationDistribution {0, two_pi}; std::uniform_int_distribution positionOffsetDistribution {-1500, +1500}; std::uniform_int_distribution treeDistribution {1, 3}; std::uniform_int_distribution treeVariantDistribution {1, 4}; train1 = std::make_shared(brush47rvc); train1->location.setPosition({52000, 50000, 2000}); train1->bogies.front().setPosition(train1->bogies.front().position() + train1->location.position()); train1->bogies.back().setPosition(train1->bogies.back().position() + train1->location.position()); train2 = std::make_shared(brush47rvc); train2->location.setPosition({52000, 30000, 2000}); train2->bogies.front().setPosition(train2->bogies.front().position() + train2->location.position()); train2->bogies.back().setPosition(train2->bogies.back().position() + train2->location.position()); for (auto x = 40000; x < 100000; x += 5000) { for (auto y = 65000; y < 125000; y += 5000) { gameState->world.create( std::dynamic_pointer_cast(gameState->assets.at(std::format( "Tree-{:#02}-{}", treeDistribution(randomdev), treeVariantDistribution(randomdev)))), Location {{x + positionOffsetDistribution(randomdev), y + positionOffsetDistribution(randomdev), 1}, {0, rotationDistribution(randomdev), 0}}); } } rail.addLinksBetween({42000, 50000, 1000}, {65000, 50000, 1000}); rail.addLinksBetween({65000, 50000, 1000}, {75000, 45000, 2000}); } void content(const SceneShader & shader) const override { terrain.render(shader); water.render(shader); rail.render(shader); std::ranges::for_each(gameState->assets, [&shader](const auto & asset) { if (const auto renderable = std::dynamic_pointer_cast(asset.second)) { renderable->render(shader); } }); } void lights(const SceneShader &) const override { } void environment(const SceneShader &, const SceneRenderer & r) const override { env->render(r, *this); } void shadows(const ShadowMapper & shadowMapper) const override { terrain.shadows(shadowMapper); std::ranges::for_each(gameState->assets, [&shadowMapper](const auto & asset) { if (const auto renderable = std::dynamic_pointer_cast(asset.second)) { renderable->shadows(shadowMapper); } }); } }; BOOST_GLOBAL_FIXTURE(TestMainWindowAppBase); BOOST_DATA_TEST_CASE(cam, boost::unit_test::data::xrange(500, 30000, 1300) * boost::unit_test::data::xrange(500, 10000, 300) * boost::unit_test::data::xrange(50000, 500000, 70000), dist, near, far) { static constexpr GlobalPosition4D pos {-10, -10, 60000, 0}; const Camera cam {pos, half_pi, 1.F, near, far}; const auto e = cam.extentsAtDist(dist); BOOST_CHECK_CLOSE_VECI(e[0], pos + GlobalPosition4D(-dist, dist, -dist, dist)); BOOST_CHECK_CLOSE_VECI(e[1], pos + GlobalPosition4D(-dist, dist, dist, dist)); BOOST_CHECK_CLOSE_VECI(e[2], pos + GlobalPosition4D(dist, dist, -dist, dist)); BOOST_CHECK_CLOSE_VECI(e[3], pos + GlobalPosition4D(dist, dist, dist, dist)); } BOOST_AUTO_TEST_CASE(camSeaFloor) { const Camera cam {{100, 200, 300}, half_pi, 1.F, 100, 2000}; const auto e = cam.extentsAtDist(2000); BOOST_CHECK_CLOSE_VECI(e[0], GlobalPosition4D(-1700, 2000, -1500, 1800)); BOOST_CHECK_CLOSE_VECI(e[1], GlobalPosition4D(-1900, 2200, 2300, 2000)); BOOST_CHECK_CLOSE_VECI(e[2], GlobalPosition4D(1900, 2000, -1500, 1800)); BOOST_CHECK_CLOSE_VECI(e[3], GlobalPosition4D(2100, 2200, 2300, 2000)); } BOOST_FIXTURE_TEST_SUITE(w, TestRenderOutput); BOOST_AUTO_TEST_CASE(basic) { class TestSceneRenderer : public SceneRenderer { using SceneRenderer::SceneRenderer; public: void saveBuffers(const std::filesystem::path & prefix) const { std::filesystem::create_directories(prefix); Texture::save(gAlbedoSpec, (prefix / "albedo.tga").c_str()); Texture::savePosition(gPosition, (prefix / "position.tga").c_str()); Texture::saveNormal(gNormal, (prefix / "normal.tga").c_str()); Texture::save(gIllumination, (prefix / "illumination.tga").c_str()); } }; TestSceneRenderer ss {size, output}; ss.camera.setView({-10000, -10000, 60000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); const TestScene scene; ss.render(scene); ss.saveBuffers("/tmp/basic"); Texture::save(outImage, "/tmp/basic/final.tga"); } BOOST_AUTO_TEST_CASE(terrain) { SceneRenderer ss {size, output}; ss.camera.setView({310000000, 490000000, 600000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); class TestTerrain : public SceneProvider { std::shared_ptr gd = std::make_shared(GeoData::loadFromAsciiGrid(FIXTURESDIR "height/SD19.asc")); Terrain terrain {gd}; Water water {gd}; void content(const SceneShader & shader) const override { terrain.render(shader); water.render(shader); } void environment(const SceneShader &, const SceneRenderer & sr) const override { sr.setAmbientLight({0.1, 0.1, 0.1}); sr.setDirectionalLight({1, 1, 1}, {{0, quarter_pi}}, *this); } void lights(const SceneShader &) const override { } void shadows(const ShadowMapper & shadowMapper) const override { terrain.shadows(shadowMapper); } }; ss.render(TestTerrain {}); Texture::save(outImage, "/tmp/terrain.tga"); } BOOST_AUTO_TEST_CASE(railnet) { SceneRenderer ss {size, output}; ss.camera.setView({0, 0, 10000}, glm::normalize(glm::vec3 {1, 1, -0.5F})); class TestRail : public SceneProvider { RailLinks net; public: TestRail() { net.addLinksBetween({20000, 10000, 0}, {100000, 100000, 0}); net.addLinksBetween({20000, 10000, 0}, {10000, 10000, 0}); net.addLinksBetween({10000, 20000, 0}, {100000, 120000, 0}); net.addLinksBetween({10000, 20000, 0}, {10000, 10000, 0}); net.addLinksBetween({100000, 100000, 0}, {100000, 120000, 0}); } void content(const SceneShader & shader) const override { net.render(shader); } void environment(const SceneShader &, const SceneRenderer & sr) const override { sr.setAmbientLight({0.1, 0.1, 0.1}); sr.setDirectionalLight({1, 1, 1}, {{0, quarter_pi}}, *this); } void lights(const SceneShader &) const override { } void shadows(const ShadowMapper &) const override { } }; ss.render(TestRail {}); Texture::save(outImage, "/tmp/railnet.tga"); } BOOST_AUTO_TEST_SUITE_END();