Sign in to follow this  
Rozik

PointSprite always same Size and just a black square

Recommended Posts

hi everyone, i am trying to learn to use pointsprites for particles but i am running into some problems. all i am trying to do for now is display one particle and go from there but the problems i got are: 1. the particle is just shown as a blank black square even though the Texture is loaded and set correctly 2. the size of it doesnt change at all when i move the camera Please can someone take a look at my code and tell me whats wrong with it? Or please point me to a good tutorial about pointsprites all i can find are tutorials about particle systems but no single tutorial about how to draw just one single sprite the right way this is what i use for FVF and custom vertex:
struct PARTICLECUSTOMVERTEX{
	float x, y, z;
	DWORD PSIZE;
	DWORD Diffuse;
};
#define D3DFVF_PARTICLEVERTEX (D3DFVF_XYZ | D3DFVF_PSIZE | D3DFVF_DIFFUSE)


and here is my code so far
class FBSParticleSystem
{
private:
protected:
public:
	FBSParticle *m_Particles;
	DWORD m_NumParticles;
	LPDIRECT3DVERTEXBUFFER9 m_pVB;
	LPDIRECT3DTEXTURE9 m_Texture;
	
	FBSParticleSystem(LPDIRECT3DDEVICE9 Device, DWORD NumParticles)
	{
		m_NumParticles = NumParticles;
		m_Particles = new FBSParticle[m_NumParticles];
		m_pVB = NULL;
		m_Texture = NULL;
		Device->CreateVertexBuffer(m_NumParticles*sizeof(PARTICLECUSTOMVERTEX), 0, D3DFVF_PARTICLEVERTEX, D3DPOOL_DEFAULT, &m_pVB, NULL);
		if(FAILED(D3DXCreateTextureFromFile(Device, "2.bmp", &m_Texture))){
			MessageBox(NULL, "Could not find 2.bmp", "Particle", MB_OK);
		}
	}

	~FBSParticleSystem()
	{
		if(m_pVB)
			m_pVB->Release();

		if(m_Texture)
			m_Texture->Release();

		if(m_Particles)
			delete [] m_Particles;
	}

	VOID Update(LPDIRECT3DDEVICE9 g_pd3dDevice)
	{
		DWORD Time = timeGetTime();
		PARTICLECUSTOMVERTEX *vertices = new PARTICLECUSTOMVERTEX[m_NumParticles];

		for(DWORD Counter = 0; Counter < m_NumParticles; Counter++)
		{
			vertices[Counter].x = 0;
			vertices[Counter].y = 5;
			vertices[Counter].z = 0;		
		}

		VOID* pVertices = NULL;
		m_pVB->Lock( 0, sizeof(PARTICLECUSTOMVERTEX) * m_NumParticles, (void**)&pVertices, 0 );
		memcpy( pVertices, vertices, sizeof(PARTICLECUSTOMVERTEX)*m_NumParticles );
		m_pVB->Unlock();

		FLOAT MinSize, Scale1, Scale2, Scale3, Size;

		Size = 1.0;
		MinSize = Scale1 = Scale2 = 0;
		Scale3 = 0.2;

		g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, false );
		g_pd3dDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);	
		g_pd3dDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
		g_pd3dDevice->SetRenderState( D3DRS_POINTSIZE,    *((DWORD*)&Size ));
		g_pd3dDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&MinSize));
		g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_A,  *((DWORD*)&Scale1));
		g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_B,  *((DWORD*)&Scale2));
		g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_C,  *((DWORD*)&Scale3));		

        g_pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(PARTICLECUSTOMVERTEX) );
        g_pd3dDevice->SetFVF( D3DFVF_PARTICLEVERTEX );
		g_pd3dDevice->SetTexture(0, m_Texture);
        g_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, m_NumParticles );
	}
};


Share this post


Link to post
Share on other sites
ok i solved the texture problem and the positioning problem

but still the sprite has the same size no matter how far the camera is away from it

anyone have any ideas or a hint what should make the spirte shrink and grow when the camera gets closer or moves away?

Share this post


Link to post
Share on other sites
There are 3 render states to determine the size of the point sprite. They are called something like POINTSPRITESIZEA B and C. The SDK documentation contains the exact formula used to calculate the final size, but you'll probably need to change them a bit to have the distance matter.
Retracted :).

Hope this helps.

Share this post


Link to post
Share on other sites
Look into the PointScaleA, PointScaleB, and PointScaleC renderstates. also PointScaleEnable.

d3dDevice.RenderState.PointScaleA = 1.0f;
d3dDevice.RenderState.PointScaleB = 1.0f;
d3dDevice.RenderState.PointScaleC = 0.004f;

d3dDevice.RenderState.PointScaleEnable = true;
d3dDevice.RenderState.PointSize = this.particleSize; //initial point size

This works for me and i dont think its perfect(point scaling doesnt look good, might have to mess around with the values) but it should give you a good starting point.

Share this post


Link to post
Share on other sites
If you wish to use the psize in your vertex you must check the D3DFVFCAPS_PSIZE value of the d3dcaps structure. If it is not supported by your card (which it sounds like it's not), you will need to use software or mixed vertex processing in order to include it in the FVF.

I fought with this same problem for days because directx samples and docs about point sprites don't clue the reader in.

Share this post


Link to post
Share on other sites
i tinkered so much with those numbers but i cant get it to work
i am useing the folowing values which i got from a tutorial now but its still not working so i am guessing there might be another error somewhere.



Size = 0.08;
MinSize = 0.0f;
Scale1 = 0.0f;
Scale2 = 0.0f;
Scale3 = 1.0f;
g_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, *((DWORD*)&Size ));
g_pd3dDevice->SetRenderState(D3DRS_POINTSIZE_MIN, *((DWORD*)&MinSize));
g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_A, *((DWORD*)&Scale1));
g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_B, *((DWORD*)&Scale2));
g_pd3dDevice->SetRenderState(D3DRS_POINTSCALE_C, *((DWORD*)&Scale3));

Share this post


Link to post
Share on other sites
@Nuget hmm could you please show me what to check for?

and if my card doesnt support the size thing wouldnt i have trouble with the sample applications from the sdk?

Share this post


Link to post
Share on other sites
The samples most likely use software or mixed vertex processing for precisely this reason. They could also check just like the following:


// retrieve the device capabilities like this:
D3DCAPS9 d3dcaps;
pDirect3D9->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps);

// these flags will determine hardware/software vertex processing
DWORD deviceFlags = NULL;

// check for psize support like this:
if (d3dcaps.FVFCaps & D3DFVFCAPS_PSIZE) {
// not supported, use software vertex processing
deviceFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
// psize is supported, use hardware vertex processing
else {
deviceFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
}

// now create the device
// assuming you have your own hWnd, present params, and device pointer
pDirect3D9->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
hWnd, deviceFlags, &pd3dpp, &pD3DDevice);

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this