Pass Manager - Callback for Nodes / CgFX support example

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Pass Manager - Callback for Nodes / CgFX support example

Post by Nadro »

Hi,
I'm currently working on CgFX support for IrrCg, all work very well, but in Irrlicht we can't acces to node passes. I think that we should create in core small callback for easy manage it.

Currently it looks like this:

Code: Select all

{
     for (i=0; i<SolidNodeList.size(); ++i)
     SolidNodeList[i].Node->render();
}
What You think about some similar for it:

Code: Select all

{
     for (i=0; i<SolidNodeList.size(); ++i)
     SolidNodeList[i].Node->getRenderCallback()->execute();
}
Function getRenderCallback() is pointer to class which default execute normal "Node->render()", but we will can override this class by other. It will be also useful in feature for easy manage techniques from *.fx files.

I know, about LightManager callback but, this idea I think will be more elastic and usefull for integrate in each node rendering via drawAll() function.
Last edited by Nadro on Thu Jul 02, 2009 11:44 pm, edited 1 time in total.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

There's absolutely no reason to do it that way. Simply because you can overwrite the render method in your custom scene node. You'd also have to overwrite your callback pointer, so you'd gain nothing here.
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

And btw in irrlicht svn aka 1.6 is a lightmanager which has a callback before each render pass and before each scenenode....that should be enough.
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

@Hybrid
Yes I can overwrite render function in custom scene node, but global usage custom scene nodes isn't the best method... We will need create custom scene node for each avaiable node in Irrlicht, so in my opinion this is not attractive solution for user. What with eg. CAnimatedMeshSceneNode? We don't have acces for derived this class and change only render() function, similat with other nodes, so I think, that callback method is better :)

@Sudi
This callback isn't usefull for manage effect techniques, because we need loop function for it.

Update:
My first method isn't good, because this is wrong place for callback. We should apply technique callback in each node render function, so instead:

Code: Select all

driver->setMaterial(Materials[i]);
driver->drawMeshBuffer(mb);
in render function each node, we should add:

Code: Select all

RenderCallback->Execute(Materials[i],mb);
and standard callback will the same as oryginal part, so:

Code: Select all

driver->setMaterial(Materials[i]);
driver->drawMeshBuffer(mb);
but if we apply technique for node it should look like this:

Code: Select all

driver->setMaterial(Materials[i]);
for(int i = 0; i < techniqueCount; i++)
{
setTechnique(Technique[i]);
driver->drawMeshBuffer(mb);
}
What You think about it? We target to more shader rendering structure, instead of fixed pipeline (DX10, OGL3) so manage technique will be very useful for us I think.

Of course I can prepare patch for support this callbacks if You wish.
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
sudi
Posts: 1686
Joined: Fri Aug 26, 2005 8:38 pm

Post by sudi »

ah ok i get it. yeah that seams to be a nice change actually
We're programmers. Programmers are, in their hearts, architects, and the first thing they want to do when they get to a site is to bulldoze the place flat and build something grand. We're not excited by renovation:tinkering,improving,planting flower beds.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

OK, I prepare patch for it:
http://nadro.net46.net/Patches/irrlicht ... r_cb.patch
This support currently nodes:
CAnimatedMeshSceneNode
CMeshSceneNode
CCubeSceneNode
CSphereSceneNode
CTerrainSceneNode
COctTreeSceneNode

As You see, withou callback all work as in old function. I tested it with CGFX and all works perfectly, it's very usefull for manage effects with passes, standard materials are good for one pass shaders, but for manage effects materials isn't enought. I will send example for usage it with CgFX today ;)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hi, sorry for my big delay with example, but in last time I didn't have much time for CgFX, because I had many work with my game. Today, I can release small CgFX Multi Material example. You can download it from:
http://www.sendspace.com/file/r0royx
For support multipasses we need custom rendering callback, I use this from my patch and as You see it works very good for it. How looks CgFX support?

Code: Select all

1. Create Custom Rendering callback eg:

class CRC : public ICgRenderCallback // ICgRenderCallback is inherit from IRenderCallback, but has got also OnSetConstants function.
{
public:
    CRC(){};
    ~CRC(){};

    void Update(video::IVideoDriver* Driver, const video::SMaterial &Material, const IMeshBuffer* MeshBuffer)
    {
        Driver->setMaterial(Material);

        pass = cgGetFirstPass(myCgTechnique);

        while (pass)
        {
            // OnRender
            Driver->drawMeshBuffer(MeshBuffer);

            cgResetPassState(pass);
            pass = cgGetNextPass(pass);
        }

        if(Driver->getDriverType() == EDT_DIRECT3D9)
        {
            Device->getVideoDriver()->getExposedVideoData().D3D9.D3DDev9->SetVertexShader(NULL);
            Device->getVideoDriver()->getExposedVideoData().D3D9.D3DDev9->SetPixelShader(NULL);
        }
    }

    void Update_ITL(video::IVideoDriver* Driver, const video::SMaterial &Material, const video::S3DVertex* vertices, u32 vertexCount, const u16* indexList, u32 triangleCount)
    {
    }

    void OnSetConstants( ICgServices* services,const irr::video::SMaterial& Material )
    {
        WVP = cgGetNamedEffectParameter(myCgEffect, "WVP");
        irr::core::matrix4 WorldViewProjection;
        WorldViewProjection = Device->getVideoDriver()->getTransform(irr::video::ETS_PROJECTION);
        WorldViewProjection *= Device->getVideoDriver()->getTransform(irr::video::ETS_VIEW);
        WorldViewProjection *= Device->getVideoDriver()->getTransform(irr::video::ETS_WORLD);
        cgSetMatrixParameterfr(WVP, WorldViewProjection.pointer());

        FirstMap = cgGetNamedEffectParameter(myCgEffect, "FirstMap");
        GPU->getCgServices()->setTexture( FirstMap,Material.TextureLayer[0], 0 );
        cgSetSamplerState(FirstMap);

        SecondMap = cgGetNamedEffectParameter(myCgEffect, "SecondMap");
        GPU->getCgServices()->setTexture( SecondMap,Material.TextureLayer[1], 1 );
        cgSetSamplerState(SecondMap);

        cgSetPassState(pass);
    }
};

2. Create effect via IrrCg interface
3. Apply MaterialType (from step 2) and RenderCallback (from step 1) to node.

Thats all!
What do You think about this idea? What with native IRenderCallback support in Irrlicht?

BTW. I have question for setBasicRenderStates, why in OpenGL we have got always reset for filtering, wraping, biaslod, but in d3d9 only when lastmaterial.option != material.option? I think that we should also apply always reset this states in d3d9. What do You think about it?
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

BTW. I have question for setBasicRenderStates, why in OpenGL we have got always reset for filtering, wraping, biaslod, but in d3d9 only when lastmaterial.option != material.option? I think that we should also apply always reset this states in d3d9. What do You think about it?
Yes there's no caching at the moment. It's even worse in setRenderStates2dMode (Which I made a little patch to fix but have not committed yet). I will be working to improve that. I think the overhead for these things in OpenGL are less than for D3D though.

I don't mind your idea but I'd like to get hybrid's definitive answer on it. He may decide it's too much overhead in the case that no one uses it.
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Probably the only reason that it's not done in D3D is that I don't know if it's necessary for that driver as well. The thing for OpenGL is that those values are stored on a per-texture level. Since we don't test if the current texture was set all the time we need to assume that the values are wrong. And since we did not encounter renderstate problems under D3D so far, it seems to work under D3D as is. If not, we should fix it.
Of course it would be really good to reduce the renderstate changes (in case they don't actually change). As said, the 2d mode changes are even worse and introduced a noticeable slowdown in the last few hundred revisions in trunk. So any progress on this would be welcome.

On the original topic of this thread: I still don't get the whole intention of this callback. There seem to be many things packed into one structure, but not necessarily related. One thing is the callback before each meshbuffer. Another thing is multi-passes. Maybe I missed other things here?
So the callback before meshbuffers needs to be checked for integration into the LightsManager. At least it seems to be the first place to add such a thing. Multi-passes need a proper integration into the material structure, in order to allow them in all drivers and with all render techniques. At that point we might have a multi-dimensional material, which would automatically applied to render tasks. There's no need to drill holes into Irrlicht's infrastructure just to overcome problems only temporarily or in an ad-hoc way.
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

All states we can apply via current avaiable IMaterialRenderer, but where in have in plan put entry for multipass? it can't be "hide" entry for user because eg. in native D3D9 we need another function for support it, than in Cg or custom effects structure. How it will be look in material structure, if we manualy defined loop function for passes in application? Only we can change applying this rendercallback to node to applying this callback to material, but some callback have to exist. How is currently dev team idea for multi material? I put this question, because I can help with them and I can prepare some patches, but I need know what it should be look, but in my opinion simple IRenderCallback is better solution for it :) Multi-Material = MultiPass Material?
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

On second thought I may have misunderstood the exact purpose of this proposal. I didn't realise you wanted to have such a specific implementation for each scene node types which calls the function after every draw call, and I also didn't realise you wanted something that specifically passed meshbuffers. I retract most of my statements on this matter.

I agree with hybrid that it should be handled via the SMaterial interface, it would require much much less (If any) per-node tweaking than this proposal, and is a cleaner, more convenient solution overall.

If you want to get specific, some kind of structure that takes more than one material (As a substitute for SMaterial), and renders them in sequence would probably be ideal. A very simple implmentation would be to store "SMaterial* nextMaterial" in SMaterial that defaults to 0, and the drivers would iterate through the pointers from the first SMaterial passed to it until it reaches a pointer that's 0 (The default). This idea could also be handled mostly in CNullDriver reducing most of the worker needed for the individual drivers.

A quick usage case thing:

Code: Select all

SMaterial myFirstMaterial;
SMaterial mySecondMaterial;

myFirstMaterial.nextMaterial = &mySecondMaterial;

driver->setMaterial(myFirstMaterial);
driver->drawMeshBuffer(a mesh buffer);

Inside CNullDriver we would have:

void CNullDriver::drawMeshBuffer(IMeshBuffer* mb)
{
	SMaterial cachedMaterial = Material;

	while(true)
	{
		// Specific drawing code here.

		if(Material.nextMaterial)
			Material = *Material.nextMaterial;
		else
			break;
	}

	Material = cachedMaterial;
}
This isn't a suggestion on how to implement it specifically as its not exactly user friendly, but thinking along those lines would probably get us moving in the right direction.

Cheers
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Yes, that's kind of the structure I have in mind as well. Moreover, we need another dimension of fallback materials for each implementation (especially the shader ones). And of course the outstanding per-layer material instead of just one complex material combining all layers of a meshbuffer. I did not even start to think about a proper structure, so it's far too early for a pointer into the correct direction. But I guess I can still provide some arguments in an ongoing discussion :)
Nadro
Posts: 1648
Joined: Sun Feb 19, 2006 9:08 am
Location: Warsaw, Poland

Post by Nadro »

Hmmm... it's very good idea and I have to agree with You, this should be better. So NextMaterial instead of RenderCallback and improvments in setBasicRenderStates will be very usefull for manage effect files, but what with minimize render states? so sorting this material and use queue?

Code: Select all

setMaterial
setPass 0
draw all meshbuffers, which usage this pass
endPass 0
setPass 1
draw all meshbuffers, wchich usage this pass
endPass 1
endMaterial
Now I have to wait with release IrrCg 0.8 to official support nextmaterial in Irrlicht heh :)
Library helping with network requests, tasks management, logger etc in desktop and mobile apps: https://github.com/GrupaPracuj/hermes
hybrid
Admin
Posts: 14144
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Post by hybrid »

Oh, that could take a very loong time... Better use some workaround :)
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

Remember my Fur demo? I rendered meshbuffers multiple times per material. Strangely, people couldn't work out how I did it. I'm still waiting for other peoples' fur demos... :wink:
Post Reply