void CParticleEffectBinding::BBoxCalcStart( bool bFullBBoxUpdate, Vector &bbMin, Vector &bbMax ) { if ( !GetAutoUpdateBBox() ) return; if ( bFullBBoxUpdate ) { // We're going to fully recompute the bbox. bbMin.Init( FLT_MAX, FLT_MAX, FLT_MAX ); bbMax.Init( -FLT_MAX, -FLT_MAX, -FLT_MAX ); } else { // We're going to push out the bbox using just some of the particles. if ( m_bLocalSpaceTransformIdentity ) { bbMin = m_Min; bbMax = m_Max; } else { ITransformAABB( m_LocalSpaceTransform.As3x4(), m_Min, m_Max, bbMin, bbMax ); } } }
void CParticleEffectBinding::BBoxCalcEnd( bool bFullBBoxUpdate, bool bboxSet, Vector &bbMin, Vector &bbMax ) { if ( !GetAutoUpdateBBox() ) return; // Get the bbox into world space. Vector bbMinWorld, bbMaxWorld; if ( m_bLocalSpaceTransformIdentity ) { bbMinWorld = bbMin; bbMaxWorld = bbMax; } else { TransformAABB( m_LocalSpaceTransform.As3x4(), bbMin, bbMax, bbMinWorld, bbMaxWorld ); } if( bFullBBoxUpdate ) { // If there were ANY particles in the system, then we've got a valid bbox here. Otherwise, // we don't have anything, so leave m_Min and m_Max at the sort origin. if ( bboxSet ) { m_Min = bbMinWorld; m_Max = bbMaxWorld; } else { m_Min = m_Max = m_pSim->GetSortOrigin(); } } else { // Take whatever our bbox was + pushing out from other particles. m_Min = bbMinWorld; m_Max = bbMaxWorld; } }
//----------------------------------------------------------------------------- // Rendering //----------------------------------------------------------------------------- int CNewParticleEffect::DrawModel( int flags, const RenderableInstance_t &instance ) { VPROF_BUDGET( "CNewParticleEffect::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); if ( r_DrawParticles.GetBool() == false ) return 0; if ( !GetClientMode()->ShouldDrawParticles() || !ParticleMgr()->ShouldRenderParticleSystems() ) return 0; if( flags & STUDIO_SHADOWDEPTHTEXTURE ) return 0; if ( m_hOwner && m_hOwner->IsDormant() ) return 0; // do distance cull check here. We do it here instead of in particles so we can easily only do // it for root objects, not bothering to cull children individually CMatRenderContextPtr pRenderContext( materials ); if ( !m_pDef->IsScreenSpaceEffect() && !m_pDef->IsViewModelEffect() ) { Vector vecCamera; pRenderContext->GetWorldSpaceCameraPosition( &vecCamera ); if ( ( CalcSqrDistanceToAABB( m_MinBounds, m_MaxBounds, vecCamera ) > ( m_pDef->m_flMaxDrawDistance * m_pDef->m_flMaxDrawDistance ) ) ) return 0; } if ( ( flags & STUDIO_TRANSPARENCY ) || !IsBatchable() || !m_pDef->IsDrawnThroughLeafSystem() ) { int viewentity = render->GetViewEntity(); C_BaseEntity *pCameraObject = cl_entitylist->GetEnt( viewentity ); // apply logic that lets you skip rendering a system if the camera is attached to its entity if ( ( ( pCameraObject && ( m_pDef->m_nSkipRenderControlPoint != -1 ) && ( m_pDef->m_nSkipRenderControlPoint <= m_nHighestCP ) && ( GetControlPointEntity( m_pDef->m_nSkipRenderControlPoint ) == pCameraObject ) ) ) || ( ( pCameraObject && ( m_pDef->m_nAllowRenderControlPoint != -1 ) && ( m_pDef->m_nAllowRenderControlPoint <= m_nHighestCP ) && ( GetControlPointEntity( m_pDef->m_nAllowRenderControlPoint ) != pCameraObject ) ) ) ) return 0; Vector4D vecDiffuseModulation( 1.0f, 1.0f, 1.0f, 1.0f ); //instance.m_nAlpha / 255.0f ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); Render( pRenderContext, vecDiffuseModulation, ( flags & STUDIO_TRANSPARENCY ) ? IsTwoPass() : false, pCameraObject ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PopMatrix(); } else { g_pParticleSystemMgr->AddToRenderCache( this ); } if ( cl_particles_show_bbox.GetBool() ) { Vector center = GetRenderOrigin(); Vector mins = m_MinBounds - center; Vector maxs = m_MaxBounds - center; int r, g; if ( GetAutoUpdateBBox() ) { // red is bad, the bbox update is costly r = 255; g = 0; } else { // green, this effect presents less cpu load r = 0; g = 255; } Vector vecCurCPPos = GetControlPointAtCurrentTime( 0 ); debugoverlay->AddBoxOverlay( center, mins, maxs, QAngle( 0, 0, 0 ), r, g, 0, 16, 0 ); debugoverlay->AddTextOverlayRGB( center, 0, 0, r, g, 0, 64, "%s:(%d)", GetEffectName(), m_nActiveParticles ); } return 1; }
void CNewParticleEffect::DebugDrawBbox ( bool bCulled ) { int nParticlesShowBboxCost = g_cl_particle_show_bbox_cost; bool bShowCheapSystems = false; if ( nParticlesShowBboxCost < 0 ) { nParticlesShowBboxCost = -nParticlesShowBboxCost; bShowCheapSystems = true; } Vector center = GetRenderOrigin(); Vector mins = m_MinBounds - center; Vector maxs = m_MaxBounds - center; int r, g, b; bool bDraw = true; if ( bCulled ) { r = 64; g = 64; b = 64; } else if ( nParticlesShowBboxCost > 0 ) { float fAmount = (float)m_nActiveParticles / (float)nParticlesShowBboxCost; if ( fAmount < 0.5f ) { if ( bShowCheapSystems ) { r = 0; g = 255; b = 0; } else { // Prevent the screen getting spammed with low-count particles which aren't that expensive. bDraw = false; r = 0; g = 0; b = 0; } } else if ( fAmount < 1.0f ) { // green 0.5-1.0 blue int nBlend = (int)( 512.0f * ( fAmount - 0.5f ) ); nBlend = MIN ( 255, MAX ( 0, nBlend ) ); r = 0; g = 255 - nBlend; b = nBlend; } else if ( fAmount < 2.0f ) { // blue 1.0-2.0 red int nBlend = (int)( 256.0f * ( fAmount - 1.0f ) ); nBlend = MIN ( 255, MAX ( 0, nBlend ) ); r = nBlend; g = 0; b = 255 - nBlend; } else { r = 255; g = 0; b = 0; } } else { if ( GetAutoUpdateBBox() ) { // red is bad, the bbox update is costly r = 255; g = 0; b = 0; } else { // green, this effect presents less cpu load r = 0; g = 255; b = 0; } } if ( bDraw ) { debugoverlay->AddBoxOverlay( center, mins, maxs, QAngle( 0, 0, 0 ), r, g, b, 16, 0 ); debugoverlay->AddTextOverlayRGB( center, 0, 0, r, g, b, 64, "%s:(%d)", GetEffectName(), m_nActiveParticles ); } }
//----------------------------------------------------------------------------- // Rendering //----------------------------------------------------------------------------- int CNewParticleEffect::DrawModel( int flags ) { VPROF_BUDGET( "CNewParticleEffect::DrawModel", VPROF_BUDGETGROUP_PARTICLE_RENDERING ); if ( r_DrawParticles.GetBool() == false ) return 0; // City17: DX7? Don't draw. if( engine->GetDXSupportLevel() < 80 ) return 0; if ( !g_pClientMode->ShouldDrawParticles() || !ParticleMgr()->ShouldRenderParticleSystems() ) return 0; if( flags & STUDIO_SHADOWDEPTHTEXTURE ) return 0; // do distance cull check here. We do it here instead of in particles so we can easily only do // it for root objects, not bothering to cull children individually CMatRenderContextPtr pRenderContext( materials ); Vector vecCamera; pRenderContext->GetWorldSpaceCameraPosition( &vecCamera ); if ( CalcSqrDistanceToAABB( m_MinBounds, m_MaxBounds, vecCamera ) > ( m_pDef->m_flMaxDrawDistance * m_pDef->m_flMaxDrawDistance ) ) return 0; if ( flags & STUDIO_TRANSPARENCY ) { int viewentity = render->GetViewEntity(); C_BaseEntity *pCameraObject = cl_entitylist->GetEnt( viewentity ); // apply logic that lets you skip rendering a system if the camera is attached to its entity if ( pCameraObject && ( m_pDef->m_nSkipRenderControlPoint != -1 ) && ( m_pDef->m_nSkipRenderControlPoint <= m_nHighestCP ) && ( GetControlPointEntity( m_pDef->m_nSkipRenderControlPoint ) == pCameraObject ) ) return 0; pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PushMatrix(); pRenderContext->LoadIdentity(); Render( pRenderContext, IsTwoPass(), pCameraObject ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->PopMatrix(); } else { g_pParticleSystemMgr->AddToRenderCache( this ); } if ( !IsRetail() && cl_particles_show_bbox.GetBool() ) { Vector center = GetRenderOrigin(); Vector mins = m_MinBounds - center; Vector maxs = m_MaxBounds - center; int r, g; if ( GetAutoUpdateBBox() ) { // red is bad, the bbox update is costly r = 255; g = 0; } else { // green, this effect presents less cpu load r = 0; g = 255; } debugoverlay->AddBoxOverlay( center, mins, maxs, QAngle( 0, 0, 0 ), r, g, 0, 16, 0 ); debugoverlay->AddTextOverlayRGB( center, 0, 0, r, g, 0, 64, "%s:(%d)", GetEffectName(), m_nActiveParticles ); } return 1; }