From 480ec8e2fc2776cef65a85931426b53f3e5ce881 Mon Sep 17 00:00:00 2001 From: Matt Pharr Date: Tue, 24 Aug 2021 09:40:23 -0700 Subject: [PATCH] Update from book source. SceneStateManager -> BasicSceneBuilder Add various object creation methods to BasicScene Remove redundant threadAllocators parameter from BasicScene::CreateMaterials() --- src/pbrt/cmd/pbrt.cpp | 4 +- src/pbrt/cpu/render.cpp | 24 +-- src/pbrt/paramdict.h | 2 +- src/pbrt/parser.cpp | 28 ++- src/pbrt/scene.cpp | 293 +++++++++++++++++------------- src/pbrt/scene.h | 71 ++++---- src/pbrt/wavefront/integrator.cpp | 14 +- 7 files changed, 222 insertions(+), 214 deletions(-) diff --git a/src/pbrt/cmd/pbrt.cpp b/src/pbrt/cmd/pbrt.cpp index 7c0f5a5..ca8f878 100644 --- a/src/pbrt/cmd/pbrt.cpp +++ b/src/pbrt/cmd/pbrt.cpp @@ -256,8 +256,8 @@ int main(int argc, char *argv[]) { } else { // Parse provided scene description files BasicScene scene; - SceneStateManager manager(&scene); - ParseFiles(&manager, filenames); + BasicSceneBuilder builder(&scene); + ParseFiles(&builder, filenames); // Render the scene if (options.useGPU || options.wavefront) diff --git a/src/pbrt/cpu/render.cpp b/src/pbrt/cpu/render.cpp index 0914792..c19a49f 100644 --- a/src/pbrt/cpu/render.cpp +++ b/src/pbrt/cpu/render.cpp @@ -42,8 +42,7 @@ void RenderCPU(BasicScene &parsedScene) { }; // Filter - Filter filter = Filter::Create(parsedScene.filter.name, parsedScene.filter.parameters, - &parsedScene.filter.loc, alloc); + Filter filter = parsedScene.CreateFilter(); // Film // It's a little ugly to poke into the camera's parameters here, but we @@ -56,21 +55,14 @@ void RenderCPU(BasicScene &parsedScene) { ErrorExit(&parsedScene.camera.loc, "The specified camera shutter times imply that the shutter " "does not open. A black image will result."); - Film film = Film::Create(parsedScene.film.name, parsedScene.film.parameters, - exposureTime, parsedScene.camera.cameraTransform, filter, - &parsedScene.film.loc, alloc); + Film film = parsedScene.CreateFilm(exposureTime, filter); // Camera Medium cameraMedium = findMedium(parsedScene.camera.medium, &parsedScene.camera.loc); - Camera camera = Camera::Create(parsedScene.camera.name, parsedScene.camera.parameters, - cameraMedium, parsedScene.camera.cameraTransform, film, - &parsedScene.camera.loc, alloc); + Camera camera = parsedScene.CreateCamera(cameraMedium, film); - // Create _Sampler_ for rendering Point2i fullImageResolution = camera.GetFilm().FullResolution(); - Sampler sampler = - Sampler::Create(parsedScene.sampler.name, parsedScene.sampler.parameters, - fullImageResolution, &parsedScene.sampler.loc, alloc); + Sampler sampler = parsedScene.CreateSampler(fullImageResolution); // Textures LOG_VERBOSE("Starting textures"); @@ -85,17 +77,15 @@ void RenderCPU(BasicScene &parsedScene) { LOG_VERBOSE("Starting materials"); std::map namedMaterials; std::vector materials; - parsedScene.CreateMaterials(textures, threadAllocators, &namedMaterials, &materials); + parsedScene.CreateMaterials(textures, &namedMaterials, &materials); LOG_VERBOSE("Finished materials"); Primitive accel = parsedScene.CreateAggregate(textures, shapeIndexToAreaLights, media, namedMaterials, materials); // Integrator - const RGBColorSpace *integratorColorSpace = parsedScene.film.parameters.ColorSpace(); - std::unique_ptr integrator(Integrator::Create( - parsedScene.integrator.name, parsedScene.integrator.parameters, camera, sampler, - accel, lights, integratorColorSpace, &parsedScene.integrator.loc)); + std::unique_ptr integrator( + parsedScene.CreateIntegrator(camera, sampler, accel, lights)); // Helpful warnings for (const auto &sh : parsedScene.shapes) diff --git a/src/pbrt/paramdict.h b/src/pbrt/paramdict.h index 8a13667..1b1cad0 100644 --- a/src/pbrt/paramdict.h +++ b/src/pbrt/paramdict.h @@ -67,7 +67,7 @@ enum class ParameterType { }; // SpectrumType Definition -enum class SpectrumType { Albedo, Unbounded, Illuminant }; +enum class SpectrumType { Illuminant, Albedo, Unbounded }; inline std::string ToString(SpectrumType t) { switch (t) { diff --git a/src/pbrt/parser.cpp b/src/pbrt/parser.cpp index b8dc662..1ad7ffd 100644 --- a/src/pbrt/parser.cpp +++ b/src/pbrt/parser.cpp @@ -603,7 +603,7 @@ void parse(ParserTarget *target, std::unique_ptr t) { static std::atomic warnedTransformBeginEndDeprecated{false}; - std::vector, SceneStateManager *>> imports; + std::vector, BasicSceneBuilder *>> imports; LOG_VERBOSE("Started parsing %s", std::string(t->loc.filename.begin(), t->loc.filename.end())); @@ -659,11 +659,9 @@ void parse(ParserTarget *target, std::unique_ptr t) { // Helper function for pbrt API entrypoints that take a single string // parameter and a ParameterVector (e.g. pbrtShape()). - // using BasicEntrypoint = void (SceneStateManager::*)(const std::string &, - // ParsedParameterVector, FileLoc); auto basicParamListEntrypoint = [&](void (ParserTarget::*apiFunc)(const std::string &, - ParsedParameterVector, FileLoc), + ParsedParameterVector, FileLoc), FileLoc loc) { Token t = *nextToken(TokenRequired); std::string_view dequoted = dequoteString(t); @@ -773,34 +771,34 @@ void parse(ParserTarget *target, std::unique_ptr t) { Printf("%sImport \"%s\"\n", dynamic_cast(target)->indent(), filename); else { - SceneStateManager *stateManager = dynamic_cast(target); - CHECK(stateManager); + BasicSceneBuilder *builder = dynamic_cast(target); + CHECK(builder); - if (stateManager->currentBlock != SceneStateManager::BlockState::WorldBlock) + if (builder->currentBlock != BasicSceneBuilder::BlockState::WorldBlock) ErrorExit(&tok->loc, "Import statement only allowed inside world " "definition block."); filename = ResolveFilename(filename); - SceneStateManager *importScene = stateManager->CopyForImport(); + BasicSceneBuilder *importBuilder = builder->CopyForImport(); if (RunningThreads() == 1) { std::unique_ptr timport = Tokenizer::CreateFromFile(filename, parseError); if (timport) - parse(importScene, std::move(timport)); - stateManager->MergeImported(importScene); + parse(importBuilder, std::move(timport)); + builder->MergeImported(importBuilder); } else { auto job = [=](std::string filename) { Timer timer; std::unique_ptr timport = Tokenizer::CreateFromFile(filename, parseError); if (timport) - parse(importScene, std::move(timport)); + parse(importBuilder, std::move(timport)); LOG_VERBOSE("Elapsed time to parse \"%s\": %.2fs", filename, timer.ElapsedSeconds()); }; Future jobFinished = RunAsync(job, filename); - imports.push_back(std::make_pair(std::move(jobFinished), importScene)); + imports.push_back(std::make_pair(std::move(jobFinished), importBuilder)); } } } else if (tok->token == "Identity") @@ -984,9 +982,9 @@ void parse(ParserTarget *target, std::unique_ptr t) { for (auto &import : imports) { import.first.Wait(); - SceneStateManager *stateManager = dynamic_cast(target); - CHECK(stateManager); - stateManager->MergeImported(import.second); + BasicSceneBuilder *builder = dynamic_cast(target); + CHECK(builder); + builder->MergeImported(import.second); // HACK: let import.second leak so that its TransformCache isn't deallocated... } } diff --git a/src/pbrt/scene.cpp b/src/pbrt/scene.cpp index ec3bef1..d080187 100644 --- a/src/pbrt/scene.cpp +++ b/src/pbrt/scene.cpp @@ -5,6 +5,7 @@ #include #include +#include #ifdef PBRT_BUILD_GPU_RENDERER #include #endif // PBRT_BUILD_GPU_RENDERER @@ -45,14 +46,14 @@ static std::string ToString(const std::pair &p) { return StringPrintf("[ std::pair first: %s second: %s ]", p.first, p.second); } -std::string SceneStateManager::ToString() const { +std::string BasicSceneBuilder::ToString() const { return StringPrintf( - "[ SceneStateManager camera: %s film: %s sampler: %s integrator: %s " + "[ BasicSceneBuilder camera: %s film: %s sampler: %s integrator: %s " "filter: %s accelerator: %s ]", camera, film, sampler, integrator, filter, accelerator); } -SceneStateManager::GraphicsState::GraphicsState() { +BasicSceneBuilder::GraphicsState::GraphicsState() { currentMaterialIndex = 0; } @@ -83,8 +84,8 @@ SceneStateManager::GraphicsState::GraphicsState() { STAT_COUNTER("Scene/Object instances created", nObjectInstancesCreated); STAT_COUNTER("Scene/Object instances used", nObjectInstancesUsed); -// SceneStateManager Method Definitions -SceneStateManager::SceneStateManager(BasicScene *scene) +// BasicSceneBuilder Method Definitions +BasicSceneBuilder::BasicSceneBuilder(BasicScene *scene) : scene(scene) #ifdef PBRT_BUILD_GPU_RENDERER , @@ -97,47 +98,48 @@ SceneStateManager::SceneStateManager(BasicScene *scene) sampler.name = SceneEntity::internedStrings.Lookup("zsobol"); filter.name = SceneEntity::internedStrings.Lookup("gaussian"); integrator.name = SceneEntity::internedStrings.Lookup("volpath"); - - ParameterDictionary dict({}, RGBColorSpace::sRGB); - currentMaterialIndex = scene->AddMaterial(SceneEntity("diffuse", dict, {})); accelerator.name = SceneEntity::internedStrings.Lookup("bvh"); + film.name = SceneEntity::internedStrings.Lookup("rgb"); film.parameters = ParameterDictionary({}, RGBColorSpace::sRGB); + + ParameterDictionary dict({}, RGBColorSpace::sRGB); + currentMaterialIndex = scene->AddMaterial(SceneEntity("diffuse", dict, {})); } -void SceneStateManager::ReverseOrientation(FileLoc loc) { +void BasicSceneBuilder::ReverseOrientation(FileLoc loc) { VERIFY_WORLD("ReverseOrientation"); graphicsState.reverseOrientation = !graphicsState.reverseOrientation; } -void SceneStateManager::ColorSpace(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::ColorSpace(const std::string &name, FileLoc loc) { if (const RGBColorSpace *cs = RGBColorSpace::GetNamed(name)) graphicsState.colorSpace = cs; else Error(&loc, "%s: color space unknown", name); } -void SceneStateManager::Identity(FileLoc loc) { +void BasicSceneBuilder::Identity(FileLoc loc) { FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = pbrt::Transform();) } -void SceneStateManager::Translate(Float dx, Float dy, Float dz, FileLoc loc) { +void BasicSceneBuilder::Translate(Float dx, Float dy, Float dz, FileLoc loc) { FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = graphicsState.ctm[i] * pbrt::Translate(Vector3f(dx, dy, dz));) } -void SceneStateManager::CoordinateSystem(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::CoordinateSystem(const std::string &name, FileLoc loc) { namedCoordinateSystems[name] = graphicsState.ctm; } -void SceneStateManager::CoordSysTransform(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::CoordSysTransform(const std::string &name, FileLoc loc) { if (namedCoordinateSystems.find(name) != namedCoordinateSystems.end()) graphicsState.ctm = namedCoordinateSystems[name]; else Warning(&loc, "Couldn't find named coordinate system \"%s\"", name); } -void SceneStateManager::Camera(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::Camera(const std::string &name, ParsedParameterVector params, FileLoc loc) { ParameterDictionary dict(std::move(params), graphicsState.colorSpace); @@ -156,18 +158,20 @@ void SceneStateManager::Camera(const std::string &name, ParsedParameterVector pa graphicsState.currentOutsideMedium); } -void SceneStateManager::AttributeBegin(FileLoc loc) { +void BasicSceneBuilder::AttributeBegin(FileLoc loc) { VERIFY_WORLD("AttributeBegin"); pushedGraphicsStates.push_back(graphicsState); pushStack.push_back(std::make_pair('a', loc)); } -void SceneStateManager::AttributeEnd(FileLoc loc) { +void BasicSceneBuilder::AttributeEnd(FileLoc loc) { VERIFY_WORLD("AttributeEnd"); + // Issue error on unmatched _AttributeEnd_ if (pushedGraphicsStates.empty()) { Error(&loc, "Unmatched AttributeEnd encountered. Ignoring it."); return; } + // NOTE: must keep the following consistent with code in ObjectEnd graphicsState = std::move(pushedGraphicsStates.back()); pushedGraphicsStates.pop_back(); @@ -181,7 +185,7 @@ void SceneStateManager::AttributeEnd(FileLoc loc) { pushStack.pop_back(); } -void SceneStateManager::Attribute(const std::string &target, ParsedParameterVector attrib, +void BasicSceneBuilder::Attribute(const std::string &target, ParsedParameterVector attrib, FileLoc loc) { ParsedParameterVector *currentAttributes = nullptr; if (target == "shape") { @@ -212,24 +216,48 @@ void SceneStateManager::Attribute(const std::string &target, ParsedParameterVect } } -void SceneStateManager::WorldBegin(FileLoc loc) { +void BasicSceneBuilder::Sampler(const std::string &name, ParsedParameterVector params, + FileLoc loc) { + ParameterDictionary dict(std::move(params), graphicsState.colorSpace); + VERIFY_OPTIONS("Sampler"); + sampler = SceneEntity(name, std::move(dict), loc); +} + +void BasicSceneBuilder::WorldBegin(FileLoc loc) { VERIFY_OPTIONS("WorldBegin"); + // Reset graphics state for _WorldBegin_ currentBlock = BlockState::WorldBlock; for (int i = 0; i < MaxTransforms; ++i) graphicsState.ctm[i] = pbrt::Transform(); graphicsState.activeTransformBits = AllTransformsBits; namedCoordinateSystems["world"] = graphicsState.ctm; - // Pass these along now - scene->SetFilm(std::move(film)); + // Pass pre-_WorldBegin_ entities to _scene_ scene->SetSampler(std::move(sampler)); + + scene->SetFilm(std::move(film)); scene->SetIntegrator(std::move(integrator)); scene->SetFilter(std::move(filter)); scene->SetAccelerator(std::move(accelerator)); scene->SetCamera(std::move(camera)); } -void SceneStateManager::LightSource(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::MakeNamedMedium(const std::string &name, + ParsedParameterVector params, FileLoc loc) { + ParameterDictionary dict(std::move(params), graphicsState.mediumAttributes, + graphicsState.colorSpace); + // Issue error if medium _name_ is multiply-defined + if (mediumNames.find(name) != mediumNames.end()) { + ErrorExitDeferred(&loc, "Named medium \"%s\" redefined.", name); + return; + } + mediumNames.insert(name); + + scene->AddMedium( + TransformedSceneEntity(name, std::move(dict), loc, RenderFromObject())); +} + +void BasicSceneBuilder::LightSource(const std::string &name, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("LightSource"); ParameterDictionary dict(std::move(params), graphicsState.lightAttributes, @@ -238,7 +266,7 @@ void SceneStateManager::LightSource(const std::string &name, ParsedParameterVect graphicsState.currentOutsideMedium)); } -void SceneStateManager::Shape(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::Shape(const std::string &name, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("Shape"); @@ -286,7 +314,7 @@ void SceneStateManager::Shape(const std::string &name, ParsedParameterVector par } } -void SceneStateManager::ObjectBegin(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::ObjectBegin(const std::string &name, FileLoc loc) { VERIFY_WORLD("ObjectBegin"); pushedGraphicsStates.push_back(graphicsState); @@ -306,7 +334,7 @@ void SceneStateManager::ObjectBegin(const std::string &name, FileLoc loc) { activeInstanceDefinition = new ActiveInstanceDefinition(name, loc); } -void SceneStateManager::ObjectEnd(FileLoc loc) { +void BasicSceneBuilder::ObjectEnd(FileLoc loc) { VERIFY_WORLD("ObjectEnd"); if (!activeInstanceDefinition) { ErrorExitDeferred(&loc, "ObjectEnd called outside of instance definition"); @@ -340,7 +368,7 @@ void SceneStateManager::ObjectEnd(FileLoc loc) { activeInstanceDefinition = nullptr; } -void SceneStateManager::ObjectInstance(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::ObjectInstance(const std::string &name, FileLoc loc) { VERIFY_WORLD("ObjectInstance"); if (activeInstanceDefinition) { @@ -366,7 +394,7 @@ void SceneStateManager::ObjectInstance(const std::string &name, FileLoc loc) { } } -void SceneStateManager::EndOfFiles() { +void BasicSceneBuilder::EndOfFiles() { if (currentBlock != BlockState::WorldBlock) ErrorExitDeferred("End of files before \"WorldBegin\"."); @@ -387,13 +415,13 @@ void SceneStateManager::EndOfFiles() { scene->Done(); } -SceneStateManager *SceneStateManager::CopyForImport() { - SceneStateManager *importManager = new SceneStateManager(scene); - importManager->renderFromWorld = renderFromWorld; - importManager->graphicsState = graphicsState; - importManager->currentBlock = currentBlock; +BasicSceneBuilder *BasicSceneBuilder::CopyForImport() { + BasicSceneBuilder *importBuilder = new BasicSceneBuilder(scene); + importBuilder->renderFromWorld = renderFromWorld; + importBuilder->graphicsState = graphicsState; + importBuilder->currentBlock = currentBlock; if (activeInstanceDefinition) { - importManager->activeInstanceDefinition = new ActiveInstanceDefinition( + importBuilder->activeInstanceDefinition = new ActiveInstanceDefinition( activeInstanceDefinition->entity.name, activeInstanceDefinition->entity.loc); // In case of nested imports, go up to the true root parent since @@ -402,13 +430,13 @@ SceneStateManager *SceneStateManager::CopyForImport() { ActiveInstanceDefinition *parent = activeInstanceDefinition; while (parent->parent) parent = parent->parent; - importManager->activeInstanceDefinition->parent = parent; + importBuilder->activeInstanceDefinition->parent = parent; ++parent->activeImports; } - return importManager; + return importBuilder; } -void SceneStateManager::MergeImported(SceneStateManager *imported) { +void BasicSceneBuilder::MergeImported(BasicSceneBuilder *imported) { while (!imported->pushedGraphicsStates.empty()) { ErrorExitDeferred("Missing end to AttributeBegin"); imported->pushedGraphicsStates.pop_back(); @@ -461,7 +489,7 @@ void SceneStateManager::MergeImported(SceneStateManager *imported) { mergeSet(spectrumTextureNames, imported->spectrumTextureNames, "texture"); } -void SceneStateManager::Option(const std::string &name, const std::string &value, +void BasicSceneBuilder::Option(const std::string &name, const std::string &value, FileLoc loc) { std::string nName = normalizeArg(name); @@ -511,84 +539,76 @@ void SceneStateManager::Option(const std::string &name, const std::string &value ErrorExitDeferred(&loc, "%s: unknown option", name); } -void SceneStateManager::Transform(Float tr[16], FileLoc loc) { +void BasicSceneBuilder::Transform(Float tr[16], FileLoc loc) { FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = Transpose( pbrt::Transform(SquareMatrix<4>(pstd::MakeSpan(tr, 16))));) } -void SceneStateManager::ConcatTransform(Float tr[16], FileLoc loc) { +void BasicSceneBuilder::ConcatTransform(Float tr[16], FileLoc loc) { FOR_ACTIVE_TRANSFORMS( graphicsState.ctm[i] = graphicsState.ctm[i] * Transpose(pbrt::Transform(SquareMatrix<4>(pstd::MakeSpan(tr, 16))));) } -void SceneStateManager::Rotate(Float angle, Float dx, Float dy, Float dz, FileLoc loc) { +void BasicSceneBuilder::Rotate(Float angle, Float dx, Float dy, Float dz, FileLoc loc) { FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = graphicsState.ctm[i] * pbrt::Rotate(angle, Vector3f(dx, dy, dz));) } -void SceneStateManager::Scale(Float sx, Float sy, Float sz, FileLoc loc) { +void BasicSceneBuilder::Scale(Float sx, Float sy, Float sz, FileLoc loc) { FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = graphicsState.ctm[i] * pbrt::Scale(sx, sy, sz);) } -void SceneStateManager::LookAt(Float ex, Float ey, Float ez, Float lx, Float ly, Float lz, +void BasicSceneBuilder::LookAt(Float ex, Float ey, Float ez, Float lx, Float ly, Float lz, Float ux, Float uy, Float uz, FileLoc loc) { class Transform lookAt = pbrt::LookAt(Point3f(ex, ey, ez), Point3f(lx, ly, lz), Vector3f(ux, uy, uz)); FOR_ACTIVE_TRANSFORMS(graphicsState.ctm[i] = graphicsState.ctm[i] * lookAt;); } -void SceneStateManager::ActiveTransformAll(FileLoc loc) { +void BasicSceneBuilder::ActiveTransformAll(FileLoc loc) { graphicsState.activeTransformBits = AllTransformsBits; } -void SceneStateManager::ActiveTransformEndTime(FileLoc loc) { +void BasicSceneBuilder::ActiveTransformEndTime(FileLoc loc) { graphicsState.activeTransformBits = EndTransformBits; } -void SceneStateManager::ActiveTransformStartTime(FileLoc loc) { +void BasicSceneBuilder::ActiveTransformStartTime(FileLoc loc) { graphicsState.activeTransformBits = StartTransformBits; } -void SceneStateManager::TransformTimes(Float start, Float end, FileLoc loc) { +void BasicSceneBuilder::TransformTimes(Float start, Float end, FileLoc loc) { VERIFY_OPTIONS("TransformTimes"); graphicsState.transformStartTime = start; graphicsState.transformEndTime = end; } -void SceneStateManager::PixelFilter(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::PixelFilter(const std::string &name, ParsedParameterVector params, FileLoc loc) { ParameterDictionary dict(std::move(params), graphicsState.colorSpace); VERIFY_OPTIONS("PixelFilter"); filter = SceneEntity(name, std::move(dict), loc); } -void SceneStateManager::Film(const std::string &type, ParsedParameterVector params, +void BasicSceneBuilder::Film(const std::string &type, ParsedParameterVector params, FileLoc loc) { ParameterDictionary dict(std::move(params), graphicsState.colorSpace); VERIFY_OPTIONS("Film"); film = SceneEntity(type, std::move(dict), loc); } -void SceneStateManager::Sampler(const std::string &name, ParsedParameterVector params, - FileLoc loc) { - ParameterDictionary dict(std::move(params), graphicsState.colorSpace); - - VERIFY_OPTIONS("Sampler"); - sampler = SceneEntity(name, std::move(dict), loc); -} - -void SceneStateManager::Accelerator(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::Accelerator(const std::string &name, ParsedParameterVector params, FileLoc loc) { ParameterDictionary dict(std::move(params), graphicsState.colorSpace); VERIFY_OPTIONS("Accelerator"); accelerator = SceneEntity(name, std::move(dict), loc); } -void SceneStateManager::Integrator(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::Integrator(const std::string &name, ParsedParameterVector params, FileLoc loc) { ParameterDictionary dict(std::move(params), graphicsState.colorSpace); @@ -596,29 +616,13 @@ void SceneStateManager::Integrator(const std::string &name, ParsedParameterVecto integrator = SceneEntity(name, std::move(dict), loc); } -void SceneStateManager::MakeNamedMedium(const std::string &name, - ParsedParameterVector params, FileLoc loc) { - ParameterDictionary dict(std::move(params), graphicsState.mediumAttributes, - graphicsState.colorSpace); - - if (mediumNames.find(name) != mediumNames.end()) { - ErrorExitDeferred(&loc, "Named medium \"%s\" redefined.", name); - return; - } - - mediumNames.insert(name); - - scene->AddMedium( - TransformedSceneEntity(name, std::move(dict), loc, RenderFromObject())); -} - -void SceneStateManager::MediumInterface(const std::string &insideName, +void BasicSceneBuilder::MediumInterface(const std::string &insideName, const std::string &outsideName, FileLoc loc) { graphicsState.currentInsideMedium = insideName; graphicsState.currentOutsideMedium = outsideName; } -void SceneStateManager::Texture(const std::string &name, const std::string &type, +void BasicSceneBuilder::Texture(const std::string &name, const std::string &type, const std::string &texname, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("Texture"); @@ -648,7 +652,7 @@ void SceneStateManager::Texture(const std::string &name, const std::string &type name, TextureSceneEntity(texname, std::move(dict), loc, RenderFromObject())); } -void SceneStateManager::Material(const std::string &name, ParsedParameterVector params, +void BasicSceneBuilder::Material(const std::string &name, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("Material"); @@ -660,7 +664,7 @@ void SceneStateManager::Material(const std::string &name, ParsedParameterVector graphicsState.currentMaterialName.clear(); } -void SceneStateManager::MakeNamedMaterial(const std::string &name, +void BasicSceneBuilder::MakeNamedMaterial(const std::string &name, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("MakeNamedMaterial"); @@ -676,13 +680,13 @@ void SceneStateManager::MakeNamedMaterial(const std::string &name, scene->AddNamedMaterial(name, SceneEntity("", std::move(dict), loc)); } -void SceneStateManager::NamedMaterial(const std::string &name, FileLoc loc) { +void BasicSceneBuilder::NamedMaterial(const std::string &name, FileLoc loc) { VERIFY_WORLD("NamedMaterial"); graphicsState.currentMaterialName = name; graphicsState.currentMaterialIndex = -1; } -void SceneStateManager::AreaLightSource(const std::string &name, +void BasicSceneBuilder::AreaLightSource(const std::string &name, ParsedParameterVector params, FileLoc loc) { VERIFY_WORLD("AreaLightSource"); graphicsState.areaLightName = name; @@ -692,6 +696,73 @@ void SceneStateManager::AreaLightSource(const std::string &name, } // BasicScene Method Definitions +void BasicScene::SetSampler(SceneEntity sampler) { + this->sampler = std::move(sampler); +} + +void BasicScene::AddMedium(TransformedSceneEntity medium) { + std::lock_guard lock(mediaMutex); + // Define _create_ lambda function for _Medium_ creation + auto create = [=]() { + std::string type = medium.parameters.GetOneString("type", ""); + // Check for missing medium ``type'' or animated medium transform + if (type.empty()) + ErrorExit(&medium.loc, "No parameter string \"type\" found for medium."); + if (medium.renderFromObject.IsAnimated()) + Warning(&medium.loc, "Animated transformation provided for medium. Only the " + "start transform will be used."); + + return Medium::Create(type, medium.parameters, + medium.renderFromObject.startTransform, &medium.loc, + threadAllocators.Get()); + }; + + mediaFutures[medium.name] = RunAsync(create); +} + +std::map BasicScene::CreateMedia() { + std::lock_guard lock(mediaMutex); + // Consume futures for asynchronously-created _Medium_ objects + LOG_VERBOSE("Consume media futures start"); + for (auto &m : mediaFutures) { + CHECK(mediaMap.find(m.first) == mediaMap.end()); + mediaMap[m.first] = m.second.Get(); + } + mediaFutures.clear(); + LOG_VERBOSE("Consume media futures finished"); + + return mediaMap; +} + +Sampler BasicScene::CreateSampler(Point2i res) const { + Allocator alloc = threadAllocators.Get(); + return Sampler::Create(sampler.name, sampler.parameters, res, &sampler.loc, alloc); +} + +Filter BasicScene::CreateFilter() const { + Allocator alloc = threadAllocators.Get(); + return Filter::Create(filter.name, filter.parameters, &filter.loc, alloc); +} + +Film BasicScene::CreateFilm(Float exposureTime, Filter filter) const { + Allocator alloc = threadAllocators.Get(); + return Film::Create(film.name, film.parameters, exposureTime, camera.cameraTransform, + filter, &film.loc, alloc); +} + +Camera BasicScene::CreateCamera(Medium cameraMedium, Film film) const { + Allocator alloc = threadAllocators.Get(); + return Camera::Create(camera.name, camera.parameters, cameraMedium, + camera.cameraTransform, film, &camera.loc, alloc); +} + +std::unique_ptr BasicScene::CreateIntegrator( + Camera camera, Sampler sampler, Primitive accel, std::vector lights) const { + const RGBColorSpace *integratorColorSpace = film.parameters.ColorSpace(); + return Integrator::Create(integrator.name, integrator.parameters, camera, sampler, + accel, lights, integratorColorSpace, &integrator.loc); +} + BasicScene::BasicScene() : threadAllocators([]() { pstd::pmr::memory_resource *baseResource = pstd::pmr::get_default_resource(); @@ -709,10 +780,6 @@ void BasicScene::SetFilm(SceneEntity film) { this->film = std::move(film); } -void BasicScene::SetSampler(SceneEntity sampler) { - this->sampler = std::move(sampler); -} - void BasicScene::SetIntegrator(SceneEntity integrator) { this->integrator = std::move(integrator); } @@ -768,32 +835,13 @@ void BasicScene::startLoadingNormalMaps(const ParameterDictionary ¶meters) { normalMapFutures[filename] = RunAsync(create, filename); } -void BasicScene::AddMedium(TransformedSceneEntity medium) { - std::lock_guard lock(mediaMutex); - - auto create = [=]() { - std::string type = medium.parameters.GetOneString("type", ""); - if (type.empty()) - ErrorExit(&medium.loc, "No parameter string \"type\" found for medium."); - - if (medium.renderFromObject.IsAnimated()) - Warning(&medium.loc, "Animated transformation provided for medium. Only the " - "start transform will be used."); - return Medium::Create(type, medium.parameters, - medium.renderFromObject.startTransform, &medium.loc, - threadAllocators.Get()); - }; - - mediaFutures[medium.name] = RunAsync(create); -} - void BasicScene::AddFloatTexture(std::string name, TextureSceneEntity texture) { if (texture.renderFromObject.IsAnimated()) Warning(&texture.loc, "Animated world to texture transforms are not supported. " "Using start transform."); std::lock_guard lock(textureMutex); - if (texture.texName != "imagemap" && texture.texName != "ptex") { + if (texture.name != "imagemap" && texture.name != "ptex") { serialFloatTextures.push_back( std::make_pair(std::move(name), std::move(texture))); return; @@ -826,7 +874,7 @@ void BasicScene::AddFloatTexture(std::string name, TextureSceneEntity texture) { // Pass nullptr for the textures, since they shouldn't be accessed // anyway. TextureParameterDictionary texDict(&texture.parameters, nullptr); - return FloatTexture::Create(texture.texName, renderFromTexture, texDict, + return FloatTexture::Create(texture.name, renderFromTexture, texDict, &texture.loc, alloc, Options->useGPU); }; floatTextureFutures[name] = RunAsync(create, texture); @@ -835,7 +883,7 @@ void BasicScene::AddFloatTexture(std::string name, TextureSceneEntity texture) { void BasicScene::AddSpectrumTexture(std::string name, TextureSceneEntity texture) { std::lock_guard lock(textureMutex); - if (texture.texName != "imagemap" && texture.texName != "ptex") { + if (texture.name != "imagemap" && texture.name != "ptex") { serialSpectrumTextures.push_back( std::make_pair(std::move(name), std::move(texture))); return; @@ -871,7 +919,7 @@ void BasicScene::AddSpectrumTexture(std::string name, TextureSceneEntity texture TextureParameterDictionary texDict(&texture.parameters, nullptr); // Only create SpectrumType::Albedo for now; will get the other two // types in CreateTextures(). - return SpectrumTexture::Create(texture.texName, renderFromTexture, texDict, + return SpectrumTexture::Create(texture.name, renderFromTexture, texDict, SpectrumType::Albedo, &texture.loc, alloc, Options->useGPU); }; @@ -997,7 +1045,6 @@ void BasicScene::Done() { } void BasicScene::CreateMaterials(const NamedTextures &textures, - ThreadLocal &threadAllocators, std::map *namedMaterialsOut, std::vector *materialsOut) { LOG_VERBOSE("Starting to consume normal map futures"); @@ -1075,10 +1122,10 @@ NamedTextures BasicScene::CreateTextures() { // These should be fast since they should hit the texture cache SpectrumTexture unboundedTex = SpectrumTexture::Create( - tex.second.texName, renderFromTexture, texDict, SpectrumType::Unbounded, + tex.second.name, renderFromTexture, texDict, SpectrumType::Unbounded, &tex.second.loc, alloc, Options->useGPU); SpectrumTexture illumTex = SpectrumTexture::Create( - tex.second.texName, renderFromTexture, texDict, SpectrumType::Illuminant, + tex.second.name, renderFromTexture, texDict, SpectrumType::Illuminant, &tex.second.loc, alloc, Options->useGPU); textures.unboundedSpectrumTextures[tex.first] = unboundedTex; @@ -1091,9 +1138,8 @@ NamedTextures BasicScene::CreateTextures() { pbrt::Transform renderFromTexture = tex.second.renderFromObject.startTransform; TextureParameterDictionary texDict(&tex.second.parameters, &textures); - FloatTexture t = - FloatTexture::Create(tex.second.texName, renderFromTexture, texDict, - &tex.second.loc, alloc, Options->useGPU); + FloatTexture t = FloatTexture::Create(tex.second.name, renderFromTexture, texDict, + &tex.second.loc, alloc, Options->useGPU); textures.floatTextures[tex.first] = t; } @@ -1107,13 +1153,13 @@ NamedTextures BasicScene::CreateTextures() { pbrt::Transform renderFromTexture = tex.second.renderFromObject.startTransform; TextureParameterDictionary texDict(&tex.second.parameters, &textures); SpectrumTexture albedoTex = SpectrumTexture::Create( - tex.second.texName, renderFromTexture, texDict, SpectrumType::Albedo, + tex.second.name, renderFromTexture, texDict, SpectrumType::Albedo, &tex.second.loc, alloc, Options->useGPU); SpectrumTexture unboundedTex = SpectrumTexture::Create( - tex.second.texName, renderFromTexture, texDict, SpectrumType::Unbounded, + tex.second.name, renderFromTexture, texDict, SpectrumType::Unbounded, &tex.second.loc, alloc, Options->useGPU); SpectrumTexture illumTex = SpectrumTexture::Create( - tex.second.texName, renderFromTexture, texDict, SpectrumType::Illuminant, + tex.second.name, renderFromTexture, texDict, SpectrumType::Illuminant, &tex.second.loc, alloc, Options->useGPU); textures.albedoSpectrumTextures[tex.first] = albedoTex; @@ -1125,21 +1171,6 @@ NamedTextures BasicScene::CreateTextures() { return textures; } -std::map BasicScene::CreateMedia() { - std::lock_guard lock(mediaMutex); - - LOG_VERBOSE("Consume media futures start"); - for (auto &m : mediaFutures) { - CHECK(mediaMap.find(m.first) == mediaMap.end()); - mediaMap[m.first] = m.second.Get(); - } - - mediaFutures.clear(); - LOG_VERBOSE("Consume media futures finished"); - - return mediaMap; -} - std::vector BasicScene::CreateLights( const NamedTextures &textures, std::map *> *shapeIndexToAreaLights) { diff --git a/src/pbrt/scene.h b/src/pbrt/scene.h index d903194..76109e1 100644 --- a/src/pbrt/scene.h +++ b/src/pbrt/scene.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -28,6 +29,8 @@ namespace pbrt { +class Integrator; + // SceneEntity Definition struct SceneEntity { // SceneEntity Public Methods @@ -170,21 +173,7 @@ struct InstanceDefinitionSceneEntity { std::vector animatedShapes; }; -struct TextureSceneEntity : public TransformedSceneEntity { - TextureSceneEntity() = default; - TextureSceneEntity(const std::string &texName, ParameterDictionary parameters, - FileLoc loc, const AnimatedTransform &renderFromObject) - : TransformedSceneEntity("", std::move(parameters), loc, renderFromObject), - texName(texName) {} - - std::string ToString() const { - return StringPrintf("[ TextureSeneEntity name: %s parameters: %s loc: %s " - "renderFromObject: %s texName: %s ]", - name, parameters, loc, renderFromObject, texName); - } - - std::string texName; -}; +using TextureSceneEntity = TransformedSceneEntity; struct LightSceneEntity : public TransformedSceneEntity { LightSceneEntity() = default; @@ -272,10 +261,12 @@ struct TransformSet { // BasicScene Definition class BasicScene { public: + // BasicScene Public Methods BasicScene(); - void SetFilm(SceneEntity film); void SetSampler(SceneEntity sampler); + + void SetFilm(SceneEntity film); void SetIntegrator(SceneEntity integrator); void SetFilter(SceneEntity filter); void SetAccelerator(SceneEntity accelerator); @@ -295,19 +286,16 @@ class BasicScene { void Done(); - NamedTextures CreateTextures(); - void CreateMaterials(const NamedTextures &sceneTextures, - ThreadLocal &threadAllocators, std::map *namedMaterials, std::vector *materials); - std::map CreateMedia(); - std::vector CreateLights( const NamedTextures &textures, std::map *> *shapeIndexToAreaLights); + std::map CreateMedia(); + Primitive CreateAggregate( const NamedTextures &textures, const std::map *> &shapeIndexToAreaLights, @@ -315,12 +303,20 @@ class BasicScene { const std::map &namedMaterials, const std::vector &materials); - // Public for now... - public: + Sampler CreateSampler(Point2i res) const; + + Filter CreateFilter() const; + Film CreateFilm(Float exposureTime, Filter filter) const; + Camera CreateCamera(Medium cameraMedium, Film film) const; + std::unique_ptr CreateIntegrator(Camera camera, Sampler sampler, + Primitive accel, + std::vector lights) const; + + NamedTextures CreateTextures(); + // BasicScene Public Members SceneEntity film, sampler, integrator, filter, accelerator; CameraSceneEntity camera; - std::vector> namedMaterials; std::vector materials; std::vector shapes; @@ -329,14 +325,14 @@ class BasicScene { std::map instanceDefinitions; private: + // BasicScene Private Methods void startLoadingNormalMaps(const ParameterDictionary ¶meters); - ThreadLocal threadAllocators; - + // BasicScene Private Members std::mutex mediaMutex; std::map> mediaFutures; + mutable ThreadLocal threadAllocators; std::map mediaMap; - std::mutex materialMutex; std::map> normalMapFutures; std::map normalMaps; @@ -361,11 +357,11 @@ class BasicScene { std::mutex instanceDefinitionMutex, instanceUseMutex; }; -// SceneStateManager Definition -class SceneStateManager : public ParserTarget { +// BasicSceneBuilder Definition +class BasicSceneBuilder : public ParserTarget { public: - // SceneStateManager Public Methods - SceneStateManager(BasicScene *scene); + // BasicSceneBuilder Public Methods + BasicSceneBuilder(BasicScene *scene); void Option(const std::string &name, const std::string &value, FileLoc loc); void Identity(FileLoc loc); void Translate(Float dx, Float dy, Float dz, FileLoc loc); @@ -413,13 +409,13 @@ class SceneStateManager : public ParserTarget { void EndOfFiles(); - SceneStateManager *CopyForImport(); - void MergeImported(SceneStateManager *); + BasicSceneBuilder *CopyForImport(); + void MergeImported(BasicSceneBuilder *); std::string ToString() const; private: - // SceneStateManager::GraphicsState Definition + // BasicSceneBuilder::GraphicsState Definition struct GraphicsState { // GraphicsState Public Methods GraphicsState(); @@ -447,7 +443,7 @@ class SceneStateManager : public ParserTarget { }; friend void parse(ParserTarget *scene, std::unique_ptr t); - // SceneStateManager Private Methods + // BasicSceneBuilder Private Methods class Transform RenderFromObject(int index) const { return pbrt::Transform((renderFromWorld * graphicsState.ctm[index]).GetMatrix()); } @@ -459,7 +455,7 @@ class SceneStateManager : public ParserTarget { bool CTMIsAnimated() const { return graphicsState.ctm.IsAnimated(); } - // SceneStateManager Private Members + // BasicSceneBuilder Private Members BasicScene *scene; GraphicsState graphicsState; enum class BlockState { OptionsBlock, WorldBlock }; @@ -490,9 +486,6 @@ class SceneStateManager : public ParserTarget { std::set namedMaterialNames, mediumNames; std::set floatTextureNames, spectrumTextureNames, instanceNames; int currentMaterialIndex = 0, currentLightIndex = -1; - - // These have to wait until WorldBegin to be passed along since they - // may be updated until then. SceneEntity film, sampler, integrator, filter, accelerator; CameraSceneEntity camera; }; diff --git a/src/pbrt/wavefront/integrator.cpp b/src/pbrt/wavefront/integrator.cpp index becc00b..7b842c0 100644 --- a/src/pbrt/wavefront/integrator.cpp +++ b/src/pbrt/wavefront/integrator.cpp @@ -120,8 +120,7 @@ WavefrontPathIntegrator::WavefrontPathIntegrator( return iter->second; }; - filter = Filter::Create(scene.filter.name, scene.filter.parameters, &scene.filter.loc, - alloc); + filter = scene.CreateFilter(); Float exposureTime = scene.camera.parameters.GetOneFloat("shutterclose", 1.f) - scene.camera.parameters.GetOneFloat("shutteropen", 0.f); @@ -130,17 +129,14 @@ WavefrontPathIntegrator::WavefrontPathIntegrator( "The specified camera shutter times imply that the shutter " "does not open. A black image will result."); - film = Film::Create(scene.film.name, scene.film.parameters, exposureTime, - scene.camera.cameraTransform, filter, &scene.film.loc, alloc); + film = scene.CreateFilm(exposureTime, filter); initializeVisibleSurface = film.UsesVisibleSurface(); - sampler = Sampler::Create(scene.sampler.name, scene.sampler.parameters, - film.FullResolution(), &scene.sampler.loc, alloc); + sampler = scene.CreateSampler(film.FullResolution()); samplesPerPixel = sampler.SamplesPerPixel(); Medium cameraMedium = findMedium(scene.camera.medium, &scene.camera.loc); - camera = Camera::Create(scene.camera.name, scene.camera.parameters, cameraMedium, - scene.camera.cameraTransform, film, &scene.camera.loc, alloc); + camera = scene.CreateCamera(cameraMedium, film); // Textures LOG_VERBOSE("Starting to create textures"); @@ -165,7 +161,7 @@ WavefrontPathIntegrator::WavefrontPathIntegrator( LOG_VERBOSE("Starting to create materials"); std::map namedMaterials; std::vector materials; - scene.CreateMaterials(textures, threadAllocators, &namedMaterials, &materials); + scene.CreateMaterials(textures, &namedMaterials, &materials); haveBasicEvalMaterial.fill(false); haveUniversalEvalMaterial.fill(false); -- GitLab