Made a particle engine, an easy problem

Started by
9 comments, last by Muzlack 21 years, 9 months ago
Ok, I made my own particle engine! I''m pretty proud of myself because I didn''t copy any code except setting up render states which I didn''t know how to do, but I have a small problem, and I''m not quite sure what is wrong. Ok, when NOTHING else besides particles is rendered, it works fine, but when I add in a cube that I made that is behind the particles, the particles just look really bright, and you can hardly see them. It looks like the cube is just more lit up. I did do a
  
D3DDevice->SetRenderState(D3DRS_ALPHABLENDABLE, FALSE);
  
In fact, here''s my render code for the particle:
  
void Particle::Render() {
	D3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
	D3DDevice->SetRenderState(D3DRS_ZENABLE,FALSE);
	D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
	D3DDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
    D3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	D3DDevice->SetTexture(0,tex);
	D3DDevice->SetVertexShader(PARTICLEFVF);
	D3DDevice->SetStreamSource(0,vb,sizeof(CustomV));
	D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);
	D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
	D3DDevice->SetTexture(0,NULL);
	D3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);
	D3DDevice->SetRenderState(D3DRS_ZENABLE,TRUE);
}
  
any help?
--Muzlack
Advertisement
I''d guess it''s the alpha value of the bitmap you are using as a particle. Try making the particle bitmap darker (I think paintshop pro includes alpha values in the colour selector if it helps). I believe its possible to have black with an alpha value of 0 all the way through to 255 and the same for any other colour, so if you are using black and white for your particle, try checking the colours alpha value in your paint package if the option is available, you may find that your white is acting more as you''d expect a light grey to work because it has an alpha value of less than 255 and is therefore not solid but still semi transparent.
Cheers,SteveLiquidigital Online
Ok, I have a little bit better an explanation of the problem. The lighter the background is, the less you can see of the particle. I tried darkening it and it didn''t work. I think the problem is that no matter what, it builds up on the brightness rather than taking it away. I''m not sure, but I think this is called like additive alpha blending or something like that. Does anyone know how to remedy it?
--Muzlack
I figured I might as well post the code, its not long at all


  #include "particle.h"Particle::Particle(LPDIRECT3DDEVICE8 device) {	D3DDevice=device;   //High quality filtering to make things look nice		SetSize(5.0f);	SetTexture("Particle.bmp");		D3DDevice->CreateVertexBuffer(6*sizeof(CustomV),D3DUSAGE_WRITEONLY,PARTICLEFVF,D3DPOOL_MANAGED,&vb);	SetColor(255,255,255);	UpdateVertices();}void Particle::SetColor(int r, int g, int b) {	r1=r;	g1=g;	b1=b;	UpdateVertices();}void Particle::UpdateVertices() {	VOID* pVertices;	CustomV cvVertices[]={		{-size, -size,0.0f,D3DCOLOR_XRGB(r1,g1,b1), 0.0f,1.0f,},		{-size, size, 0.0f, D3DCOLOR_XRGB(r1,g1,b1),0.0f, 0.0f,},		{size, -size, 0.0f,D3DCOLOR_XRGB(r1,g1,b1), 1.0f, 1.0f,},		{size, -size, 0.0f, D3DCOLOR_XRGB(r1,g1,b1),1.0f, 1.0f,},		{-size, size,0.0f,D3DCOLOR_XRGB(r1,g1,b1), 0.0f, 0.0f, },		{size, size,0.0f,D3DCOLOR_XRGB(r1,g1,b1), 1.0f, 0.0f, }};	vb->Lock(0,0, (BYTE**)&pVertices,0);	memcpy(pVertices,cvVertices,sizeof(cvVertices));	vb->Unlock();}void Particle::SetSize(float s) {	size=s;}void Particle::SetTexture(char *file) {	D3DXCreateTextureFromFile(D3DDevice, file, &tex);}void Particle::Render() {	D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);	D3DDevice->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);	D3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);	D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);	D3DDevice->SetTexture(0,tex);	D3DDevice->SetVertexShader(PARTICLEFVF);	D3DDevice->SetStreamSource(0,vb,sizeof(CustomV));	D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);	D3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);	D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);}  
--Muzlack

      BOOL cGraphics::EnableAlphaBlending(BOOL Enable){	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, Enable);	m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);	m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);	return TRUE;}    


That function sorts my alpha blending, I believe your line "D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);" , needs replacing with "D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);"

Hope that helps


[edited by - mephs on June 25, 2002 9:37:05 PM]
Cheers,SteveLiquidigital Online
Close, but no cigar. now Color keying goes away.. here''s the new code for render:


  void Particle::Alpha(BOOL enable) {	D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);	D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);		D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);}void Particle::Render() {	Alpha(TRUE);	D3DDevice->SetTransform(D3DTS_WORLD,&mat);	D3DDevice->SetRenderState(D3DRS_LIGHTING,FALSE);	D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);	D3DDevice->SetTexture(0,tex);	D3DDevice->SetVertexShader(PARTICLEFVF);	D3DDevice->SetStreamSource(0,vb,sizeof(CustomV));	D3DDevice->DrawPrimitive(D3DPT_TRIANGLELIST,0,2);	D3DDevice->SetRenderState(D3DRS_LIGHTING,TRUE);	D3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);	Alpha(FALSE);}  
--Muzlack
Not that it has anything to do with your problem but...

You might want to split your classes up into ParticleType and Particle (or ParticleInstance).
The ParticleType class contains all the parameters for that particular type of particle (ie the fire particles) and the ParticleInstance class holds the individual particle''s data (ie position, color).

Make the ParticleType class contain a linked list (or stl vector or whatever) of all the ParticleInstances.

Then put the a Render routine in the ParticleType... this routine should setup your d3d render states, loop through each ParticleInstance in it''s list and call the ParticleInstance''s Render function, then cleanup. In the instances Render function you only need to draw the actual triangles (no d3d setup).

The advantage of doing everything like this is that you dont set the render state for every particle - you only do it once... far more efficient use of d3d! Changing render states, setting textures, whaever should be avoided where possible on ALL hardware.


Sorry to be such a ''smart ass'' but hopefully you dont mind a little friendly advice...
bump
try changing
D3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
to
D3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

what you want is for the DSTALPHA to be 1-SRCALPHA
still doesn''t work, I''ve tried it both with:


  	D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);	D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);	D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);  

and

  	D3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);	D3DDevice->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_SRCALPHA);		D3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);  

--Muzlack

This topic is closed to new replies.

Advertisement