Jump to content
  • Advertisement
Sign in to follow this  
Aqua Costa

[DirectX 10] Updating instances buffer

This topic is 2703 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I want to update the instances buffer every frame so that only the instances inside the view frustum are drawn.


This is the struct of each instance:

struct InstanceData
{
D3DXVECTOR2 mTransform;
float mSpacing;
};


Then I have:
-two vectors of size = numInstances;
-a var containing the number of instances inside the frustum;
-and a ID3D10Buffer capable of storing all instances data in case all instances are inside the frustum (so ID3D10Buffer.ByteWidth = sizeof(InstanceData) * mNumInstances;) and I create the buffer with D3D10_CPU_ACCESS_WRITE flag.


std::vector<InstanceData> instInFrustumData;
InstInFrustumBuffer->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

[...]

InstInFrustumBuffer->Unmap();


Then I draw the instances like this:

VB[1] = InstInFrustumBuffer;

[...]

mpD3dDevice->DrawIndexedInstanced(mNumFaces*3, mNumInstancesInFrustum, 0, 0, 0);


However nothing is drawn and in PIX the instance data is full of default values so I guess I'm doing something wrong...

Share this post


Link to post
Share on other sites
Advertisement
Did you also specify the D3D10_USAGE_DYNAMIC flag when creating the instance buffer?

If you already have that flag can you show the code between the Map and Unmap calls.
[url=""][/url]

Share this post


Link to post
Share on other sites
yes I use the D3D10_USAGE_DYNAMIC flag.

Function called each frame

void SomeClass::updateInstances()
{
mNumInstancesInFrustum = 0;

mpInstInFrustumB->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

for(int x = 0; x < mNumInstances; x++)
{
if(mpCamera->point2DInFrustum(instData[x].mTransform +
D3DXVECTOR2(instData[x].mSpacing/2 + mpCamera->getPosition().x, instData[x].mSpacing/2 + mpCamera->getPosition().z), instData[x].mSpacing/2)
!= OUTSIDE)
{
instInFrustumData[mNumInstancesInFrustum] = instData[x];
mNumInstancesInFrustum++;
}
}

mpInstInFrustumB->Unmap();
}


I was thinking: In my project the mpInstInFrustumB ByteWidth = sizeof(InstanceData) * mNumInstances; where mNumInstances is 100, but usually only about 15 instances are inside the frustum so most of the buffer isnt used thats why in my draw call I set number of instances to the number of instances inside the frustum
(example: mpInstInFrustumB ByteWidth = sizeof(InstanceData) * 100, and numInstances set in draw call is 8)

mpD3dDevice->DrawIndexedInstanced(mNumFaces*3, mNumInstancesInFrustum /*= 8*/, 0, 0, 0);


Can this cause an error?

Share this post


Link to post
Share on other sites

Can this cause an error?


Nope, that is how I did it and it worked.


Your code looks fine.

Did you set the bind flags to D3D10_BIND_VERTEX_BUFFER?

You could try passing the D3D10_SUBRESOURCE_DATA when creating the buffer and fill it with some dummy variables and see if that works just to make sure there aren't any other "logical" errors involved.

Share this post


Link to post
Share on other sites
is this cast (void**) &instInFrustumData correct? Because Map() exceptsa void** and instInFrustumData is a std::vector...

Share this post


Link to post
Share on other sites
laugh.gif

Next time post your entire code and not just a quick hack&slash code snippet from your top secret engine.

You can't pass a std::vector directly, you must do this (presuming you have at least one object in the frustum so that yourStdVector[0] won't crash you program):



std::vector<bla> v;


for(every object in frustum)
{
// fill the data in the vector
}

bla* bufferPointer=NULL;
const bla& first=v[0];

directXBuffer->Map(....., &bufferPointer);
memcpy(bufferPointer,&first,sizeof(bla)*v.size());
directXBuffer->Unmap();




The pointer that you get back from the Map function is the directX buffer's memory mapped to the CPU address space so that you can write to it using the cpu & main system RAM. So that should be some NULL pointer that you pass in since once you will call Map this pointer will be set to point to the memory you can write to.

std::vector stores that data as a continuous block of memory, but you must use the v[0] thing to get the first element and not &yourStdVector if you want to make a memcpy.

The code above uses another vector to store the data and perform one big memcpy at once. You could also try directly writing into bufferPointer (bufferPointer=yourData).

Share this post


Link to post
Share on other sites
It worked ::thumbs up::


laugh.gif

Next time post your entire code and not just a quick hack&slash code snippet from your top secret engine.


Well I try to post as little code as possible because its easier to read, and I guess people will get scared if they see a post with the code of a complete class (about 500 lines of code) :unsure:

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!