Skip to main content
gamedev.net
🔒 Locked

Particles aren't rendering

Started by timmay314 Jan 8, 2004 at 7:46 PM 4 replies 400+ views
Original Post
timmay314
timmay314
I am trying to create a particle system for the first time. I''m copying from the particle system in the book "Special Effects Game Programming with DirectX" and changing only a very small amount to suit my specific program, but it inexplicably renders nothing. Everything but the particles render normally, but the particles don''t render at all. Nothing fails in the Render() method, so I don''t understand what''s going on. Here''s my various relevant code. I''m also using lighting if that matters. Any idea of what''s going on here?
struct PARTICLEVERTEX
{
	D3DXVECTOR3 vPos;
	float fSize;
	D3DCOLOR color;
};
#define PARTICLEFVF (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_PSIZE)

HRESULT Render()
{
	g_pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSIZE_MIN, 0);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_A, 0);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_B, 0);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_C, 1);

	g_pD3DDevice->SetStreamSource(0, m_vbParticles, 0, sizeof(PARTICLEVERTEX));
	g_pD3DDevice->SetFVF(PARTICLEFVF);
	g_pD3DDevice->SetTexture(0, m_texParticle);

	PARTICLEVERTEX *pVertices;
	if(FAILED(m_vbParticles->Lock(0, m_iVBSize * sizeof(PARTICLEVERTEX),
		(void**)&pVertices, D3DLOCK_DISCARD)))
		return E_FAIL;

	int iParticlesToRender = 0;
	for(int i = 0; i < m_iMaxCount; i++)
	{
		if(m_aParticles[i].m_bExists)
		{
			CParticle* pPart = &m_aParticles[i];
			pVertices->vPos = pPart->m_vPos;
			pVertices->fSize = 1.0f;
			pVertices->color = D3DCOLOR_ARGB(255, 255, 255, 255);
			pVertices++;

			iParticlesToRender++;
			if(iParticlesToRender == m_iVBSize)
			{
				m_vbParticles->Unlock();
				if(FAILED(g_pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, 0, 
					iParticlesToRender)))
					return E_FAIL;
				if(FAILED(m_vbParticles->Lock(0, m_iVBSize * sizeof(PARTICLEVERTEX), 
					(void**)&pVertices, D3DLOCK_DISCARD)))
					return E_FAIL;
				iParticlesToRender = 0;
			}
		}
	}

	m_vbParticles->Unlock();
	if(iParticlesToRender)
	{
		if(FAILED(g_pD3DDevice->DrawPrimitive(D3DPT_POINTLIST, 0, iParticlesToRender)))
			return E_FAIL;
	}

	g_pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE);
	g_pD3DDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE);
	g_pD3DDevice->SetTexture(0, NULL);
	return S_OK;
}
Supernat02
Supernat02
Several things...

Did you specify the D3DUSAGE_POINTS flag in the CreateVertexBuffer call?

Device->CreateVertexBuffer(x*sizeof(PARTICLEVERTEX), D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY, PARTICLEFVF, D3DPOOL_DEFAULT, &m_vbParticles, 0);

// Add this function somewhere.
inline DWORD FLOAT2DWORD(FLOAT f) {return *((DWORD*)&f);}

Also, in your initialization routine, you don''t have to, but probably would want to say:

//Make default size 1.0f
Device->SetRenderState(D3DRS_POINTSIZE, FLOAT2DWORD(1.0f));

// Make minimum size 0.2f (just for testing purposes)
Device->SetRenderState(D3DRS_POINTSIZE_MIND, FLOAT2DWORD(0.0f));

When you set the Point scale attenuation factors, remember that the SetRenderState only accepts DWORDS, not floats. Hence, the reason for converting the floats above to DWORDS. So, try:

g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_A, FLOAT2DWORD(1.0f));
g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_B, FLOAT2DWORD(0.0f));
g_pD3DDevice->SetRenderState(D3DRS_POINTSCALE_C, FLOAT2DWORD(0.0f));

I would also just try setting A attenuation first, instead of C.

Some further info would help if that doesn''t do the trick. If you could provide the actual creation of the vertex buffer, what the variable iVBSize represents (I assume it''s used in batching), and

Have you verified that the texture for the point sprite is not null by breakpoint?

Also, have you set break points in the debugger to verify that iParticlesToRender is greater than 0, that m_iMaxCount is valid, and that m_bExists is valid?

Good luck,
Chris
Chris ByersMicrosoft DirectX MVP - 2005
timmay314
timmay314
Those changes didn't do it . m_iVBSize is the number of vertices in the vertex buffer. You mentioned something about batching...I don't know what that means, but it is done this way so that the video card and CPU are both processing simultaneously to make things faster. m_iVBSize is a constant (defined as 100 now, but subject to tweaking if this ever starts working). Here's my VB creation code.

g_pD3DDevice->CreateVertexBuffer(m_iVBSize * sizeof(PARTICLEVERTEX),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
PARTICLEFVF, D3DPOOL_DEFAULT, &m_vbParticles, NULL);


I had checked the texture and such before using breakpoints. They are all fine, and DrawPrimitive is called.

I'm using the first texture I could find, and it happens to be 64 by 64. This is obviously bigger than the particle, but I have no clue if this is a problem or not.

I had a function similar to FLOAT2DWORD but I couldn't figure out what it did so I left it out. I added it back in, but it didn't make a difference.


[edited by - timmay314 on January 8, 2004 11:31:11 PM]
timmay314
timmay314
Woah, I just fixed it. Apparently there was a problem with the material...? I have to set it to something bright for it to work. The book didn''t mention lighting or materials so I assumed they were irrelivent for particles. If the particles are different colors, I obviously don''t want to set the material every time - that''s too expensive. I don''t really understand what''s going on so I don''t know what I should do - should I just disable lighting for this part of the rendering?
timmay314
timmay314
I turn off lighting and then turned it back on and that part is working correctly now. Unfortunately, the particle size member of the struct prevents everything from working. Unless I take it out (and change the FVF and all use of it), nothing renders at all. What could be the problem with specifying the size?

One more thing - how do I get these to blend and get it to recognize the blackness on the edge of the texture as transparent? I added this code to where it is setting the render states and it looks okay except the blackness doesn''t go away.

g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
Supernat02
Supernat02
Some video cards do not support varying particle sizes as I understand...I''m pretty sure I read that somewhere. I know I read that there is a max particle size anyway. You should look into using a shader to render the particles. It''s not limited by size. Check the MaxPointSize variable of your D3DCAPS9 structure to find the max point size.

Try:

g_pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x08);
g_pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);

g_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCCOLOR);
g_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTCOLOR);


This might do the trick, I don''t know.

Batching is exactly what you said, something to help the GPU and CPU work better together.

Good luck,
Chris
Chris ByersMicrosoft DirectX MVP - 2005

Topic Locked

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

Sign in to reply to this topic.