Ogre Version: 2.1
Operating System: Linux
Render System: OpenGL3+
I have spent more time than I should trying to bind Ogre with nuklear, and I have it basically working using MovableObject and Renderable, but I seem to have hit a wall with scissoring.
My goal is to create this using only v2.1 function, with no calls to the v1 namespace. I have used some older examples with dead api calls (https://github.com/OGRECave/ogre-imgui) and Ogre's CustomRenderable/DynamicGeometry examples to get it working, but nuklear relies on glScissor before every glDrawElements call to work properly. Without it I get artifacts like the one below.
I am currently looking into doing something through the command buffer - I am still learning, but if I understand it correctly I would want to create a command that calls the rendersystem->_setViewport(), then on every draw command from nuklear I would want to add that viewport command to the command buffer, followed by a draw command translated from nuklear, and finally finish it with a _setViewport command to reset everything.
Getting into it though, this seemed needlesly complicated and riddled with pitfalls just to apply glScissor to a few elements. Before I get too much deeper into it, are there any alternatives or concepts that I'm missing that would make this simpler?
[2.1] Renderable with clipping
-
- Gnoblar
- Posts: 4
- Joined: Sun May 05, 2019 10:20 pm
Re: [2.1] Renderable with clipping
One last post before I give up. I basically tried to redo the RenderQueue's renderGL3() function. Code below.
I checked it out on renderdoc and there are calls to glMultiDrawElementsIndirect(0) as expected - though I'm concerned about that 0 - and the vertex/fragment shader is bound properly, but nothing appears on screen and there is no input to the vertex shader. Could that mean the VAO is not created/set correctly?
I checked it out on renderdoc and there are calls to glMultiDrawElementsIndirect(0) as expected - though I'm concerned about that 0 - and the vertex/fragment shader is bound properly, but nothing appears on screen and there is no input to the vertex shader. Could that mean the VAO is not created/set correctly?
Code: Select all
void NkManager::update()
{
Ogre::Viewport *vp = mManager->getCurrentViewport();
if ( !vp ) return;
// ...
// nk_convert() to get draw list from nuklear
// ...
Ogre::Matrix4 ortho {
2.0f, 0.0f, 0.0f, -1.0f,
0.0f, -2.0f, 0.0f, 1.0f,
0.0f, 0.0f, -1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
ortho[0][0] /= (float)vp->getActualWidth();
ortho[1][1] /= (float)vp->getActualHeight();
mPass->getVertexProgramParameters()->setNamedConstant( "ProjectionMatrix", ortho );
Ogre::RenderSystem *mRenderSystem = mManager->getDestinationRenderSystem();
// PSO state
Ogre::PsoCacheHelper *psoCache = new Ogre::PsoCacheHelper( mRenderSystem );
psoCache->clearState();
psoCache->setBlendblock( mPass->getBlendblock() );
psoCache->setMacroblock( mPass->getMacroblock() );
psoCache->setVertexShader( mPass->getVertexProgram() );
psoCache->setPixelShader( mPass->getFragmentProgram() );
const struct nk_draw_command *cmd;
int32_t ri = 0;
Ogre::uint16 offset = 0;
nk_draw_foreach( cmd, nkCtx, &cmds ) {
if ( !cmd->elem_count ) continue;
mRenderables.push_back( new NkRenderable( mManager ) );
// createVao() is basically a carbon copy of the customrenderable sample for creating a vao
mRenderables[ri]->createVao( tempVertices, tempElements, offset,
cmd->elem_count, mVertexElements );
// I went through and confirmed to the best of my knowledge that tempVertices/tempElements have
// the correct vertex coordinates and element list.
// createVao also seems to create a correct variable mVao in the NkRenderable to the best of my knowledge
psoCache->setVertexFormat( mRenderables[ri]->mVao->getVertexDeclaration(),
Ogre::OT_TRIANGLE_LIST, false );
mRenderables[ri]->mRenderableHash = psoCache->getRenderableHash();
offset += cmd->elem_count;
ri += 1;
}
// Setup indirect buffer
Ogre::VaoManager *vaoManager = mManager->getDestinationRenderSystem()->getVaoManager();
Ogre::IndirectBufferPacked *indirectBuffer = 0;
unsigned char *indirectDraw = 0;
unsigned char *startIndirectDraw = 0;
int baseInstanceAndIndirectBuffers = 0;
if( vaoManager->supportsIndirectBuffers() ) {
baseInstanceAndIndirectBuffers = 2;
int numDraws = mRenderables.size();
size_t requiredBytes = numDraws * sizeof( Ogre::CbDrawCallIndexed );
indirectBuffer = vaoManager->createIndirectBuffer( requiredBytes,
Ogre::BT_DYNAMIC_PERSISTENT, 0, false );
indirectDraw = static_cast<unsigned char*>(
indirectBuffer->map( 0, indirectBuffer->getNumElements() ) );
}
else if( vaoManager->supportsBaseInstance() ) {
baseInstanceAndIndirectBuffers = 1;
indirectDraw = indirectBuffer->getSwBufferPtr();
}
startIndirectDraw = indirectDraw;
std::vector<NkRenderable*>::const_iterator itor = mRenderables.begin();
std::vector<NkRenderable*>::const_iterator end = mRenderables.end();
psoCache->clearState();
psoCache->setRenderTarget( vp->getTarget() );
while( itor != end ) {
Ogre::HlmsPso *pso = psoCache->getPso( (*itor)->mRenderableHash );
mRenderSystem->_setPipelineStateObject( pso );
mRenderSystem->bindGpuProgramParameters( Ogre::GPT_VERTEX_PROGRAM,
mPass->getVertexProgramParameters(),
Ogre::GPV_ALL );
mRenderSystem->bindGpuProgramParameters( Ogre::GPT_FRAGMENT_PROGRAM,
mPass->getFragmentProgramParameters(),
Ogre::GPV_ALL );
mRenderSystem->_setVertexArrayObject( (*itor)->mVao );
mRenderSystem->_setIndirectBuffer( indirectBuffer );
void *indBufOffset = reinterpret_cast<void*>( indirectBuffer->_getFinalBufferStart() +
( indirectDraw - startIndirectDraw ));
Ogre::CbDrawCallIndexed *drawCmd = new Ogre::CbDrawCallIndexed(
baseInstanceAndIndirectBuffers, (*itor)->mVao, indBufOffset );
mRenderSystem->_render( drawCmd );
indirectDraw += sizeof( Ogre::CbDrawCallIndexed );
itor++;
delete drawCmd;
}
if( baseInstanceAndIndirectBuffers == 2 && indirectBuffer )
{
indirectBuffer->unmap( Ogre::UO_UNMAP_ALL );
}
while( mRenderables.size() > 0 )
{
delete mRenderables.back();
mRenderables.pop_back();
}
}
-
- Gnoblar
- Posts: 4
- Joined: Sun May 05, 2019 10:20 pm
Re: [2.1] Renderable with clipping
I'm probably just sending electrons into the aether, but I got it working after going through the renderGL3 code and reading into the indirect buffer a bit more. I'm still concerned about not being able to see the vertex data in RenderDoc, but I can hold off on figuring that out for some other time. I also got it by doing RenderSystem->_setViewport() before every draw call, which feels kind of dirty. I noticed that the master branch has RenderSystem->setScissorTest(), but not v2-1. Why is that removed in 2.1?
One other thing, to use the example in PsoCacheHelper.h I had to change the prototype of setVertex/FragmentShader to accept a const GpuProgramPtr&. I don't know if this is just my lack of experience with C++, but I couldn't get it to work with the result of mPass->getVertexProgram() otherwise.
And lastly, I couldn't get the RenderQueueListener events to fire and had to hook into the RenderTargetListener events. I tried to grep the source to find where that's called and didn't seem to find it. I think only renderQueueStarted fires. Is this correct?
One other thing, to use the example in PsoCacheHelper.h I had to change the prototype of setVertex/FragmentShader to accept a const GpuProgramPtr&. I don't know if this is just my lack of experience with C++, but I couldn't get it to work with the result of mPass->getVertexProgram() otherwise.
And lastly, I couldn't get the RenderQueueListener events to fire and had to hook into the RenderTargetListener events. I tried to grep the source to find where that's called and didn't seem to find it. I think only renderQueueStarted fires. Is this correct?