Rendering to a texture to use in a workspace.

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


Post Reply
Smooth
Gnoblar
Posts: 8
Joined: Mon Oct 01, 2018 2:04 pm

Rendering to a texture to use in a workspace.

Post by Smooth »

Hi.

I'm working on a project where I'm trying to use a custom workspace to render the scene to a Ogre::TexturePtr and then reuse that texture in another custom workspace that renders to the window. My problem is that Ogre can't find the texture in the second workspace.

I am adding the texture using the following code:

Code: Select all

PassQuad->addQuadTextureSource(0, texture->getName(), 0);
This gives me the following error message:

Can't find texture with name: '[Hash 0x30d29d67]' If it's a global texture, trying to use it in the output channel will fail.

How can I add this texture to the compositor node so that Ogre can use it? (I'm using Ogre 2.1).
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: Rendering to a texture to use in a workspace.

Post by dark_sylinc »

Hi!

That's incorrect, the names are local to the workspace's node, not to live textures.

Keep using addQuadTextureSource, but the name you use isn't the texture's. It has to be to a node input or to a global texture and you pass the texture as an external one when instantiating the workspace.

See the compositor manual.
In script terms:

Code: Select all

compositor_node Tutorial_DynamicCubemapRenderingNode
{
	in 0 rt_renderwindow
	in 1 demo_dynamic_cubemap

	target rt_renderwindow
	{
		pass render_quad
		{
			input 0 demo_dynamic_cubemap
		}
	}
}

workspace Tutorial_DynamicCubemapWorkspace
{
	//Render Window on channel #0
	connect_external 0 Tutorial_DynamicCubemapRenderingNode 0
	//Cubemap on channel #1
	connect_external 1 Tutorial_DynamicCubemapRenderingNode 1
}
That is, addQuadTextureSource expects you to enter "demo_dynamic_cubemap". You pass your actual texture via addWorkspace, which inside the compositor will be referenced as "demo_dynamic_cubemap".
Smooth
Gnoblar
Posts: 8
Joined: Mon Oct 01, 2018 2:04 pm

Re: Rendering to a texture to use in a workspace.

Post by Smooth »

Thanks for clearing that up.

However, I'm still a bit unsure of how to pass the texture correctly so that it can be available in my workspace.

As you say:
You pass your actual texture via addWorkspace,


Do I insert the texture as a part of the CompositorChannelVec?

like this ? :

Code: Select all


Ogre::CompositorChannelVec externalChannels(1);

	externalChannels[0].textures.push_back(texture);
	
Can I then access this texture by name in the compositor node inside the workspace?
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: Rendering to a texture to use in a workspace.

Post by dark_sylinc »

Yes, that is correct.

Because you inserted it in externalChannels[0 ], it is in connect_external 0

Btw if you don't set externalChannels[0].target = texture->getBuffer(0)->getRenderTarget(0), you will only be able to use the external texture as a... texture, but you won't be able to render to it from that compositor.
Smooth
Gnoblar
Posts: 8
Joined: Mon Oct 01, 2018 2:04 pm

Re: Rendering to a texture to use in a workspace.

Post by Smooth »

Thanks again, but I still have some problems getting this to work as intended.

I ended up defining my the external texture like this, including my final render target :

Code: Select all

	Ogre::CompositorChannelVec externalChannels(2);

	externalChannels[0].target = renderTarget;
	externalChannels[1].textures.push_back(texture);
This is how I connect the external texture to the compositor node:

Code: Select all

	workspaceDef->connectExternal(1, compositorNode->getName(), 0);
And this is how I use the texture inside the node :

Code: Select all

	compoitorNodeDef->addTextureSourceName("texture_input", 0, Ogre::TextureDefinitionBase::TEXTURE_INPUT);
and later again in a quad pass :

Code: Select all

	passQuad->addQuadTextureSource(0, "texture_input", 0);

When I try to run the application with this code it gives me the following error :
Exception thrown: read access violation.
**externalTarget** was nullptr.
I have tried to also include a target for the second element of the CompositorChannelVec, like this:

Code: Select all

	Ogre::CompositorChannelVec externalChannels(2);

	externalChannels[0].target = renderTarget;
	externalChannels[1].textures.push_back(texture);
	externalChannels[1].target = texture->getBuffer(0)->getRenderTarget(0);
but that just results in a black rectangle on the final render target where I want my texture to be.

Do you know what I'm doing wrong?
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: Rendering to a texture to use in a workspace.

Post by dark_sylinc »

It doesn't look like you're rendering to the final target at all.

Could you post the entire code setting up the compositor?
Smooth
Gnoblar
Posts: 8
Joined: Mon Oct 01, 2018 2:04 pm

Re: Rendering to a texture to use in a workspace.

Post by Smooth »

For testing purposes, I’m rendering four different views to the final render target using four different workspaces. The first three workspaces are just rendering the scene and some post effects to its own quarter of the screen. They all seem to work as intended. On the last workspace, I try to render the contents of a texture onto the last corner of the final render target, and this is where the trouble begins. Se image below:


Image

This is the code I'm using to set up the last workspace:

Code: Select all

const Ogre::String workspaceDefName = "window4_def";

	Ogre::CompositorManager2* ogreCompositorManager = mGraphics->GetOgreRoot()->getCompositorManager2();

	assert(!ogreCompositorManager->hasWorkspaceDefinition(workspaceDefName));

	Ogre::CompositorWorkspaceDef* workspaceDef =
		ogreCompositorManager->addWorkspaceDefinition(workspaceDefName);

	Ogre::String compositorNodeDefName = workspaceDefName + "node";

	if (ogreCompositorManager->hasNodeDefinition(compositorNodeDefName))
	{
		ogreCompositorManager->removeNodeDefinition(compositorNodeDefName);
	}


	Ogre::CompositorNodeDef* compoitorNodeDef = ogreCompositorManager->addNodeDefinition(compositorNodeDefName);


	compoitorNodeDef->setNumTargetPass(1);

	
	compoitorNodeDef->addTextureSourceName("render_target", 0, Ogre::TextureDefinitionBase::TEXTURE_INPUT);
	compoitorNodeDef->addTextureSourceName("texture_input", 1, Ogre::TextureDefinitionBase::TEXTURE_INPUT);

	Ogre::CompositorTargetDef *targetDef = compoitorNodeDef->addTargetPass("render_target");

	Ogre::CompositorPassQuadDef *passQuad = static_cast<Ogre::CompositorPassQuadDef*>(targetDef->addPass(Ogre::PASS_QUAD));
	passQuad->mMaterialName = "Ogre/Copy/4xFP32";

	passQuad->addQuadTextureSource(0, "texture_input", 0);
	passQuad->mViewportModifierMask = 0xff;
	passQuad->mExecutionMask = 0xff;


	workspaceDef->connectExternal(0, compoitorNodeDef->getName(), 0);
	workspaceDef->connectExternal(1, compoitorNodeDef->getName(), 1);


	Ogre::CompositorChannelVec externalChannels(2);

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


	Ogre::CompositorWorkspace * workspace =
		ogreCompositorManager->addWorkspace(
			mGraphics->_GetSceneManager(),
			externalChannels,
			mGraphics->GetFloatingCamera(),
			workspaceDefName,
			/*enabled*/ true,
			/*position*/ -1,
			/*uavBuffers*/ NULL,
			/*initialLayouts*/ NULL,
			/*initialUavAccess*/ NULL,
			Ogre::Vector4(0.5, 0.5, 0.5, 0.5),
			0xff,
			0xff);
I am rendering to the texture using a separate workspace and I have checked the texture using RenderDoc so I know that it isn't empty.
xrgo
OGRE Expert User
OGRE Expert User
Posts: 1148
Joined: Sat Jul 06, 2013 10:59 pm
Location: Chile
x 168

Re: Rendering to a texture to use in a workspace.

Post by xrgo »

I think you should do something like this:

Code: Select all

    Ogre::Pass *materialPass = Ogre::MaterialManager::getSingletonPtr()->getByName("Ogre/Copy/4xFP32")->getTechnique(0)->getPass(0);
    materialPass ->getTextureUnitState(0)->setTexture( mySuperTextureGpu );
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: Rendering to a texture to use in a workspace.

Post by dark_sylinc »

OK, everything you posted looks correct.

Thus I don't know why it is not working. When you debug it in RenderDoc, is the texture bound to the render quad pass? Is the shader covering the correct region of the screen? (given the custom viewport, there's the possibility the actual bug is caused by the render being drawn out of place, thus it doesn't actually hit any pixel).
xrgo wrote: Tue Aug 20, 2019 5:49 pm I think you should do something like this:

Code: Select all

    Ogre::Pass *materialPass = Ogre::MaterialManager::getSingletonPtr()->getByName("Ogre/Copy/4xFP32")->getTechnique(0)->getPass(0);
    materialPass ->getTextureUnitState(0)->setTexture( mySuperTextureGpu );
That could work, but it will stop working if "Ogre/Copy/4xFP32" is modified again somewhere, and if it's a rendertarget then it won't play nice in the future with Vulkan / D3D12 RenderSystems.
However it can be useful to quickly test if that part works.
Post Reply