[Ogre 2.1] Porting CEGUI to OGRE 2.1
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
[Ogre 2.1] Porting CEGUI to OGRE 2.1
I am currently trying to migrate CEGUI to OGRE 2.1.
I currently have a working version of CEGUI for OGRE 2.0, where the v1 viewports have been replaced by the v2 compositor. This version is available on the CEGUI official repository.
From what I have seen, 2 aspects make CEGUI incompatible with OGRE 2.1 without changes:
- CEGUI sets all the blend and rendering options using functions that have been removed (RenderSystem::_setSceneBlending, RenderSystem::_setCullingMode, etc.)
- CEGUI is using either the fixed pipeline or HLSL/GLSL shaders incompatible with DX11 / GL3+
My first thought was "No problem, HLMS addresses both aspects, it will be easy to port CEGUI to use HLMS!"
Well... it turns out that it is not as easy as I thought...
My big issue is that CEGUI directly calls the RenderSystem::_render function with the render operation as parameter.
As such, I have not yet figured out how I could provide the HLMS information to the RenderSystem without important changes.
From my understanding, here is what happens when a render operation is done:
- The HLMS macroblock is passed to the RS using the RenderSystem::_setHlmsMacroblock function
- The HLMS blendblock is passed to the RS using the RenderSystem::_setHlmsBlendblock function
- The HLMS shaders are retrieved using the HLMS::getMaterial function and passed to the RS using the RenderSystem::_setProgramsFromHlms
I could pass the macroblock and the blendblock to the render system, but I do not know how to get the shaders as I do not have any Renderable object.
Can they be retrieved from another way?
However, I feel this would be a "quick and dirty" port.
I feel that the correct way to do it would be to:
- Replace all the v1 classes by v2 classes (using the VAO)
- Create a Renderable object for the GUI and use the render queue to render it
Am I right?
Or would it be better on a performance point of view to keep calling low level functions like RenderSystem::_render? In this case, would it change anything to use the VAO instead of the v1 classes?
I currently have a working version of CEGUI for OGRE 2.0, where the v1 viewports have been replaced by the v2 compositor. This version is available on the CEGUI official repository.
From what I have seen, 2 aspects make CEGUI incompatible with OGRE 2.1 without changes:
- CEGUI sets all the blend and rendering options using functions that have been removed (RenderSystem::_setSceneBlending, RenderSystem::_setCullingMode, etc.)
- CEGUI is using either the fixed pipeline or HLSL/GLSL shaders incompatible with DX11 / GL3+
My first thought was "No problem, HLMS addresses both aspects, it will be easy to port CEGUI to use HLMS!"
Well... it turns out that it is not as easy as I thought...
My big issue is that CEGUI directly calls the RenderSystem::_render function with the render operation as parameter.
As such, I have not yet figured out how I could provide the HLMS information to the RenderSystem without important changes.
From my understanding, here is what happens when a render operation is done:
- The HLMS macroblock is passed to the RS using the RenderSystem::_setHlmsMacroblock function
- The HLMS blendblock is passed to the RS using the RenderSystem::_setHlmsBlendblock function
- The HLMS shaders are retrieved using the HLMS::getMaterial function and passed to the RS using the RenderSystem::_setProgramsFromHlms
I could pass the macroblock and the blendblock to the render system, but I do not know how to get the shaders as I do not have any Renderable object.
Can they be retrieved from another way?
However, I feel this would be a "quick and dirty" port.
I feel that the correct way to do it would be to:
- Replace all the v1 classes by v2 classes (using the VAO)
- Create a Renderable object for the GUI and use the render queue to render it
Am I right?
Or would it be better on a performance point of view to keep calling low level functions like RenderSystem::_render? In this case, would it change anything to use the VAO instead of the v1 classes?
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Additional precisions : at the moment, I have created a datablock using the HLMS Unlit.
My idea was to use this datablock to feed the render system with the macroblock, the blencblock and the shaders.
My idea was to use this datablock to feed the render system with the macroblock, the blencblock and the shaders.
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
CEGUI always used manual rendering to do its stuff on Ogre, which wasn't exactly the best idea on 1.x; but as a quick hack, it worked.
If there's a D3D11 port of CEGUI, then the macro and blendblocks can translate to rasterizer and blend states. You might want to take a look at that.
As for rendering:
IIRC CEGUI doesn't need a world transform matrix because it updates the vertices directly (correct me if I'm wrong). You could indeed use one Renderable & MovableObject per widget to make the Hlms happy.
But if you want it quick and dirty; you could have a dummy Renderable & MovableObject (to provide to fillBufferForV2), and draw every widget yourself replicating the functionality that is on RenderQueue::renderGL3.
If there's a D3D11 port of CEGUI, then the macro and blendblocks can translate to rasterizer and blend states. You might want to take a look at that.
As for rendering:
IIRC CEGUI doesn't need a world transform matrix because it updates the vertices directly (correct me if I'm wrong). You could indeed use one Renderable & MovableObject per widget to make the Hlms happy.
But if you want it quick and dirty; you could have a dummy Renderable & MovableObject (to provide to fillBufferForV2), and draw every widget yourself replicating the functionality that is on RenderQueue::renderGL3.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Thanks a lot for your answer!
I have tried the quick and dirty version, but it's reaaaaaaally dirty
By doing this, I have an assertion in OgreHlmsBufferManager.cpp, on this line:
So I think I will try the clean version ^^
From what I have understood from CEGUI, it uses a world transform matrix, but the calculation is already done:
I will keep you informed. Thanks for the help!
I have tried the quick and dirty version, but it's reaaaaaaally dirty
Code: Select all
// Apply the HLMS blocks to the render system
d_pimpl->d_renderSystem->_setHlmsBlendblock(d_pimpl->d_hlmsDatablock->getBlendblock());
d_pimpl->d_renderSystem->_setHlmsMacroblock(d_pimpl->d_hlmsDatablock->getMacroblock());
// Create a dummy renderable / movable object to retrieve the shaders
Ogre::SceneManager* sceneManager = d_pimpl->d_ogreRoot->getSceneManagerIterator().getNext();
Ogre::v1::SimpleRenderable dummyRenderable((Ogre::IdType)0, &sceneManager->_getEntityMemoryManager(Ogre::SCENE_DYNAMIC), sceneManager);
dummyRenderable.setRenderOperation(renderOp);
dummyRenderable.setDatablock(d_pimpl->d_hlmsDatablock);
sceneManager->getRootSceneNode()->attachObject(&dummyRenderable);
// Fill the dummy queued renderable
Ogre::QueuedRenderable queuedRenderable;
queuedRenderable.movableObject = &dummyRenderable;
queuedRenderable.renderable = &dummyRenderable;
d_pimpl->d_hlmsDatablock->calculateHash();
queuedRenderable.hash = d_pimpl->d_hlmsDatablock->mTextureHash;
Ogre::Hlms *hlms = d_pimpl->d_ogreRoot->getHlmsManager()->getHlms(static_cast<Ogre::HlmsTypes>(d_pimpl->d_hlmsDatablock->mType));
const Ogre::HlmsCache *hlmsCache = hlms->getMaterial(&Ogre::HlmsCache(), Ogre::HlmsCache(), queuedRenderable, false);
// Pass the shader to the render system
d_pimpl->d_renderSystem->_setProgramsFromHlms(hlmsCache);
// Fill the buffers
Ogre::CommandBuffer commandBuffer;
hlms->fillBuffersForV1(hlmsCache, queuedRenderable, false, 0, &commandBuffer);
sceneManager->getRootSceneNode()->detachObject(&dummyRenderable);
Code: Select all
shaderBufferCmd->bufferPacked == texBuffer
So I think I will try the clean version ^^
From what I have understood from CEGUI, it uses a world transform matrix, but the calculation is already done:
Code: Select all
void OgreGeometryBuffer::updateMatrix() const
{
// translation to position geometry and offset to pivot point
Ogre::Matrix4 trans;
trans.makeTrans(d_translation.d_x + d_pivot.d_x,
d_translation.d_y + d_pivot.d_y,
d_translation.d_z + d_pivot.d_z);
// rotation
Ogre::Matrix4 rot(Ogre::Quaternion(
d_rotation.d_w, d_rotation.d_x, d_rotation.d_y, d_rotation.d_z));
// translation to remove rotation pivot offset
Ogre::Matrix4 inv_pivot_trans;
inv_pivot_trans.makeTrans(-d_pivot.d_x, -d_pivot.d_y, -d_pivot.d_z);
// calculate final matrix
d_matrix = trans * rot * inv_pivot_trans;
d_matrixValid = true;
}
I will keep you informed. Thanks for the help!
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Big step forward: the GUI is displaying, but... not exactly as expected
Might need some adjustements
Might need some adjustements
-
- Gremlin
- Posts: 196
- Joined: Tue Jan 27, 2009 12:27 am
- x 24
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
How did you do setup the transparency ? In the neighbour thread Porting Gorilla xrgo is having problem with porting Gorilla to Ogre 2.1, he seems to be stuck on the transparency. I didn't have time to look into it myself.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Actually, I replaced the shaders / fixed pipeline used in CEGUI by the HLMS Unlit system.
I also applied the blending settings used by CEGUI on the HLMS datablock:
Then, when I set a texture with alpha using the HLMSUnlitDatablock::setTexture function, the transparency gets rendered automatically.
The hard part is to replace all the manual drawing operations by a "HLMS compatible" operation.
To do this, I had to create a MovableObject and multiple Renderable objects. For each Renderable, a HLMSUnlitDatablock is set.
When the Renderable objects are assigned to the "mRenderables" field of the MovableObject, they are renderend automatically (if the MovableObject is attached to the scene).
I will upload my code once it is working
I also applied the blending settings used by CEGUI on the HLMS datablock:
Code: Select all
// Blend parameters
if (d_pimpl->d_activeBlendMode == BM_RTT_PREMULTIPLIED)
{
d_pimpl->d_hlmsBlendblock.mSourceBlendFactor = Ogre::SBF_ONE;
d_pimpl->d_hlmsBlendblock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
}
else
{
d_pimpl->d_hlmsBlendblock.mSeparateBlend = true;
d_pimpl->d_hlmsBlendblock.mSourceBlendFactor = Ogre::SBF_SOURCE_ALPHA;
d_pimpl->d_hlmsBlendblock.mDestBlendFactor = Ogre::SBF_ONE_MINUS_SOURCE_ALPHA;
d_pimpl->d_hlmsBlendblock.mSourceBlendFactorAlpha = Ogre::SBF_ONE_MINUS_DEST_ALPHA;
d_pimpl->d_hlmsBlendblock.mDestBlendFactorAlpha = Ogre::SBF_ONE;
}
The hard part is to replace all the manual drawing operations by a "HLMS compatible" operation.
To do this, I had to create a MovableObject and multiple Renderable objects. For each Renderable, a HLMSUnlitDatablock is set.
When the Renderable objects are assigned to the "mRenderables" field of the MovableObject, they are renderend automatically (if the MovableObject is attached to the scene).
I will upload my code once it is working
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Finally, I have managed to display a GUI on OGRE 2.1 using CEGUI!
In the end, the way to make it work was easier than what I had first tried.
It seems that the shaders in the 0.8.4 version of CEGUI are already compatible with OpenGL 3+, so I was able to use them to display the GUI instead of using the HLMS Unlit component.
I only used the HLMS macroblock and blendblock to pass the rendering parameters to the rendering system before calling the _render function.
By doing this, only few changes are required in CEGUI, and it even seems better on a performance point of view because it avoids all the HLMS mecanisms that are not necessary for CEGUI (auto-instanciating, etc.).
However, I still have 3 things to do before I can say that CEGUI is successfully ported to OGRE 2.1:
- Use the HLMS samplerblock for the texture filtering parameters
- Make it work on D3D11 (not tested yet)
- Resolve the clipping bug that can be seen in the attached screenshot
Concerning this bug, my first guess is that it comes from the scissors test.
In CEGUI 0.8.4, the scissors test is used this way:
I have replaced this code by the following:
But the issue is still present...
Does someone have a clue on how I could fix this?
Thanks!
In the end, the way to make it work was easier than what I had first tried.
It seems that the shaders in the 0.8.4 version of CEGUI are already compatible with OpenGL 3+, so I was able to use them to display the GUI instead of using the HLMS Unlit component.
I only used the HLMS macroblock and blendblock to pass the rendering parameters to the rendering system before calling the _render function.
By doing this, only few changes are required in CEGUI, and it even seems better on a performance point of view because it avoids all the HLMS mecanisms that are not necessary for CEGUI (auto-instanciating, etc.).
However, I still have 3 things to do before I can say that CEGUI is successfully ported to OGRE 2.1:
- Use the HLMS samplerblock for the texture filtering parameters
- Make it work on D3D11 (not tested yet)
- Resolve the clipping bug that can be seen in the attached screenshot
Concerning this bug, my first guess is that it comes from the scissors test.
In CEGUI 0.8.4, the scissors test is used this way:
Code: Select all
d_renderSystem.setScissorTest(
i->clip, d_clipRect.left(), d_clipRect.top(),
d_clipRect.right(), d_clipRect.bottom());
Code: Select all
Ogre::RenderTarget* renderTarget = d_owner.getOgreRenderTarget();
for (int index = 0; index < renderTarget->getNumViewports(); ++index)
{
if (i->clip)
{
renderTarget->getViewport(index)->setScissors(d_clipRect.left(), d_clipRect.top(),
d_clipRect.right(), d_clipRect.bottom());
}
}
Does someone have a clue on how I could fix this?
Thanks!
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Messing up with the Viewport can have unintended consequences because it could be shared by other compositor passes (specially since you're trying to modify all of them rather than the active one). Of course if the viewport is later restored to its original values after you're done, you can avoid these unintended consequences.
The reason it failed is because the actual scissor rects are set when RenderSystem::_setViewport is called.
After you've changed the viewport's scissors, you need to call _setViewport( vp ) again. Mind you this is probably slow.
I removed RenderSystem::setScissorTest because it was being abused; causing important slowdowns. Therefore it was moved to where API docs recommend it should be set: on a more global scale, like per pass (hence the data lives in the compositor).
There are other ways to filter stuff, like clipping in the pixel shader, clamping vertices to the edges, or use the stencil buffer.
Setting the scissor test can be a performance gain if you will be rendering a lot of widgets inside its parent widget. But usually its children will contain more children which means more scissor test changes...
Edit: Forgot to congratulate you for getting it running on 2.1!!! Congrats!!!
The reason it failed is because the actual scissor rects are set when RenderSystem::_setViewport is called.
After you've changed the viewport's scissors, you need to call _setViewport( vp ) again. Mind you this is probably slow.
I removed RenderSystem::setScissorTest because it was being abused; causing important slowdowns. Therefore it was moved to where API docs recommend it should be set: on a more global scale, like per pass (hence the data lives in the compositor).
There are other ways to filter stuff, like clipping in the pixel shader, clamping vertices to the edges, or use the stencil buffer.
Setting the scissor test can be a performance gain if you will be rendering a lot of widgets inside its parent widget. But usually its children will contain more children which means more scissor test changes...
Edit: Forgot to congratulate you for getting it running on 2.1!!! Congrats!!!
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Thanks And thanks for your help!
The scissors test is now also working \o/
On OpenGL 3+, there is only one thing that is not working: texture filtering.
I have replaced this code:
By this code:
But the texture still not seem to be filtered (cf. attachment), although this code is called after the RenderSystem::_setTexture function, as stated in the RenderSystem::_setHlmsSamplerblock documentation.
Any idea of what I have missed?
The scissors test is now also working \o/
On OpenGL 3+, there is only one thing that is not working: texture filtering.
I have replaced this code:
Code: Select all
d_renderSystem._setTextureUnitFiltering(0, FO_LINEAR, FO_LINEAR, FO_POINT);
d_renderSystem._setTextureAddressingMode(0, S_textureAddressMode);
d_renderSystem._setTextureMatrix(0, Matrix4::IDENTITY);
d_renderSystem._setAlphaRejectSettings(CMPF_ALWAYS_PASS, 0, false);
d_renderSystem._setTextureBlendMode(0, S_colourBlendMode);
d_renderSystem._setTextureBlendMode(0, S_alphaBlendMode);
d_renderSystem._disableTextureUnitsFrom(1);
Code: Select all
d_renderSystem._setTextureMatrix(0, Matrix4::IDENTITY);
d_renderSystem._setTextureBlendMode(0, S_colourBlendMode);
d_renderSystem._setTextureBlendMode(0, S_alphaBlendMode);
d_renderSystem._disableTextureUnitsFrom(1);
Ogre::HlmsSamplerblock samplerblock;
samplerblock.mMinFilter = FO_LINEAR;
samplerblock.mMagFilter = FO_LINEAR;
samplerblock.mMipFilter = FO_POINT;
samplerblock.mU = TAM_CLAMP;
samplerblock.mV = TAM_CLAMP;
samplerblock.mW = TAM_CLAMP;
samplerblock.mCompareFunction = CMPF_ALWAYS_PASS;
d_renderSystem._setHlmsSamplerblock(0, &samplerblock);
Any idea of what I have missed?
- Attachments
-
- TextureFiltering.png (21.09 KiB) Viewed 6303 times
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
You need to create the samplerblock via HlsmManager::getSamplerblock like any other block.
Beware that:
Beware that:
- getSamplerblock increases the block's reference count. When you're done using it call destroyBlendblock
- getSamplerblock runs a linear search. You probably don't want to call this function every frame for every object. Cache the result when creating the widget.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Yes! You are right, that was the issue, thanks again!
I have also corrected the creation of the macroblock and blendblock
I have seen your new asserts to force creating HLMS blocks using the get*block function, good idea
However, it seems that the _hlmsBlendblockCreated function is not overridden by the GL3+ renderer, so the assert is triggered in debug mode.
I guess this function should be added in the GL3+ renderer, even if it only fills a "dummy" mRsData?
Anyway, in release mode, CEGUI now works perfectly on my project with OGRE 2.1 on the Open GL3+ renderer!
It does not work yet on D3D11, the shaders are too old I need to take the shaders in the D3D11 CEGUI renderer.
I was wondering: do I have the rights to upload my CEGUI source files on this forum, as attachment?
I have created a post on the CEGUI forum too, I hope my changes will be accepted as a pull request for CEGUI 0.8.x
I have also corrected the creation of the macroblock and blendblock
I have seen your new asserts to force creating HLMS blocks using the get*block function, good idea
However, it seems that the _hlmsBlendblockCreated function is not overridden by the GL3+ renderer, so the assert is triggered in debug mode.
I guess this function should be added in the GL3+ renderer, even if it only fills a "dummy" mRsData?
Anyway, in release mode, CEGUI now works perfectly on my project with OGRE 2.1 on the Open GL3+ renderer!
It does not work yet on D3D11, the shaders are too old I need to take the shaders in the D3D11 CEGUI renderer.
I was wondering: do I have the rights to upload my CEGUI source files on this forum, as attachment?
I have created a post on the CEGUI forum too, I hope my changes will be accepted as a pull request for CEGUI 0.8.x
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Ouch! Will fix it when I get back.Jayray wrote:I have seen your new asserts to force creating HLMS blocks using the get*block function, good idea
However, it seems that the _hlmsBlendblockCreated function is not overridden by the GL3+ renderer, so the assert is triggered in debug mode.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Thanks!
For those who want a CEGUI version compatible with OGRE 2.1 (OpenGL 3+ rendersystem only atm), here is the thread I have created on the official CEGUI forum : http://cegui.org.uk/forum/viewtopic.php ... 388#p33388
And the link to the pull request: https://bitbucket.org/cegui/cegui/pull- ... -with/diff
One step left: making it work with the D3D11 rendersystem!
For those who want a CEGUI version compatible with OGRE 2.1 (OpenGL 3+ rendersystem only atm), here is the thread I have created on the official CEGUI forum : http://cegui.org.uk/forum/viewtopic.php ... 388#p33388
And the link to the pull request: https://bitbucket.org/cegui/cegui/pull- ... -with/diff
One step left: making it work with the D3D11 rendersystem!
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Damn, D3D11 is also a bit recalcitrant...
I have replaced the shaders with D3D11-compatible shaders, but I get the following error when rendering:
I have replaced the shaders with D3D11-compatible shaders, but I get the following error when rendering:
The shaders are bound using the RenderSystem::bindGpuProgram function. I have seen that the code that binds the shaders to the D3D11 context is commented in the D3D11RenderSystem::bindGpuProgram function, is it normal?OGRE EXCEPTION(3:RenderingAPIException): D3D11 device cannot draw
Error Description:ID3D11DeviceContext::Draw: A Vertex Shader is always required when drawing, but none is currently bound.
in D3D11RenderSystem::_render at F:/Dev/Add-ons/OGRE/Ogre_v2.1_Src/RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp (line 3067)
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Mmm... bindGpuProgram is another vestige floating around. I don't think it's in use. Probably dead code (though may still be useful for Compute Shaders).
The new way is to use _setProgramsFromHlms. You can create a dummy HlmsCache in which you store the actual needed ptrs, if you want.
The new way is to use _setProgramsFromHlms. You can create a dummy HlmsCache in which you store the actual needed ptrs, if you want.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Hi,
I have finally managed to take some time to continue the CEGUI porting on the D3D11 render system.
Using _setProgramsFromHlms with a dummy HlmsCache, I am now able to use the CEGUI HLSL shaders with Ogre 2.1.
However, it seems that the texture passed to the pixel shader is always null: all the texture.Sample() function always returns (0, 0, 0, 0)...
I do not think that the issue comes from the shaders as they are very basic and my tests tend to show that they are OK, but I can post them if needed.
The texture is passed to the render system with this code:
Then, the shaders parameters are bound using this code:
As this works for the OpenGL3+ render system, I suppose that I am only missing a step to pass the texture information to the D3D11 render system, but I cannot find which one...
I have analyzed the RenderQueue::renderSingleObject() and the HlmsLowLevel::fillBuffersFor() functions, but I cannot find what I am missing
Maybe the call to _setTextureUnitSettings? But I do not have a pass, so I have no TextureUnitState object.
Or some fragment program parameters that I have to pass using the bindGpuProgramParameters function?
Any help would greatly appreciated (as always )
Thanks!
I have finally managed to take some time to continue the CEGUI porting on the D3D11 render system.
Using _setProgramsFromHlms with a dummy HlmsCache, I am now able to use the CEGUI HLSL shaders with Ogre 2.1.
However, it seems that the texture passed to the pixel shader is always null: all the texture.Sample() function always returns (0, 0, 0, 0)...
I do not think that the issue comes from the shaders as they are very basic and my tests tend to show that they are OK, but I can post them if needed.
The texture is passed to the render system with this code:
Code: Select all
d_renderSystem._setTexture(0, true, i->texture.get());
d_renderSystem._setTextureCoordCalculation(0, TEXCALC_NONE);
d_renderSystem._setTextureCoordSet(0, 0);
d_renderSystem._setTextureMatrix(0, Matrix4::IDENTITY);
d_renderSystem._setTextureBlendMode(0, S_colourBlendMode);
d_renderSystem._setTextureBlendMode(0, S_alphaBlendMode);
d_renderSystem._disableTextureUnitsFrom(1);
d_renderSystem._setHlmsSamplerblock(0, d_owner.getHlmsSamplerblock());
d_renderSystem._render(d_renderOp);
Code: Select all
if (d_pimpl->d_useGLSL)
{
if(d_pimpl->d_useGLSLCore)
{
d_pimpl->d_vertexShaderParameters->
setNamedConstant("modelViewPerspMatrix", getWorldViewProjMatrix());
d_pimpl->d_renderSystem->
bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM,
d_pimpl->d_vertexShaderParameters,
Ogre::GPV_ALL);
}
d_pimpl->d_pixelShaderParameters->
setNamedConstant("texture0", 0);
d_pimpl->d_renderSystem->
bindGpuProgramParameters(Ogre::GPT_FRAGMENT_PROGRAM,
d_pimpl->d_pixelShaderParameters,
Ogre::GPV_ALL);
}
else
{
d_pimpl->d_vertexShaderParameters->
setNamedConstant("worldViewProjMatrix", getWorldViewProjMatrix());
d_pimpl->d_renderSystem->
bindGpuProgramParameters(Ogre::GPT_VERTEX_PROGRAM,
d_pimpl->d_vertexShaderParameters,
Ogre::GPV_ALL);
}
I have analyzed the RenderQueue::renderSingleObject() and the HlmsLowLevel::fillBuffersFor() functions, but I cannot find what I am missing
Maybe the call to _setTextureUnitSettings? But I do not have a pass, so I have no TextureUnitState object.
Or some fragment program parameters that I have to pass using the bindGpuProgramParameters function?
Any help would greatly appreciated (as always )
Thanks!
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
D3D11 needs a texture and a sampler.
C++ side, you need to call RenderSystem::setTexture & RenderSystem::_setHlmsSamplerblock.
HLSL side, you need to use register( t0 ) to use the texture at slot 0; and register( s0 ) to use the sampler at slot 0. (In D3D11 you can use the same sampler for many different textures if you want, whereas in GL you are tied to one sampler per texture).
If you're doing that ok, then I suggest RenderDoc. It even supports debugging HLSL code. Should be a no brainer once you hook it.
C++ side, you need to call RenderSystem::setTexture & RenderSystem::_setHlmsSamplerblock.
HLSL side, you need to use register( t0 ) to use the texture at slot 0; and register( s0 ) to use the sampler at slot 0. (In D3D11 you can use the same sampler for many different textures if you want, whereas in GL you are tied to one sampler per texture).
If you're doing that ok, then I suggest RenderDoc. It even supports debugging HLSL code. Should be a no brainer once you hook it.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
I will try that, thanks!
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
I finally got CEGUI working on the D3D11 renderer!
RenderDoc confirmed what I thought: the texture passed to my shader was "null", meaning all pixels had the (0, 0, 0, 0) value.
After some digging in the D3D11 render system, I found out that the texture was filled differently depending on the "dynamic" flag (HBU_STATIC or HBU_DYNAMIC). By default, this flag is set as static when creating a texture using the Ogre::TextureManager::createManual() function. When changing it to dynamic, the textures are well filled and displayed!
But this leads me to some questions:
- What is the exact role of this flag? Is it comparable to the SCENE_STATIC flag, i.e. a performance optimisation for textures that can be updated but should not be updated too often?
- If this is the case, does that mean that there is a bug in the D3D11 render system causing the textures with this flag to be not updated? Or should a function be called each time the texture is updated? (the textures are well filled in OpenGL3+ however)
- In the case of a UI engine like CEGUI, what flag is recommended? Dynamic as some textures might be updated often, or static as there are many static images? Or both, depending on the texture type? (static for images, dynamic for textures that will be updated)
Thanks again for your help!
RenderDoc confirmed what I thought: the texture passed to my shader was "null", meaning all pixels had the (0, 0, 0, 0) value.
After some digging in the D3D11 render system, I found out that the texture was filled differently depending on the "dynamic" flag (HBU_STATIC or HBU_DYNAMIC). By default, this flag is set as static when creating a texture using the Ogre::TextureManager::createManual() function. When changing it to dynamic, the textures are well filled and displayed!
But this leads me to some questions:
- What is the exact role of this flag? Is it comparable to the SCENE_STATIC flag, i.e. a performance optimisation for textures that can be updated but should not be updated too often?
- If this is the case, does that mean that there is a bug in the D3D11 render system causing the textures with this flag to be not updated? Or should a function be called each time the texture is updated? (the textures are well filled in OpenGL3+ however)
- In the case of a UI engine like CEGUI, what flag is recommended? Dynamic as some textures might be updated often, or static as there are many static images? Or both, depending on the texture type? (static for images, dynamic for textures that will be updated)
Thanks again for your help!
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Apparently my post has been eclipsed by all the other posts of the week-end ^^
Just to be sure before I send a pull request for CEGUI: should I set the dynamic flag for the CEGUI textures, or should the static flag work as well and there is a bug in the D3D11 render system for static textures?
Thanks!
Just to be sure before I send a pull request for CEGUI: should I set the dynamic flag for the CEGUI textures, or should the static flag work as well and there is a bug in the D3D11 render system for static textures?
Thanks!
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
If you were uploading your texture using blitToMemory, I fixed a bug in D3D11 last week that could be causing what you describe.
- Jayray
- Greenskin
- Posts: 115
- Joined: Sun Sep 09, 2012 5:29 pm
- Location: Strasbourg, France
- x 9
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
The texture is indeed uploaded using blitToMemory, but I was already using the latest source including your commit.
But with the HBU_DYNAMIC flag set, everything is OK, the issue is only present with the HBU_STATIC flag.
Is there a drawback to setting the HBU_DYNAMIC flag instead of HBU_STATIC?
Thanks!
But with the HBU_DYNAMIC flag set, everything is OK, the issue is only present with the HBU_STATIC flag.
Is there a drawback to setting the HBU_DYNAMIC flag instead of HBU_STATIC?
Thanks!
-
- Gremlin
- Posts: 196
- Joined: Tue Jan 27, 2009 12:27 am
- x 24
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Are you comparing HBU_STATIC and HBU_DYNAMIC here, or the default and HBU_DYNAMIC ?
From the source :
So the default is not only set to HBU_STATIC, but also to HBU_WRITE_ONLY
From the source :
Code: Select all
TU_DEFAULT = TU_AUTOMIPMAP | TU_STATIC_WRITE_ONLY
- dark_sylinc
- OGRE Team Member
- Posts: 5296
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1278
- Contact:
Re: [Ogre 2.1] Porting CEGUI to OGRE 2.1
Any, all, or none of the following may happen:Jayray wrote:Is there a drawback to setting the HBU_DYNAMIC flag instead of HBU_STATIC?
- The memory is placed in system RAM. So when the GPU wants to read, it has to do across the PCIe bridge every time (Slower).
- The memory is placed in GPU RAM but some component (e.g. cache) is snooping around for possible changes (Slower).
- The runtime API/driver reserves more RAM in preparation for discard being called (often). This will waste RAM, and can take away space from other dynamic buffers that actually need to be updated very often. Taking away space is critical because if the API runs out of reserved space, the discard will just cause a stall instead of returning immediately.
But if you won't be updating it often, you're then just getting the disadvantages, with no advantages.