diff --git a/src/game/client/components/particles.cpp b/src/game/client/components/particles.cpp index dd574045a..f8ae0ac4c 100644 --- a/src/game/client/components/particles.cpp +++ b/src/game/client/components/particles.cpp @@ -172,6 +172,17 @@ void CParticles::OnInit() } } +bool CParticles::ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize) +{ + float ScreenX0, ScreenY0, ScreenX1, ScreenY1; + Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1); + + // always uses the mid of the particle + float SizeHalf = CurSize / 2; + + return CurPos.x + SizeHalf >= ScreenX0 && CurPos.x - SizeHalf <= ScreenX1 && CurPos.y + SizeHalf >= ScreenY0 && CurPos.y - SizeHalf <= ScreenY1; +} + void CParticles::RenderGroup(int Group) { // don't use the buffer methods here, else the old renderer gets many draw calls @@ -210,33 +221,37 @@ void CParticles::RenderGroup(int Group) vec2 p = m_aParticles[i].m_Pos; float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a); - if(LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != m_aParticles[i].m_Color.a || LastQuadOffset != QuadOffset) + // the current position, respecting the size, is inside the viewport, render it, else ignore + if(ParticleIsVisibleOnScreen(p, Size)) { - Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[LastQuadOffset - SPRITE_PART_SLICE]); - Graphics()->RenderQuadContainerAsSpriteMultiple(m_ParticleQuadContainerIndex, LastQuadOffset, CurParticleRenderCount, s_aParticleRenderInfo); - CurParticleRenderCount = 0; - LastQuadOffset = QuadOffset; + if(LastColor[0] != m_aParticles[i].m_Color.r || LastColor[1] != m_aParticles[i].m_Color.g || LastColor[2] != m_aParticles[i].m_Color.b || LastColor[3] != m_aParticles[i].m_Color.a || LastQuadOffset != QuadOffset) + { + Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[LastQuadOffset - SPRITE_PART_SLICE]); + Graphics()->RenderQuadContainerAsSpriteMultiple(m_ParticleQuadContainerIndex, LastQuadOffset, CurParticleRenderCount, s_aParticleRenderInfo); + CurParticleRenderCount = 0; + LastQuadOffset = QuadOffset; - Graphics()->SetColor( - m_aParticles[i].m_Color.r, - m_aParticles[i].m_Color.g, - m_aParticles[i].m_Color.b, - m_aParticles[i].m_Color.a); + Graphics()->SetColor( + m_aParticles[i].m_Color.r, + m_aParticles[i].m_Color.g, + m_aParticles[i].m_Color.b, + m_aParticles[i].m_Color.a); - LastColor[0] = m_aParticles[i].m_Color.r; - LastColor[1] = m_aParticles[i].m_Color.g; - LastColor[2] = m_aParticles[i].m_Color.b; - LastColor[3] = m_aParticles[i].m_Color.a; + LastColor[0] = m_aParticles[i].m_Color.r; + LastColor[1] = m_aParticles[i].m_Color.g; + LastColor[2] = m_aParticles[i].m_Color.b; + LastColor[3] = m_aParticles[i].m_Color.a; + } + + s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[0] = p.x; + s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[1] = p.y; + + s_aParticleRenderInfo[CurParticleRenderCount].m_Scale = Size; + s_aParticleRenderInfo[CurParticleRenderCount].m_Rotation = m_aParticles[i].m_Rot; + + ++CurParticleRenderCount; } - s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[0] = p.x; - s_aParticleRenderInfo[CurParticleRenderCount].m_Pos[1] = p.y; - - s_aParticleRenderInfo[CurParticleRenderCount].m_Scale = Size; - s_aParticleRenderInfo[CurParticleRenderCount].m_Rotation = m_aParticles[i].m_Rot; - - ++CurParticleRenderCount; - i = m_aParticles[i].m_NextPart; } @@ -252,25 +267,30 @@ void CParticles::RenderGroup(int Group) while(i != -1) { - Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[m_aParticles[i].m_Spr - SPRITE_PART_SLICE]); - Graphics()->QuadsBegin(); float a = m_aParticles[i].m_Life / m_aParticles[i].m_LifeSpan; vec2 p = m_aParticles[i].m_Pos; float Size = mix(m_aParticles[i].m_StartSize, m_aParticles[i].m_EndSize, a); - Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot); + // the current position, respecting the size, is inside the viewport, render it, else ignore + if(ParticleIsVisibleOnScreen(p, Size)) + { + Graphics()->TextureSet(GameClient()->m_ParticlesSkin.m_SpriteParticles[m_aParticles[i].m_Spr - SPRITE_PART_SLICE]); + Graphics()->QuadsBegin(); - Graphics()->SetColor( - m_aParticles[i].m_Color.r, - m_aParticles[i].m_Color.g, - m_aParticles[i].m_Color.b, - m_aParticles[i].m_Color.a); // pow(a, 0.75f) * + Graphics()->QuadsSetRotation(m_aParticles[i].m_Rot); - IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size); - Graphics()->QuadsDraw(&QuadItem, 1); + Graphics()->SetColor( + m_aParticles[i].m_Color.r, + m_aParticles[i].m_Color.g, + m_aParticles[i].m_Color.b, + m_aParticles[i].m_Color.a); // pow(a, 0.75f) * + + IGraphics::CQuadItem QuadItem(p.x, p.y, Size, Size); + Graphics()->QuadsDraw(&QuadItem, 1); + Graphics()->QuadsEnd(); + } i = m_aParticles[i].m_NextPart; - Graphics()->QuadsEnd(); } Graphics()->WrapNormal(); Graphics()->BlendNormal(); diff --git a/src/game/client/components/particles.h b/src/game/client/components/particles.h index df76b1806..0347527f6 100644 --- a/src/game/client/components/particles.h +++ b/src/game/client/components/particles.h @@ -95,5 +95,7 @@ private: CRenderGroup m_RenderTrail; CRenderGroup m_RenderExplosions; CRenderGroup m_RenderGeneral; + + bool ParticleIsVisibleOnScreen(const vec2 &CurPos, float CurSize); }; #endif