Correct way to modify CompositorShadowNode

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Correct way to modify CompositorShadowNode

Post by xrgo »

Hello! I am having a problem when re-creating my compositor workspace stuffs for VR, but first some context:

I do most of my stuffs by code instead of scripts, so I have a createShadowNodeDefinition method:

Code: Select all

void yWorkspaceManager::createShadowNodeDefinition(){

    Ogre::CompositorShadowNodeDef* shadowNodeDef = mCompositorManager->addShadowNodeDefinition( "MainEngineShadowNode" );

    int spotlightsShadows = 0;
    int textureCount = mPssmSplitsCount + spotlightsShadows;

    shadowNodeDef->setNumLocalTextureDefinitions( 1 );
    shadowNodeDef->setNumShadowTextureDefinitions( textureCount );
    shadowNodeDef->setNumTargetPass( textureCount+1 ); //+1 clear

    Ogre::TextureDefinitionBase::TextureDefinition *texDef = shadowNodeDef->addTextureDefinition( "shadowAtlas" );
    texDef->fsaa = false;
    texDef->width = 4096*textureCount;
    texDef->height = 4096;
    texDef->formatList.push_back( Ogre::PF_D32_FLOAT );


    float step = 1.0f/textureCount;

    for(int i=0; i<textureCount; i++){
        int lightIndex = 0;
        int split = i;
        if( i >= mPssmSplitsCount ){
            lightIndex = i-mPssmSplitsCount+1;
            split = 0;
        }
        Ogre::ShadowTextureDefinition *shadTexDef = shadowNodeDef->addShadowTextureDefinition( lightIndex, split, "shadowAtlas", 0, Ogre::Vector2( i*step, 0.0 ), Ogre::Vector2( step, 1.0 ), 0 );
        if( i >= mPssmSplitsCount ){
            shadTexDef->shadowMapTechnique = Ogre::SHADOWMAP_FOCUSED;
        }
        else{
            shadTexDef->shadowMapTechnique = Ogre::SHADOWMAP_PSSM;
            shadTexDef->numSplits = mPssmSplitsCount;
            shadTexDef->pssmLambda = mPssmLambda;
        }
    }

    {
        Ogre::CompositorTargetDef *targetDef = shadowNodeDef->addTargetPass( "shadowAtlas" );
        targetDef->setNumPasses( 1 );
        //Clear
        Ogre::CompositorPassClearDef *passClearDef = static_cast<Ogre::CompositorPassClearDef*>( targetDef->addPass( Ogre::PASS_CLEAR ) );
        passClearDef->mProfilingId = "SHADOW_CLEAR_PASS";
        passClearDef->mColourValue = Ogre::ColourValue::White;
        passClearDef->mIncludeOverlays = false;
    }

    for(int i=0; i<textureCount; i++){
        Ogre::CompositorTargetDef *targetDef = shadowNodeDef->addTargetPass( "shadowAtlas" );
        targetDef->setNumPasses( 1 );

        //Scene
        Ogre::CompositorPassSceneDef *passSceneDef = static_cast<Ogre::CompositorPassSceneDef*>( targetDef->addPass( Ogre::PASS_SCENE ) );
        passSceneDef->mProfilingId = "SHADOW_SCENE_PASS_"+Ogre::StringConverter::toString(i);
        passSceneDef->mShadowMapIdx = i;
        passSceneDef->mIncludeOverlays = false;
        passSceneDef->mUpdateLodLists = false;
        //passSceneDef->mVisibilityMask = 1 << 4;

        if( i >= mPssmSplitsCount ){
            targetDef->setShadowMapSupportedLightTypes( 1u << Ogre::Light::LT_SPOTLIGHT );
        }
        else{
            targetDef->setShadowMapSupportedLightTypes( 1u << Ogre::Light::LT_DIRECTIONAL );
        }

    }

}
and I have a createVRWorkspaceDefinition for my VR rendering, like this:

Code: Select all

void yWorkspaceManager::createVRWorkspaceDefinition(){

    //MAIN RENDER NODE DEFINITION
    Ogre::CompositorNodeDef *renderNodeDef = mCompositorManager->addNodeDefinition( "MainEngineRenderingNodeStereo" );

    renderNodeDef->addTextureSourceName( "renderwindow", 0, Ogre::TextureDefinitionBase::TEXTURE_INPUT );
    renderNodeDef->addTextureSourceName( "TerraShadowTexture", 1, Ogre::TextureDefinitionBase::TEXTURE_INPUT );


    renderNodeDef->setNumLocalTextureDefinitions(1);

    Ogre::TextureDefinitionBase::TextureDefinition *renderTexLeft = renderNodeDef->addTextureDefinition("renderAux");
    renderTexLeft->formatList.push_back( Ogre::PF_FLOAT16_RGB );

    renderNodeDef->setNumTargetPass( 2 );
    {
        //RENDER
        {
            Ogre::CompositorTargetDef *targetDef = renderNodeDef->addTargetPass( "renderAux" );
            targetDef->setNumPasses( 3 );

            //CLEAR
            Ogre::CompositorPassClearDef *passClearDef = static_cast<Ogre::CompositorPassClearDef*>( targetDef->addPass( Ogre::PASS_CLEAR ) );
            passClearDef->mColourValue = Ogre::ColourValue::Black;
            passClearDef->mProfilingId = "STEREO_CLEAR_PASS";

            //SCENE LEFT
            Ogre::CompositorPassSceneDef *passSceneDefLeft = static_cast<Ogre::CompositorPassSceneDef*>( targetDef->addPass( Ogre::PASS_SCENE ) );
            passSceneDefLeft->mVpLeft = 0;
            passSceneDefLeft->mVpTop = 0;
            passSceneDefLeft->mVpWidth = 0.5;
            passSceneDefLeft->mVpHeight = 1.0;
            passSceneDefLeft->mExposedTextures.push_back( "TerraShadowTexture" );
            passSceneDefLeft->mCameraName = "CameraLeft";
            passSceneDefLeft->mCullCameraName = "CameraCull";
            passSceneDefLeft->mShadowNode = "MainEngineShadowNode";
            passSceneDefLeft->mShadowNodeRecalculation = Ogre::SHADOW_NODE_FIRST_ONLY;
            passSceneDefLeft->mProfilingId = "STEREO_LEFT_SCENE_PASS";

            //SCENE RIGHT
            Ogre::CompositorPassSceneDef *passSceneDefRight = static_cast<Ogre::CompositorPassSceneDef*>( targetDef->addPass( Ogre::PASS_SCENE ) );
            passSceneDefRight->mVpLeft = 0.5;
            passSceneDefRight->mVpTop = 0;
            passSceneDefRight->mVpWidth = 0.5;
            passSceneDefRight->mVpHeight = 1.0;
            passSceneDefRight->mCameraName = "CameraRight";
            passSceneDefRight->mCullCameraName = "CameraCull";
            passSceneDefRight->mReuseCullData = true;
            passSceneDefRight->mUpdateLodLists = false;
            passSceneDefRight->mIncludeOverlays = false;
            passSceneDefRight->mShadowNode = "MainEngineShadowNode";
            passSceneDefRight->mShadowNodeRecalculation = Ogre::SHADOW_NODE_REUSE;
            passSceneDefRight->mProfilingId = "STEREO_RIGHT_SCENE_PASS";
        }
        //POST PROCESS
        {
            Ogre::CompositorTargetDef *targetDef = renderNodeDef->addTargetPass( "renderwindow" );
            targetDef->setNumPasses( 1 );

            //QUAD
            Ogre::CompositorPassQuadDef *passQuadDef = static_cast<Ogre::CompositorPassQuadDef*>( targetDef->addPass( Ogre::PASS_QUAD ) );
            passQuadDef->mMaterialName = "FinalProcessingMat";
            passQuadDef->addQuadTextureSource( 0, "renderAux", 0 );
            passQuadDef->mProfilingId = "STEREO_FINAL_PROCESSING_QUAD_PASS";
        }
    }

    //MAIN WORKSPACE DEFINITION
    Ogre::CompositorWorkspaceDef *workspaceDef = mCompositorManager->addWorkspaceDefinition( "MainEngineWorkspaceStereo" );
    workspaceDef->connectExternal( 0, "MainEngineRenderingNodeStereo", 0 );
    workspaceDef->connectExternal( 1, "MainEngineRenderingNodeStereo", 1 ); //for terra shadows

}
Lastly I just create the actual workspace with the method createVRWorkspace:

Code: Select all

void yWorkspaceManager::createVRWorkspace( Ogre::TexturePtr eyesRenderTexture, Ogre::Camera* eyeCameras[2], const Ogre::ShadowMapper* shadowMapper ){

    yAssert( yUtils::isGraphicsThread(), "VR workspace must be created in Graphics thread" );

    Ogre::CompositorChannelVec externalChannels( 2 );
    externalChannels[0].target = eyesRenderTexture->getBuffer(0)->getRenderTarget();
    externalChannels[0].textures.push_back( eyesRenderTexture );

    externalChannels[1].target = mNullTex->getBuffer(0)->getRenderTarget();
    externalChannels[1].textures.push_back( mNullTex );

    Ogre::ResourceLayoutMap initialLayouts;
    Ogre::ResourceAccessMap initialUavAccess;

    if( shadowMapper ){
        shadowMapper->fillUavDataForCompositorChannel( externalChannels[1], initialLayouts,
                initialUavAccess );
    }

    mVRWorkspace = mCompositorManager->addWorkspace( mSceneManager, externalChannels, eyeCameras[0],
                                                "MainEngineWorkspaceStereo", true, -1,
                                                (Ogre::UavBufferPackedVec*)0, &initialLayouts,
                                                &initialUavAccess );


    // Mirror the texture to the main window
    Ogre::Pass *vrMirrorMaterialPass = Ogre::MaterialManager::getSingletonPtr()->getByName("Mirror")->getTechnique(0)->getPass(0);
    vrMirrorMaterialPass->getTextureUnitState(0)->setTexture( eyesRenderTexture );
    mWorkspaceMirror = mCompositorManager->addWorkspace( mSceneManager, mRenderWindow, eyeCameras[0], "WorkspaceMirror", true );
}
so now its a matter of just call all those 3 methods and its working!!

BUTTTTTT! at some point I need to change some shadow params like number of splits and lambda... so I call my refreshWorkspaces method:

Code: Select all


void yWorkspaceManager::refreshWorkspaces(){

    mCompositorManager->removeWorkspace( mVRWorkspace );

    mCompositorManager->removeShadowNodeDefinition( "MainEngineShadowNode" );
    createShadowNodeDefinition(); //create again with new params

    createVRWorkspace( mEyesRenderTexture, mEyeCameras );
}
And all I get is black image =(

Before I was rendering each eye to a separated texture and it was working fine, now I mixed it to one texture and I get this problem.

the problem disappears if I comment out the post processing target pass :S that's strange... but obviously I need the post process. Its like if this target pass breaks things but profiler says the quad pass is being executed.

In summary: code above works fine until I call refreshWorkspaces

Since my objective here is to change the CompositorShadowNode, what would be the correct way to do it? or maybe I am doing it fine (conceptually) and I just have a silly mistake I don't see.... or... a bug!

Please help!
thank youuuuuuu!!!!
Post Reply