void WaveParticleManager::SpawnCircularWave(int numberOfParticles, glm::vec2 position, float amplitude, float speed, float radius) { float dispersionAngle = 2.0f * 3.14159f / numberOfParticles; float initializationTime = (radius / speed); for (int i = 0; i < numberOfParticles; ++i) { WaveParticle* waveParticle = GetNextParticle(); WaveParticle* waveParticle2 = GetNextParticle(); float dispersionAngle = 2.0f * 3.14159f / numberOfParticles; waveParticle->Initialize(glm::rotate(glm::vec2(1.f, 0.f), i * dispersionAngle), position, amplitude, speed, initializationTime, radius, dispersionAngle); waveParticle2->Initialize(glm::rotate(glm::vec2(1.f, 0.f), i * dispersionAngle), position, -amplitude, speed, 0.f , radius, dispersionAngle); } }
//-------------------------------------------------------------------------------------- // Name: EmitParticles() // Desc: //-------------------------------------------------------------------------------------- VOID CParticleEmitter::EmitParticles( PARTICLE* pParticles, FLOAT32 fElapsedTime, FLOAT32 fCurrentTime, FRMCOLOR Colors[NUM_COLORS], FLOAT32 fTimePerColor, EmitParticleShader *epShader, GLuint *srcBuffer, GLuint *pVAOs, GLuint *dstBuffer, FRM_VERTEX_ELEMENT* pVertexLayout, UINT32 nVertexSize, BOOL bUseTransformFeedback, GLuint Query ) { // Determine the color of the particles to be emitted FLOAT32 t = ( fCurrentTime / fTimePerColor ) - FrmFloor( fCurrentTime / fTimePerColor ); UINT32 nColorIndex = (INT32)FrmFloor( fCurrentTime / fTimePerColor ) % NUM_COLORS; FRMCOLOR vColor1 = Colors[ nColorIndex ]; FRMCOLOR vColor2 = Colors[(nColorIndex+1) % NUM_COLORS ]; FRMCOLOR vColor = FrmLerp( t, vColor1, vColor2 ); m_fLeftOverParticles += m_fEmissionRate * fElapsedTime; if( !bUseTransformFeedback ) { // Create the needed number of particles based upon our emission rate. for( INT32 i = 0; i < (INT32)NUM_PARTICLES; i++ ) { // Get the next particle PARTICLE* pParticle = GetNextParticle( pParticles ); if( FrmRand() < m_fLeftOverParticles / NUM_PARTICLES ) { FLOAT32 fAngle = m_fEmitterSpread * ( FrmRand() - 0.5f ); FRMMATRIX4X4 matRotate = FrmMatrixRotate( FrmRadians(fAngle), 0.0f, 0.0f, -1.0f ); FRMVECTOR3 vVelocity = FrmVector3TransformCoord( m_vVelocity, matRotate ); pParticle->m_vPosition = m_vPosition + FrmSphrand( m_fEmitterRadius ); pParticle->m_vVelocity = vVelocity * ApplyVariance( 1.0f, m_fSpeedVariance ); pParticle->m_vColor = FRMVECTOR4( vColor.r/255.0f, vColor.g/255.0f, vColor.b/255.0f, vColor.a/255.0f ); pParticle->m_vColor.a = ApplyVariance( m_fInitialOpacity, m_fOpacityVariance ); pParticle->m_fStartTime = fCurrentTime; pParticle->m_fLifeSpan = ApplyVariance( m_fInitialLifeSpan, m_fLifeSpanVariance ); pParticle->m_fInitialSize = ApplyVariance( m_fInitialSize, m_fInitialSizeVariance ); pParticle->m_fSizeIncreaseRate = ApplyVariance( m_fSizeIncreaseRate, m_fSizeIncreaseRateVarience ); } } } else { // Using transform feedback to do particle emission // Set up the shader glUseProgram( epShader->ShaderID ); glUniform3fv( epShader->slotvPosition, 1, (FLOAT32 *)&m_vPosition ); glUniform3fv( epShader->slotvVelocity, 1, (FLOAT32 *)&m_vVelocity ); glUniform1f( epShader->slotfEmitterSpread, m_fEmitterSpread ); glUniform1f( epShader->slotfEmitterRadius, m_fEmitterRadius ); glUniform1f( epShader->slotfSpeedVariance, m_fSpeedVariance ); glUniform1f( epShader->slotfInitialOpacity, m_fInitialOpacity ); glUniform1f( epShader->slotfOpacityVariance, m_fOpacityVariance ); glUniform1f( epShader->slotfInitialLifeSpan, m_fInitialLifeSpan ); glUniform1f( epShader->slotfLifeSpanVariance, m_fLifeSpanVariance ); glUniform1f( epShader->slotfInitialSize, m_fInitialSize ); glUniform1f( epShader->slotfInitialSizeVariance, m_fInitialSizeVariance ); glUniform1f( epShader->slotfSizeIncreaseRate, m_fSizeIncreaseRate ); glUniform1f( epShader->slotfSizeIncreaseRateVariance, m_fSizeIncreaseRateVarience ); glUniform1f( epShader->slotfTime, fCurrentTime ); glUniform4f( epShader->slotvColor, vColor.r/255.0f, vColor.g/255.0f, vColor.b/255.0f, vColor.a/255.0f ); glUniform1f( epShader->slotfEmissionRate, m_fLeftOverParticles/NUM_PARTICLES ); glEnable( GL_RASTERIZER_DISCARD ); glBindVertexArray(pVAOs[0]); // set source buffer glBindBuffer( GL_ARRAY_BUFFER, *srcBuffer ); FrmSetVertexLayout( pVertexLayout, nVertexSize, 0 ); glBindBuffer( GL_ARRAY_BUFFER, 0 ); glBindVertexArray(0); // set destination buffer glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, *dstBuffer ); glBindVertexArray(pVAOs[0]); glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, Query); // Perfom transform feedback glBeginTransformFeedback( GL_POINTS ); glDrawArrays( GL_POINTS, 0, NUM_PARTICLES ); glEndTransformFeedback(); glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); glDisable( GL_RASTERIZER_DISCARD ); glBindVertexArray(0); glBindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0 ); } m_fLeftOverParticles -= FrmFloor( m_fLeftOverParticles ); }