Esempio n. 1
0
void
HdxShadowTask::Sync(HdSceneDelegate* delegate,
                    HdTaskContext* ctx,
                    HdDirtyBits* dirtyBits)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();
    GLF_GROUP_FUNCTION();

    // Extract the lighting context information from the task context
    GlfSimpleLightingContextRefPtr lightingContext;
    if (!_GetTaskContextData(ctx, 
            HdxTokens->lightingContext, 
            &lightingContext)) {
        return;
    }

    GlfSimpleLightVector const glfLights = lightingContext->GetLights();
    GlfSimpleShadowArrayRefPtr const shadows = lightingContext->GetShadows();
    HdRenderIndex &renderIndex = delegate->GetRenderIndex();

    const bool dirtyParams = (*dirtyBits) & HdChangeTracker::DirtyParams;
    if (dirtyParams) {
        // Extract the new shadow task params from exec
        if (!_GetTaskParams(delegate, &_params)) {
            return;
        }
    }

    if (!renderIndex.IsSprimTypeSupported(HdPrimTypeTokens->simpleLight)) {
        return;
    }

    // Iterate through all lights and for those that have shadows enabled
    // and ensure we have enough passes to render the shadows.
    size_t passCount = 0;
    for (size_t lightId = 0; lightId < glfLights.size(); lightId++) {
        const HdStLight* light = static_cast<const HdStLight*>(
            renderIndex.GetSprim(HdPrimTypeTokens->simpleLight,
                                 glfLights[lightId].GetID()));

        if (!glfLights[lightId].HasShadow()) {
            continue;
        }

        // It is possible the light is nullptr for area lights converted to 
        // simple lights, however they should not have shadows enabled.
        TF_VERIFY(light);

        // Extract the collection from the HD light
        VtValue vtShadowCollection =
            light->Get(HdLightTokens->shadowCollection);
        const HdRprimCollection &col =
            vtShadowCollection.IsHolding<HdRprimCollection>() ?
            vtShadowCollection.Get<HdRprimCollection>() : HdRprimCollection();

        // Creates or reuses a pass with the right geometry that will be
        // used during Execute phase to draw the shadow maps.
        if (passCount < _passes.size()) {
            // Note here that we may want to sort the passes by collection
            // to invalidate fewer passes if the collections match already.
            // SetRprimCollection checks for identity changes on the collection
            // and no-ops in that case.
            _passes[passCount]->SetRprimCollection(col);
        } else {
            // Create a new pass if we didn't have enough already,
            HdRenderPassSharedPtr p = boost::make_shared<HdSt_RenderPass>
                (&renderIndex, col);
            _passes.push_back(p);
        }
        passCount++;
    }
    
    // Shrink down to fit to conserve resources
    // We may want hysteresis here if we find the count goes up and down
    // frequently.
    if (_passes.size() > passCount) {
        _passes.resize(passCount);
    }
    
    // Shrink down to fit to conserve resources
    if (_renderPassStates.size() > _passes.size()) {
        _renderPassStates.resize(_passes.size());
    } 
    
    // Ensure all passes have the right params set.
    if (dirtyParams) {
        TF_FOR_ALL(it, _renderPassStates) {
            _UpdateDirtyParams(*it, _params);
        }
    }
Esempio n. 2
0
void
HdxShadowTask::_Sync(HdTaskContext* ctx)
{
    HD_TRACE_FUNCTION();
    HF_MALLOC_TAG_FUNCTION();

    // Extract the lighting context information from the task context
    GlfSimpleLightingContextRefPtr lightingContext;
    if (!_GetTaskContextData(ctx, HdxTokens->lightingContext, &lightingContext)) {
        return;
    }
    GlfSimpleShadowArrayRefPtr const shadows = lightingContext->GetShadows();

    _TaskDirtyState dirtyState;

    _GetTaskDirtyState(HdTokens->geometry, &dirtyState);


    // Check if the collection version has changed, if so, it means
    // that we should extract the new collections
    // from the lights in the render index, and then recreate the passes
    // required to render the shadow maps
    const bool collectionChanged = (_collectionVersion != dirtyState.collectionVersion);

    if ((dirtyState.bits & HdChangeTracker::DirtyParams) ||
        collectionChanged) {
        _collectionVersion = dirtyState.collectionVersion;

        // Extract the new shadow task params from exec
        HdxShadowTaskParams params;
        if (!_GetSceneDelegateValue(HdTokens->params, &params)) {
            return;
        }

        _depthBiasEnable = params.depthBiasEnable;
        _depthBiasConstantFactor = params.depthBiasConstantFactor;
        _depthBiasSlopeFactor = params.depthBiasSlopeFactor;
        _depthFunc = params.depthFunc;

        // XXX TODO: What to do about complexity?

        // We can now use the light information now
        // and create a pass for each
        _passes.clear();
        _renderPassStates.clear();

        HdSceneDelegate* delegate = GetDelegate();
        const HdRenderIndex &renderIndex = delegate->GetRenderIndex();
        
        // Extract the HD lights used to render the scene from the 
        // task context, we will use them to find out what
        // lights are dirty and if we need to update the
        // collection for shadows mapping
        
        // XXX: This is inefficient, need to be optimized
        SdfPathVector sprimPaths = renderIndex.GetSprimSubtree(
                                                   HdPrimTypeTokens->light,
                                                   SdfPath::AbsoluteRootPath());
        SdfPathVector lightPaths =
            HdxSimpleLightTask::ComputeIncludedLights(
                sprimPaths,
                params.lightIncludePaths,
                params.lightExcludePaths);
        
        HdxLightPtrConstVector lights;
        TF_FOR_ALL (it, lightPaths) {
             const HdxLight *light = static_cast<const HdxLight *>(
                                         renderIndex.GetSprim(
                                                 HdPrimTypeTokens->light, *it));

             if (light != nullptr) {
                lights.push_back(light);
            }
        }
        
        GlfSimpleLightVector const glfLights = lightingContext->GetLights();
        
        TF_VERIFY(lights.size() == glfLights.size());
        
        // Iterate through all lights and for those that have
        // shadows enabled we will extract the colection from 
        // the render index and create a pass that during execution
        // it will be used for generating each shadowmap
        for (size_t lightId = 0; lightId < glfLights.size(); lightId++) {
            
            if (!glfLights[lightId].HasShadow()) {
                continue;
            }
            
            // Extract the collection from the HD light
            VtValue vtShadowCollection =
                lights[lightId]->Get(HdxLightTokens->shadowCollection);
            const HdRprimCollection &col =
                vtShadowCollection.IsHolding<HdRprimCollection>() ?
                    vtShadowCollection.Get<HdRprimCollection>() : HdRprimCollection();

            // Creates a pass with the right geometry that will be
            // use during Execute phase to draw the maps
            HdRenderPassSharedPtr p = boost::make_shared<HdRenderPass>
                (&delegate->GetRenderIndex(), col);

            HdRenderPassShaderSharedPtr renderPassShadowShader
                (new HdRenderPassShader(HdxPackageRenderPassShadowShader()));
            HdRenderPassStateSharedPtr renderPassState
                (new HdRenderPassState(renderPassShadowShader));

            // Update the rest of the renderpass state parameters for this pass
            renderPassState->SetOverrideColor(params.overrideColor);
            renderPassState->SetWireframeColor(params.wireframeColor);
            renderPassState->SetLightingEnabled(false);
            
            // XXX : This can be removed when Hydra has support for 
            //       transparent objects.
            renderPassState->SetAlphaThreshold(1.0 /* params.alphaThreshold */);
            renderPassState->SetTessLevel(params.tessLevel);
            renderPassState->SetDrawingRange(params.drawingRange);
            renderPassState->SetCullStyle(params.cullStyle);
            
            _passes.push_back(p);
            _renderPassStates.push_back(renderPassState);
        }
    }