Jump to content
  • Advertisement
Sign in to follow this  
Enalis

I'm in dire need of someone who knows this stuff

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

I wrote a particle system once for a 2d game that worked great and I decided to adapt it to 3d and I plan on adding things like wind resistance and all kinds of stuff but anyway. I am currently implementing 3 different rendering methods... cpu billboarding, arb point sprites (GL_EXT), and a cg vertex shader billboarding. both the cpu billboarding and cg vertex shader billboarding don't blend the particles correctly. For instance when you look down with the camera at the particles, it doesn't blend right, and in some other instances. And the arb point sprites don't draw at all. If you can spot anything in this code please let me know. I'd like to move on for now from particles but it's been bugging me. Here's the drawing code
void cParticleSystem::Draw(void){
	cParticle *index = head;

	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glDisable(GL_LIGHTING);
	
	glBindTexture(GL_TEXTURE_2D, texture[0]);
	glBlendFunc( GL_SRC_ALPHA, GL_ONE );

	if (renderMethod == CPU_BILLBOARDS){
		double mat[16];
		glGetDoublev( GL_MODELVIEW_MATRIX, mat );
		cVector3 right(mat[0], mat[4], mat[8]);
		cVector3 up(mat[1], mat[5], mat[9]);
		cVector3 point0, point1, point2, point3;

		while (index){
			cVector3 point0 = index->position + (((-right) - up) * index->size );
			cVector3 point1 = index->position + ((right - up) * index->size );
			cVector3 point2 = index->position + ((right + up) * index->size );
			cVector3 point3 = index->position + (((-right) + up) * index->size );

			cVector3 color;
			if (index->life > 1.0){
				double percent = ((index->life - 1.0) / (index->startLife - 1.0));
				double oneMinusPercent = 1.0 - percent;
				color = (startColor * percent) + (endColor * oneMinusPercent);
			}else{
				color = endColor;
			}

			glColor4d(color.x, color.y, color.z, index->life);

			glBegin(GL_QUADS);
			glTexCoord2d(0, 0); glVertex3f(point0.x, point0.y, point0.z);
			glTexCoord2d(1, 0); glVertex3f(point1.x, point1.y, point1.z);
			glTexCoord2d(1, 1); glVertex3f(point2.x, point2.y, point2.z);
			glTexCoord2d(0, 1); glVertex3f(point3.x, point3.y, point3.z);
			glEnd();

			index = index->next;
		}
	}else if( renderMethod == ARB_POINT_SPRITES ){
		float quadratic[] =  { 1.0f, 0.0f, 0.01f };
		glPointParameterfvARB( GL_POINT_DISTANCE_ATTENUATION_ARB, quadratic );

		glPointParameterfARB( GL_POINT_FADE_THRESHOLD_SIZE_ARB, 60.0f );

		glPointParameterfARB( GL_POINT_SIZE_MIN_ARB, 1.0f );
		glPointParameterfARB( GL_POINT_SIZE_MAX_ARB, index->size );

		glTexEnvf( GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE );

		glEnable( GL_POINT_SPRITE_ARB );
		
		while( index ){
			glPointSize( index->size );
	
			cVector3 color;
			if (index->life > 1.0){
				double percent = ((index->life - 1.0) / (index->startLife - 1.0));
				double oneMinusPercent = 1.0 - percent;
				color = (startColor * percent) + (endColor * oneMinusPercent);
			}else{
				color = endColor;
			}
	
			glColor4d(color.x, color.y, color.z, index->life);
			glBegin( GL_POINTS );
				glVertex3d( index->position.x, index->position.y, index->position.z);
				index = index->next;
			glEnd();
		}

		glDisable( GL_POINT_SPRITE_ARB );
	}else if( renderMethod == CG_VERTEX_SHADER ){
		cParticle  *index = head;

        // Compute billboard vertices on the GPU...
        // Track the combined model-view-projection matrix
		cgGLSetStateMatrixParameter( m_CGparam_modelViewProj,
									 CG_GL_MODELVIEW_PROJECTION_MATRIX,
									 CG_GL_MATRIX_IDENTITY );

        // Load the billboard size into a constant register
        //float fSize[] = { 1.0f, 0.0f, 0.0f, 0.0f };
        //cgGLSetParameter4fv( m_CGparam_size, fSize );

        // Create a pre-rotated quad for use by the shader...

		float mat[16];
		glGetFloatv( GL_MODELVIEW_MATRIX, mat );

		cVector3f vRight( mat[0], mat[4], mat[8] );
		cVector3f vUp( mat[1], mat[5], mat[9] );
		cVector3f vCenter( 0.0f, 0.0f, 0.0f );

		cVector3f vPoint0 = vCenter + (-vRight - vUp);
		cVector3f vPoint1 = vCenter + ( vRight - vUp);
		cVector3f vPoint2 = vCenter + ( vRight + vUp);
		cVector3f vPoint3 = vCenter + (-vRight + vUp);

		float preRotatedQuad[16] = {
			vPoint0.x, vPoint0.y, vPoint0.z, 0.0f,
			vPoint1.x, vPoint1.y, vPoint1.z, 0.0f,
			vPoint2.x, vPoint2.y, vPoint2.z, 0.0f,
			vPoint3.x, vPoint3.y, vPoint3.z, 0.0f
		};

		cgGLSetParameterArray4f( m_CGparam_preRotatedQuad, 0, 4, preRotatedQuad );

        // Bind the shader and render the particles...
		cgGLBindProgram( m_CGprogram );
		cgGLEnableProfile( m_CGprofile );

		glBindTexture( GL_TEXTURE_2D, texture[0] );

		float fAdjustedSize = index->size;

		glBegin( GL_QUADS );{
			while( index ){
				cVector3 color;
				if (index->life > 1.0){
					double percent = ((index->life - 1.0) / (index->startLife - 1.0));
					double oneMinusPercent = 1.0 - percent;
					color = (startColor * percent) + (endColor * oneMinusPercent);
				}else{
					color = endColor;
				}
	
				glColor4d(color.x, color.y, color.z, index->life);

				vCenter.x = index->position.x;
				vCenter.y = index->position.y;
				vCenter.z = index->position.z;
                
				glTexCoord4f( 0.0f, 0.0f, 0.0f, fAdjustedSize );
				glVertex3f( vCenter.x, vCenter.y, vCenter.z );

				glTexCoord4f( 1.0f, 0.0f, 1.0f, fAdjustedSize );
				glVertex3f( vCenter.x, vCenter.y, vCenter.z );

				glTexCoord4f( 1.0f, 1.0f, 2.0f, fAdjustedSize );
				glVertex3f( vCenter.x, vCenter.y, vCenter.z );

				glTexCoord4f( 0.0f, 1.0f, 3.0f, fAdjustedSize );
				glVertex3f( vCenter.x, vCenter.y, vCenter.z );

				index = index->next;
			}
		}
		glEnd();

		cgGLDisableProfile( m_CGprofile );
	}
}

Share this post


Link to post
Share on other sites
Advertisement
Just a stab in the dark here as I'm knackered from fighting coding MD3 stuff but usually your blendfunc is GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA for normal blending, not GL_SRC_ALPHA, GL_ONE as you currently have it.

Like I say it's just the first thing I noticed, may not be any help to you but I hope it is.

Best of luck.

Share this post


Link to post
Share on other sites
Note that, for some blend modes, you need to actually sort the particles far-to-near before generating the geometry, each frame.

For particles with additive blending mode (ONE, ONE), draw order doesn't matter.

Share this post


Link to post
Share on other sites
try disabling depthwriting with glDepthMask(GL_FALSE);
this will inshure that particles won't block each other.

You will still need to sort them though.

Share this post


Link to post
Share on other sites
I find that if I disable depth writing and use glDepthFunc(GL_SRC_ALPHA, GL_ONE);

Everything is fine... however, it's when I set the blending to take into consideration what's behind it with glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), then I need to sort everything by depth and render from back to front.

I recommend doing what someone else here mentioned and simply disable depth writing while rendering the particles, it's fast, is OK to look at and takes into consideration, previously rendered geometry (It also prevents each particle being rendered, no matter how far away it is, from culling the pixels of the next to be rendered particle if it's Z depth is greater than any previously rendered) I pretty much always render the particle systems last.

However, saying all that, after looking at your supplied code, I doubt this will help, as I see no state changes... so perhaps it's not the problem... I dunno... I blame beer.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!