Page 2 of 5

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

Posted: Tue Jul 26, 2011 9:11 pm
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.

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

Posted: Thu Jul 28, 2011 8:22 am
by ent1ty
I suppose that's what comes out of the main developer being an ignorant who's even proud of it

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

Posted: Thu Jul 28, 2011 9:03 am
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.

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

Posted: Thu Jul 28, 2011 9:17 am
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

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

Posted: Thu Jul 28, 2011 9:26 am
by CuteAlien
So it _is_ about that forum style ^^. Strange how angry people can get just for getting an updated forum *sigh*

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

Posted: Thu Jul 28, 2011 9:33 am
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

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

Posted: Thu Jul 28, 2011 8:40 pm
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.

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

Posted: Sun Oct 07, 2012 7:03 am
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)

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

Posted: Sun Oct 07, 2012 3:21 pm
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.

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

Posted: Sun Oct 07, 2012 7:12 pm
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

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

Posted: Sun Oct 07, 2012 10:04 pm
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.

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

Posted: Fri Oct 19, 2012 9:25 pm
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.

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

Posted: Sat Oct 20, 2012 8:24 am
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);
}
 

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

Posted: Sat Oct 20, 2012 11:41 am
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

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

Posted: Sat Oct 20, 2012 7:28 pm
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