Ogre 2.2 Rectangle2D filled with

A place for users of OGRE to discuss ideas and experiences of utilitising OGRE in their games / demos / applications.
Post Reply
peetcreative
Gnoblar
Posts: 7
Joined: Tue Feb 11, 2020 10:19 pm

Ogre 2.2 Rectangle2D filled with

Post by peetcreative »

Hey,

my aim is to draw a static Rectangle with (video) image content in the back ground of my scene.
Besides the videoloading, I'm stuck at the point drawing a simple Rectangle like background in setSky method of SceneManager.
I got through the code in Scenemanager, but hardly understand according sky.material and shader code. I'm having a hard time understanding the new HLMS system as a concept. I read the doc of https://ogrecave.github.io/ogre-next/api/2.2/hlms.html .

So what's my first aim is to draw a simple white rectangle. So exchanged in some Sample like V2Mesh the code in createScene01() with:

Code: Select all

        mRectangle2D = sceneManager->createRectangle2D();
        mRectangle2D->setGeometry(
                    Ogre::Vector2(-1.0f, -1.0f),
                    Ogre::Vector2(2.0f, 2.0f)
        );

        mRectangle2D->initialize( Ogre::BT_DEFAULT,
                              Ogre::Rectangle2D::GeometryFlagQuad | Ogre::Rectangle2D::GeometryFlagNormals );
        mRectangle2D->setGeometry( -Ogre::Vector2::UNIT_SCALE, Ogre::Vector2( 2.0f ) );
        mRectangle2D->setRenderQueueGroup( 212u ); // Render after most stuff
        sceneManager->getRootSceneNode(Ogre::SCENE_STATIC)->attachObject( mRectangle2D );

        mRectangle2D->setMaterialName("RedMaterial", Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);

Or I put this texture_map.material file to the other material files so it gets loaded.

Code: Select all

material Template/texture_map
 {
    technique
    {
       pass
        {
          texture_unit
          {
            texture image.png
          }
       }   
    }
 }
and exchanged

Code: Select all

mRectangle2D->setMaterialName("RedMaterial", Ogre::ResourceGroupManager::INTERNAL_RESOURCE_GROUP_NAME);
Both cases I'm stuck because with that the new Hlms needs a shader.

Code: Select all

OGRE EXCEPTION(3:RenderingAPIException): Fixed Function pipeline is no longer allowed nor supported. The material BaseWhite must use shaders in HlmsLowLevel::calculateHashFor at
The videoloading to a TextureGPU works so far and also passing the TextureGPU to a HlmsUnlitDatablock.
Passing this to a manual Object with setDatablock works. Here it doesn't.

Thanks for your help!
Peter
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: Ogre 2.2 Rectangle2D filled with

Post by dark_sylinc »

What you're trying to do is best achieved with a pass_quad pass. Although it can be done with a Rectangle2D too.

However you're missing to setup a custom shader.

See this post: viewtopic.php?p=548470#p548470

What you need to do is modify TutorialSky_Postprocess shader to sample from a Texture2D instead of a TextureCube.
This material system hasn't changed much since Ogre 1.x, thus Ogre 1.x documentation regarding material scripts still applies.
peetcreative
Gnoblar
Posts: 7
Joined: Tue Feb 11, 2020 10:19 pm

Re: Ogre 2.2 Rectangle2D filled with

Post by peetcreative »

Thanks for the hint using a render_quad.
OK, I managed to modify the SkyPostprocess.material (see below) and according glsl script so that it colours the whole background.

Code: Select all

// SkyPostprocess.material

// GLSL shaders
vertex_program SkyPostprocess_vs_GLSL glsl
{
	source SkyPostprocess_vs.glsl
	default_params
	{
		param_named_auto worldViewProj worldviewproj_matrix
	}
}

fragment_program SkyPostprocess_ps_GLSL glsl
{
	source SkyPostprocess_ps.glsl
}


// Material definition
material SkyPostprocess
{
	technique
	{
		pass
		{
			depth_check on
			depth_write off

			cull_hardware none

			vertex_program_ref SkyPostprocess_vs_GLSL
			{
			}

			fragment_program_ref SkyPostprocess_ps_GLSL
			{
			}

			texture_unit
			{
			}
		}
	}
}
and the pixel shader

Code: Select all

#version 330

out vec4 fragColour;

void main()
{
	fragColour = vec4(0,0,255,255);
}
I added the following to my target in the compositor script.

Code: Select all

		pass render_quad
		{
			load { all dont_care }
			store
			{
				depth	dont_care
				stencil	dont_care
			}
			material SkyPostprocess
		}
So this works, kind of. I will look a bit deeper into shaders and low-level materials so I use the image in the texture.

However rendering to the Rectangle2D doesn't.
What I meant in the first place is rendering to a 2D rectangle somewhere behind the scene rather than to the whole screen. And if I think about it, the rectangle should possibly be dynamic in 2D space.
So if I understand render_quad correctly, it is rendering over the whole target. So I would have to define a new target with a new viewport.

Therefore I thought using Rectangle2D is the right way to go here.
But if I do the following, the 2D Rectangle won't appear. (Did some changes to the code above. Tinkered around)

Code: Select all

        mProjectionRectangle2D = sceneManager->createRectangle2D(Ogre::SCENE_DYNAMIC);
        mProjectionRectangle2D->setName("Rectangle2D");
        mProjectionRectangle2D->initialize(
            Ogre::BT_DEFAULT ,
            Ogre::Rectangle2D::GeometryFlagQuad | Ogre::Rectangle2D::GeometryFlagNormals);
        mProjectionRectangle2D->setRenderQueueGroup(212u);
        mProjectionRectangle2D->setGeometry(
            Ogre::Vector2(0.0f, 0.0f),
            Ogre::Vector2(2.0f,2.0f)
        );
        sceneManager->getRootSceneNode( Ogre::SCENE_DYNAMIC )
            ->attachObject(mProjectionRectangle2D);
        Ogre::MaterialManager &materialManager =
            Ogre::MaterialManager::getSingleton();

        Ogre::MaterialPtr material = 
            materialManager.getByName( "SkyPostprocess", "General" );
        mProjectionRectangle2D->setMaterial(material);
        mProjectionRectangle2D->setVisible(true);
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: Ogre 2.2 Rectangle2D filled with

Post by dark_sylinc »

I'm not fully sure why the Rectangle2D is not appearing. I suggest to use RenderDoc and go into the Geometry tab, where you can see the 'post transform' vertices (VS Out), to see where your rectangle is actually landing on screen.

Image

Notice that SkyPostprocess material expects vertices to be in clip space, this means that the viewport is in [-1;1] range, not [0;1]
peetcreative wrote: Tue Jul 14, 2020 12:52 pm

Code: Select all

		pass render_quad
		{
			load { all dont_care }
			store
			{
				depth	dont_care
				stencil	dont_care
			}
			material SkyPostprocess
		}
Be careful there: You're setting 'load dont_care' however the SkyPostprocess has depth_check on (not sure if you need it, depends on how you're rendering). This means depth_check on expects the depth buffer to already be populated with valid values, but dont_care on the depth buffer means the opposite.
You probably want to set load to 'clear'
peetcreative
Gnoblar
Posts: 7
Joined: Tue Feb 11, 2020 10:19 pm

Re: Ogre 2.2 Rectangle2D filled with

Post by peetcreative »

Hey,

I had some progress with the approach of using render_quad. With Ogre/Copy/4xFP32 material script I tried to use a texture I created manually. I update the texture with FrameListener.
However it seems to load and render_quad, but color is not changing.

TutorialTest.compositor

Code: Select all

compositor_node TutorialTestRenderingNode
{
	in 0 rt_renderwindow

	in 1 some_texture

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

		//Compositor will issue the appropiate barriers because
		//it knows testTexture will be used as a texture.
		pass render_quad
		{
			load {
				all				clear
				clear_colour	0 0 0 1
			}
			store {
				//We only care about the contents of the colour target
				depth			dont_care
				stencil			dont_care
			}
			material Ogre/Copy/4xFP32
			input 0 some_texture
		}

		pass render_scene
		{
			overlays	on
		}
	}
}

workspace TutorialTestWorkspace
{
	connect_external 0 TutorialTestRenderingNode 0
	connect_external 1 TutorialTestRenderingNode 1
}
TutorialTest.cpp

Code: Select all

...
    class TutorialTestGraphicsSystem : public GraphicsSystem, public Ogre::FrameListener
    {
        Ogre::TextureGpu *mTexture;
        Ogre::uint8 *mImageData;
        size_t mImageDataSize;
        Ogre::uint8 mColor;
        Ogre::StagingTexture* mStagingTexture;
        Ogre::uint8 mIttr;
        virtual Ogre::CompositorWorkspace* setupCompositor()
        {
            Ogre::TextureGpuManager *textureManager =
            mRoot->getRenderSystem()->getTextureGpuManager();

            Ogre::TextureGpu *renderTexture = mRenderWindow->getTexture();
            mTexture = textureManager->createTexture(
                "some_texture",
                Ogre::GpuPageOutStrategy::Discard,
                Ogre::TextureFlags::AutomaticBatching |
                Ogre::TextureFlags::ManualTexture |
                Ogre::TextureFlags::Reinterpretable,
                Ogre::TextureTypes::Type2D );

            mTexture->setResolution( renderTexture->getWidth(), renderTexture->getHeight());
            mTexture->setPixelFormat( Ogre::PFG_RGBA8_UNORM );

            mTexture->scheduleTransitionTo( Ogre::GpuResidency::Resident );

            const size_t bytesPerRow = mTexture->_getSysRamCopyBytesPerRow( 0 );

            mStagingTexture = textureManager->getStagingTexture(
                mTexture->getWidth(),
                mTexture->getHeight(),
                mTexture->getDepth(),
                mTexture->getNumSlices(),
                mTexture->getPixelFormat() );

            const Ogre::uint32 rowAlignment = 4u;
            mImageDataSize = Ogre::PixelFormatGpuUtils::getSizeBytes(
                mTexture->getWidth(),
                mTexture->getHeight(),
                mTexture->getDepth(),
                mTexture->getNumSlices(),
                mTexture->getPixelFormat(),
                rowAlignment );

            mImageData = reinterpret_cast<Ogre::uint8*>(
                OGRE_MALLOC_SIMD( mImageDataSize,
                                  Ogre::MEMCATEGORY_RESOURCE ) );
            memset(mImageData, 0, mImageDataSize);

            Ogre::CompositorChannelVec channels( 2u );
            channels[0] = renderTexture;
            channels[1] = mTexture;

            mRoot->addFrameListener( this );
            Ogre::CompositorManager2 *compositorManager = mRoot->getCompositorManager2();
            return compositorManager->addWorkspace( mSceneManager, channels, mCamera,
                                                    "TutorialTestWorkspace", true );

        }

        virtual bool frameRenderingQueued( const Ogre::FrameEvent& evt )
        {
            if (mIttr++ < 3)
                return true;
            else
                mIttr = 0;
            const size_t bytesPerRow = mTexture->_getSysRamCopyBytesPerRow( 0 );

            if (mColor <255)
                mColor++;
            else
                mColor = 0;
            //So color should shift in 255 frames from black to red
            for(size_t i = 0; i < mImageDataSize; i++)
            {
                mImageData[i] = i % 4 == 0 ? mColor : 0;
            }
            mStagingTexture->startMapRegion();
            Ogre::TextureBox texBox = mStagingTexture->mapRegion(
                mTexture->getWidth(),
                mTexture->getHeight(),
                mTexture->getDepth(),
                mTexture->getNumSlices(),
                mTexture->getPixelFormat() );
            texBox.copyFrom( mImageData,
                             mTexture->getWidth(),
                             mTexture->getHeight(),
                             bytesPerRow );
            mStagingTexture->stopMapRegion();
            mStagingTexture->upload( texBox, mTexture, 0, 0, 0, false );
            mTexture->notifyDataIsReady();
            return true;
        }

        virtual void setupResources(void)
        {
            GraphicsSystem::setupResources();

            Ogre::ConfigFile cf;
            cf.load(mResourcePath + "resources2.cfg");

            Ogre::String originalDataFolder = cf.getSetting( "DoNotUseAsResource", "Hlms", "" );

            if( originalDataFolder.empty() )
                originalDataFolder = "./";
            else if( *(originalDataFolder.end() - 1) != '/' )
                originalDataFolder += "/";
        }

    public:
        TutorialTestGraphicsSystem( GameState *gameState ) :
            GraphicsSystem( gameState ),
            mTexture(nullptr),
            mImageData(nullptr),
            mImageDataSize(0),
            mStagingTexture(nullptr),
            mIttr(3)
        {
        }
    };
....
Seems I'm still missing some concept about compositor scripts.
peetcreative
Gnoblar
Posts: 7
Joined: Tue Feb 11, 2020 10:19 pm

Re: Ogre 2.2 Rectangle2D filled with

Post by peetcreative »

I got actually sth working now. It looks a bit hacky. I create the texture in the Compositor script now. And look it up after adding the workspace.
Changed TutorialTest.compositor

Code: Select all

compositor_node TutorialTestRenderingNode
{
	in 0 rt_renderwindow

	texture some_texture target_width target_height PFG_RGBA8_UNORM

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

		pass render_quad
		{
			material Ogre/Copy/4xFP32
			input 0 some_texture
		}

		pass render_scene
		{
			overlays	on
		}
	}
}

workspace TutorialTestWorkspace
{
	connect_external 0 TutorialTestRenderingNode 0
}

and in TutorialTest.cpp I add the Workspace and lookup the Texture afterwards.

Code: Select all

...
        virtual Ogre::CompositorWorkspace* setupCompositor()
        {
            Ogre::TextureGpuManager *textureManager =
            mRoot->getRenderSystem()->getTextureGpuManager();

            Ogre::TextureGpu *renderTexture = mRenderWindow->getTexture();

            Ogre::CompositorChannelVec channels( 2u );
            channels[0] = renderTexture;
            channels[1] = mTexture;

            mRoot->addFrameListener( this );
            Ogre::CompositorManager2 *compositorManager = mRoot->getCompositorManager2();
            Ogre::CompositorWorkspace* ws = compositorManager->addWorkspace( mSceneManager, renderTexture, mCamera,
                                                    "TutorialTestWorkspace", true );
            Ogre::CompositorNode *wsnode = ws->findNode("TutorialTestRenderingNode");
            mTexture = wsnode->getLocalTextures()[0];
            const size_t bytesPerRow = mTexture->_getSysRamCopyBytesPerRow( 0 );
            mStagingTexture = textureManager->getStagingTexture(
                mTexture->getWidth(),
                mTexture->getHeight(),
                mTexture->getDepth(),
                mTexture->getNumSlices(),
                mTexture->getPixelFormat() );

            const Ogre::uint32 rowAlignment = 4u;
            mImageDataSize = Ogre::PixelFormatGpuUtils::getSizeBytes(
                mTexture->getWidth(),
                mTexture->getHeight(),
                mTexture->getDepth(),
                mTexture->getNumSlices(),
                mTexture->getPixelFormat(),
                rowAlignment );

            mImageData = reinterpret_cast<Ogre::uint8*>(
                OGRE_MALLOC_SIMD( mImageDataSize,
                                  Ogre::MEMCATEGORY_RESOURCE ) );
            memset(mImageData, 0, mImageDataSize);
            return ws;
        }
...
Post Reply