VOID FrmRenderTextureToScreen_GLES( FLOAT32 sx, FLOAT32 sy, FLOAT32 w, FLOAT32 h, UINT32 hTexture, INT32 hShaderProgram, INT32 hScreenSizeLoc ) { struct { GLint x, y, width, height; } viewport; glGetIntegerv( GL_VIEWPORT, (GLint*)&viewport ); FLOAT32 fTextureWidth = w; FLOAT32 fTextureHeight = h; FLOAT32 fScreenWidth = (FLOAT32)viewport.width; FLOAT32 fScreenHeight = (FLOAT32)viewport.height; if( sx < 0.0f ) sx += fScreenWidth - fTextureWidth; if( sy < 0.0f ) sy += fScreenHeight - fTextureHeight; sx = FrmFloor( sx ); sy = FrmFloor( sy ); // Set the geoemtry FRMVECTOR4 vQuad[] = { // Screenspace x Screenspace y tu tv FRMVECTOR4( sx, sy, 0.0f, 1.0f ), FRMVECTOR4( sx, sy+fTextureHeight, 0.0f, 0.0f ), FRMVECTOR4( sx+fTextureWidth, sy+fTextureHeight, 1.0f, 0.0f ), FRMVECTOR4( sx+fTextureWidth, sy, 1.0f, 1.0f ), }; glVertexAttribPointer( 0, 4, GL_FLOAT, 0, 0, vQuad ); glEnableVertexAttribArray( 0 ); // Set the texture glActiveTexture( GL_TEXTURE0 ); glBindTexture( GL_TEXTURE_2D, hTexture ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glEnable( GL_BLEND ); glDisable( GL_DEPTH_TEST ); // Set the shader program glUseProgram( hShaderProgram ); glUniform2f( hScreenSizeLoc, fScreenWidth, fScreenHeight ); // Draw the quad glDrawArrays( GL_TRIANGLE_FAN, 0, 4 ); glEnable( GL_DEPTH_TEST ); glDisable( GL_BLEND ); }
//-------------------------------------------------------------------------------------- // 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 ); }