From 5db6e9c3d9f7a9dbf570b7601237356c3590bbf1 Mon Sep 17 00:00:00 2001 From: d1str4ught <> Date: Tue, 26 Aug 2025 03:18:09 +0200 Subject: [PATCH] particle batching almost good --- src/EffectLib/EffectInstance.cpp | 40 ++++-- src/EffectLib/EffectInstance.h | 11 +- src/EffectLib/EffectManager.cpp | 149 ++++++++++++++++------ src/EffectLib/EffectManager.h | 3 + src/EffectLib/EffectMeshInstance.cpp | 3 +- src/EffectLib/ParticleInstance.cpp | 142 +++++++++++++++++---- src/EffectLib/ParticleInstance.h | 21 ++- src/EffectLib/ParticleSystemData.cpp | 2 +- src/EffectLib/ParticleSystemInstance.cpp | 102 +++++++++++++-- src/EffectLib/ParticleSystemInstance.h | 13 +- src/EffectLib/Type.h | 2 +- src/UserInterface/Locale_inc.h | 1 + src/UserInterface/PythonNetworkStream.cpp | 10 +- 13 files changed, 386 insertions(+), 113 deletions(-) diff --git a/src/EffectLib/EffectInstance.cpp b/src/EffectLib/EffectInstance.cpp index 752632e..b456a3f 100644 --- a/src/EffectLib/EffectInstance.cpp +++ b/src/EffectLib/EffectInstance.cpp @@ -95,7 +95,7 @@ void CEffectInstance::OnUpdate() void CEffectInstance::OnRender() { - STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); + STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE); STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); @@ -106,19 +106,30 @@ void CEffectInstance::OnRender() STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); - ///// + STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); - STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); std::for_each(m_ParticleInstanceVector.begin(),m_ParticleInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render)); + + STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + std::for_each(m_MeshInstanceVector.begin(),m_MeshInstanceVector.end(),std::mem_fn(&CEffectElementBaseInstance::Render)); - ///// STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER); STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER); @@ -128,6 +139,7 @@ void CEffectInstance::OnRender() STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); ++ms_iRenderingEffectCount; } @@ -271,6 +283,16 @@ void CEffectInstance::Clear() __Initialize(); } +void CEffectInstance::BatchParticles() +{ + std::for_each(m_ParticleInstanceVector.begin(), m_ParticleInstanceVector.end(), std::mem_fn(&CParticleSystemInstance::BatchParticles)); +} + +void CEffectInstance::RenderMeshes() +{ + std::for_each(m_MeshInstanceVector.begin(), m_MeshInstanceVector.end(), std::mem_fn(&CEffectElementBaseInstance::Render)); +} + void CEffectInstance::__Initialize() { m_isAlive = FALSE; diff --git a/src/EffectLib/EffectInstance.h b/src/EffectLib/EffectInstance.h index cb1cdfd..e90fd44 100644 --- a/src/EffectLib/EffectInstance.h +++ b/src/EffectLib/EffectInstance.h @@ -1,8 +1,8 @@ #pragma once - -#include "../eterlib/GrpObjectInstance.h" -#include "../eterlib/Pool.h" -#include "../mileslib/Type.h" +#include "UserInterface/Locale_inc.h" +#include "Eterlib/GrpObjectInstance.h" +#include "Eterlib/Pool.h" +#include "Mileslib/Type.h" #include "EffectElementBaseInstance.h" #include "EffectData.h" @@ -55,6 +55,9 @@ class CEffectInstance : public CGraphicObjectInstance void OnRenderShadow() {} // Not used void OnRenderPCBlocker() {} // Not used + void BatchParticles(); + void RenderMeshes(); + protected: void __Initialize(); diff --git a/src/EffectLib/EffectManager.cpp b/src/EffectLib/EffectManager.cpp index 165ba3c..a9860aa 100644 --- a/src/EffectLib/EffectManager.cpp +++ b/src/EffectLib/EffectManager.cpp @@ -3,7 +3,7 @@ #include "../eterlib/StateManager.h" #include "EffectManager.h" - +extern std::unordered_map> g_particleVertexBatch; void CEffectManager::GetInfo(std::string* pstInfo) { @@ -82,50 +82,15 @@ void CEffectManager::Update() } } - -struct CEffectManager_LessEffectInstancePtrRenderOrder -{ - bool operator() (CEffectInstance* pkLeft, CEffectInstance* pkRight) - { - return pkLeft->LessRenderOrder(pkRight); - } -}; - -struct CEffectManager_FEffectInstanceRender -{ - inline void operator () (CEffectInstance * pkEftInst) - { - pkEftInst->Render(); - } -}; - void CEffectManager::Render() { STATEMANAGER.SetTexture(0, NULL); STATEMANAGER.SetTexture(1, NULL); - - if (m_isDisableSortRendering) - { - for (TEffectInstanceMap::iterator itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end();) - { - CEffectInstance * pEffectInstance = itor->second; - pEffectInstance->Render(); - ++itor; - } - } - else - { - static std::vector s_kVct_pkEftInstSort; - s_kVct_pkEftInstSort.clear(); - TEffectInstanceMap& rkMap_pkEftInstSrc=m_kEftInstMap; - TEffectInstanceMap::iterator i; - for (i=rkMap_pkEftInstSrc.begin(); i!=rkMap_pkEftInstSrc.end(); ++i) - s_kVct_pkEftInstSort.push_back(i->second); + g_particleVertexBatch.clear(); - std::sort(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_LessEffectInstancePtrRenderOrder()); - std::for_each(s_kVct_pkEftInstSort.begin(), s_kVct_pkEftInstSort.end(), CEffectManager_FEffectInstanceRender()); - } + __RenderParticles(); + __RenderMeshes(); } BOOL CEffectManager::RegisterEffect(const char * c_szFileName,bool isExistDelete,bool isNeedCache) @@ -439,6 +404,112 @@ void CEffectManager::__DestroyEffectDataMap() m_kEftDataMap.clear(); } +void CEffectManager::__RenderParticles() +{ + STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1); + + STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE); + STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); + + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + for (auto itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end(); ++itor) { + itor->second->BatchParticles(); + } + + for (auto& [pTexture, vtxBatch] : g_particleVertexBatch) { + if (vtxBatch.empty()) + continue; + + STATEMANAGER.SetTexture(0, pTexture); + STATEMANAGER.DrawPrimitiveUP( + D3DPT_TRIANGLELIST, + vtxBatch.size() / 3, + vtxBatch.data(), + sizeof(TPDTVertex)); + } + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP); + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG2); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP); + + STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER); + STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER); + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); + STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); +} + +void CEffectManager::__RenderMeshes() +{ + STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); + + STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_NONE); + STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_NONE); + + STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + STATEMANAGER.SaveRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + STATEMANAGER.SaveRenderState(D3DRS_ALPHATESTENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE); + STATEMANAGER.SaveRenderState(D3DRS_LIGHTING, FALSE); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + STATEMANAGER.SaveTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + for (auto itor = m_kEftInstMap.begin(); itor != m_kEftInstMap.end(); ++itor) { + itor->second->RenderMeshes(); + } + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLORARG2); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_COLOROP); + + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG1); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAARG2); + STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ALPHAOP); + + STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MINFILTER); + STATEMANAGER.RestoreSamplerState(0, D3DSAMP_MAGFILTER); + + STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_SRCBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_DESTBLEND); + STATEMANAGER.RestoreRenderState(D3DRS_ALPHATESTENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE); + STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE); + STATEMANAGER.RestoreRenderState(D3DRS_LIGHTING); +} + void CEffectManager::Destroy() { __DestroyEffectInstanceMap(); diff --git a/src/EffectLib/EffectManager.h b/src/EffectLib/EffectManager.h index a395a85..6f910f7 100644 --- a/src/EffectLib/EffectManager.h +++ b/src/EffectLib/EffectManager.h @@ -76,6 +76,9 @@ class CEffectManager : public CScreen, public CSingleton void __DestroyEffectCacheMap(); void __DestroyEffectDataMap(); + void __RenderParticles(); + void __RenderMeshes(); + protected: bool m_isDisableSortRendering; TEffectDataMap m_kEftDataMap; diff --git a/src/EffectLib/EffectMeshInstance.cpp b/src/EffectLib/EffectMeshInstance.cpp index e69cc69..8d076b3 100644 --- a/src/EffectLib/EffectMeshInstance.cpp +++ b/src/EffectLib/EffectMeshInstance.cpp @@ -167,8 +167,7 @@ void CEffectMeshInstance::OnRender() } Color.a = fAlpha * rFrameData.fVisibility; - STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, DWORD(Color)); - STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_TEX1); + STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, Color); STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLELIST, rFrameData.dwIndexCount/3, &rFrameData.PDTVertexVector[0], diff --git a/src/EffectLib/ParticleInstance.cpp b/src/EffectLib/ParticleInstance.cpp index c94cf9a..3ef0403 100644 --- a/src/EffectLib/ParticleInstance.cpp +++ b/src/EffectLib/ParticleInstance.cpp @@ -155,7 +155,13 @@ void CParticleInstance::UpdateColor(float time, float elapsedTime) if (m_pParticleProperty->m_TimeEventColor.empty()) return; - m_dcColor = GetTimeEventBlendValue(time, m_pParticleProperty->m_TimeEventColor); + m_Color = GetTimeEventBlendValue(time, m_pParticleProperty->m_TimeEventColor); + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + for (auto& vtx : m_ParticleMesh) { + vtx.diffuse = m_Color; + } +#endif } void CParticleInstance::UpdateGravity(float time, float elapsedTime) @@ -179,12 +185,9 @@ void CParticleInstance::UpdateAirResistance(float time, float elapsedTime) void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal) { -#ifdef WORLD_EDITOR +#ifndef ENABLE_BATCHED_PARTICLE_RENDERING STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color); -#else - STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_dcColor); #endif - ///// D3DXVECTOR3 v3Up; @@ -319,27 +322,60 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal) { D3DXVECTOR3 v3Position; D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal); - m_ParticleMesh[0].position = v3Position - v3Up + v3Cross; - m_ParticleMesh[1].position = v3Position - v3Up - v3Cross; - m_ParticleMesh[2].position = v3Position + v3Up + v3Cross; - m_ParticleMesh[3].position = v3Position + v3Up - v3Cross; + + D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left + D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right + D3DXVECTOR3 p2 = v3Position + v3Up + v3Cross; // top-left + D3DXVECTOR3 p3 = v3Position + v3Up - v3Cross; // top-right + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + // triangle 1: p0, p1, p2 + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + + // triangle 2: p2, p1, p3 + m_ParticleMesh[3].position = p2; + m_ParticleMesh[4].position = p1; + m_ParticleMesh[5].position = p3; +#else + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + m_ParticleMesh[3].position = p3; +#endif } else { - m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross; - m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross; - m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross; - m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross; + D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left + D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right + D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left + D3DXVECTOR3 p3 = m_v3Position + v3Up - v3Cross; // top-right + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + // triangle 1: p0, p1, p2 + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + + // triangle 2: p2, p1, p3 + m_ParticleMesh[3].position = p2; + m_ParticleMesh[4].position = p1; + m_ParticleMesh[5].position = p3; +#else + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + m_ParticleMesh[3].position = p3; +#endif } } void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation) { -#ifdef WORLD_EDITOR +#ifndef ENABLE_BATCHED_PARTICLE_RENDERING STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, m_Color); -#else - STATEMANAGER.SetRenderState(D3DRS_TEXTUREFACTOR, (DWORD)m_dcColor); #endif ///// @@ -474,17 +510,52 @@ void CParticleInstance::Transform(const D3DXMATRIX * c_matLocal, const float c_f { D3DXVECTOR3 v3Position; D3DXVec3TransformCoord(&v3Position, &m_v3Position, c_matLocal); - m_ParticleMesh[0].position = v3Position - v3Up + v3Cross; - m_ParticleMesh[1].position = v3Position - v3Up - v3Cross; - m_ParticleMesh[2].position = v3Position + v3Up + v3Cross; - m_ParticleMesh[3].position = v3Position + v3Up - v3Cross; + + D3DXVECTOR3 p0 = v3Position - v3Up + v3Cross; // bottom-left + D3DXVECTOR3 p1 = v3Position - v3Up - v3Cross; // bottom-right + D3DXVECTOR3 p2 = v3Position + v3Up + v3Cross; // top-left + D3DXVECTOR3 p3 = v3Position + v3Up - v3Cross; // top-right + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + // triangle 1: p0, p1, p2 + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + + // triangle 2: p2, p1, p3 + m_ParticleMesh[3].position = p2; + m_ParticleMesh[4].position = p1; + m_ParticleMesh[5].position = p3; +#else + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + m_ParticleMesh[3].position = p3; +#endif } else { - m_ParticleMesh[0].position = m_v3Position - v3Up + v3Cross; - m_ParticleMesh[1].position = m_v3Position - v3Up - v3Cross; - m_ParticleMesh[2].position = m_v3Position + v3Up + v3Cross; - m_ParticleMesh[3].position = m_v3Position + v3Up - v3Cross; + D3DXVECTOR3 p0 = m_v3Position - v3Up + v3Cross; // bottom-left + D3DXVECTOR3 p1 = m_v3Position - v3Up - v3Cross; // bottom-right + D3DXVECTOR3 p2 = m_v3Position + v3Up + v3Cross; // top-left + D3DXVECTOR3 p3 = m_v3Position + v3Up - v3Cross; // top-right + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + // triangle 1: p0, p1, p2 + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + + // triangle 2: p2, p1, p3 + m_ParticleMesh[3].position = p2; + m_ParticleMesh[4].position = p1; + m_ParticleMesh[5].position = p3; +#else + m_ParticleMesh[0].position = p0; + m_ParticleMesh[1].position = p1; + m_ParticleMesh[2].position = p2; + m_ParticleMesh[3].position = p3; +#endif } } @@ -500,20 +571,31 @@ void CParticleInstance::__Initialize() m_v3Velocity = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_v2Scale = D3DXVECTOR2(1.0f, 1.0f); -#ifdef WORLD_EDITOR m_Color = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f); -#else - m_dcColor.m_dwColor = 0xffffffff; + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + for (auto& vtx : m_ParticleMesh) { + vtx.diffuse = m_Color; + } #endif m_byFrameIndex = 0; m_rotationType = CParticleProperty::ROTATION_TYPE_NONE; m_fFrameTime = 0; +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + m_ParticleMesh[0].texCoord = D3DXVECTOR2(0.0f, 1.0f); + m_ParticleMesh[1].texCoord = D3DXVECTOR2(0.0f, 0.0f); + m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f); + m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 1.0f); + m_ParticleMesh[4].texCoord = D3DXVECTOR2(0.0f, 0.0f); + m_ParticleMesh[5].texCoord = D3DXVECTOR2(1.0f, 0.0f); +#else m_ParticleMesh[0].texCoord = D3DXVECTOR2(0.0f, 1.0f); m_ParticleMesh[1].texCoord = D3DXVECTOR2(0.0f, 0.0f); m_ParticleMesh[2].texCoord = D3DXVECTOR2(1.0f, 1.0f); m_ParticleMesh[3].texCoord = D3DXVECTOR2(1.0f, 0.0f); +#endif } CParticleInstance::CParticleInstance() @@ -526,7 +608,11 @@ CParticleInstance::~CParticleInstance() Destroy(); } -TPTVertex * CParticleInstance::GetParticleMeshPointer() +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING +const std::array& CParticleInstance::GetParticleMeshPointer() +#else +const std::array& CParticleInstance::GetParticleMeshPointer() +#endif { return m_ParticleMesh; } diff --git a/src/EffectLib/ParticleInstance.h b/src/EffectLib/ParticleInstance.h index df64cc9..dce2303 100644 --- a/src/EffectLib/ParticleInstance.h +++ b/src/EffectLib/ParticleInstance.h @@ -1,8 +1,11 @@ #pragma once +#include "UserInterface/Locale_inc.h" #include "Type.h" #include "Eterlib/GrpBase.h" #include "EterLib/Pool.h" +#include + class CParticleProperty; class CEmitterProperty; @@ -38,11 +41,8 @@ class CParticleInstance D3DXVECTOR2 m_v2Scale; float m_fRotation; -#ifdef WORLD_EDITOR + D3DXCOLOR m_Color; -#else - DWORDCOLOR m_dcColor; -#endif BYTE m_byTextureAnimationType; float m_fLastFrameTime; @@ -68,7 +68,11 @@ class CParticleInstance void Transform(const D3DXMATRIX * c_matLocal=NULL); void Transform(const D3DXMATRIX * c_matLocal, const float c_fZRotation); - TPTVertex * GetParticleMeshPointer(); +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + const std::array& GetParticleMeshPointer(); +#else + const std::array& GetParticleMeshPointer(); +#endif void DeleteThis(); @@ -76,7 +80,12 @@ class CParticleInstance protected: void __Initialize(); - TPTVertex m_ParticleMesh[4]; + +#ifdef ENABLE_BATCHED_PARTICLE_RENDERING + std::array m_ParticleMesh; +#else + std::array m_ParticleMesh; +#endif public: static CDynamicPool ms_kPool; diff --git a/src/EffectLib/ParticleSystemData.cpp b/src/EffectLib/ParticleSystemData.cpp index dedb566..1a67b9c 100644 --- a/src/EffectLib/ParticleSystemData.cpp +++ b/src/EffectLib/ParticleSystemData.cpp @@ -262,7 +262,7 @@ BOOL CParticleSystemData::OnLoadScript(CTextFileLoader & rTextFileLoader) c.g = fG; c.b = fB; c.a = fA; - t.m_Value.m_dwColor = /*(DWORD)*/ (DWORD)c; + t.m_Value = c; m_ParticleProperty.m_TimeEventColor.push_back(t); } } diff --git a/src/EffectLib/ParticleSystemInstance.cpp b/src/EffectLib/ParticleSystemInstance.cpp index 4c04668..76e79d6 100644 --- a/src/EffectLib/ParticleSystemInstance.cpp +++ b/src/EffectLib/ParticleSystemInstance.cpp @@ -5,6 +5,8 @@ #include "ParticleSystemInstance.h" #include "ParticleInstance.h" +std::unordered_map> g_particleVertexBatch; + CDynamicPool CParticleSystemInstance::ms_kPool; void CParticleSystemInstance::DestroySystem() @@ -254,7 +256,7 @@ void CParticleSystemInstance::CreateParticles(float fElapsedTime) pInstance->m_Color.b = m_pParticleProperty->m_TimeEventColorBlue.front().m_Value; pInstance->m_Color.a = m_pParticleProperty->m_TimeEventAlpha.front().m_Value; #else - pInstance->m_dcColor = m_pParticleProperty->m_TimeEventColor.front().m_Value; + pInstance->m_Color = m_pParticleProperty->m_TimeEventColor.front().m_Value; #endif } @@ -348,13 +350,16 @@ namespace NParticleRenderer { } - inline void operator () (CParticleInstance * pInstance) + inline void operator () (CParticleInstance * pInstance, LPDIRECT3DTEXTURE9 pTexture) { + auto& vtxBatch = g_particleVertexBatch[pTexture]; + const auto& particleMesh = pInstance->GetParticleMeshPointer(); + pInstance->Transform(pmat,D3DXToRadian(-30.0f)); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); pInstance->Transform(pmat,D3DXToRadian(+30.0f)); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); } }; @@ -366,23 +371,31 @@ namespace NParticleRenderer { } - inline void operator () (CParticleInstance * pInstance) + inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture) { + auto& vtxBatch = g_particleVertexBatch[pTexture]; + const auto& particleMesh = pInstance->GetParticleMeshPointer(); + pInstance->Transform(pmat); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); + pInstance->Transform(pmat,D3DXToRadian(-60.0f)); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); + pInstance->Transform(pmat,D3DXToRadian(+60.0f)); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); } }; struct NormalRenderer { - inline void operator () (CParticleInstance * pInstance) + inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture) { + auto& vtxBatch = g_particleVertexBatch[pTexture]; + const auto& particleMesh = pInstance->GetParticleMeshPointer(); + pInstance->Transform(); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); } }; struct AttachRenderer @@ -393,20 +406,85 @@ namespace NParticleRenderer { } - inline void operator () (CParticleInstance * pInstance) + inline void operator () (CParticleInstance* pInstance, LPDIRECT3DTEXTURE9 pTexture) { + auto& vtxBatch = g_particleVertexBatch[pTexture]; + const auto& particleMesh = pInstance->GetParticleMeshPointer(); + pInstance->Transform(pmat); - STATEMANAGER.DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, pInstance->GetParticleMeshPointer(), sizeof(TPTVertex)); + vtxBatch.insert(vtxBatch.end(), particleMesh.begin(), particleMesh.end()); } }; } void CParticleSystemInstance::OnRender() { + g_particleVertexBatch.clear(); + CScreen::Identity(); STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, m_pParticleProperty->m_bySrcBlendType); STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, m_pParticleProperty->m_byDestBlendType); STATEMANAGER.SetTextureStageState(0,D3DTSS_COLOROP,m_pParticleProperty->m_byColorOperationType); + + if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE) + { + if (!m_pParticleProperty->m_bAttachFlag) + { + auto obj = NParticleRenderer::NormalRenderer(); + ForEachParticleRendering(obj); + } + else + { + auto obj = NParticleRenderer::AttachRenderer(mc_pmatLocal); + ForEachParticleRendering(obj); + } + } + else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_2FACE) + { + if (!m_pParticleProperty->m_bAttachFlag) + { + auto obj = NParticleRenderer::TwoSideRenderer(); + ForEachParticleRendering(obj); + } + else + { + auto obj = NParticleRenderer::TwoSideRenderer(mc_pmatLocal); + ForEachParticleRendering(obj); + } + } + else if (m_pParticleProperty->m_byBillboardType == BILLBOARD_TYPE_3FACE) + { + if (!m_pParticleProperty->m_bAttachFlag) + { + auto obj = NParticleRenderer::ThreeSideRenderer(); + ForEachParticleRendering(obj); + } + else + { + auto obj = NParticleRenderer::ThreeSideRenderer(mc_pmatLocal); + ForEachParticleRendering(obj); + } + } + + for (auto& [pTexture, vtxBatch] : g_particleVertexBatch) { + if (vtxBatch.empty()) + continue; + + STATEMANAGER.SetTexture(0, pTexture); + STATEMANAGER.DrawPrimitiveUP( + D3DPT_TRIANGLELIST, + vtxBatch.size() / 3, + vtxBatch.data(), + sizeof(TPDTVertex)); + } +} + +void CParticleSystemInstance::BatchParticles() +{ + CScreen::Identity(); + STATEMANAGER.SetRenderState(D3DRS_SRCBLEND, m_pParticleProperty->m_bySrcBlendType); + STATEMANAGER.SetRenderState(D3DRS_DESTBLEND, m_pParticleProperty->m_byDestBlendType); + STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, m_pParticleProperty->m_byColorOperationType); if (m_pParticleProperty->m_byBillboardType < BILLBOARD_TYPE_2FACE) { if (!m_pParticleProperty->m_bAttachFlag) diff --git a/src/EffectLib/ParticleSystemInstance.h b/src/EffectLib/ParticleSystemInstance.h index 720a327..37d37c4 100644 --- a/src/EffectLib/ParticleSystemInstance.h +++ b/src/EffectLib/ParticleSystemInstance.h @@ -1,12 +1,12 @@ #pragma once - +#include "UserInterface/Locale_inc.h" #include "EffectElementBaseInstance.h" #include "ParticleInstance.h" #include "ParticleProperty.h" -#include "../eterlib/GrpScreen.h" -#include "../eterlib/StateManager.h" -#include "../eterLib/GrpImageInstance.h" +#include "Eterlib/GrpScreen.h" +#include "Eterlib/StateManager.h" +#include "EterLib/GrpImageInstance.h" #include "EmitterProperty.h" class CParticleSystemInstance : public CEffectElementBaseInstance @@ -26,13 +26,12 @@ class CParticleSystemInstance : public CEffectElementBaseInstance DWORD dwFrameIndex; for(dwFrameIndex=0; dwFrameIndexGetTextureReference().GetD3DTexture()); TParticleInstanceList::iterator itor = m_ParticleInstanceListVector[dwFrameIndex].begin(); for (; itor != m_ParticleInstanceListVector[dwFrameIndex].end(); ++itor) { if (!InFrustum(*itor)) return; - FunObj(*itor); + FunObj(*itor, m_kVct_pkImgInst[dwFrameIndex]->GetTextureReference().GetD3DTexture()); } } } @@ -58,6 +57,8 @@ class CParticleSystemInstance : public CEffectElementBaseInstance DWORD GetEmissionCount(); + void BatchParticles(); + protected: void OnInitialize(); void OnDestroy(); diff --git a/src/EffectLib/Type.h b/src/EffectLib/Type.h index a399165..ddb4ee3 100644 --- a/src/EffectLib/Type.h +++ b/src/EffectLib/Type.h @@ -190,7 +190,7 @@ typedef CTimeEvent TTimeEventTypeShort; typedef CTimeEvent TTimeEventTypeFloat; typedef CTimeEvent TTimeEventTypeWord; typedef CTimeEvent TTimeEventTypeDoubleWord; -typedef CTimeEvent TTimeEventTypeColor; +typedef CTimeEvent TTimeEventTypeColor; typedef CTimeEvent TTimeEventTypeVector2; typedef CTimeEvent TTimeEventTypeVector3; diff --git a/src/UserInterface/Locale_inc.h b/src/UserInterface/Locale_inc.h index 0f4007d..ed13429 100644 --- a/src/UserInterface/Locale_inc.h +++ b/src/UserInterface/Locale_inc.h @@ -4,3 +4,4 @@ #define ENABLE_DRAGON_SOUL_SYSTEM #define ENABLE_NEW_EQUIPMENT_SYSTEM //#define ENABLE_DISCORD_RPC +#define ENABLE_BATCHED_PARTICLE_RENDERING diff --git a/src/UserInterface/PythonNetworkStream.cpp b/src/UserInterface/PythonNetworkStream.cpp index 424879a..1c2f301 100644 --- a/src/UserInterface/PythonNetworkStream.cpp +++ b/src/UserInterface/PythonNetworkStream.cpp @@ -532,7 +532,7 @@ bool CPythonNetworkStream::CheckPacket(TPacketHeader * pRetHeader) if (!s_packetHeaderMap.Get(header, &PacketType)) { - TraceError("Unknown packet header: %d, last: %d %d", header, g_iLastPacket[0], g_iLastPacket[1]); + LogBoxf("Unknown packet header: %d, last: %d %d", header, g_iLastPacket[0], g_iLastPacket[1]); ClearRecvBuffer(); PostQuitMessage(0); @@ -559,10 +559,10 @@ bool CPythonNetworkStream::CheckPacket(TPacketHeader * pRetHeader) { if (!Peek(PacketType.iPacketSize)) { - //Tracef("Not enough packet size: header %d packet size: %d, recv buffer size: %d", - // header, - // PacketType.iPacketSize, - // GetRecvBufferSize()); + Tracef("Not enough packet size: header %d packet size: %d, recv buffer size: %d", + header, + PacketType.iPacketSize, + GetRecvBufferSize()); return false; } }