Hardware instancing patch... please can we get it in 1.8.0??

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by hybrid »

Well, I made my suggestions and didn't see a reply so far. So this one seems to be likely dead. If not, someone will have to provide an updated patch.
The suggestions for 1.8 won't go into 1.8. The todo list was already fixed before the threads were created. But it will be taken into consideration for the next releases fo course.
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Re: Hardware instancing patch... please can we get it in 1.8

Post by ent1ty »

I suppose that's what comes out of the main developer being an ignorant who's even proud of it
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by CuteAlien »

wtf ent1ty? Is this because you didn't get your forum-style so far?
Adding patches is hard enough already when they do basically work as they should (although often enough without tests which usually means they just compile). Hybrid already mentioned a list of problems with this one and so far devsh didn't seem to try to improve it.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Re: Hardware instancing patch... please can we get it in 1.8

Post by ent1ty »

CuteAlien wrote:wtf ent1ty? Is this because you didn't get your forum-style so far?
No... i actually don't give a damn about it anymore.

That's what hybrid said himself
hybrid wrote:Well, I can live quite good with knowing that 7 people are working with an uncomfortable theme due to my ignorance.
Kinda makes you wonder, what else can he live "quite good" with
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
CuteAlien
Admin
Posts: 9628
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by CuteAlien »

So it _is_ about that forum style ^^. Strange how angry people can get just for getting an updated forum *sigh*
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
ent1ty
Competition winner
Posts: 1106
Joined: Sun Nov 08, 2009 11:09 am

Re: Hardware instancing patch... please can we get it in 1.8

Post by ent1ty »

Ok, again: it is not about the forum style, it is about something he said in the thread about forum styles but was not directly connected to forum styles
irrRenderer 1.0
Height2Normal v. 2.1 - convert height maps to normal maps

Step back! I have a void pointer, and I'm not afraid to use it!
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by hybrid »

Might be either your or my lack of english mother tongue. But IMHO, my statement above was directly connected to forum styles. Anyway, this thread is not about forum styles, so let's keep this on topic.
For this patch, the token has been passed back to the original author (or someone else who want to take it). I will also come back to this one, but only in the order of todos and dependng on my time. I definitely find this technqiue interesting, even though it's not as useful as many think. Though the first results already showed it here as well. Moreover, I'd like to have a better API way to use this method. But I won't spend too much time on the basic preparation right now. There's much more urgent stuff first.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by Granyte »

Has there been any progress on this?
is the main thing stoping the integration the sample or the lack of dx9 suport?

Cause now that i'm done with my vertex texture patch I could get working on this for dx9 (the dx10 driver i'm working on already has the base for it irrlicht only need an unified arch to get it working)
Mel
Competition winner
Posts: 2292
Joined: Wed May 07, 2008 11:40 am
Location: Granada, Spain

Re: Hardware instancing patch... please can we get it in 1.8

Post by Mel »

I think there should be a common interface for all these features, then, anyone could code their own systems, and share them if they wanted, because if not, the engine would end having a version almost for each patch that was done. Put all the features in common, think of the best way to have them into the engine, and then, code them in your preferred API. Or at least, have a draft for what the engine should aim for.
"There is nothing truly useless, it always serves as a bad example". Arthur A. Schmitt
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by Granyte »

I totaly agree it's quite easy to add new feature the problem is that irrlich won't be able to handle them unless you do heavy modification to the API
hybrid
Admin
Posts: 14143
Joined: Wed Apr 19, 2006 9:20 pm
Location: Oldenburg(Oldb), Germany
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by hybrid »

Well, reviewing the posts on the first page, it's both the example and the lack of DX support (and lack of software mode), which prevents addition to the engine. We added geometry shaders even without DX support, as DX9 does not support them. But here, we need support for DX at least, and in theory also for software drivers, as it would be a very basic render call. So it could be often tried by people using it with DX or software drivers and wondering why this does not render there.
The example is necessary to make sure that everything works as expected - including the way to prepare the data and do the render call in the end. Right now, the example was quite weird, not showing the actual way to use this function, but lots of other stuff which is not really related.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by Granyte »

Alright i hacked hardware instancing arround in DX9 and honestly it was painfull

ill just finish writing a proper exemple and ill submit a patch.
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by Granyte »

alright here is the new instancing demo i wrote based on the code from the first page
This demo should work for openGL with the patch provided on the first page and dx9 with shader instancing

Shader instancing should work for dx9(and opengl if any one write the code) even without any modification to irrlicht itself

How ever i don't have a shader code for shader instancing in openGL but it should not be hard to write for anyone that has any GLSL knowledge

Code: Select all

 
 
 
 
 
 
 
 
 
 
 
 
 
 
#ifdef _MSC_VER
// We'll also define this to stop MSVC complaining about sprintf().
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "Irrlicht.lib")
#endif
 
 
 
 
 
 
 
 
 
 
#include <irrlicht.h>
#include <driverChoice.h>
 
using namespace irr;
 
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
 
 
 
 
 
struct InstancingShaderCB : public video::IShaderConstantSetCallBack
{
    core::matrix4* instanceWorldArray;
    irr::video::E_DRIVER_TYPE Currentdriver;
    InstancingShaderCB(irr::video::E_DRIVER_TYPE currentdriver)
    {
        Currentdriver=currentdriver;
        if (Currentdriver == EDT_OPENGL)
            instanceWorldArray = new core::matrix4[248];
        else if (Currentdriver == EDT_DIRECT3D9)
            instanceWorldArray = new core::matrix4[62];
    }
   void OnSetConstants(video::IMaterialRendererServices* services,
      s32 userData)
   {
       core::matrix4 viewProjection;
       viewProjection = services->getVideoDriver()->getTransform(video::ETS_PROJECTION);
         viewProjection *= services->getVideoDriver()->getTransform(video::ETS_VIEW);
         if (Currentdriver == EDT_OPENGL)
            services->setVertexShaderConstant("instanceWorldArray", (f32*)instanceWorldArray, 16*248);
         else if (Currentdriver == EDT_DIRECT3D9)
             services->setVertexShaderConstant("instanceWorldArray", (f32*)instanceWorldArray, 16*62);
      services->setVertexShaderConstant("viewProjection", viewProjection.pointer(), 16);
   }
};
 
 
 
class InstanceManager : public scene::ISceneNode
{
 
    /*
    First, we declare some member variables:
    The Node array,  the mesh buffer, the mesh and the material instanced scenenode 
    we also need to keep track of the shader callback.
    */
    video::SMaterial Material;
    IMeshBuffer* bBuffer;
    IMesh* aMesh;
    InstancingShaderCB* callback;
    /*Variable to handle shader instancing*/
    IMesh* bMesh;
    bool fakeinstancing;
     SMeshBufferLightMap dupBuffer;
    /*
        We treat the instance manager as a scene node so we don't really have to care about it in the future
    */
 
    public:
 
    InstanceManager(scene::ISceneNode* parent, scene::ISceneManager* mgr, s32 id, bool Fakeinstancing)
        : scene::ISceneNode(parent, mgr, id)
    {
        fakeinstancing = Fakeinstancing;
        
 
 
         //shader
    s32 mtrlShader;
   callback = new InstancingShaderCB(mgr->getVideoDriver()->getDriverType());
   
   if (mgr->getVideoDriver()->getDriverType() == EDT_OPENGL)
       mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/instancing.vert", "", video::EVST_VS_2_0,
                            "../../media/instancing.frag", "", video::EPST_PS_2_0,callback, video::EMT_SOLID);
   else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
        mtrlShader = SceneManager->getVideoDriver()->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles("../../media/Instancing.hlsl", "vsmain", video::EVST_VS_3_0,
                            "../../media/Instancing.hlsl", "psmain", video::EPST_PS_3_0,callback, video::EMT_SOLID);
   
   callback->drop();
   Material.Lighting = false;
   Material.setTexture(0, SceneManager->getVideoDriver()->getTexture("../../media/wall.jpg"));
   Material.MaterialType = (video::E_MATERIAL_TYPE)mtrlShader;
 
    //!mesh generation
   aMesh = SceneManager->getGeometryCreator()->createSphereMesh(1,8,8);
   bBuffer = aMesh->getMeshBuffer(0);
   bBuffer->setHardwareMappingHint(scene::EHM_STATIC);
 
 
 
 
   IMesh* bMesh = mgr->getMeshManipulator()->createMeshWith2TCoords(aMesh);
   IMeshBuffer* bBuffer = bMesh->getMeshBuffer(0);
 
   //!create dupBuffer with bBuffer repeated NUM_BATCH_INSTANCES times
  
   if (mgr->getVideoDriver()->getDriverType() == EDT_OPENGL)
   for (int k=0;k<248;k++)
   {
      S3DVertex2TCoords* verts = (S3DVertex2TCoords*)bBuffer->getVertices();
      for (u32 i=0; i<bBuffer->getVertexCount(); i++)
      {
         verts[i].TCoords2.X = k;//assign the index of instance that each vertex belongs to
      }
      dupBuffer.append(verts,bBuffer->getVertexCount(),bBuffer->getIndices(),bBuffer->getIndexCount());
      dupBuffer.setHardwareMappingHint(scene::EHM_STATIC);
   }
   else if (mgr->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
   {
       for (int k=0;k<62;k++)
   {
      S3DVertex2TCoords* verts = (S3DVertex2TCoords*)bBuffer->getVertices();
      for (u32 i=0; i<bBuffer->getVertexCount(); i++)
      {
         verts[i].TCoords2.X = k;//assign the index of instance that each vertex belongs to
      }
      dupBuffer.append(verts,bBuffer->getVertexCount(),bBuffer->getIndices(),bBuffer->getIndexCount());
      dupBuffer.setHardwareMappingHint(scene::EHM_STATIC);
   }
   }
    }
    /*The node array is put here to be public only for the purpose of the demo in the future a function coud take care of this without having it public*/
    
    core::array<ISceneNode*> totalNodeArray;
 
 
    /*Create an empty scenenode and return the pointer to the user
    this empty scene node is used for irrlicht and the user to manage the instance
    Each instance can be manipulated individualy through thier own empty scenenode*/
    ISceneNode* AddInstance(vector3df pos, f32 scale,vector3df Rotation )
    {
        ISceneNode* empty = SceneManager->addEmptySceneNode();
      empty->setPosition(pos);
      empty->setScale(vector3df(scale));
      empty->setRotation(Rotation);
      totalNodeArray.push_back(empty);
      return empty;
    }
    /*
    we always register this for rendering since visibility is handeled in the sub node
    */
    virtual void OnRegisterSceneNode()
    {
        
        SceneManager->registerNodeForRendering(this);
 
        ISceneNode::OnRegisterSceneNode();
    }
 
    /*
    In the render() method most of the interesting stuff happens: The manager goes through the node array and upload thier matrices to the shader callback
    In OpenGL we render per batches of 248 and in dx per batches of 62 this is due to the amount of variable register availible being diferent in both drivers
    in the future if a vertex texture patch is accepted both could be made to render every node in a single draw call and fetch thier matrices from a texture
    */
    virtual void render()
    {
        SceneManager->getVideoDriver()->setMaterial(Material);
            int nRemainingBoxes = totalNodeArray.size();
            int node_idx = 0;
            while( nRemainingBoxes > 0)
            {
                int nRenderBoxes;
                if (SceneManager->getVideoDriver()->getDriverType() == EDT_OPENGL)
                    nRenderBoxes = core::min_( nRemainingBoxes, 248 );
                else if (SceneManager->getVideoDriver()->getDriverType() == EDT_DIRECT3D9)
                    nRenderBoxes = core::min_( nRemainingBoxes, 62 );
 
               nRemainingBoxes -= nRenderBoxes;
               for (int i=0;i<nRenderBoxes;  i++)
                    callback->instanceWorldArray[i] = totalNodeArray[node_idx++]->getAbsoluteTransformation();
               if (fakeinstancing == false)
                SceneManager->getVideoDriver()->drawMeshBuffer(bBuffer,nRenderBoxes);
               else
                SceneManager->getVideoDriver()->drawMeshBuffer(&dupBuffer);
            }
    }
 
    /*
    Here we return the bounding box for the whole instance batch to make sure the node does not get culled wen there is still even a single instance in the view fulstrum
    */
    virtual const core::aabbox3d<f32>& getBoundingBox() const
    {
        core::aabbox3d<f32> mbb;
 
 
        for (u32 i = 0; i<this->totalNodeArray.size(); i++)
        {
            mbb.addInternalPoint(totalNodeArray[i]->getPosition());
        }
        return mbb;
    }
 
    virtual u32 getMaterialCount() const
    {
        return 1;
    }
 
    virtual video::SMaterial& getMaterial(u32 i)
    {
        return Material;
    }   
};
 
 
 
bool initIrrlicht(s32 w, s32 h, bool opengl = true, s32 bpp=32, bool fullscreen=false, bool stentil = false);
 
 
 
 
int main()
{
 
    video::E_DRIVER_TYPE driverType=driverChoiceConsole();
    if (driverType==video::EDT_COUNT)
        return 1;
    bool usefakeinst = false;
    bool animate = false;
    char i;
        
            printf("Please press 'y' if you want to use Shader Instancing.\n");
            std::cin >> i;
            if (i == 'y')
            {
                usefakeinst = true;
            }
            printf("Please press 'y' if you want each instance to be animated.\n");
            std::cin >> i;
            if (i == 'y')
            {
                animate = true;
            }
    // create device and exit if creation failed
 
    IrrlichtDevice * device = createDevice(driverType, core::dimension2d<u32>(640, 480));
 
    if (device == 0)
        return 1; // could not create selected driver.
 
    /* The creation was successful, now we set the event receiver and
        store pointers to the driver and to the gui environment. */
    
        
    device->setWindowCaption(L"Irrlicht Engine - Hardware Instancing Demo");
 
   video::IVideoDriver* driver = device->getVideoDriver();
    scene::ISceneManager* smgr = device->getSceneManager();
    IGUIEnvironment* env = device->getGUIEnvironment();
   InstanceManager* InstancingTest = new InstanceManager(smgr->getRootSceneNode(),smgr,-1,usefakeinst);
  
 
   //!save transformation in one EmptySceneNode which doesn't render itself
   f32 scale = 18.5f;
   for (u32 i=0;i<50;i++)
      for (u32 j=1;j<21;j++)
         for (u32 k=0;k<21;k++)
   {
     
       scene::ISceneNode* empty = InstancingTest->AddInstance(vector3df(i*scale,j*scale,k*scale),scale*0.5,vector3df(rand()%360,rand()%360,rand()%360));
       if (animate== true)
       {
      scene::ISceneNodeAnimator* anim =
            smgr->createFlyCircleAnimator(vector3df(i*scale,j*scale,k*scale),rand()/20,rand()*0.0000001);
        if (anim)
        {
            
            
            empty->addAnimator(anim);
            anim->drop();
        }
       }
       
   }
 
   scene::ICameraSceneNode* cam = smgr->addCameraSceneNodeFPS();
 
  
   device->getCursorControl()->setVisible(false);
 
   s32 lastFPS = -1;
   while(device->run())
   {
      if (device->isWindowActive())
      {
         driver->beginScene(true, true, SColor(255,122,122,122));
 
         smgr->drawAll();
 
         
         {
            
         }
         env->drawAll();
 
         driver->endScene();
 
         int fps = driver->getFPS();
 
         if (lastFPS != fps)
         {
            core::stringw str = L"fps: ";
            str += fps;
            str += ", poly: ";
            str += driver->getPrimitiveCountDrawn();
            str += ", Node count:";
            str += InstancingTest->totalNodeArray.size();
            device->setWindowCaption(str.c_str());
            lastFPS = fps;
         }
      }
   }
 
   device->drop();
 
   return 0;
}
 
 
 
 

if there is anything missing from this demo or that should be reworked tell me ill update it

here is the dx9 shader code

Code: Select all

 
 
 
 
 
 
 
cbuffer cbParams : register(c0)
{
 
 
float4x4 instanceWorldArray[62];
float4x4 viewProjection;
 
};
struct VS_INPUT
{
    float4 vPosition  : POSITION;
    float3 vNormal   : NORMAL;
    float2 texCoord  : TEXCOORD0;
    float4 color      : COLOR;
    float2 Index  : TEXCOORD1;
};
 
 
struct VS_OUTPUT
{
    float4 Position   :POSITION;   // vertex position 
    float2 TexCoord   : TEXCOORD;  // tex coords
};
 
VS_OUTPUT vsmain(VS_INPUT Inputs)
{
 
    VS_OUTPUT tout;
   float4 pos = mul(Inputs.vPosition,instanceWorldArray[Inputs.Index.x]);
   tout.Position = mul(pos,viewProjection);
   tout.TexCoord = Inputs.texCoord;
    return tout;
}
 
 
 
sampler2D tex0;
 
float4 psmain( VS_OUTPUT input ):COLOR0
{
   return tex2D(tex0,input.TexCoord);
}
 
devsh
Competition winner
Posts: 2057
Joined: Tue Dec 09, 2008 6:00 pm
Location: UK
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by devsh »

*clap* *clap*

at Granyte making the right choice of action

dont moan about something, fix it


I would have retouched this, but I'm currently too busy trying to get compute shaders into my branch irrlicht
Granyte
Posts: 850
Joined: Tue Jan 25, 2011 11:07 pm
Contact:

Re: Hardware instancing patch... please can we get it in 1.8

Post by Granyte »

i re wrote this because i really wan to have my real instancing patch for dx9 integrated once it's finished

and for your compute shader try to make a post on how you buit them so i can use the same interphase for the dx11 driver
Post Reply