how to do multiple terras

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


Post Reply
Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

how to do multiple terras

Post by Nickak2003 »

So, is it possible to have multiple terras at once? Like, page them in and out and stitch them together? How would I go about this? I'm sort of clueless.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: how to do multiple terras

Post by dark_sylinc »

I can't remember if it was supported. I ported Terra to another engine and we're using multiple Terras there. IIRC these changes to support multiple Terras were sync'ed with Ogre.

If everything is alright (i.e. planets align), simply creating another Ogre::Terra pointer should do (and setting a different offset, of course). You need to call Terra::update() on both to determine visibility of the chunks to draw, and recalculate shadows if light direction changes.

Each Terra can have its own material datablock.
Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

Re: how to do multiple terras

Post by Nickak2003 »

Well the problem seems to come from the shadow mapper, each terra has its own shadow mapper and yet that shadow mapper is bound specifically to a compositor channel [2]. Wouldn't i need to somehow swap these maps on the compositor channel?
Nickak2003
Goblin
Posts: 272
Joined: Thu Jun 10, 2004 4:19 am
x 26

Re: how to do multiple terras

Post by Nickak2003 »

Code: Select all

    
    if (terra){
         
        //Terra is initialized
        const Ogre::ShadowMapper* shadowMapper = terra->getShadowMapper();
        shadowMapper->fillUavDataForCompositorChannel(&externalChannels[1], initialLayouts,
            initialUavAccess);

    }else{
    
        //The texture is not available. Create a dummy dud.
        Ogre::TextureGpuManager* textureManager = root->getRenderSystem()->getTextureGpuManager();
        Ogre::TextureGpu* nullTex = textureManager->createOrRetrieveTexture("DummyNull",
            Ogre::GpuPageOutStrategy::Discard,
            Ogre::TextureFlags::ManualTexture,
            Ogre::TextureTypes::Type2D);
        nullTex->setResolution(1u, 1u);
        nullTex->setPixelFormat(Ogre::PFG_R10G10B10A2_UNORM);
        nullTex->scheduleTransitionTo(Ogre::GpuResidency::Resident);
        externalChannels[1] = nullTex;
    }

    getSceneManager()->setForwardClustered(true, 4, 4, 24, 20, 5, 20, 0, 1200);

    mWorkspace = compositorManager->addWorkspace(sceneManager, externalChannels, camera,
        "Tutorial_TerrainWorkspace", true, -1,
        (Ogre::UavBufferPackedVec*)0, &initialLayouts,
        &initialUavAccess);
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: how to do multiple terras

Post by dark_sylinc »

This issue is split in 2 parts:

Part 1:
Well the problem seems to come from the shadow mapper, each terra has its own shadow mapper and yet that shadow mapper is bound specifically to a compositor channel [2]. Wouldn't i need to somehow swap these maps on the compositor channel?
2.2 Answer:
The compositor workspace is something you're in control of. The shadow mapper is bound to channel[2] but this is not a hard limit, and this is to expose the texture to Ogre, so that the proper memory barriers are set in place (otherwise rendering may start before the compute shader is done writing to the shadow map)

The modified script would look like this (I'm skipping the shadow node since that stays the same):

Code: Select all

compositor_node Tutorial_TerrainRenderingNode
{
	in 0 rt_renderwindow
	in 1 TerraShadowTexture1
	in 2 TerraShadowTexture2

	target rt_renderwindow
	{
		pass clear
		{
			colour_value 0.2 0.4 0.6 1
		}

		pass render_scene
		{
			load
			{
				all				clear
				clear_colour	0.2 0.4 0.6 1
			}
			store
			{
				colour	store_or_resolve
				depth	dont_care
				stencil	dont_care
			}

			expose TerraShadowTexture1
			expose TerraShadowTexture2

			overlays	on
			shadows		Tutorial_TerrainShadowNode
		}
	}
}

workspace Tutorial_TerrainWorkspace
{
	connect_external 0 Tutorial_TerrainRenderingNode 0
	connect_external 1 Tutorial_TerrainRenderingNode 1
	connect_external 2 Tutorial_TerrainRenderingNode 2
}
And C++ code:

Code: Select all

CompositorChannelVec externalChannels( 2 );
//Render window
externalChannels[0] = renderWindow->getTexture();

//Terra's Shadow texture
ResourceLayoutMap initialLayouts;
ResourceAccessMap initialUavAccess;

//Terra is initialized
ShadowMapper const *shadowMapper = mTerra0->getShadowMapper();
shadowMapper->fillUavDataForCompositorChannel( &externalChannels[1], initialLayouts,
                                               initialUavAccess );
shadowMapper = mTerra1->getShadowMapper();
mTerra->getShadowMapper();
        shadowMapper->fillUavDataForCompositorChannel( &externalChannels[2], initialLayouts,
                                                       initialUavAccess );

return compositorManager->addWorkspace( sceneManager, externalChannels, camera,
                                        "Tutorial_TerrainWorkspace", true, -1,
                                        (UavBufferPackedVec*)0, &initialLayouts,
                                        &initialUavAccess );
2.3 Answer:
Exposing the texture to the compositor has been removed since it was user hostile and even if you knew what you were doing, it was very error prone and certain rendering algorithms could simply not be implemented. Although this may result in slightly higher CPU overhead (profiling reveals it's negligible), our sanity demanded it.
So you don't need to do anything in 2.3.

Part 2:

Part 1 answers and solves your question, but you're still left with the fact that HlmsPbsTerraShadows only accepts one terrain shadow map at at a time.
There are two possible solutions:

1. Modify HlmsPbsTerraShadows (and its shader code) to support multiple Terras. That means commandBuffer->addCommand<CbTexture>() needs to either be called per renderable rather than in HlmsPbsTerraShadows::hlmsTypeChanged; or you set all textures at once.
This also means HlmsPbsTerraShadows::getPassBufferSize needs to be called for N terras.
And the shader code needs to index the texture and offsets to use per terrain idx.

It's possible but it's a bit more than just 2 lines of code changes.

2. Keep things as is, and assume there is only ever one Terra active, and actively switch HlmsPbsTerraShadows::mTerra based on the position of the camera. This means however, there may be a sudden "pop" when crossing the seams between the terrains because there's suddenly an entire quadrant of Items being affected by terrain shadows while another quadrant loses those shadows.
If there's few or no items at the boundaries, this issue won't be noticed at all.
Note that terrain-shadows-on-terrain will still work as normal. It's just terrain-shadows-on-items what's affected.
Post Reply