Crafter.Graphics/examples/Sponza/project.cpp
2026-05-19 00:27:09 +02:00

92 lines
3.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import std;
import Crafter.Build;
namespace fs = std::filesystem;
using namespace Crafter;
// Sponza geometry + albedo: CC BY 3.0, Frank Meinl (Crytek), packaged by
// Jimmie Bergmann (https://github.com/jimmiebergmann/Sponza) and Morgan
// McGuire (https://casual-effects.com/data). The full asset bundle is
// ~280 MB — too large to live in this repo. GitFetch lands it in the
// per-user crafter-build cache on first build and reuses thereafter.
constexpr std::string_view kSponzaGitUrl = "https://github.com/jimmiebergmann/Sponza.git";
constexpr std::string_view kSponzaCommitSHA = "222338979d32f4f4818466291bdbc29f192b86ba";
// Every albedo is normalized to this size so they can live as layers of
// one texture_2d_array on the GPU (WebGPU array textures require
// identical layer dimensions). 1024 matches the majority of Sponza's
// textures; the few outliers (256×1024 chain, 512² thorn, 2048² curtains)
// get bilinear-resized via stb_image_resize2.
constexpr std::uint16_t kAlbedoSize = 1024u;
extern "C" Configuration CrafterBuildProject(std::span<const std::string_view> args) {
bool isWasm = false;
for (std::string_view a : args) {
if (a.starts_with("--target=") && a.find("wasm") != std::string_view::npos) {
isWasm = true;
break;
}
}
std::vector<std::string> graphicsArgs(args.begin(), args.end());
Configuration* graphics = LocalProject({
.projectFile = "../../project.cpp",
.args = graphicsArgs,
});
Configuration cfg;
cfg.path = "./";
cfg.name = "Sponza";
cfg.outputName = "Sponza";
cfg.type = ConfigurationType::Executable;
if (isWasm) {
cfg.target = "wasm32-wasip1";
cfg.defines.push_back({"CRAFTER_GRAPHICS_WINDOW_DOM", ""});
cfg.compileFlags.push_back("-msimd128");
}
ApplyStandardArgs(cfg, args);
cfg.dependencies = { graphics };
std::array<fs::path, 0> ifaces = {};
std::array<fs::path, 1> impls = { "main" };
cfg.GetInterfacesAndImplementations(ifaces, impls);
// Fetch Sponza once into the shared crafter-build cache, then process
// it into a per-material bundle under build/sponza-bundle-<hash>/.
// Hashing on (sha, albedoSize) so changing either invalidates the
// bundle without touching the rest of the example's build tree.
fs::path sponzaRoot = GitFetch({
.url = std::string(kSponzaGitUrl),
.commit = std::string(kSponzaCommitSHA),
});
std::string bundleKey = std::format("{}|{}", kSponzaCommitSHA, kAlbedoSize);
auto bundleHash = std::hash<std::string>{}(bundleKey);
fs::path bundleDir = fs::path("build") / std::format("sponza-bundle-{:016x}", bundleHash);
if (auto err = BuildOBJBundle(
sponzaRoot / "sponza.obj",
sponzaRoot / "sponza.mtl",
bundleDir,
kAlbedoSize); !err.empty()) {
std::println(std::cerr, "Sponza bundle error: {}", err);
std::exit(1);
}
// Forward every produced file (.cmesh, .ctex, scene.txt) as a
// passthrough — they're already compressed by Crafter.Asset, no
// further compression needed. cfg.files copies them flat into
// the executable's bin dir.
for (const auto& entry : fs::directory_iterator(bundleDir)) {
if (entry.is_regular_file()) cfg.files.push_back(entry.path());
}
if (isWasm) {
cfg.files.emplace_back(fs::path("raygen.wgsl"));
cfg.files.emplace_back(fs::path("closesthit.wgsl"));
cfg.files.emplace_back(fs::path("miss.wgsl"));
EnableWasiBrowserRuntime(cfg);
} else {
cfg.shaders.emplace_back(fs::path("raygen.glsl"), std::string("main"), ShaderType::RayGen);
cfg.shaders.emplace_back(fs::path("closesthit.glsl"), std::string("main"), ShaderType::ClosestHit);
cfg.shaders.emplace_back(fs::path("miss.glsl"), std::string("main"), ShaderType::Miss);
}
return cfg;
}