• Announcements

• Wondering what's new and changed at GameDev.net?06/20/17

Check out the latest Staff Blog update that talks about what's changed, what's new, and what's up with these "Pixels".
Followers 0

DX11 DX11 Instancing - Only render certain instances

2 posts in this topic

Hi guys!

So, imagine you have a scene with 1000 trees and your rendering it with instancing, quite a lot, and you wan't to implement a lod system. Now your lod system is actually done, but now how do you change the buffers for that tree (the one too far away).

Illustration (real):

Now as you see I have quite a lot of trees there, but now I only wan't some of those trees from my instanced buffer to be rendered. As I understand you have to update the buffer, but wouldn't that be quite heavy, or do I have to split up the instanced buffer into chunks, and update those? Right below I'm gonna show you how I handle my rendering.

Rendering:

UberBuffer._instance = true;
InstancedMesh[i]->SendInstancedData(ObjectBuffer, Camera, Bufferphase, devcon); // doesn't really matter for now, but if you wan't it, say it :)

bool changed = false;

for (int lod = -1; lod < InstancedMesh[i]->Lods.GetCount(); lod++) // we start from -1 as some meshes don't have lods, so we actually trick it!
{
if (changed)
{
InstancedMesh[i]->SendBuffers(devcon, dev, Camera, ObjectBuffer, Bufferphase);
changed = false;
}

if (lod > -1) // is this a lod?
{
for (int instance = 0; instance < InstancedMesh[i]->instanceCount; instance++)
{
if (sqrtf(D3DXVec3Dot(&*Camera->GetPostion(), &InstancedMesh[i]->instances[instance].pos)) >= InstancedMesh[i]->Lods.GetComputedADistance(lod)) // distance...
{
InstancedMesh[i]->Lods.GetComputedLod(lod)->SendVIBuffers(devcon, dev, Bufferphase); // new vertex buffer
changed = true;

// DO SOME STUFF HERE
}
}
}

UberShader.Render(devcon, Bufferphase, true, InstancedMesh[i]->instanceCount); // Render Instanced, one line of code: devcon->DrawInstanced(Bufferphase.IndexCount, instanceCount, 0, 0);

for (int inSM = 0; inSM < (InstancedMesh[i]->SubMeshes.size()); inSM++) // Sub meshes, doesn't really matter so much for now, I'll take care of those.
{
InstancedMesh[i]->SendSubBuffers(devcon, dev, Camera, ObjectBuffer, Bufferphase, inSM);
}
} 

Now for each Lod i check all the instances for the distance, and if the distance is larger, then apply the different vertex buffer. But somehow I only need to apply this vertex buffer to the instances affected by it!

Now how is this possible?

0

Share on other sites

I would try to just use two different vertex buffers, and you can stick with a single instance buffer.  The trick is to reshuffle your instance data to have all of the high LOD instances in a continuous block, while the lower LOD instances should be in a separate block (you could just as easily implement this with two instance buffers I guess...).  This takes two draw calls, but that isn't a big deal.

This would require modifying the data in the buffers, but it would only be necessary once in a while when the view is significantly moved.  If you store your instances in an intelligent order (like in a quadtree fashion) then moving the data around should be minimally intrusive and will let you quickly get through the update.

0

Share on other sites

Alright got it working, thanks for pointing the way!

0