Skip to main content
gamedev.net
🔒 Locked

Point Sprites

Started by sakky Jan 13, 2005 at 12:13 AM 3 replies 650+ views
Original Post
sakky
sakky
I have a quick question about point sprites; how efficient are they? I render 100 – 200 of them for an old 2D scrolling start field effect. I am also going to use them for fire, smoke, explosions, bullets and pretty much every thing that uses special effects. I have separate textures for each point sprite that I will use. All the sprites however are alpha-blended. I’ve noticed a little lag in the star field when I made a start field with 10,000 stars. I still got a little lag with any thing over 200. Maybe it’s how I’m rendering them, but they seam to work alright in small quantities. But I need tons of them to do what I want to do. So, what is the best way to use these little guys? I’m just using a vertex buffer. I lock it and update the vertex information each frame according to the particles each frame.
Take back the internet with the most awsome browser around, FireFox
MikeyO
MikeyO
If the stars are static, you dont need to lock/unlock the vertex buffer at all, and that is likely what's slowing it down.. Just translate the stars. I use point sprites to render stars (in 3d, mind you), and I can render about a million stars (not all on screen at once, majority are to the sides and behind) at ~60fps.
sakky
sakky
Okay, what do you mean by static? Here, look at my implementation->

// The objects//typedef struct _VERTEX {	D3DXVECTOR4 XYZRHW;	D3DCOLOR	RGB;} VERTEX,*LPVERTEX;typedef struct _PARTICLE {	DWORD X, Y, Z;	DWORD RGB;} PARTICLE, *LPPARTICLE;// Initialization//	LPVOID					 lpMemPtr = NULL;	HRESULT					 hRet;	if ( FAILED( hRet = g_lpD3DDevice->CreateVertexBuffer( MAX_PARTICLES * sizeof( VERTEX ),														   D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,														   D3DFVF_VERTEX,														   D3DPOOL_DEFAULT,														   &g_lpD3DEmiter,														   NULL ) ) )	{		return ( FALSE );	}	for ( int I = 0; I < MAX_PARTICLES; I++ )	{		g_vParticleHeap[ I ].X = rand( ) % 640;		g_vParticleHeap[ I ].Y = rand( ) % 480;		g_vParticleHeap[ I ].Z = ( ( rand( ) % 2 ) + 1 );	}    g_lpD3DDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );    g_lpD3DDevice->SetRenderState( D3DRS_POINTSCALEENABLE,  TRUE );    g_lpD3DDevice->SetRenderState( D3DRS_POINTSIZE,			FtoDW( 32.0F ) );	g_lpD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE,	TRUE );	g_lpD3DDevice->SetRenderState( D3DRS_SRCBLEND,			D3DBLEND_ONE );	g_lpD3DDevice->SetRenderState( D3DRS_DESTBLEND,			D3DBLEND_ONE );	if ( FAILED( hRet = D3DXCreateTextureFromFile( g_lpD3DDevice, "Sprite.bmp", &g_lpD3DSprite ) ) )	{		return ( hRet );	}	g_lpD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );	g_lpD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );// Rendering loop//LPVERTEX		 lpVertices = NULL;if ( SUCCEEDED( g_lpD3DEmiter->Lock( 0, 										MAX_PARTICLES * sizeof( VERTEX ),										( void** )&lpVertices,										D3DLOCK_DISCARD ) ) ){	for ( int I = 0; I < MAX_PARTICLES; I++ )	{		switch ( g_vParticleHeap[ I ].Z )		{		case 0: g_vParticleHeap[ I ].X -= 3; break;		case 1: g_vParticleHeap[ I ].X -= 2; break;		case 2: g_vParticleHeap[ I ].X -= 1; break;		}		if ( g_vParticleHeap[ I ].X <= 0 )		{			g_vParticleHeap[ I ].X = 640;			g_vParticleHeap[ I ].Y = rand( ) % 480;			g_vParticleHeap[ I ].Z = ( ( rand( ) % 2 ) + 1 );			break;		}		switch ( g_vParticleHeap[ I ].Z )		{		case 0: g_vParticleHeap[ I ].RGB = D3DCOLOR_XRGB( 220, 220, 220 ); break;		case 1: g_vParticleHeap[ I ].RGB = D3DCOLOR_XRGB( 180, 180, 180 ); break;		case 2: g_vParticleHeap[ I ].RGB = D3DCOLOR_XRGB( 120, 120, 120 ); break;		}		lpVertices[ I ].XYZRHW = D3DXVECTOR4( ( FLOAT )g_vParticleHeap[ I ].X,												( FLOAT )g_vParticleHeap[ I ].Y,												0.5F,												1.0F );			lpVertices[ I ].RGB	   = g_vParticleHeap[ I ].RGB;	}	g_lpD3DEmiter->Unlock( );}


I don’t understand what you mean by static. How would you change the vertices in the vertex buffer with out locking it? Or do you mean NOT using a vertex buffer and rendering the particles one at a time?
Take back the internet with the most awsome browser around, FireFox
sakky
sakky
Oh, I see what you mean. Just translate the vertices.
Take back the internet with the most awsome browser around, FireFox
wazoo69
wazoo69
Just be carefull of making your app TOO CPU-bound. By only passing 4 vertices at a time to the GPU, you're wasting a lot of valuable bandwidth..

Check out the DirectX FAQ in the MSDN. There's some tips there for trying to maximize GPU usage leaving more cycles for your game (and letting your graphics hardware work a bit more)..

ie. instead of locking down the entire vertex buffer and updating/rendering the vertex data, the FAQ has a good suggestion on working with chunks of the buffer at a time.

You can play around with how big a chunk you want to pass at once to the GPU, but this should start to make more efficient usage of it.

Also, how "efficient" are using creation macros in every frame? I mean in your particle updating area, you're using the D3DXCOLOR_XRGB macro quite a bit (ie. multiply it by the number of particles in your array).

What about just having a pre-defined DWORD of the color choice(s) that you can refer to?

ie.
//put this somewhere OTHER than your updating loopDWORD dwColLayer1 = D3DXCOLOR_XRGB(220, 220, 220);then you just need to have the sprites's diffuse color updated like:case 0: g_vParticleHeap[ I ].RGB = dwColLayer1;


Again, I may be getting too anal here...perhaps the MACRO evaluation/execution time just isn't worth something like that?


Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.