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 );
}
}
}
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
}
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 );
}
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 );
}
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!!!!