Ogre3d 2.1 Ported LibRocket

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


Post Reply
User avatar
SolarPortal
OGRE Contributor
OGRE Contributor
Posts: 203
Joined: Sat Jul 16, 2011 8:29 pm
Location: UK
x 51
Contact:

Ogre3d 2.1 Ported LibRocket

Post by SolarPortal »

Hi, We want to give back again to the community. Our engine uses LibRocket as one of the GUI systems and it needed upgraded to 2.1.

Today, we just finished the port for librocket. We first upgraded it inside our engine but we decided to then upgrade the example from the wiki found here: :D
http://www.ogre3d.org/tikiwiki/tiki-ind ... =libRocket

Here is the new Ogre3d 2.1 supporting version which has both working DX11 and OpenGL3+ for librocket. No mobile tests have been made yet.
Download: http://www.chi-ad.com/Downloads/Ogre3D/ ... Rocket.zip ( I would have uploaded it to the forum but it is a bit big lol :P )
Note: It requires Ogre3d 2.1 most recent build at time of posting, OIS & LibRocket.

Included in the archive is a working demo example that can run in both render systems.

For more interesting read now, these were the rough changes that had to be made.
> I had to use a Custom Compositor Pass Provider that would create a RocketPass which would execute the rendering at the end of the workspace render_window.
> In the workspace compositor_node for rendering, i added a pass that used

Code: Select all

pass custom LibRocket
{
}
> The RenderQueueListener and functions which eventually calls update/render is out of date, this was the reason for the above custom compositor.
> Since Fixed Function no longer exists, shaders took its place with a material. These can be found in the zip archive above.
> The Rendering function inside "RenderInterfaceOgre3D" needed complete reworking to engage. The example calls it "OgreRocket::RenderInterface".
Here is the new code:

Code: Select all

	void RenderInterface::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation)
	{
		// This function has been edited by Jayce Young and Hannah Young from Aurasoft UK
		// It was built for the Skyline Game Engine // http://home.aurasoft-skyline.co.uk
		// Edited on 15/03/2016

		mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
		mRenderSystem->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
		mRenderSystem->_setViewMatrix(Ogre::Matrix4::IDENTITY);

		// Grab Projection Matrix
		Ogre::Matrix4 projection_matrix = getProjectionMatrix();

		// Create Transform Matrix for positioning.
		Ogre::Matrix4 transform;
		transform.makeTrans(translation.x, translation.y, 0);
		
		RocketCompiledGeometry* ogre3d_geometry = (RocketCompiledGeometry*)geometry;

		// No more Fixed Function, Shaders are now required! Check media folder for RocketShaders
		Ogre::MaterialPtr mMaterial = Ogre::MaterialManager::getSingleton().getByName("Rocket2D");
		if (!mMaterial->isLoaded())mMaterial->load();

		// Set the pass to the scene manager
		//scene.sceneManager->_setPass(mMaterial->getTechnique(0)->getPass(0)); // <<<<< MIGHTNEED!!!!Seems to work without though.

		// Set the vertex and fragment program from the material we are loading from.
		Ogre::GpuProgramPtr vertexProgram = mMaterial->getTechnique(0)->getPass(0)->getVertexProgram();
		Ogre::GpuProgramPtr pixelProgram = mMaterial->getTechnique(0)->getPass(0)->getFragmentProgram();

		if (ogre3d_geometry->mTexture != NULL)
		{
			mRenderSystem->_setTexture(0, true, ogre3d_geometry->mTexture->mTexture.get());
			Ogre::HlmsSamplerblock sampler;
			sampler.setAddressingMode(Ogre::TextureAddressingMode::TAM_CLAMP);
			sampler.setFiltering(Ogre::TextureFilterOptions::TFO_TRILINEAR);
			mRenderSystem->_setHlmsSamplerblock(0, &sampler);
			mRenderSystem->_disableTextureUnitsFrom(1);
		}
		else{
			// Choose a program that does not require a texture to render and use pure color with instead.
			if (mRenderSystem->getName() == "Direct3D11 Rendering Subsystem"){
				Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPHLSL_NoTexture");
				if (!noTexPixelShader.isNull()){
					if (!noTexPixelShader->isLoaded()){	noTexPixelShader->load(); }
					pixelProgram = noTexPixelShader;
				}
			}
			else if (mRenderSystem->getName() == "OpenGL 3+ Rendering Subsystem"){
				Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPGLSL_NoTexture");
				if (!noTexPixelShader.isNull()){
					if (!noTexPixelShader->isLoaded()){	noTexPixelShader->load(); }
					pixelProgram = noTexPixelShader;
				}
			}/*else if (mRenderSystem->getName() == "OpenGLSLES......."){ // Put correct render system name into play
				Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPGLSLES_NoTexture");
				 if (!noTexPixelShader.isNull()){
					 if (!noTexPixelShader->isLoaded()){ noTexPixelShader->load(); }
					 pixelProgram = noTexPixelShader;
				 }
			 }*/

			// Finally Disable the texture unit
			mRenderSystem->_disableTextureUnit(0);
		}

		Ogre::HlmsCache hlmsCache;
		hlmsCache.vertexShader = vertexProgram;
		hlmsCache.pixelShader = pixelProgram;
		hlmsCache.type = Ogre::HlmsTypes::HLMS_LOW_LEVEL;
		mRenderSystem->_setProgramsFromHlms(&hlmsCache);

		// Bind the necessary shader settings to the Vertex Shader to send in the transform matrix information.
		Ogre::GpuProgramParametersSharedPtr vsParams = hlmsCache.vertexShader->getDefaultParameters();
		vsParams->setNamedConstant("transformMat", projection_matrix * transform);
		mRenderSystem->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, vsParams, Ogre::GPV_ALL);

		// Set the macro and blending information for the HLMS system.
		mRenderSystem->_setHlmsMacroblock(mMaterial->getTechnique(0)->getPass(0)->getMacroblock());
		mRenderSystem->_setHlmsBlendblock(mMaterial->getTechnique(0)->getPass(0)->getBlendblock());

		mRenderSystem->_render(ogre3d_geometry->mRenderOperation);
	}
> The Projection Matrix and Transform matrix are multiplied together and sent into the shaders as _setProjectionMatrix() and _setWorldMatrix() don't do anything an i believe they were for fixed function.
Note: projection matrix creation is handled outside of the RenderInterface as it only needs called once per frame, whereas the render for rocket is called many times over with different transforms.

> Again, a hlms cache is used to handle the generation of shaders and shader parameters.
> This required 2 pixel shaders to work, one for the Texture related passes and another for simple Colour backgrounds. Hence the if statement to switch pixel shader
> There are more changes, but you can see all the code in the archive above.

The only thing that has not been upgraded is the "render_system->setScissorTest" as we haven't come across a librocket document that needs it yet.
If we need them and add them, then we will try to update the archive again.

Q) (Ogre Devs)Do you want to add this to the wiki for keepsakes, it won't be disappearing of our server anytime soon lol :P

Anyway, Thanks for the great rendering engine and we hope that this feature give back helps someone :)
Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk
Transporter
Minaton
Posts: 933
Joined: Mon Mar 05, 2012 11:37 am
Location: Germany
x 110

Re: Ogre3d 2.1 Ported LibRocket

Post by Transporter »

You have access to the Wiki with your forum login, too. But I'll try out your example and update the code in the Wiki.
User avatar
SolarPortal
OGRE Contributor
OGRE Contributor
Posts: 203
Joined: Sat Jul 16, 2011 8:29 pm
Location: UK
x 51
Contact:

Re: Ogre3d 2.1 Ported LibRocket

Post by SolarPortal »

Thanks :) oh i will have to try that :)

Edit: Attempted to the upload file onto the wiki, but it says its too big.
This was from my account page and there wasn't an upload button on the editing page that i could use.
Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk
dermont
Bugbear
Posts: 812
Joined: Thu Dec 09, 2004 2:51 am
x 42

Re: Ogre3d 2.1 Ported LibRocket

Post by dermont »

Thanks for this, demo works great.
User avatar
SolarPortal
OGRE Contributor
OGRE Contributor
Posts: 203
Joined: Sat Jul 16, 2011 8:29 pm
Location: UK
x 51
Contact:

Re: Ogre3d 2.1 Ported LibRocket

Post by SolarPortal »

Thanks for the feedback and no problem! Happy to help :D
Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk
User avatar
SolarPortal
OGRE Contributor
OGRE Contributor
Posts: 203
Joined: Sat Jul 16, 2011 8:29 pm
Location: UK
x 51
Contact:

Re: Ogre3d 2.1 Ported LibRocket - 2-1 - PSO port

Post by SolarPortal »

Hey,

We have decided to move on the 2-1 PSO branch and had to report the Librocket GUI system. We have it running well with no issues. You may have seen the port on Gorrila(http://www.ogre3d.org/forums/viewtopic. ... 23#p529823)

So here are the changes:

(File:) RenderInterfaceOgre3D.cpp (Function:) Rocket::Core::CompiledGeometryHandle RenderInterfaceOgre3D::CompileGeometry()
replace:

Code: Select all

geometry->render_operation.operationType = Ogre::v1::RenderOperation::OT_TRIANGLE_LIST;
with:

Code: Select all

#ifdef OGRE_PSO
	geometry->render_operation.operationType = Ogre::OperationType::OT_TRIANGLE_LIST;
#else
	geometry->render_operation.operationType = Ogre::v1::RenderOperation::OT_TRIANGLE_LIST;
#endif
Next, we need to change the rendering function:
(File:) RenderInterfaceOgre3D.cpp (Function:) void RenderInterfaceOgre3D::RenderCompiledGeometry
Full function code below:

Code: Select all

void RenderInterfaceOgre3D::RenderCompiledGeometry(Rocket::Core::CompiledGeometryHandle geometry, const Rocket::Core::Vector2f& translation)
{
	//lprint("Rendering Rocket on screen now!");
	render_system->_setWorldMatrix(Ogre::Matrix4::IDENTITY);
	render_system->_setProjectionMatrix(Ogre::Matrix4::IDENTITY);
	render_system->_setViewMatrix(Ogre::Matrix4::IDENTITY);

	// If works, then cache these vars. If not remove
	Ogre::Matrix4 projection_matrix = getProjectionMatrix();

	// Create the Transform for the world matrix
	Ogre::Matrix4 transform;
	Ogre::Vector3 tl = Ogre::Vector3(translation.x, translation.y, 0);
	transform.makeTrans(translation.x, translation.y, 0);

	// Now setup the renderables
	RocketOgre3DCompiledGeometry* ogre3d_geometry = (RocketOgre3DCompiledGeometry*)geometry;

	// Get material and load if necessary.
	Ogre::MaterialPtr mMaterial = Ogre::MaterialManager::getSingleton().getByName("Rocket2D");
	if (!mMaterial->isLoaded())mMaterial->load();

	// Set the pass to the scene manager
	//scene.sceneManager->_setPass(mMaterial->getTechnique(0)->getPass(0));

	// Set the vertex and fragment program from the material we are loading from.
	Ogre::GpuProgramPtr vertexProgram = mMaterial->getTechnique(0)->getPass(0)->getVertexProgram();
	Ogre::GpuProgramPtr pixelProgram = mMaterial->getTechnique(0)->getPass(0)->getFragmentProgram();

	// Load the texture to render.
	if (ogre3d_geometry->texture != NULL){
		render_system->_setTexture(0, true, ogre3d_geometry->texture->texture->getName());

#ifndef _DEBUG		
		Ogre::HlmsSamplerblock sampler;
		sampler.setAddressingMode(Ogre::TextureAddressingMode::TAM_CLAMP);
		sampler.setFiltering(Ogre::TextureFilterOptions::TFO_TRILINEAR);
		render_system->_setHlmsSamplerblock(0, &sampler);

		render_system->_disableTextureUnitsFrom(1);
#endif
	}
	else{
		// Choose a program that does not require a texture to render pure color with.
		if (render_system->getName() == "Direct3D11 Rendering Subsystem"){
			Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPHLSL_NoTexture");
			if (!noTexPixelShader.isNull()){
				if (!noTexPixelShader->isLoaded()){
					noTexPixelShader->load();
				}

				pixelProgram = noTexPixelShader;
			}
		}
		else if (render_system->getName() == "OpenGL 3+ Rendering Subsystem"){
			Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPGLSL_NoTexture");
			if (!noTexPixelShader.isNull()){
				if (!noTexPixelShader->isLoaded()){
					noTexPixelShader->load();
				}

				pixelProgram = noTexPixelShader;
			}
		}/*else if (render_system->getName() == "OpenGLSLES......."){ // Put correct render system name into play
			Ogre::GpuProgramPtr noTexPixelShader = Ogre::GpuProgramManager::getSingleton().getByName("rocket2DFPGLSLES_NoTexture");
			if (!noTexPixelShader.isNull()){
			if (!noTexPixelShader->isLoaded()){
			noTexPixelShader->load();
			}

			pixelProgram = noTexPixelShader;
			}
			}*/

		// Finally Disable the texture unit
		render_system->_disableTextureUnit(0);
	}

#ifdef OGRE_PSO
	// Destroy the last pso created before making a new one.
	if (hasPSO){
		render_system->_hlmsPipelineStateObjectDestroyed(&pso);
	}

	// Create the PSO for the current render of the GUI
	pso.initialize();
	pso.operationType = Ogre::OT_TRIANGLE_LIST;
	pso.vertexShader = vertexProgram;
	pso.pixelShader = pixelProgram;
	pso.macroblock = mMaterial->getTechnique(0)->getPass(0)->getMacroblock();
	pso.blendblock = mMaterial->getTechnique(0)->getPass(0)->getBlendblock();
	pso.vertexElements = ogre3d_geometry->render_operation.vertexData->vertexDeclaration->convertToV2(); // Required by DX11 or it will crash! :D

	// Create & Set the PSO to the render system
	render_system->_hlmsPipelineStateObjectCreated(&pso);
	render_system->_setPipelineStateObject(&pso);

	// Bind the necessary shader settings to the Vertex Shader to send in the transform matrix information.
	Ogre::GpuProgramParametersSharedPtr vsParams = pso.vertexShader->getDefaultParameters();
	vsParams->setNamedConstant("transformMat", projection_matrix * transform);
	render_system->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, vsParams, Ogre::GPV_ALL);

	// Send the render through. Ogre::v1::CbRenderOp cmd is needed for DX11. 
	// A straight renderOperation passed in _render will work in OpenGL.
	Ogre::v1::CbRenderOp cmd = Ogre::v1::CbRenderOp(ogre3d_geometry->render_operation);
	render_system->_setRenderOperation(&cmd);
	
	// Prepare the render system
	render_system->_render(ogre3d_geometry->render_operation);

	hasPSO = true;
	// Destroy the pso buffer for the next time around
	//render_system->_hlmsPipelineStateObjectDestroyed(&pso);
#else
	Ogre::HlmsCache hlmsCache;
	hlmsCache.vertexShader = vertexProgram;
	hlmsCache.pixelShader = pixelProgram;
	hlmsCache.type = Ogre::HlmsTypes::HLMS_LOW_LEVEL;
	render_system->_setProgramsFromHlms(&hlmsCache);

	// Bind the necessary shader settings to the Vertex Shader to send in the transform matrix information.
	Ogre::GpuProgramParametersSharedPtr vsParams = hlmsCache.vertexShader->getDefaultParameters();
	vsParams->setNamedConstant("transformMat", projection_matrix * transform);
	render_system->bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM, vsParams, Ogre::GPV_ALL);

	// Set the macro and blending information for the HLMS system.
	render_system->_setHlmsMacroblock(mMaterial->getTechnique(0)->getPass(0)->getMacroblock());
	render_system->_setHlmsBlendblock(mMaterial->getTechnique(0)->getPass(0)->getBlendblock());
	
	// Prepare the render system
	render_system->_render(ogre3d_geometry->render_operation);
#endif
}
Head over to the RenderInterfaceOgre3D.h

(File:) RenderInterfaceOgre3D.h: (Line) 96 approx

Underneath the int scissor_bottom variable, add this:

Code: Select all

#ifdef OGRE_PSO
		bool hasPSO;
		Ogre::HlmsPso pso;
#endif
Compile your code and librocket should run in DX11 and OpenGL3+ as long as the shaders and work from the previous post are completed.
Hope this helps :D

p.s. Also, if you get compile errors with CbRenderOp. See this post on the changes: http://www.ogre3d.org/forums/viewtopic.php?f=25&t=88797
Lead developer of the Skyline Game Engine: https://aurasoft-skyline.co.uk
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Re: Ogre3d 2.1 Ported LibRocket

Post by Slicky »

The file download link is no longer valid.

I am trying to chase down which GUI works with 2.1PSO (I think that is the version I have).

We really should set up some of these on github or bitbucket so the code is not lost and can be improved/fixed over time.
User avatar
Zonder
Ogre Magi
Posts: 1168
Joined: Mon Aug 04, 2008 7:51 pm
Location: Manchester - England
x 73

Re: Ogre3d 2.1 Ported LibRocket

Post by Zonder »

Slicky wrote: Thu Sep 06, 2018 9:51 am The file download link is no longer valid.

I am trying to chase down which GUI works with 2.1PSO (I think that is the version I have).

We really should set up some of these on github or bitbucket so the code is not lost and can be improved/fixed over time.
I am pretty sure 2.1PSO got merged back to 2.1
There are 10 types of people in the world: Those who understand binary, and those who don't...
Slicky
Bronze Sponsor
Bronze Sponsor
Posts: 614
Joined: Mon Apr 14, 2003 11:48 pm
Location: Was LA now France
x 25

Re: Ogre3d 2.1 Ported LibRocket

Post by Slicky »

I think you are right (still getting up to speed). So I am using 2.1.
User avatar
blitzcoder
Halfling
Posts: 99
Joined: Wed Oct 09, 2019 4:06 am
x 18
Contact:

Re: Ogre3d 2.1 Ported LibRocket

Post by blitzcoder »

would be nice if this is ported to 1.1x as well or the sample works w/o any issues?

There's also the newer and maintained version called RmlUI (C++14) that is forked from libRocket:
https://github.com/mikke89/RmlUi

New Blitz3D/BlitzBasic/BlitzMax Home - https://blitzcoder.org
Post Reply