• Advertisement

Archived

This topic is now archived and is closed to further replies.

i couldn't stuff all my particles now in one large VB coz...,

This topic is 5541 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

hello, well it's because 1. i'd like my particles to have multiple textures(ie, animating), 2. i want it to rotate, 3. each type uses different textures 4. each type too have their own orientation towards the camera 5. different x,y,z sizes so does that mean, EACH of my particle has it's own World Transformation and SetTexture now? and now i have to use materials too because i can't go for lock/unlock for each of them, also, i know this is possible but i don't know how, the texture contains a sequence of frames, say 16, so how do i retrieve each of them, method should be very fast though, many thanks hope you could give me some advice if there's any other way, especially changing the particle's color [edited by - mickey on December 5, 2002 8:11:04 AM]

Share this post


Link to post
Share on other sites
Advertisement
hi
I think the best thing to do is to render each particle as a quad (4 vertices), like in the Billboarding SDK sample.
Sort your particles by texture.
You should use one big vertex buffer, that you lock each frame just before you render, fill it with your newly computed vertices, unlock and render it.
you can write something like (pseudo-C++ code):
CParticleList
{
int count;
LPDIRECT3DTEXTURE8 pTex = ...;
YOUR_VERTEX_FORMAT buf[4*count];
void Render(int* pos) {
for (int i=0;i m_pd3dDevice->SetTexture(0, pTex);
m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, *pos, 2);
(*pos) += 4;
}
}
};

CParticleSystem:
{
int numTextures;
CParticleList particles[numTextures];
void Render() {
int pos = VertexBufferPosition;
for (int i=0;i particles->Render(&pos);
}
};

Just load your data into the vertex buffer before you render, and you are done. Loading requires that you multiply each vertex by its particle transformation matrix, which can be slow; and that is why current games do not display lots of different particles: it is very expensive.

Again, look at the Billboarding sample code, it will help you with the orientation towards the camera. (in this sample, all the trees are oriented so that they face the camera)

About animating your particles, I suggest using a big texture, containing your 16 frames, and change the vertex texture
coordinates each frame, so that only 1 frame is drawn

Hope this helps

Share this post


Link to post
Share on other sites
EDIT :: Should've read Tibo's post - before writing this oh well - this may still be somewhat useful.

Well, particles are usually quite small - can't you have a single texture with more than one particle type in it? If you had a 256x256 texture, you could fit (for example) 4 types of particle, each with 8 frames of animation, each frame 32 x 32 pixels big on that one texture, and then you wouldn't need to change texture for each particle. Of course, if you need more types of particle, or larger particles, or longer animations then you'd have to either use bigger textures (which wouldn't necessarily work on all cards), or split the texture up and SetTexture() for each group of particles.

There are two ways of retreiving a specific part of the texture.
1) Alter the vertices in the vertex buffer, using different texture coordinates.
2) Use a texture transformation matrix to get the card to transform the coords itself.

In the first method you'd need to lock the vertex buffer each frame, and change the texture coordinates (you could also change the colour and position here) - but you would change the coords for every particle at once. Then you'd call DrawPrimitive once to draw every particle.

In the second method you have to group your particles, and set up the texture transform matrix for each group (don't set it for every particle unless).

Hope that helps,

John B

[edited by - JohnBSmall on December 5, 2002 11:20:35 AM]

Share this post


Link to post
Share on other sites
hi,

how do i use the texture transformation to index into the appropriate frame on the texture?

i already tried scaling/rotatino and it works great, but do i use a translation matrix to index? coz it doesn't seem to work?

wish i could still use dx' point sprites though even with all the features i want..,

edit:
okay say i have my quad's tu/tv 0.0f to 1.0f only(covers the entire texture),

then my texture has it's size 128x128 consisting of 16 frames of fires, so that's 32x32, ehm, how do i get row 2 col 2?

thanks!

[edited by - mickey on December 5, 2002 12:45:53 AM]

Share this post


Link to post
Share on other sites
Use fractional tu/tv coordinates to map to portions of a texture file.

Use this formula:

tu = (1 / texture_file_width) * texture_left_pixel_offset;
tv = (1 / texture_file_height) * texture_top_pixel_offset;

So, in your example, row 2, column 2 would be at left pixel offset 64, top pixel offset 64, and would have a texture file size of 128x128, right? So:

tu = (1 / 128) * 64;
tv = (1 / 128) * 64;

Those would be the texture coordinates of the upper-left corner of the quad.

--Hoozit.


----------------------
Check out my game demo and resume at
www.fivestory.com/projects/game.

Share this post


Link to post
Share on other sites
hi HoozitWhatzit,

no not that, i''d like to know what kind of matrix i''ll be using if i am to use the texture transformation states, but still thanks for the formulas,

Share this post


Link to post
Share on other sites
Warning: This may be incorrect, as I don't have the SDK here with me.

If I remember correctly, the texture transform matrix is different from the normal projection, view and world matrices, as it only uses the first 3x3 section of the matrix. Therefore, using the normal D3DXTranslate function to get the matrix will not work (it works for scaling because scaling uses the inner section of the matrix anyway, but for translations it wouldn't work). I can't remember if there is a special utility function to make a texture transform matrix for you, but I don't think there is, so that means you'll need to produce the matrix yourself (probably best to make an inline function to set a texture matrix up given, for example, a rect specifying which section of the texture to use).

Hope that helps,

John B

[edited by - JohnBSmall on December 6, 2002 12:03:44 PM]

Share this post


Link to post
Share on other sites
DrawPrimitve can render a part of the triangles right?

And you can use matrices BETWEEN the renders.

.lick

[edited by - Pipo DeClown on December 6, 2002 12:06:06 PM]

Share this post


Link to post
Share on other sites
Exactly, Pipo - no reasons NOT to use one VB so far.


Regards

Thomas Tomiczek
THONA Consulting Ltd.
(Microsoft MVP C#/.NET)

Share this post


Link to post
Share on other sites
JohnBSMall:

i really hope you could help me here, i still have no idea how to index into the appropriate texture using matrices., or is even possible?

just remember, i have the 4 quad's tu/tv covering the entire texture, so if i want row 2, col 2, how will i index to it having 16 frames in one 128 x 128 texture,

Pipo de Clown:
well i guess you could use this method,
> DrawPrimitve can render a part of the triangles right
but if you're not going to do do what i wanted to happen like individual rotations,textures, orientation towards the camera etc., then i don't really see any sense putting all the particles in one large VB and renering them part by part since having one vb that contains only 4 verts is the same, we still have to call all these transformations stuffs etc.,

edit:
hi johnbsmall, with what you said,
i started toying with the matrix i feed for the texture transformation using the first 3 cols/rows only, and this thing scrolls the texture horizontally,

D3DXMatrixIdentity(&matTexture);
matTexture._31 = timeGetTime() / 1000.0f;
or use ._32 for vertical scroll

so yes we're getting near(matTexture._31 = 2.0f will use 3rd frame first row(should be combined with a scaling matrix), but i don't have any clear idea what's going on..,

did you come across this in the sdk?
>it only uses the first 3x3 section of the matrix
coz i haven't read anything like that, hope you could clear things for me, thanks

[edited by - mickey on December 7, 2002 2:34:36 AM]

Share this post


Link to post
Share on other sites
Well, I can''t remember where I first read that texture matrices don''t use the entire 4x4 grid. It was probably on these forums actually.

Anyway, you seem to have practically solved your problem, if I were you, I''d set it up so that the texture coords in the vertex buffer point to the first frame of the texture, and then you don''t have to worry about scaling the coordinates at all - just translate them (by setting matrix._31 and matrix._32 as you have been doing) to the correct section of the texture.

Anyway, as for what''s been going on, my knowledge of matrix algebra isn''t too brilliant, but what''s happenning (I think) is roughly:
1 0 0   1   1
0 1 0 x 2 = 2
0 0 1 1 1
Identity matrix
1 0 1   1   2
0 1 0 x 2 = 2
0 0 1 1 1
Translation matrix
1 0 0   1   1
0 2 0 x 2 = 4
0 0 1 1 1
Scaling matrix

So the coordinates get multiplied (scaled) by the numbers going down in the diagonal (the ones that are 1 in the identity matrix), and have the numbers on the right hand end added on.
It gets much more complicated when you start making rotation matrices and things.
(Don''t ask me why the vector for the texture coords contains 3 numbers, I''m pretty sure the 3rd can be important, but I can''t really remember why, I think it''s used for perspective correction)

All that could be wrong though - so it''d be best to check a book or website if you want to really understand it. IIRC there''s an article about matrices over on gamasutra - it''ll be about 4x4 matrices, but the same principals apply.

Hope that helps,

John B

Share this post


Link to post
Share on other sites
hi JohnBSmall, couldn't figure it out though without yuor help,

anyway, am back to my former question, so right now, this is how my particle system works now,


// on init
CreateOneQuadVBForParticle();

// before render
SetTextureStageStates()
SetRenderStates(lighting, ambient full, alphablending modes)
GetViewMatrix()

// on render
for(each particle type)
{
SetTexture()
for(each particle)
{
SetUpMaterial()
SetUpMatrices for WorldTrans ( scale,rot,and trans)
SetUpMatrices for Texture ( scale, trans )
MultiplyAllMarices() ( texture and world)
SetMaterial()
SetTransform( D3DTSWORLD )
SetTransform( D3DTS_TEXTURE0 )
DrawPrimitive( quadVB )
}
}


there are around 8 matrix multiplication there within the loop..,

pls, i can't figure out any other way to optimize it, if you could just tell me how to "individually" rotate and set the frame on the texture of each particle, then maybe there's a way to optimize this then,

better yet, if you have any ideas how NeverwinterNights made their particle system, then that's what i'm going to do (you could see it by download their model viewer at their website)

or if there's still sense that i could have all my particles in one large VB...

many thanks for your time,

edit:
btw i already tested this on a voodoo3 p3-800,
it's 45 fps with 1512 particles, 15 fps with 5512 particles,
am not happy with this since there's nothing on the screen but the particles,

[edited by - mickey on December 7, 2002 12:34:56 AM]

Share this post


Link to post
Share on other sites
If memory isn''t a problem for you, perhaps it would be faster if you save the particles'' location in the matrix itself, and not as an (x, y, z) combination. This would ultimatly save you time when the particles don''t move (which wouldn''t happen I bet), but if they have a constant speed, you could use matrices directly, instead of converting from (x, y, z) to a matrix once per particle per frame. That would probably save you some time.

You could also use that for the rotation matrix (you could save it as one matrix, even, if they don''t need to rotate) and also for the texture matrix. Doing this correctly might remove some of the matrix multiplies you use, and would improve performance.

Also, combining this method with the use of a single VB and lock/unlock would be faster, especially if you plan on using 1000 particles per system and the same texture on them all.

Hope this helps.

Share this post


Link to post
Share on other sites
hello,

just wondering if anybody else can further optimize my post above? (before sirob)

thanks,

[edited by - mickey on December 12, 2002 5:13:56 AM]

Share this post


Link to post
Share on other sites
Your best bet is to use a vertex shader with a custom vertex structure or to use point sprites. For instance, I use the following three setups in my latest book:

* Use a vertex buffer w/4 vertices and for each frame, loop through each particle, stuff in coordinates, set a new world transformation, and render to polygons. I get about 500 frames per second on this demo.

* Use point sprites. I get about 750 frames per second.

* Use a vertex shader that uses a large vertex buffer filled with 4 vertices per particle. The vertex shader transforms the vertices for me, so there''s no need to preprocess or set individual world transformations - just set the world transformation once and render all the particles. I get about 750 frames per second.

The point sprites are nice to use, but have some draw-backs. First, support is limited; not all cards support point sprites. Also, point sprites have a small maximum size. On my card (A Radeon 8500), my point sprites can only be something like 20 units in size.

The vertex shader uses 4 vertices per particle, but rendering speed is matching that of point sprites. Very fast and very flexible.



Jim Adams
home.att.net/~rpgbook
Author, Programming Role-Playing Games with DirectX
and Focus On: Advanced Animation with DirectX

Share this post


Link to post
Share on other sites

  • Advertisement