Exemplo n.º 1
0
    void VegetationSpawnManager::Render(
        Metal::DeviceContext& context, LightingParserContext& parserContext,
        unsigned techniqueIndex, RenderCore::Assets::DelayStep delayStep)
    {
        if (_pimpl->_cfg._objectTypes.empty()) return;

        _pimpl->FillInDrawCallSets();

        auto& sharedStates = _pimpl->_modelCache->GetSharedStateSet();
        auto captureMarker = sharedStates.CaptureState(
            context, parserContext.GetStateSetResolver(), parserContext.GetStateSetEnvironment());
        auto& state = parserContext.GetTechniqueContext()._runtimeState;
        state.SetParameter(u("SPAWNED_INSTANCE"), 1);
        auto cleanup = MakeAutoCleanup(
            [&state]() { state.SetParameter(u("SPAWNED_INSTANCE"), 0); });

        auto& resources = *_pimpl->_resources;
        for (unsigned b=0; b<unsigned(_pimpl->_drawCallSets.size()); ++b)
            ModelRenderer::RenderPrepared(
                RenderCore::Assets::ModelRendererContext(context, parserContext, techniqueIndex),
                sharedStates, _pimpl->_drawCallSets[b], delayStep,
                [&context, b, &resources](ModelRenderer::DrawCallEvent evnt)
                {
                    VegetationSpawn_DrawInstances(
                        context, resources, b, 
                        evnt._indexCount, evnt._firstIndex, evnt._firstVertex);
                });
    }
Exemplo n.º 2
0
    void BasicSceneParser::Model::RenderOpaque(
        RenderCore::Metal::DeviceContext* context, 
        LightingParserContext& parserContext, 
        unsigned techniqueIndex)
    {
            //  This class shows a simple method for rendering an object
            //  using the ModelRenderer class.
            //
            //  There are a few steps involved. The ModelRenderer/ModelScaffold
            //  classes are very flexible and efficient. But the flexibility
            //  brings with it a little bit of complexity.
            //
            //  Basically, I think of a "model" is an discrete single exporter from Max 
            //  (or Maya, etc).
            //  It might come via a Collada file or some intermediate format. But at
            //  run-time we want some highly optimized format that can be loaded quickly,
            //  and that also allows for a certain amount of flexibility while rendering.
            //
            //  There are 3 important classes:
            //      ModelRenderer is the class that can actually render a model file. It's
            //      mostly a static class, however. Once it's constructed, we can't change
            //      it (other than by setting animation parameters). ModelRenderer manages
            //      the low-level graphics API objects required for rendering.
            //
            //      ModelScaffold is a light weight representation of what it contained in
            //      the model file. It never uses the low level graphics API, and we can't
            //      render from it directly.
            //
            //      SharedStateSet contains state related information (from the low level
            //      graphics API) for rendering one or more models. Normally we want multiple
            //      models to share the same SharedStateSet. When multiple models use the
            //      same SharedStateSet, we can reorder rendering operations between all those
            //      models. But we can choose the granularity at which this occurs.
            //      So, for example if we have a city made from many models, we can created a
            //      single SharedStateSet for that city. That would means we can perform
            //      draw command sorting on the city as a whole (rather than just within a 
            //      single model)
            //
            //  First, we need to load the ModelScaffold object. We have to load this before
            //  we can construct the ModelRenderer.
        using namespace RenderCore::Assets;
        if (!_modelRenderer) {

                //  We're going to use the Assets::GetAssetComp<> function to initialize
                //  our ModelScaffold. These are other ways to create a ModelScaffold, 
                //  though (eg, Assets::GetAsset<>, or just using the constructor directly)
                //
                //  In this case, we use GetAssetComp to cause the system to execute a
                //  Collada compile when required. This will compile the input Collada
                //  file into our run-time format in a file in the intermediate store.
                //
                //  The compile can occur in a background thread. When this happens,
                //  we will get thrown a Assets::Exceptions::PendingAsset exception
                //  until the compile is finished. We aware that some assets that are
                //  compiled or loaded in the background can throw PendingAsset when
                //  they are not ready!
                //
                //  We can also get a Assets::Exceptions::InvalidAsset if asset can
                //  never be correctly loaded (eg, missing file or something)
            const char sampleAsset[] = "game/model/galleon/galleon.dae";
            const char sampleMaterial[] = "game/model/galleon/galleon.material";
            auto& scaffold = Assets::GetAssetComp<ModelScaffold>(sampleAsset);
            auto& matScaffold = Assets::GetAssetComp<MaterialScaffold>(sampleMaterial, sampleAsset);

                //  We want to create a Assets::DirectorySearchRules object before we
                //  make the ModelRenderer. This is used when we need to find the 
                //  dependent assets (like textures). In this case, we just need to
                //  add the directory that contains the dae file as a search path
                //  (though if we needed, we could add other paths as well).
            auto searchRules = Assets::DefaultDirectorySearchRules(sampleAsset);

                //  Now, finally we can construct the model render.
                //
                //  Each model renderer is associated with a single level of detail
                //  (though the ModelScaffold could contain information for multiple
                //  levels of detail)
                //
                //  During the constructor of ModelRenderer, all of the low level 
                //  graphics API resources will be constructed. So it can be expensive
                //  in some cases.
                //
                //  Also note that if we get an allocation failure while making a 
                //  low level resource (like a vertex buffer), it will throw an
                //  exception.
            const unsigned levelOfDetail = 0;
            _modelRenderer = std::unique_ptr<ModelRenderer>(
                new ModelRenderer(
                    scaffold, matScaffold, ModelRenderer::Supplements(),
                    *_sharedStateSet, &searchRules, levelOfDetail));
        }

            //  Before using SharedStateSet for the first time, we need to capture the device 
            //  context state. If we were rendering multiple models with the same shared state, we would 
            //  capture once and render multiple times with the same capture.
        auto captureMarker = _sharedStateSet->CaptureState(*context, parserContext.GetStateSetResolver(), parserContext.GetStateSetEnvironment());

            //  Finally, we can render the object!
        _modelRenderer->Render(
            RenderCore::Assets::ModelRendererContext(*context, parserContext, techniqueIndex),
            *_sharedStateSet, Identity<Float4x4>());
    }