diff --git a/DataSpec/DNACommon/Tweaks/ITweakGuiColors.hpp b/DataSpec/DNACommon/Tweaks/ITweakGuiColors.hpp index 53eb3002a..85bfda64c 100644 --- a/DataSpec/DNACommon/Tweaks/ITweakGuiColors.hpp +++ b/DataSpec/DNACommon/Tweaks/ITweakGuiColors.hpp @@ -22,6 +22,7 @@ struct ITweakGuiColors : BigYAML const zeus::CColor& shadow; }; + virtual const zeus::CColor& GetInvPhazonSuitFilterMod() const=0; virtual const zeus::CColor& GetRadarStuffColor() const=0; virtual const zeus::CColor& GetRadarPlayerPaintColor() const=0; virtual const zeus::CColor& GetRadarEnemyPaintColor() const=0; diff --git a/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp b/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp index 30aa11fb4..be9be1120 100644 --- a/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp +++ b/DataSpec/DNAMP1/Tweaks/CTweakGuiColors.hpp @@ -10,7 +10,7 @@ namespace DNAMP1 struct CTweakGuiColors : public ITweakGuiColors { DECL_YAML - DNAColor x4_; + DNAColor x4_invPhazonSuitFilterMod; DNAColor x8_radarStuffColor; DNAColor xc_radarPlayerPaintColor; DNAColor x10_radarEnemyPaintColor; @@ -140,6 +140,7 @@ struct CTweakGuiColors : public ITweakGuiColors CTweakGuiColors() = default; CTweakGuiColors(athena::io::IStreamReader& r) { this->read(r); } + const zeus::CColor& GetInvPhazonSuitFilterMod() const { return x4_invPhazonSuitFilterMod; } const zeus::CColor& GetRadarStuffColor() const { return x8_radarStuffColor; } const zeus::CColor& GetRadarPlayerPaintColor() const { return xc_radarPlayerPaintColor; } const zeus::CColor& GetRadarEnemyPaintColor() const { return x10_radarEnemyPaintColor; } diff --git a/Runtime/Character/CAnimData.cpp b/Runtime/Character/CAnimData.cpp index bb0affbce..c5c6f33be 100644 --- a/Runtime/Character/CAnimData.cpp +++ b/Runtime/Character/CAnimData.cpp @@ -813,4 +813,10 @@ zeus::CAABox CAnimData::GetBoundingBox() const return search->second; } +void CAnimData::SubstituteModelData(const TCachedToken& model) +{ + xd8_modelData = model; + x108_aabb = xd8_modelData->GetModel()->GetAABB(); +} + } diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index 5c06144cb..d149eab13 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -10,6 +10,7 @@ #include "CAdditiveAnimPlayback.hpp" #include "CCharLayoutInfo.hpp" #include "CAnimPlaybackParms.hpp" +#include "IAnimReader.hpp" #include enum class EUserEventType @@ -219,6 +220,7 @@ public: CSegId GetLocatorSegId(const std::string& name) const; zeus::CAABox GetBoundingBox(const zeus::CTransform& xf) const; zeus::CAABox GetBoundingBox() const; + void SubstituteModelData(const TCachedToken& model); static void FreeCache(); static void InitializeCache(); const CHierarchyPoseBuilder& GetPoseBuilder() const { return x2fc_poseBuilder; } diff --git a/Runtime/Character/CModelData.cpp b/Runtime/Character/CModelData.cpp index 50365758d..d6297510d 100644 --- a/Runtime/Character/CModelData.cpp +++ b/Runtime/Character/CModelData.cpp @@ -379,4 +379,54 @@ void CModelData::Render(EWhichModel which, const zeus::CTransform& xf, } } +void CModelData::InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, + const zeus::CColor& alphaColor, const zeus::CColor& additiveColor) +{ + CGraphics::SetModelMatrix(xf * zeus::CTransform::Scale(x0_scale)); + if (x10_animData) + { + CSkinnedModel& model = PickAnimatedModel(which); + model.GetModelInst()->DisableAllLights(); + CModelFlags flags = {}; + + /* Z-prime */ + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x10_animData->Render(model, flags, {}, nullptr); + + /* Normal Blended */ + lights->ActivateLights(*model.GetModelInst()); + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = alphaColor; + x10_animData->Render(model, flags, {}, nullptr); + + /* Selection Additive */ + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = additiveColor; + x10_animData->Render(model, flags, {}, nullptr); + } + else + { + CBooModel& model = *PickStaticModel(which); + model.DisableAllLights(); + CModelFlags flags = {}; + + /* Z-prime */ + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + model.Draw(flags, nullptr, nullptr); + + /* Normal Blended */ + lights->ActivateLights(model); + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = alphaColor; + model.Draw(flags, nullptr, nullptr); + + /* Selection Additive */ + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = additiveColor; + model.Draw(flags, nullptr, nullptr); + } +} + } diff --git a/Runtime/Character/CModelData.hpp b/Runtime/Character/CModelData.hpp index f866974a1..6f69afd0f 100644 --- a/Runtime/Character/CModelData.hpp +++ b/Runtime/Character/CModelData.hpp @@ -139,6 +139,9 @@ public: void Render(EWhichModel, const zeus::CTransform& xf, const CActorLights* lights, const CModelFlags& drawFlags); + void InvSuitDraw(EWhichModel which, const zeus::CTransform& xf, const CActorLights* lights, + const zeus::CColor& color0, const zeus::CColor& color1); + CAnimData* AnimationData() { return x10_animData.get(); } const CAnimData* GetAnimationData() const { return x10_animData.get(); } const TLockedToken& GetNormalModel() const { return x1c_normalModel; } diff --git a/Runtime/Graphics/CBooRenderer.cpp b/Runtime/Graphics/CBooRenderer.cpp index 67aa4704a..7b46d31fa 100644 --- a/Runtime/Graphics/CBooRenderer.cpp +++ b/Runtime/Graphics/CBooRenderer.cpp @@ -865,6 +865,14 @@ void CBooRenderer::DrawStaticGeometry(int modelCount, int mask, int targetMask) DrawSortedGeometry(modelCount, mask, targetMask); } +void CBooRenderer::DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) +{ + model.GetInstance().DrawFlat(unsortedOnly ? + CBooModel::ESurfaceSelection::UnsortedOnly : + CBooModel::ESurfaceSelection::All, + flags.m_extendedShader); +} + void CBooRenderer::PostRenderFogs() { for (const auto& warp : x2c4_spaceWarps) @@ -974,6 +982,14 @@ void CBooRenderer::BeginScene() CGraphics::SetViewport(0, 0, g_Viewport.x8_width, g_Viewport.xc_height); CGraphics::SetPerspective(75.f, CGraphics::g_ProjAspect, 1.f, 4096.f); CGraphics::SetModelMatrix(zeus::CTransform::Identity()); +#if 0 + if (x310_phazonSuitMaskCountdown != 0) + { + --x310_phazonSuitMaskCountdown; + if (x310_phazonSuitMaskCountdown == 0) + x314_phazonSuitMask.reset(); + } +#endif x318_27_currentRGBA6 = x318_26_requestRGBA6; if (!x318_31_persistRGBA6) x318_26_requestRGBA6 = false; @@ -1175,6 +1191,53 @@ void CBooRenderer::SetWorldLightFadeLevel(float level) x2fc_tevReg1Color = zeus::CColor(level, level, level, 1.f); } +void CBooRenderer::ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/ + const CTexture& indTex, const zeus::CColor& modColor, + float scale, float offX, float offY) +{ + m_phazonSuitFilter.draw(modColor, scale, offX * scale, offY * scale); +} + +void CBooRenderer::ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/) +{ + m_phazonSuitFilter.draw(modColor, 0.f, 0.f, 0.f); +} + +void CBooRenderer::DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken& indTex) +{ + m_phazonSuitFilter.drawBlurPasses(blurRadius, indTex.IsLoaded() ? indTex.GetObj() : nullptr); +} + +void CBooRenderer::DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken& indTex, + const zeus::CColor& indirectMod, float blurRadius, + float scale, float offX, float offY) +{ + /* Indirect background already in binding 0 */ + + /* Resolve alpha channel of just-drawn phazon suit into binding 1 */ + SClipScreenRect rect; + rect.x4_left = g_Viewport.x0_left; + rect.x8_top = g_Viewport.x4_top; + rect.xc_width = g_Viewport.x8_width; + rect.x10_height = g_Viewport.xc_height; + CGraphics::ResolveSpareTexture(rect, 1); + + /* Perform blur filter and resolve into binding 2 */ + DoPhazonSuitIndirectAlphaBlur(blurRadius, indTex); + + /* Draw effect; subtracting binding 1 from binding 2 for the filter 'cutout' */ + if (indTex && indTex.IsLoaded()) + ReallyDrawPhazonSuitIndirectEffect(zeus::CColor::skWhite, *indTex, indirectMod, scale, offX, offY); + else + ReallyDrawPhazonSuitEffect(nonIndirectMod); +} + +void CBooRenderer::AllocatePhazonSuitMaskTexture() +{ + x318_26_requestRGBA6 = true; + x310_phazonSuitMaskCountdown = 2; +} + void CBooRenderer::FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const { u32 bitmapWords = 0; diff --git a/Runtime/Graphics/CBooRenderer.hpp b/Runtime/Graphics/CBooRenderer.hpp index 7f99080ce..a330c0c57 100644 --- a/Runtime/Graphics/CBooRenderer.hpp +++ b/Runtime/Graphics/CBooRenderer.hpp @@ -10,6 +10,7 @@ #include "Shaders/CSpaceWarpFilter.hpp" #include "Shaders/CFogVolumePlaneShader.hpp" #include "Shaders/CFogVolumeFilter.hpp" +#include "Shaders/CPhazonSuitFilter.hpp" #include "CRandom16.hpp" #include "CPVSVisSet.hpp" #include "zeus/CRectangle.hpp" @@ -149,6 +150,10 @@ class CBooRenderer : public IRenderer std::vector x300_dynamicLights; + u32 x310_phazonSuitMaskCountdown = 0; + //std::unique_ptr x314_phazonSuitMask; + CPhazonSuitFilter m_phazonSuitFilter; + union { struct @@ -182,6 +187,12 @@ class CBooRenderer : public IRenderer CFogVolumePlaneShader* fvs); void SetupRendererStates() const; + void ReallyDrawPhazonSuitIndirectEffect(const zeus::CColor& vertColor, /*const CTexture& maskTex,*/ + const CTexture& indTex, const zeus::CColor& modColor, + float scale, float offX, float offY); + void ReallyDrawPhazonSuitEffect(const zeus::CColor& modColor /*, const CTexture& maskTex*/); + void DoPhazonSuitIndirectAlphaBlur(float blurRadius /*, float f2*/, const TLockedToken& indTex); + public: CBooRenderer(IObjectStore& store, IFactory& resFac); @@ -196,6 +207,7 @@ public: void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask); void DrawSortedGeometry(int areaIdx, int mask, int targetMask); void DrawStaticGeometry(int areaIdx, int mask, int targetMask); + void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly); void PostRenderFogs(); void AddParticleGen(const CParticleGen&); void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int); @@ -248,6 +260,10 @@ public: void PrepareDynamicLights(const std::vector& lights); void SetWorldLightMultiplyColor(const zeus::CColor& color); void SetWorldLightFadeLevel(float level); + void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken& indTex, + const zeus::CColor& indirectMod, float blurRadius, + float indScale, float indOffX, float indOffY); + void AllocatePhazonSuitMaskTexture(); void ReallyRenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const CModel* model, const CSkinnedModel* sModel); diff --git a/Runtime/Graphics/CMakeLists.txt b/Runtime/Graphics/CMakeLists.txt index 625a2ed99..d3070af1d 100644 --- a/Runtime/Graphics/CMakeLists.txt +++ b/Runtime/Graphics/CMakeLists.txt @@ -14,7 +14,8 @@ if(WIN32) Shaders/CFogVolumeFilterHLSL.cpp Shaders/CEnergyBarShaderHLSL.cpp Shaders/CRadarPaintShaderHLSL.cpp - Shaders/CMapSurfaceShaderHLSL.cpp) + Shaders/CMapSurfaceShaderHLSL.cpp + Shaders/CPhazonSuitFilterHLSL.cpp) elseif(BOO_HAS_METAL) set(PLAT_SRCS Shaders/CLineRendererShadersMetal.cpp @@ -31,7 +32,8 @@ elseif(BOO_HAS_METAL) Shaders/CFogVolumeFilterMetal.cpp Shaders/CEnergyBarShaderMetal.cpp Shaders/CRadarPaintShaderMetal.cpp - Shaders/CMapSurfaceShaderMetal.cpp) + Shaders/CMapSurfaceShaderMetal.cpp + Shaders/CPhazonSuitFilterMetal.cpp) endif() set(GRAPHICS_SOURCES @@ -70,6 +72,7 @@ set(GRAPHICS_SOURCES Shaders/CEnergyBarShader.hpp Shaders/CEnergyBarShader.cpp Shaders/CEnergyBarShaderGLSL.cpp Shaders/CRadarPaintShader.hpp Shaders/CRadarPaintShader.cpp Shaders/CRadarPaintShaderGLSL.cpp Shaders/CMapSurfaceShader.hpp Shaders/CMapSurfaceShader.cpp Shaders/CMapSurfaceShaderGLSL.cpp + Shaders/CPhazonSuitFilter.hpp Shaders/CPhazonSuitFilter.cpp Shaders/CPhazonSuitFilterGLSL.cpp ${PLAT_SRCS}) runtime_add_list(Graphics GRAPHICS_SOURCES) diff --git a/Runtime/Graphics/CModel.hpp b/Runtime/Graphics/CModel.hpp index 56a73ce69..b0b6f77f7 100644 --- a/Runtime/Graphics/CModel.hpp +++ b/Runtime/Graphics/CModel.hpp @@ -23,7 +23,7 @@ class CModel; struct CModelFlags { - u8 x0_blendMode = 0; /* Blend state 3/5 enable additive */ + u8 x0_blendMode = 0; /* >6: additive, >4: blend, else opaque */ u8 x1_matSetIdx = 0; EExtendedShader m_extendedShader = EExtendedShader::Flat; u16 x2_flags = 0; /* Flags */ @@ -36,6 +36,8 @@ struct CModelFlags : x0_blendMode(blendMode), x1_matSetIdx(shadIdx), x2_flags(flags), x4_color(col) {} /* Flags + 0x1: depth equal + 0x2: depth update 0x4: render without texture lock 0x8: depth greater 0x10: depth non-inclusive @@ -79,6 +81,13 @@ public: void UnlockTextures(); }; + enum class ESurfaceSelection + { + UnsortedOnly, + SortedOnly, + All + }; + private: CBooModel* m_next = nullptr; CBooModel* m_prev = nullptr; @@ -148,6 +157,7 @@ public: bool IsOpaque() const {return x3c_firstSortedSurface == nullptr;} void ActivateLights(const std::vector& lights); + void DisableAllLights(); void RemapMaterialData(SShader& shader); bool TryLockTextures() const; void UnlockTextures() const; @@ -165,6 +175,8 @@ public: void Draw(const CModelFlags& flags, const CSkinRules* cskr, const CPoseAsTransforms* pose) const; + void DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const; + const MaterialSet::Material& GetMaterialByIndex(int idx) const { @@ -217,6 +229,7 @@ public: void DrawUnsortedParts(const CModelFlags& flags) const; void Draw(const CModelFlags& flags) const; bool IsLoaded(int shaderIdx) const; + void Touch(int shaderIdx) { x28_modelInst->Touch(shaderIdx); } const zeus::CAABox& GetAABB() const {return m_aabb;} CBooModel& GetInstance() {return *x28_modelInst;} diff --git a/Runtime/Graphics/CModelBoo.cpp b/Runtime/Graphics/CModelBoo.cpp index 0956acbcf..490572c5f 100644 --- a/Runtime/Graphics/CModelBoo.cpp +++ b/Runtime/Graphics/CModelBoo.cpp @@ -425,6 +425,19 @@ void CBooModel::ActivateLights(const std::vector& lights) } } +void CBooModel::DisableAllLights() +{ + m_lightingData.ambient = zeus::CColor::skBlack; + + for (size_t curLight = 0 ; curLight(this)->x40_24_texturesLoaded = false; } +void CBooModel::DrawFlat(ESurfaceSelection sel, EExtendedShader extendedIdx) const +{ + const CBooSurface* surf; + CModelFlags flags = {}; + flags.m_extendedShader = extendedIdx; + + if (sel != ESurfaceSelection::SortedOnly) + { + surf = x38_firstUnsortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } + } + + if (sel != ESurfaceSelection::UnsortedOnly) + { + surf = x3c_firstSortedSurface; + while (surf) + { + DrawSurface(*surf, flags); + surf = surf->m_next; + } + } +} + void CBooModel::DrawAlphaSurfaces(const CModelFlags& flags) const { const CBooSurface* surf = x3c_firstSortedSurface; diff --git a/Runtime/Graphics/IRenderer.hpp b/Runtime/Graphics/IRenderer.hpp index 726379fe5..1ddfb8d09 100644 --- a/Runtime/Graphics/IRenderer.hpp +++ b/Runtime/Graphics/IRenderer.hpp @@ -21,6 +21,7 @@ class CModel; class CSkinnedModel; class CPVSVisSet; struct CAreaRenderOctTree; +class CModelFlags; class IRenderer { @@ -51,6 +52,7 @@ public: virtual void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask)=0; virtual void DrawSortedGeometry(int areaIdx, int mask, int targetMask)=0; virtual void DrawStaticGeometry(int areaIdx, int mask, int targetMask)=0; + virtual void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly)=0; virtual void PostRenderFogs()=0; virtual void AddParticleGen(const CParticleGen&)=0; virtual void AddPlaneObject(const void*, const zeus::CAABox&, const zeus::CPlane&, int)=0; diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp b/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp new file mode 100644 index 000000000..e9a4446d1 --- /dev/null +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilter.cpp @@ -0,0 +1,96 @@ +#include "CPhazonSuitFilter.hpp" + +namespace urde +{ + +void CPhazonSuitFilter::drawBlurPasses(float radius, const CTexture* indTex) +{ + if (!m_dataBind || indTex != m_indTex) + { + m_indTex = indTex; + m_gfxTok = CGraphics::CommitResources( + [this](boo::IGraphicsDataFactory::Context& ctx) + { + m_uniBufBlurX = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); + m_uniBufBlurY = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f), 1); + m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(zeus::CVector4f) * 2, 1); + + struct BlurVert + { + zeus::CVector3f pos; + zeus::CVector2f uv; + } blurVerts[4] = + { + {{-1.f, 1.f, 0.f}, {0.f, 1.f}}, + {{-1.f, -1.f, 0.f}, {0.f, 0.f}}, + {{ 1.f, 1.f, 0.f}, {1.f, 1.f}}, + {{ 1.f, -1.f, 0.f}, {1.f, 0.f}} + }; + m_blurVbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, blurVerts, sizeof(BlurVert), 4); + + struct Vert + { + zeus::CVector3f pos; + zeus::CVector2f screenUv; + zeus::CVector2f indUv; + zeus::CVector2f maskUv; + } verts[4] = + { + {{-1.f, 1.f, 0.f}, {0.01f, 0.99f}, {0.f, 1.f}, {0.f, 1.f}}, + {{-1.f, -1.f, 0.f}, {0.01f, 0.01f}, {0.f, 1.f}, {0.f, 1.f}}, + {{ 1.f, 1.f, 0.f}, {0.99f, 0.99f}, {0.f, 1.f}, {0.f, 1.f}}, + {{ 1.f, -1.f, 0.f}, {0.99f, 0.01f}, {0.f, 1.f}, {0.f, 1.f}} + }; + m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, verts, sizeof(Vert), 4); + + m_dataBind = TShader::BuildShaderDataBinding(ctx, *this); + return true; + }); + } + + SClipScreenRect rect; + rect.x4_left = g_Viewport.x0_left; + rect.x8_top = g_Viewport.x4_top; + rect.xc_width = g_Viewport.x8_width; + rect.x10_height = g_Viewport.xc_height; + + /* X Pass */ + zeus::CVector4f blurDir = zeus::CVector4f{2.f * radius / g_Viewport.x8_width, 0.f, 0.f, 0.f}; + m_uniBufBlurX->load(&blurDir, sizeof(zeus::CVector4f)); + + CGraphics::SetShaderDataBinding(m_dataBindBlurX); + CGraphics::DrawArray(0, 4); + CGraphics::ResolveSpareTexture(rect, 2); + + /* Y Pass */ + blurDir = zeus::CVector4f{0.f, 2.f * radius / g_Viewport.xc_height, 0.f, 0.f}; + m_uniBufBlurY->load(&blurDir, sizeof(zeus::CVector4f)); + + CGraphics::SetShaderDataBinding(m_dataBindBlurY); + CGraphics::DrawArray(0, 4); + CGraphics::ResolveSpareTexture(rect, 2); +} + +void CPhazonSuitFilter::draw(const zeus::CColor& color, + float indScale, float indOffX, float indOffY) +{ + struct Uniform + { + zeus::CColor color; + zeus::CVector4f indScaleOff; + } uniform = + { + color, + zeus::CVector4f(indScale, indScale, indOffX, indOffY) + }; + + m_uniBuf->load(&uniform, sizeof(Uniform)); + CGraphics::SetShaderDataBinding(m_dataBind); + CGraphics::DrawArray(0, 4); +} + +void CPhazonSuitFilter::Shutdown() {} + +URDE_SPECIALIZE_SHADER(CPhazonSuitFilter) + +} diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp b/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp new file mode 100644 index 000000000..c1a43829e --- /dev/null +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp @@ -0,0 +1,39 @@ +#ifndef __URDE_CPHAZONSUITFILTER_HPP__ +#define __URDE_CPHAZONSUITFILTER_HPP__ + +#include "TShader.hpp" + +namespace urde +{ +class CTexture; + +class CPhazonSuitFilter +{ + friend struct CPhazonSuitFilterGLDataBindingFactory; + friend struct CPhazonSuitFilterVulkanDataBindingFactory; + friend struct CPhazonSuitFilterMetalDataBindingFactory; + friend struct CPhazonSuitFilterD3DDataBindingFactory; + + boo::GraphicsDataToken m_gfxTok; + boo::IGraphicsBufferD* m_uniBufBlurX; + boo::IGraphicsBufferD* m_uniBufBlurY; + boo::IGraphicsBufferD* m_uniBuf; + boo::IGraphicsBufferS* m_blurVbo; + boo::IGraphicsBufferS* m_vbo; + const CTexture* m_indTex = nullptr; + boo::IShaderDataBinding* m_dataBindBlurX = nullptr; + boo::IShaderDataBinding* m_dataBindBlurY = nullptr; + boo::IShaderDataBinding* m_dataBind = nullptr; + +public: + void drawBlurPasses(float radius, const CTexture* indTex); + void draw(const zeus::CColor& color, + float indScale, float indOffX, float indOffY); + + using _CLS = CPhazonSuitFilter; +#include "TShaderDecl.hpp" +}; + +} + +#endif // __URDE_CPHAZONSUITFILTER_HPP__ diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilterGLSL.cpp b/Runtime/Graphics/Shaders/CPhazonSuitFilterGLSL.cpp new file mode 100644 index 000000000..38ba01299 --- /dev/null +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilterGLSL.cpp @@ -0,0 +1,340 @@ +#include "CPhazonSuitFilter.hpp" +#include "TShader.hpp" +#include "Graphics/CTexture.hpp" + +namespace urde +{ + +static const char* VS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"layout(location=0) in vec4 posIn;\n" +"layout(location=1) in vec4 screenUvIn;\n" +"layout(location=2) in vec4 indUvIn;\n" +"layout(location=3) in vec4 maskUvIn;\n" +"\n" +"UBINDING0 uniform PhazonSuitUniform\n" +"{\n" +" vec4 color;\n" +" vec4 indScaleOff;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec4 indScaleOff;\n" +" vec2 screenUv;\n" +" vec2 indUv;\n" +" vec2 maskUv;\n" +"};\n" +"\n" +"SBINDING(0) out VertToFrag vtf;\n" +"void main()\n" +"{\n" +" vtf.color = color;\n" +" vtf.indScaleOff = indScaleOff;\n" +" vtf.screenUv = screenUvIn.xy;\n" +" vtf.indUv = indUvIn.xy;\n" +" vtf.maskUv = maskUvIn.xy;\n" +" gl_Position = vec4(posIn.xyz, 1.0);\n" +"}\n"; + +static const char* IndFS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec4 indScaleOff;\n" +" vec2 screenUv;\n" +" vec2 indUv;\n" +" vec2 maskUv;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D screenTex;\n" +"TBINDING1 uniform sampler2D indTex;\n" +"TBINDING2 uniform sampler2D maskTex;\n" +"TBINDING3 uniform sampler2D maskTexBlur;\n" +"void main()\n" +"{\n" +" vec2 indUv = (texture(indTex, vtf.indUv).rg - vec2(0.5, 0.5)) * \n" +" vtf.indScaleOff.xy + vtf.indScaleOff.zw;\n" +" colorOut = vtf.color * texture(screenTex, indUv + vtf.screenUv) * \n" +" (texture(maskTexBlur, vtf.maskUv).a - texture(maskTex, vtf.maskUv).a);\n" +"}\n"; + +static const char* FS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec4 color;\n" +" vec4 indScaleOff;\n" +" vec2 screenUv;\n" +" vec2 indUv;\n" +" vec2 maskUv;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D screenTex;\n" +"TBINDING1 uniform sampler2D maskTex;\n" +"TBINDING2 uniform sampler2D maskTexBlur;\n" +"void main()\n" +"{\n" +" colorOut = vtf.color * texture(screenTex, vtf.screenUv) * \n" +" (texture(maskTexBlur, vtf.maskUv).a - texture(maskTex, vtf.maskUv).a);\n" +"}\n"; + +static const char* BlurVS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"layout(location=0) in vec4 posIn;\n" +"layout(location=3) in vec4 uvIn;\n" +"\n" +"UBINDING0 uniform PhazonSuitBlurUniform\n" +"{\n" +" vec4 blurDir;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" vec2 uv;\n" +" vec2 blurDir;\n" +"};\n" +"\n" +"SBINDING(0) out VertToFrag vtf;\n" +"void main()\n" +"{\n" +" vtf.uv = uvIn.xy;\n" +" vtf.blurDir = blurDir.xy;\n" +" gl_Position = vec4(posIn.xyz, 1.0);\n" +"}\n"; + +static const char* BlurFS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec2 uv;\n" +" vec2 blurDir;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D maskTex;\n" +"void main()\n" +"{\n" +" //this will be our alpha sum\n" +" float sum = 0.0;\n" +"\n" +" //apply blurring, using a 9-tap filter with predefined gaussian weights\n" +"\n" +" sum += texture(maskTex, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n" +" sum += texture(maskTex, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n" +" sum += texture(maskTex, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n" +" sum += texture(maskTex, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n" +"\n" +" sum += texture(maskTex, vtf.uv).a * 0.2270270270;\n" +"\n" +" sum += texture(maskTex, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n" +" sum += texture(maskTex, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n" +" sum += texture(maskTex, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n" +" sum += texture(maskTex, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n" +"\n" +" colorOut = vec4(1.0, 1.0, 1.0, sum);\n" +"}\n"; + +URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter) + +static boo::IVertexFormat* s_VtxFmt = nullptr; +static boo::IVertexFormat* s_BlurVtxFmt = nullptr; +static boo::IShaderPipeline* s_IndPipeline = nullptr; +static boo::IShaderPipeline* s_Pipeline = nullptr; +static boo::IShaderPipeline* s_BlurPipeline = nullptr; + +struct CPhazonSuitFilterGLDataBindingFactory : TShader::IDataBindingFactory +{ + boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CPhazonSuitFilter& filter) + { + boo::GLDataFactory::Context& cctx = static_cast(ctx); + + const boo::VertexElementDescriptor BlurVtxVmt[] = + { + {filter.m_blurVbo, nullptr, boo::VertexSemantic::Position4}, + {filter.m_blurVbo, nullptr, boo::VertexSemantic::UV4} + }; + boo::IVertexFormat* blurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt); + + boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ITexture* texs[4]; + int texBindIdxs[4]; + + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 1; + filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline, + blurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + bufs[0] = filter.m_uniBufBlurY; + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 2; + filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline, + blurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + const boo::VertexElementDescriptor VtxVmt[] = + { + {filter.m_vbo, nullptr, boo::VertexSemantic::Position4}, + {filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 0}, + {filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 1}, + {filter.m_vbo, nullptr, boo::VertexSemantic::UV4, 2} + }; + boo::IVertexFormat* vtxFmt = ctx.newVertexFormat(4, VtxVmt); + + bufs[0] = filter.m_uniBuf; + size_t texCount; + if (filter.m_indTex) + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = filter.m_indTex->GetBooTexture(); + texBindIdxs[1] = 0; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 1; + texs[3] = CGraphics::g_SpareTexture; + texBindIdxs[3] = 2; + texCount = 4; + } + else + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = CGraphics::g_SpareTexture; + texBindIdxs[1] = 1; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 2; + texCount = 3; + } + + return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline, + vtxFmt, filter.m_vbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr); + } +}; + +#if BOO_HAS_VULKAN +struct CPhazonSuitFilterVulkanDataBindingFactory : TShader::IDataBindingFactory +{ + boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CPhazonSuitFilter& filter) + { + boo::VulkanDataFactory::Context& cctx = static_cast(ctx); + + boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ITexture* texs[4]; + int texBindIdxs[4]; + + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 1; + filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline, + s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + bufs[0] = filter.m_uniBufBlurY; + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 2; + filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline, + s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + bufs[0] = filter.m_uniBuf; + size_t texCount; + if (filter.m_indTex) + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = filter.m_indTex->GetBooTexture(); + texBindIdxs[1] = 0; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 1; + texs[3] = CGraphics::g_SpareTexture; + texBindIdxs[3] = 2; + texCount = 4; + } + else + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = CGraphics::g_SpareTexture; + texBindIdxs[1] = 1; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 2; + texCount = 3; + } + + return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline, + s_VtxFmt, filter.m_vbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr); + } +}; +#endif + +TShader::IDataBindingFactory* +CPhazonSuitFilter::Initialize(boo::GLDataFactory::Context& ctx) +{ + const char* uniNames[] = {"PhazonSuitUniform"}; + const char* texNames[] = {"screenTex", "indTex", "maskTex", "maskTexBlur"}; + s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, 4, texNames, 1, uniNames, boo::BlendFactor::One, + boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + texNames[1] = "maskTex"; + texNames[2] = "maskTexBlur"; + s_Pipeline = ctx.newShaderPipeline(VS, FS, 3, texNames, 1, uniNames, boo::BlendFactor::One, + boo::BlendFactor::One, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + uniNames[0] = "PhazonSuitBlurUniform"; + texNames[0] = "maskTex"; + s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, 1, texNames, 1, uniNames, boo::BlendFactor::One, + boo::BlendFactor::Zero, boo::Primitive::TriStrips, + boo::ZTest::None, false, false, true, boo::CullMode::None); + return new CPhazonSuitFilterGLDataBindingFactory; +} + +#if BOO_HAS_VULKAN +TShader::IDataBindingFactory* +CPhazonSuitFilter::Initialize(boo::VulkanDataFactory::Context& ctx) +{ + const boo::VertexElementDescriptor VtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 2} + }; + s_VtxFmt = ctx.newVertexFormat(4, VtxVmt); + const boo::VertexElementDescriptor BlurVtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4} + }; + s_BlurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt); + s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, s_VtxFmt, boo::BlendFactor::One, + boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, boo::BlendFactor::One, + boo::BlendFactor::One, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, s_BlurVtxFmt, boo::BlendFactor::One, + boo::BlendFactor::Zero, boo::Primitive::TriStrips, + boo::ZTest::None, false, false, true, boo::CullMode::None); + return new CPhazonSuitFilterVulkanDataBindingFactory; +} +#endif + +} diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilterHLSL.cpp b/Runtime/Graphics/Shaders/CPhazonSuitFilterHLSL.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/Runtime/Graphics/Shaders/CPhazonSuitFilterMetal.cpp b/Runtime/Graphics/Shaders/CPhazonSuitFilterMetal.cpp new file mode 100644 index 000000000..5d34e4935 --- /dev/null +++ b/Runtime/Graphics/Shaders/CPhazonSuitFilterMetal.cpp @@ -0,0 +1,255 @@ +#include "CPhazonSuitFilter.hpp" +#include "TShader.hpp" +#include "Graphics/CTexture.hpp" + +namespace urde +{ + +static const char* VS = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn [[ attribute(0) ]];\n" +" float4 screenUvIn [[ attribute(1) ]];\n" +" float4 indUvIn [[ attribute(2) ]];\n" +" float4 maskUvIn [[ attribute(3) ]];\n" +"};\n" +"\n" +"struct PhazonSuitUniform\n" +"{\n" +" float4 color;\n" +" float4 indScaleOff;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +" float4 indScaleOff;\n" +" float2 screenUv;\n" +" float2 indUv;\n" +" float2 maskUv;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitUniform& psu [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.color = psu.color;\n" +" vtf.indScaleOff = psu.indScaleOff;\n" +" vtf.screenUv = v.screenUvIn.xy;\n" +" vtf.indUv = v.indUvIn.xy;\n" +" vtf.maskUv = v.maskUvIn.xy;\n" +" vtf.position = float4(v.posIn.xyz, 1.0);\n" +" return vtf;\n" +"}\n"; + +static const char* IndFS = +"#include \n" +"using namespace metal;\n" +"constexpr sampler samp(address::repeat, filter::linear);\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float4 color;\n" +" float4 indScaleOff;\n" +" float2 screenUv;\n" +" float2 indUv;\n" +" float2 maskUv;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" texture2d screenTex [[ texture(0) ]],\n" +" texture2d indTex [[ texture(1) ]],\n" +" texture2d maskTex [[ texture(2) ]],\n" +" texture2d maskTexBlur [[ texture(3) ]])\n" +"{\n" +" float2 indUv = (indTex.sample(samp, vtf.indUv).rg - float2(0.5, 0.5)) * \n" +" vtf.indScaleOff.xy + vtf.indScaleOff.zw;\n" +" return vtf.color * screenTex.sample(samp, indUv + vtf.screenUv) * \n" +" (maskTexBlur.sample(samp, vtf.maskUv).a - maskTex.sample(samp, vtf.maskUv).a);\n" +"}\n"; + +static const char* FS = +"#include \n" +"using namespace metal;\n" +"constexpr sampler samp(address::repeat, filter::linear);\n" +"struct VertToFrag\n" +"{\n" +" float4 color;\n" +" float4 indScaleOff;\n" +" float2 screenUv;\n" +" float2 indUv;\n" +" float2 maskUv;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" texture2d screenTex [[ texture(0) ]],\n" +" texture2d maskTex [[ texture(1) ]],\n" +" texture2d maskTexBlur [[ texture(2) ]])\n" +"{\n" +" return vtf.color * screenTex.sample(samp, vtf.screenUv) * \n" +" (maskTexBlur.sample(samp, vtf.maskUv).a - maskTex.sample(samp, vtf.maskUv).a);\n" +"}\n"; + +static const char* BlurVS = +"#include \n" +"using namespace metal;\n" +"struct VertData\n" +"{\n" +" float4 posIn [[ attribute(0) ]];\n" +" float4 uvIn [[ attribute(1) ]];\n" +"};\n" +"\n" +"struct PhazonSuitBlurUniform\n" +"{\n" +" float4 blurDir;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float2 uv;\n" +" float2 blurDir;\n" +"};\n" +"\n" +"vertex VertToFrag vmain(VertData v [[ stage_in ]], constant PhazonSuitBlurUniform& psu [[ buffer(2) ]])\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.uv = uvIn.xy;\n" +" vtf.blurDir = blurDir.xy;\n" +" vtf.position = float4(posIn.xyz, 1.0);\n" +" return vtf;\n" +"}\n"; + +static const char* BlurFS = +"#include \n" +"using namespace metal;\n" +"constexpr sampler samp(address::repeat, filter::linear);\n" +"struct VertToFrag\n" +"{\n" +" float4 position [[ position ]];\n" +" float2 uv;\n" +" float2 blurDir;\n" +"};\n" +"\n" +"fragment float4 fmain(VertToFrag vtf [[ stage_in ]],\n" +" texture2d maskTex [[ texture(0) ]])\n" +"{\n" +" //this will be our alpha sum\n" +" float sum = 0.0;\n" +"\n" +" //apply blurring, using a 9-tap filter with predefined gaussian weights\n" +"\n" +" sum += maskTex.sample(samp, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n" +" sum += maskTex.sample(samp, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n" +" sum += maskTex.sample(samp, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n" +" sum += maskTex.sample(samp, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n" +"\n" +" sum += maskTex.sample(samp, vtf.uv).a * 0.2270270270;\n" +"\n" +" sum += maskTex.sample(samp, vtf.uv - 1.0 * vtf.blurDir).a * 0.1945945946;\n" +" sum += maskTex.sample(samp, vtf.uv - 2.0 * vtf.blurDir).a * 0.1216216216;\n" +" sum += maskTex.sample(samp, vtf.uv - 3.0 * vtf.blurDir).a * 0.0540540541;\n" +" sum += maskTex.sample(samp, vtf.uv - 4.0 * vtf.blurDir).a * 0.0162162162;\n" +"\n" +" return float4(1.0, 1.0, 1.0, sum);\n" +"}\n"; + +URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter) + +static boo::IVertexFormat* s_VtxFmt = nullptr; +static boo::IVertexFormat* s_BlurVtxFmt = nullptr; +static boo::IShaderPipeline* s_IndPipeline = nullptr; +static boo::IShaderPipeline* s_Pipeline = nullptr; +static boo::IShaderPipeline* s_BlurPipeline = nullptr; + +struct CPhazonSuitFilterMetalDataBindingFactory : TShader::IDataBindingFactory +{ + boo::IShaderDataBinding* BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx, + CPhazonSuitFilter& filter) + { + boo::MetalDataFactory::Context& cctx = static_cast(ctx); + + boo::IGraphicsBuffer* bufs[] = {filter.m_uniBufBlurX}; + boo::PipelineStage stages[] = {boo::PipelineStage::Vertex}; + boo::ITexture* texs[4]; + int texBindIdxs[4]; + + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 1; + filter.m_dataBindBlurX = cctx.newShaderDataBinding(s_BlurPipeline, + s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + bufs[0] = filter.m_uniBufBlurY; + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 2; + filter.m_dataBindBlurY = cctx.newShaderDataBinding(s_BlurPipeline, + s_BlurVtxFmt, filter.m_blurVbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, 1, texs, texBindIdxs, nullptr); + + bufs[0] = filter.m_uniBuf; + size_t texCount; + if (filter.m_indTex) + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = filter.m_indTex->GetBooTexture(); + texBindIdxs[1] = 0; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 1; + texs[3] = CGraphics::g_SpareTexture; + texBindIdxs[3] = 2; + texCount = 4; + } + else + { + texs[0] = CGraphics::g_SpareTexture; + texBindIdxs[0] = 0; + texs[1] = CGraphics::g_SpareTexture; + texBindIdxs[1] = 1; + texs[2] = CGraphics::g_SpareTexture; + texBindIdxs[2] = 2; + texCount = 3; + } + + return cctx.newShaderDataBinding(filter.m_indTex ? s_IndPipeline : s_Pipeline, + s_VtxFmt, filter.m_vbo, nullptr, nullptr, + 1, bufs, stages, nullptr, nullptr, texCount, texs, texBindIdxs, nullptr); + } +}; + +TShader::IDataBindingFactory* +CPhazonSuitFilter::Initialize(boo::MetalDataFactory::Context& ctx) +{ + const boo::VertexElementDescriptor VtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 0}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 1}, + {nullptr, nullptr, boo::VertexSemantic::UV4, 2} + }; + s_VtxFmt = ctx.newVertexFormat(4, VtxVmt); + const boo::VertexElementDescriptor BlurVtxVmt[] = + { + {nullptr, nullptr, boo::VertexSemantic::Position4}, + {nullptr, nullptr, boo::VertexSemantic::UV4} + }; + s_BlurVtxFmt = ctx.newVertexFormat(2, BlurVtxVmt); + s_IndPipeline = ctx.newShaderPipeline(VS, IndFS, s_VtxFmt, + CGraphics::g_ViewportSamples, boo::BlendFactor::One, + boo::BlendFactor::InvSrcAlpha, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + s_Pipeline = ctx.newShaderPipeline(VS, FS, s_VtxFmt, + CGraphics::g_ViewportSamples, boo::BlendFactor::One, + boo::BlendFactor::One, boo::Primitive::TriStrips, + boo::ZTest::None, false, true, false, boo::CullMode::None); + s_BlurPipeline = ctx.newShaderPipeline(BlurVS, BlurFS, s_BlurVtxFmt, + CGraphics::g_ViewportSamples, boo::BlendFactor::One, + boo::BlendFactor::Zero, boo::Primitive::TriStrips, + boo::ZTest::None, false, false, true, boo::CullMode::None); + return new CPhazonSuitFilterMetalDataBindingFactory; +} + +} diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 534c6fe99..9827f77b0 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -1,10 +1,71 @@ #include "CInventoryScreen.hpp" +#include "GuiSys/CGuiTableGroup.hpp" namespace urde { namespace MP1 { +struct SInventoryItem +{ + u32 idx; + u32 nameStrIdx; + u32 entryStrIdx; +}; + +static const SInventoryItem ArmCannonItems[] = +{ + {0, 0x24, 0x46}, // Power Beam + {1, 0x25, 0x48}, // Ice Beam + {2, 0x26, 0x4a}, // Wave Beam + {3, 0x27, 0x4c}, // Plasma Beam + {4, 0x28, 0x4e}, // Phazon Beam +}; + +static const SInventoryItem MorphballItems[] = +{ + {5, 0x2e, 0x57}, // Morph Ball + {6, 0x2f, 0x58}, // Boost Ball + {7, 0x30, 0x59}, // Spider Ball + {8, 0x31, 0x5a}, // Morph Ball Bomb + {9, 0x32, 0x5b}, // Power Bomb +}; + +static const SInventoryItem SuitItems[] = +{ + {10, 0x33, 0x52}, // Power Suit + {11, 0x34, 0x53}, // Varia Suit + {12, 0x35, 0x54}, // Gravity Suit + {13, 0x36, 0x55}, // Phazon Suit + {14, 0x37, 0x56}, // Energy Tank +}; + +static const SInventoryItem VisorItems[] = +{ + {15, 0x38, 0x42}, // Combat Visor + {16, 0x39, 0x43}, // Scan Visor + {17, 0x3a, 0x44}, // X-Ray Visor + {18, 0x3b, 0x45}, // Thermal Visor +}; + +static const SInventoryItem SecondaryItems[] = +{ + {19, 0x3c, 0x4f}, // Space Jump Boots + {20, 0x3d, 0x50}, // Grapple Beam + {21, 0x3e, 0x51}, // Missile Launcher + {22, 0x3f, 0x5c}, // Charge Beam + {23, 0x40, 0x5d}, // Beam Combo +}; + +static const std::pair InventoryRegistry[] = +{ + {5, ArmCannonItems}, + {5, MorphballItems}, + {5, SuitItems}, + {4, VisorItems}, + {5, SecondaryItems}, +}; + CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) : CPauseScreenBase(mgr, frame, pauseStrg) @@ -96,5 +157,38 @@ void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx, } +void CInventoryScreen::UpdateSamusDollPulses() +{ + bool pulseSuit = false; + bool pulseBeam = false; + bool pulseGrapple = false; + bool pulseBoots = false; + bool pulseVisor = false; + int userSel = x70_tablegroup_leftlog->GetUserSelection(); + + if (x10_mode == EMode::RightTable) + { + if (userSel == 2) + pulseSuit = true; + else if (userSel == 0) + pulseBeam = true; + else if (userSel == 3) + pulseVisor = true; + else if (userSel == 4) + { + pulseGrapple = SecondaryItems[x1c_rightSel].idx == 20; + pulseBoots = SecondaryItems[x1c_rightSel].idx == 19; + if (SecondaryItems[x1c_rightSel].idx == 21) + pulseBeam = true; + } + } + + x19c_samusDoll->SetPulseSuit(pulseSuit); + x19c_samusDoll->SetPulseBeam(pulseBeam); + x19c_samusDoll->SetPulseGrapple(pulseGrapple); + x19c_samusDoll->SetPulseBoots(pulseBoots); + x19c_samusDoll->SetPulseVisor(pulseVisor); +} + } } diff --git a/Runtime/MP1/CInventoryScreen.hpp b/Runtime/MP1/CInventoryScreen.hpp index f5a72f90e..1cf0140e4 100644 --- a/Runtime/MP1/CInventoryScreen.hpp +++ b/Runtime/MP1/CInventoryScreen.hpp @@ -38,6 +38,7 @@ public: bool IsRightLogDynamic() const; void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); + void UpdateSamusDollPulses(); }; } diff --git a/Runtime/MP1/CPauseScreenBase.cpp b/Runtime/MP1/CPauseScreenBase.cpp index b671ca42e..efe01bac6 100644 --- a/Runtime/MP1/CPauseScreenBase.cpp +++ b/Runtime/MP1/CPauseScreenBase.cpp @@ -128,7 +128,7 @@ void CPauseScreenBase::ChangeMode(EMode mode) x70_tablegroup_leftlog->SetIsActive(true); UpdateSideTable(x70_tablegroup_leftlog); x18_ = 0; - x1c_ = 0; + x1c_rightSel = 0; x84_tablegroup_rightlog->SetUserSelection(1); UpdateSideTable(x84_tablegroup_rightlog); break; @@ -171,11 +171,11 @@ void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table) if (table == x84_tablegroup_rightlog) { - int sel = x1c_ - x18_; + int sel = x1c_rightSel - x18_; x8c_model_righthighlight->SetLocalTransform( x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel)); x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children); - int selInView = x1c_ % 5; + int selInView = x1c_rightSel % 5; if (IsRightLogDynamic()) { UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor); @@ -249,7 +249,7 @@ void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff) void CPauseScreenBase::UpdateRightTable() { x18_ = 0; - x1c_ = 0; + x1c_rightSel = 0; x84_tablegroup_rightlog->SetUserSelection(1); UpdateSideTable(x84_tablegroup_rightlog); } diff --git a/Runtime/MP1/CPauseScreenBase.hpp b/Runtime/MP1/CPauseScreenBase.hpp index c587acdfe..37b464fa0 100644 --- a/Runtime/MP1/CPauseScreenBase.hpp +++ b/Runtime/MP1/CPauseScreenBase.hpp @@ -38,7 +38,7 @@ protected: EMode x10_mode = EMode::Invalid; float x14_alpha = 0.f; u32 x18_ = 0; - u32 x1c_ = 0; + u32 x1c_rightSel = 0; zeus::CVector3f x20_; zeus::CVector3f x2c_; float x38_ = 0.f; diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index d5a5f191c..b4e1fec96 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -4,6 +4,7 @@ #include "CDependencyGroup.hpp" #include "zeus/CEulerAngles.hpp" #include "Collision/CollisionUtil.hpp" +#include "Graphics/CBooRenderer.hpp" namespace urde { @@ -113,6 +114,45 @@ static const u32 Character2and3Idxs[8][2] = {30, 31} }; +static const u8 BallGlowColors[9][3] = +{ + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xd5, 0x19}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, +}; + +static const u8 BallTransFlashColors[9][3] = +{ + {0xc2, 0x7e, 0x10}, + {0x66, 0xc4, 0xff}, + {0x60, 0xff, 0x90}, + {0x33, 0x33, 0xff}, + {0xff, 0x20, 0x20}, + {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, + {0xa6, 0x86, 0xd8}, + {0xfb, 0x98, 0x21} +}; + +static const u8 BallAuxGlowColors[9][3] = +{ + {0xc2, 0x7e, 0x10}, + {0x66, 0xc4, 0xff}, + {0x6c, 0xff, 0x61}, + {0x33, 0x33, 0xff}, + {0xff, 0x20, 0x20}, + {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, + {0xa6, 0x86, 0xd8}, + {0xfb, 0x98, 0x21} +}; + CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, bool hasSpiderBall, bool hasGrappleBeam) @@ -166,7 +206,7 @@ bool CSamusDoll::IsLoaded() const return false; if (x218_invFins && !x218_invFins.IsLoaded()) return false; - return xc8_suitModel1.operator bool(); + return xc8_suitModel0.operator bool(); } CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) @@ -196,7 +236,7 @@ bool CSamusDoll::CheckLoadComplete() if (!tok.IsLoaded()) return false; - xc8_suitModel1.emplace(BuildSuitModelData1(x44_suit)); + xc8_suitModel0.emplace(BuildSuitModelData1(x44_suit)); for (int i=0 ; i<2 ; ++i) { CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, @@ -222,55 +262,448 @@ bool CSamusDoll::CheckLoadComplete() void CSamusDoll::Update(float dt, CRandom16& rand) { + if (x1f4_invBeam.IsLoaded()) + x1f4_invBeam->Touch(0); + if (x200_invVisor.IsLoaded()) + x200_invVisor->Touch(0); + if (x20c_invGrappleBeam.IsLoaded()) + x20c_invGrappleBeam->Touch(0); + if (x1d4_spiderBallGlass.IsLoaded()) + x1d4_spiderBallGlass->Touch(0); + if (x218_invFins.IsLoaded()) + x218_invFins->Touch(0); + if (!CheckLoadComplete()) + return; + + x40_alphaIn = std::min(x40_alphaIn + 2.f * dt, 1.f); + if (x54_remTransitionTime > 0.f) + { + float oldRemTransTime = x54_remTransitionTime; + x54_remTransitionTime = std::max(0.f, x54_remTransitionTime - dt); + if (!x4c_completedMorphball && x4d_selectedMorphball && + oldRemTransTime >= x50_totalTransitionTime - 0.5f && + x54_remTransitionTime < x50_totalTransitionTime - 0.5f) + { + x238_ballTransitionFlashGen = std::make_unique(x230_ballTransitionFlash, + CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x238_ballTransitionFlashGen->SetGlobalScale(zeus::CVector3f(0.625f)); + } + + if (x54_remTransitionTime == 0.f) + { + x4c_completedMorphball = x4d_selectedMorphball; + if (!x4d_selectedMorphball) + { + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms(2, -1, 1.f, true), false); + } + } + } + + if (x270_26_pulseSuit) + x58_suitPulseFactor = std::min(x58_suitPulseFactor + 2.f * dt, 1.f); + else + x58_suitPulseFactor = std::max(x58_suitPulseFactor - 2.f * dt, 0.f); + + if (x270_27_pulseBeam) + x5c_beamPulseFactor = std::min(x5c_beamPulseFactor + 2.f * dt, 1.f); + else + x5c_beamPulseFactor = std::max(x5c_beamPulseFactor - 2.f * dt, 0.f); + + if (x270_28_pulseGrapple) + x60_grapplePulseFactor = std::min(x60_grapplePulseFactor + 2.f * dt, 1.f); + else + x60_grapplePulseFactor = std::max(x60_grapplePulseFactor - 2.f * dt, 0.f); + + if (x270_29_pulseBoots) + x64_bootsPulseFactor = std::min(x64_bootsPulseFactor + 2.f * dt, 1.f); + else + x64_bootsPulseFactor = std::max(x64_bootsPulseFactor - 2.f * dt, 0.f); + + if (x270_30_pulseVisor) + x68_visorPulseFactor = std::min(x68_visorPulseFactor + 2.f * dt, 1.f); + else + x68_visorPulseFactor = std::max(x68_visorPulseFactor - 2.f * dt, 0.f); + + if (x4c_completedMorphball) + x6c_ballPulseFactor = std::min(x6c_ballPulseFactor + 2.f * dt, 1.f); + else + x6c_ballPulseFactor = std::max(x6c_ballPulseFactor - 2.f * dt, 0.f); + + if (x44_suit == CPlayerState::EPlayerSuit::Phazon) + { + if (!x250_phazonIndirectTexture) + x250_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture"); + } + else + { + if (x250_phazonIndirectTexture) + x250_phazonIndirectTexture = TLockedToken(); + } + + if (x250_phazonIndirectTexture) + { + x260_phazonOffsetAngle += 0.03f; + g_Renderer->AllocatePhazonSuitMaskTexture(); + } + + xc8_suitModel0->AdvanceAnimationIgnoreParticles(dt, rand, true); + x134_suitModelBoots->AdvanceAnimationIgnoreParticles(dt, rand, true); + x184_ballModelData->AdvanceAnimationIgnoreParticles(dt, rand, true); + + SetupLights(); + + x22c_ballInnerGlowGen->SetGlobalTranslation(x10_xf.origin); + x22c_ballInnerGlowGen->Update(dt); + + if (x238_ballTransitionFlashGen) + { + if (x238_ballTransitionFlashGen->IsSystemDeletable()) + x238_ballTransitionFlashGen.reset(); + if (x238_ballTransitionFlashGen) + { + x22c_ballInnerGlowGen->SetGlobalTranslation(x10_xf.origin); + x22c_ballInnerGlowGen->Update(dt); + } + } + + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) + { + if (xc4_viewInterp < 0.f) + xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 0.f); + else + xc4_viewInterp = std::min(xc4_viewInterp + 3.f * dt, 1.f); + + float interp = std::fabs(xc4_viewInterp); + float oneMinusInterp = 1.f - interp; + xa4_offset = x84_interpStartOffset * interp + skInitialOffset * oneMinusInterp; + + xb0_userRot = zeus::CQuaternion::slerpShort(x70_fixedRot, x90_userInterpRot, interp); + + if (xc4_viewInterp <= 0.f) // Zoom out + xc0_userZoom = x80_fixedZoom * oneMinusInterp + xa0_userInterpZoom * interp; + else // Zoom in + xc0_userZoom = x80_fixedZoom * interp + xa0_userInterpZoom * oneMinusInterp; + } } void CSamusDoll::Draw(const CStateManager& mgr, float alpha) { + if (!IsLoaded()) + return; + alpha *= x40_alphaIn; + + float itemPulse = zeus::clamp(0.f, (std::sin(5.f * CGraphics::GetSecondsMod900()) + 1.f) * 0.5f, 1.f) * + (1.f - std::fabs(xc4_viewInterp)); + + g_Renderer->SetPerspective(55.f, g_Viewport.x8_width, g_Viewport.xc_height, 0.2f, 4096.f); + + CGraphics::SetViewPointMatrix(zeus::CTransform(xb0_userRot, xa4_offset) * + zeus::CTransform::Translate(0.f, xc0_userZoom, 0.f)); + + zeus::CTransform gunXf = xc8_suitModel0->GetScaledLocatorTransform("GUN_LCTR"); + zeus::CTransform visorXf = xc8_suitModel0->GetScaledLocatorTransform("VISOR_LCTR"); + zeus::CTransform grappleXf = xc8_suitModel0->GetScaledLocatorTransform("GRAPPLE_LCTR"); + + if (!x4c_completedMorphball || !x4d_selectedMorphball) + { + float suitPulse = itemPulse * x58_suitPulseFactor; + float bootsPulse = std::max(suitPulse, itemPulse * x64_bootsPulseFactor); + + bool phazonSuit = x44_suit == CPlayerState::EPlayerSuit::Phazon; + // Enable dst alpha 1.0 + + for (int i=0 ; i<=x118_suitModel1and2.size() ; ++i) + { + TCachedToken backupModelData = xc8_suitModel0->GetAnimationData()->GetModelData(); + if (i < x118_suitModel1and2.size()) + xc8_suitModel0->AnimationData()->SubstituteModelData(x118_suitModel1and2[i]); + xc8_suitModel0->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), + x24c_actorLights.get(), zeus::CColor(1.f, alpha), + zeus::CColor(1.f, alpha * suitPulse)); + xc8_suitModel0->AnimationData()->SubstituteModelData(backupModelData); + } + + x134_suitModelBoots->InvSuitDraw(CModelData::EWhichModel::Normal, zeus::CTransform::Identity(), + x24c_actorLights.get(), zeus::CColor(1.f, alpha), + zeus::CColor(1.f, alpha * bootsPulse)); + + { + CGraphics::SetModelMatrix(gunXf); + x1f4_invBeam->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1f4_invBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor(1.f, alpha); + x1f4_invBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x5c_beamPulseFactor); + x1f4_invBeam->Draw(flags); + } + + { + CGraphics::SetModelMatrix(visorXf); + + float visorT = std::fmod(CGraphics::GetSecondsMod900(), 1.f) * (1.f - std::fabs(xc4_viewInterp)); + float alphaBlend = (visorT < 0.25f) ? 1.f - 2.f * visorT : (visorT < 0.5f) ? 2.f * (visorT - 0.25f) + 0.5f : 1.f; + float addBlend = (visorT > 0.75f) ? 1.f - 4.f * (visorT - 0.75f) : (visorT > 0.5f) ? 4.f * (visorT - 0.5f) : 0.f; + + x200_invVisor->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor::lerp(zeus::CColor(1.f, alpha), zeus::CColor(alphaBlend, alpha), x68_visorPulseFactor); + x200_invVisor->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * addBlend * x68_visorPulseFactor); + x200_invVisor->Draw(flags); + } + + if (x270_25_hasGrappleBeam) + { + CGraphics::SetModelMatrix(grappleXf); + + x20c_invGrappleBeam->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor(1.f, alpha); + x20c_invGrappleBeam->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * itemPulse * x60_grapplePulseFactor); + x20c_invGrappleBeam->Draw(flags); + } + else if (x44_suit >= CPlayerState::EPlayerSuit::FusionPower) + { + CGraphics::SetModelMatrix(grappleXf); + + x218_invFins->GetInstance().ActivateLights(x23c_lights); + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor(1.f, alpha); + x218_invFins->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor(1.f, alpha * suitPulse); + x218_invFins->Draw(flags); + } + + if (x54_remTransitionTime > 0.f) + { + float ballT = 1.f - x54_remTransitionTime / x50_totalTransitionTime; + + float ballAlpha = 0.f; + if (x4d_selectedMorphball) + ballAlpha = 1.f - std::min(x54_remTransitionTime / 0.25f, 1.f); + else if (x4c_completedMorphball) + ballAlpha = std::max(0.f, (x54_remTransitionTime - (x50_totalTransitionTime - 0.25f)) / 0.25f); + + if (ballAlpha > 0.f) + { + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e0_ballMatIdx; + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = alpha * ballAlpha; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = x6c_ballPulseFactor * alpha * ballAlpha * itemPulse; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + } + + if (x4d_selectedMorphball && ballT > 0.5f) + { + float ballEndT = (ballT - 0.5f) / 0.5f; + float oneMinusBallEndT = 1.f - ballEndT; + + float spinScale = 0.75f * oneMinusBallEndT + 1.f; + float spinAlpha; + if (ballEndT < 0.1f) + spinAlpha = 0.f; + else if (ballEndT < 0.2f) + spinAlpha = (ballEndT - 0.1f) / 0.1f; + else if (ballEndT < 0.9f) + spinAlpha = 1.f; + else + spinAlpha = 1.f - (ballT - 0.9f) / 0.1f; + + zeus::CRelAngle spinAngle = zeus::degToRad(360.f * oneMinusBallEndT); + spinAlpha *= 0.5f; + if (spinAlpha > 0.f) + { + CModelFlags flags = {}; + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x1_matSetIdx = x1e0_ballMatIdx; + flags.x4_color = zeus::CColor(1.f, spinAlpha * alpha); + x184_ballModelData->Render(mgr, x10_xf * zeus::CTransform::RotateZ(spinAngle) * zeus::CTransform::Scale(spinScale), + x24c_actorLights.get(), flags); + } + } + + if (x270_24_hasSpiderBall) + { + CGraphics::SetModelMatrix(x10_xf); + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e4_glassMatIdx; + x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = alpha; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse; + x1d4_spiderBallGlass->Draw(flags); + } + + if (phazonSuit && alpha > 0.1f) + { + float radius = zeus::clamp(0.2f, (10.f - (xc0_userZoom >= 0.f ? xc0_userZoom : -xc0_userZoom)) / 20.f, 1.f); + float offset = std::sin(x260_phazonOffsetAngle); + zeus::CColor color = g_tweakGuiColors->GetInvPhazonSuitFilterMod(); + color.a = alpha; + g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, alpha), x250_phazonIndirectTexture, + color, radius, 0.1f, offset, offset); + } + } + } + else + { + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e0_ballMatIdx; + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = alpha; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse; + x184_ballModelData->Render(mgr, x10_xf, x24c_actorLights.get(), flags); + + const u8* c = BallGlowColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->SetModulationColor(color); + + if (alpha > 0.f) + { + if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 0) + { + const u8* c = BallTransFlashColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(color); + + if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 1) + { + const u8* c = BallAuxGlowColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; + x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(color); + } + } + x22c_ballInnerGlowGen->Render(); + } + + if (x270_24_hasSpiderBall) + { + CGraphics::SetModelMatrix(x10_xf); + CModelFlags flags = {}; + flags.x1_matSetIdx = x1e4_glassMatIdx; + x1d4_spiderBallGlass->GetInstance().ActivateLights(x23c_lights); + + flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly; + flags.x4_color = zeus::CColor::skWhite; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::Lighting; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = alpha; + x1d4_spiderBallGlass->Draw(flags); + + flags.m_extendedShader = EExtendedShader::ForcedAdditive; + flags.x4_color = zeus::CColor::skWhite; + flags.x4_color.a = x6c_ballPulseFactor * alpha * itemPulse; + x1d4_spiderBallGlass->Draw(flags); + } + } + + if (x238_ballTransitionFlashGen) + { + const u8* c = BallTransFlashColors[x1e8_ballGlowColorIdx]; + zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + x238_ballTransitionFlashGen->SetModulationColor(color); + x238_ballTransitionFlashGen->Render(); + } + + CGraphics::DisableAllLights(); } void CSamusDoll::Touch() { if (!CheckLoadComplete()) return; - xc8_suitModel1->AnimationData()->PreRender(); + xc8_suitModel0->AnimationData()->PreRender(); x134_suitModelBoots->AnimationData()->PreRender(); x184_ballModelData->AnimationData()->PreRender(); - xc8_suitModel1->Touch(CModelData::EWhichModel::Normal, 0); + xc8_suitModel0->Touch(CModelData::EWhichModel::Normal, 0); x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0); x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0); } void CSamusDoll::SetupLights() { - x23c_lights[0] = CLight::BuildDirectional(xb0_rot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); + x23c_lights[0] = CLight::BuildDirectional(xb0_userRot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack); } -void CSamusDoll::CheckTransition(bool morphballComplete) +void CSamusDoll::SetInMorphball(bool morphball) { - if (x54_ > 0.f) + if (x54_remTransitionTime > 0.f) return; - if (x4d_morphballComplete == morphballComplete) + if (x4d_selectedMorphball == morphball) return; - x4d_morphballComplete = morphballComplete; + x4d_selectedMorphball = morphball; SetTransitionAnimation(); } void CSamusDoll::SetTransitionAnimation() { - if (!x4c_intoBallComplete) + if (!x4c_completedMorphball) { - xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); + /* Into morphball */ + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); - x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(0); + x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(0); } - else if (!x4d_morphballComplete) + else if (!x4d_selectedMorphball) { - xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); + /* Outta morphball */ + xc8_suitModel0->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); - x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(1); + x50_totalTransitionTime = x54_remTransitionTime = xc8_suitModel0->GetAnimationData()->GetAnimationDuration(1); } } @@ -324,7 +757,7 @@ void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3) if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) return; SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f); - zeus::CEulerAngles angles(xb0_rot); + zeus::CEulerAngles angles(xb0_userRot); zeus::CRelAngle angX(angles.x); zeus::CRelAngle angZ(angles.z); @@ -345,7 +778,7 @@ void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3) zeus::CQuaternion quat; quat.rotateZ(angZ); quat.rotateX(angX); - xb0_rot = quat; + xb0_userRot = quat; } void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold) @@ -353,13 +786,13 @@ void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold) if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) return; zeus::CVector3f oldOffset = xa4_offset; - zeus::CMatrix3f rotMtx = xb0_rot.toTransform().basis; + zeus::CMatrix3f rotMtx = xb0_userRot.toTransform().basis; xa4_offset += rotMtx * zeus::CVector3f(offset.x, 0.f, offset.z); SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > sfxThreshold); - float oldZoom = xc0_zoom; - xc0_zoom = zeus::clamp(-4.f, xc0_zoom + offset.y, -2.2f); - bool zoomSfx = std::fabs(xc0_zoom - oldZoom) > sfxThreshold; - float zoomDelta = offset.y - (xc0_zoom - oldZoom); + float oldZoom = xc0_userZoom; + xc0_userZoom = zeus::clamp(-4.f, xc0_userZoom + offset.y, -2.2f); + bool zoomSfx = std::fabs(xc0_userZoom - oldZoom) > sfxThreshold; + float zoomDelta = offset.y - (xc0_userZoom - oldZoom); zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset; zeus::CVector3f delta = newOffset - xa4_offset; oldOffset = xa4_offset; @@ -388,7 +821,7 @@ void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold) xa4_offset = delta.normalized() + skInitialOffset; } -void CSamusDoll::BeginViewInterpolate(bool zoomOut) +void CSamusDoll::BeginViewInterpolate(bool zoomIn) { if (xc4_viewInterp == 0.f) { @@ -402,12 +835,11 @@ void CSamusDoll::BeginViewInterpolate(bool zoomOut) CSfxManager::SfxStart(1441, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); } - xc4_viewInterp = zoomOut ? FLT_EPSILON : (-1.f + FLT_EPSILON); + xc4_viewInterp = zoomIn ? FLT_EPSILON : (-1.f + FLT_EPSILON); x84_interpStartOffset = xa4_offset; - x90_interpStartRot = xb0_rot; - xa0_interpStartZoom = xc0_zoom; - - x80_ = zoomOut ? -2.2f : -3.6f; + x90_userInterpRot = xb0_userRot; + xa0_userInterpZoom = xc0_userZoom; + x80_fixedZoom = zoomIn ? -2.2f : -3.6f; } } diff --git a/Runtime/MP1/CSamusDoll.hpp b/Runtime/MP1/CSamusDoll.hpp index 32ccb7906..0e4e412fd 100644 --- a/Runtime/MP1/CSamusDoll.hpp +++ b/Runtime/MP1/CSamusDoll.hpp @@ -18,34 +18,33 @@ namespace MP1 class CSamusDoll { std::vector x0_depToks; - zeus::CTransform x10_; - float x40_ = 0.f; + zeus::CTransform x10_xf; + float x40_alphaIn = 0.f; CPlayerState::EPlayerSuit x44_suit; CPlayerState::EBeamId x48_beam; - bool x4c_intoBallComplete = false; - bool x4d_morphballComplete = false; - float x50_ = 1.f; - float x54_ = 0.f; - float x58_ = 0.f; - float x5c_ = 0.f; - float x60_ = 0.f; - float x64_ = 0.f; - float x68_ = 0.f; - float x6c_ = 0.f; - zeus::CQuaternion x70_; - float x80_ = -3.6f; + bool x4c_completedMorphball = false; + bool x4d_selectedMorphball = false; + float x50_totalTransitionTime = 1.f; + float x54_remTransitionTime = 0.f; + float x58_suitPulseFactor = 0.f; + float x5c_beamPulseFactor = 0.f; + float x60_grapplePulseFactor = 0.f; + float x64_bootsPulseFactor = 0.f; + float x68_visorPulseFactor = 0.f; + float x6c_ballPulseFactor = 0.f; + zeus::CQuaternion x70_fixedRot; + float x80_fixedZoom = -3.6f; zeus::CVector3f x84_interpStartOffset = skInitialOffset; - zeus::CQuaternion x90_interpStartRot; - float xa0_interpStartZoom = -3.6f; + zeus::CQuaternion x90_userInterpRot; + float xa0_userInterpZoom = -3.6f; zeus::CVector3f xa4_offset = skInitialOffset; - zeus::CQuaternion xb0_rot; - float xc0_zoom = -3.6f; + zeus::CQuaternion xb0_userRot; + float xc0_userZoom = -3.6f; float xc4_viewInterp = 0.f; - std::experimental::optional xc8_suitModel1; + std::experimental::optional xc8_suitModel0; rstl::reserved_vector, 2> x118_suitModel1and2; std::experimental::optional x134_suitModelBoots; std::experimental::optional x184_ballModelData; - bool x1d0_ = false; TLockedToken x1d4_spiderBallGlass; u32 x1e0_ballMatIdx; u32 x1e4_glassMatIdx; @@ -58,10 +57,11 @@ class CSamusDoll TLockedToken x224_ballInnerGlow; std::unique_ptr x22c_ballInnerGlowGen; TLockedToken x230_ballTransitionFlash; + std::unique_ptr x238_ballTransitionFlashGen; std::vector x23c_lights; std::unique_ptr x24c_actorLights; - bool x25c_ = false; - float x260_ = 0.f; + TLockedToken x250_phazonIndirectTexture; // Used to be optional + zeus::CRelAngle x260_phazonOffsetAngle; CSfxHandle x264_offsetSfx; CSfxHandle x268_rotateSfx; CSfxHandle x26c_zoomSfx; @@ -71,11 +71,11 @@ class CSamusDoll { bool x270_24_hasSpiderBall : 1; bool x270_25_hasGrappleBeam : 1; - bool x270_26_ : 1; - bool x270_27_ : 1; - bool x270_28_ : 1; - bool x270_29_ : 1; - bool x270_30_ : 1; + bool x270_26_pulseSuit : 1; + bool x270_27_pulseBeam : 1; + bool x270_28_pulseGrapple : 1; + bool x270_29_pulseBoots : 1; + bool x270_30_pulseVisor : 1; bool x270_31_loaded : 1; }; u32 _dummy = 0; @@ -98,10 +98,15 @@ public: void Update(float dt, CRandom16& rand); void Draw(const CStateManager& mgr, float alpha); void Touch(); - void CheckTransition(bool morphballComplete); + void SetInMorphball(bool morphballComplete); void SetRotation(float xDelta, float zDelta, float); void SetOffset(const zeus::CVector3f& offset, float sfxThreshold); void BeginViewInterpolate(bool zoomOut); + void SetPulseSuit(bool b) { x270_26_pulseSuit = b; } + void SetPulseVisor(bool b) { x270_30_pulseVisor = b; } + void SetPulseBoots(bool b) { x270_29_pulseBoots = b; } + void SetPulseGrapple(bool b) { x270_28_pulseGrapple = b; } + void SetPulseBeam(bool b) { x270_27_pulseBeam = b; } }; } diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index cd6490c94..dfda7688b 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -11,6 +11,7 @@ #include "Graphics/Shaders/CEnergyBarShader.hpp" #include "Graphics/Shaders/CRadarPaintShader.hpp" #include "Graphics/Shaders/CMapSurfaceShader.hpp" +#include "Graphics/Shaders/CPhazonSuitFilter.hpp" #include "Character/CCharLayoutInfo.hpp" #include "Audio/CStreamAudioManager.hpp" #include "CGBASupport.hpp" @@ -29,6 +30,7 @@ URDE_DECL_SPECIALIZE_SHADER(CFogVolumeFilter) URDE_DECL_SPECIALIZE_SHADER(CEnergyBarShader) URDE_DECL_SPECIALIZE_SHADER(CRadarPaintShader) URDE_DECL_SPECIALIZE_SHADER(CMapSurfaceShader) +URDE_DECL_SPECIALIZE_SHADER(CPhazonSuitFilter) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CColoredQuadFilter) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilter) URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilterAlpha) @@ -222,6 +224,7 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory, TShader::Initialize(); TShader::Initialize(); TShader::Initialize(); + TShader::Initialize(); TMultiBlendShader::Initialize(); TMultiBlendShader::Initialize(); TMultiBlendShader::Initialize(); @@ -354,6 +357,7 @@ void CMain::Shutdown() TShader::Shutdown(); TShader::Shutdown(); TShader::Shutdown(); + TShader::Shutdown(); TMultiBlendShader::Shutdown(); TMultiBlendShader::Shutdown(); TMultiBlendShader::Shutdown(); diff --git a/Runtime/Particle/CElementGen.cpp b/Runtime/Particle/CElementGen.cpp index 87b2ed2ed..2f6107b87 100644 --- a/Runtime/Particle/CElementGen.cpp +++ b/Runtime/Particle/CElementGen.cpp @@ -283,7 +283,7 @@ CElementGen::CElementGen(const TToken& gen, EModelOrientationType orientType, EOptionalSystemFlags flags) : x1c_genDesc(gen), x28_orientType(orientType), - x226_enableOPTS((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x230_randState(x74_randomSeed) + x226_enableOPTS((flags & EOptionalSystemFlags::Two) != EOptionalSystemFlags::None), x27c_randState(x94_randomSeed) { CGenDescription* desc = x1c_genDesc.GetObj(); @@ -297,9 +297,9 @@ CElementGen::CElementGen(const TToken& gen, { int seedVal; seedElem->GetValue(x50_curFrame, seedVal); - x74_randomSeed = seedVal; + x94_randomSeed = seedVal; } - x230_randState.SetSeed(x74_randomSeed); + x27c_randState.SetSeed(x94_randomSeed); ++g_ParticleSystemAliveCount; x224_25_LIT_ = desc->x44_29_x30_29_LIT_; x224_26_AAPH = desc->x44_26_x30_26_AAPH; @@ -318,7 +318,7 @@ CElementGen::CElementGen(const TToken& gen, CIntElement* cssdElem = desc->xa0_x8c_CSSD.get(); if (cssdElem) - cssdElem->GetValue(0, x244_CSSD); + cssdElem->GetValue(0, x2a0_CSSD); SChildGeneratorDesc& idts = desc->xa4_x90_IDTS; if (idts.m_found) @@ -342,34 +342,52 @@ CElementGen::CElementGen(const TToken& gen, CIntElement* pisyElem = desc->xc8_xb4_PISY.get(); if (pisyElem) { - pisyElem->GetValue(0, x25c_PISY); - if (x25c_PISY <= 0) - x25c_PISY = 1; + pisyElem->GetValue(0, x2a8_PISY); + if (x2a8_PISY <= 0) + x2a8_PISY = 1; } CIntElement* sisyElem = desc->xcc_xb8_SISY.get(); if (sisyElem) - pisyElem->GetValue(0, x258_SISY); + pisyElem->GetValue(0, x2a4_SISY); CIntElement* sssdElem = desc->xe4_xd0_SSSD.get(); if (sssdElem) - sssdElem->GetValue(0, x270_SSSD); + sssdElem->GetValue(0, x2ac_SSSD); CVectorElement* sspoElem = desc->xe8_xd4_SSPO.get(); if (sspoElem) - sspoElem->GetValue(0, x274_SSPO); + { + sspoElem->GetValue(0, x2b0_SSPO); + if (!sspoElem->IsFastConstant()) + x26c_24_ = true; + } CIntElement* sesdElem = desc->xf8_xe4_SESD.get(); if (sesdElem) - sesdElem->GetValue(0, x290_SESD); + sesdElem->GetValue(0, x2bc_SESD); CVectorElement* sepoElem = desc->xfc_xe8_SEPO.get(); if (sepoElem) - sepoElem->GetValue(0, x294_SEPO); + { + sepoElem->GetValue(0, x2c0_SEPO); + if (!sepoElem->IsFastConstant()) + x26c_24_ = true; + } + + CVectorElement* pofsElem = desc->x18_xc_POFS.get(); + if (pofsElem) + { + pofsElem->GetValue(x50_curFrame, xf4_POFS); + if (!pofsElem->IsFastConstant()) + x26c_24_ = true; + } CIntElement* psltElem = desc->xc_x0_PSLT.get(); if (psltElem) - psltElem->GetValue(0, x214_PSLT); + psltElem->GetValue(0, x268_PSLT); + else + x268_PSLT = INT_MAX; /* Removed from retail CVectorElement* psivElem = desc->x0_PSIV.get(); @@ -379,21 +397,17 @@ CElementGen::CElementGen(const TToken& gen, CIntElement* maxpElem = desc->x28_x1c_MAXP.get(); if (maxpElem) - maxpElem->GetValue(x50_curFrame, x70_MAXP); + maxpElem->GetValue(x50_curFrame, x90_MAXP); - x2c_particleLists.reserve(x70_MAXP); + x30_particleLists.reserve(x90_MAXP); if (x28_orientType == EModelOrientationType::One) { - x3c_parentMatrices.insert(x3c_parentMatrices.end(), x70_MAXP, + x60_parentMatrices.insert(x60_parentMatrices.end(), x90_MAXP, zeus::CMatrix3f::skIdentityMatrix3f); } - x225_26_LINE = desc->x44_24_x30_24_LINE; - x225_27_FXLL = desc->x44_25_x30_25_FXLL; - - CVectorElement* pofsElem = desc->x18_xc_POFS.get(); - if (pofsElem) - pofsElem->GetValue(x50_curFrame, x94_POFS); + x26c_31_LINE = desc->x44_24_x30_24_LINE; + x26d_24_FXLL = desc->x44_25_x30_25_FXLL; CIntElement* ltypElem = desc->x100_xec_LTYP.get(); if (ltypElem) @@ -404,16 +418,16 @@ CElementGen::CElementGen(const TToken& gen, { case LightType::None: default: - x2dc_lightType = LightType::None; + x308_lightType = LightType::None; break; case LightType::Directional: - x2dc_lightType = LightType::Directional; + x308_lightType = LightType::Directional; break; case LightType::Custom: - x2dc_lightType = LightType::Custom; + x308_lightType = LightType::Custom; break; case LightType::Spot: - x2dc_lightType = LightType::Spot; + x308_lightType = LightType::Spot; break; } } @@ -426,32 +440,32 @@ CElementGen::CElementGen(const TToken& gen, switch (EFalloffType(lfot)) { case EFalloffType::Constant: - x300_falloffType = EFalloffType::Constant; + x32c_falloffType = EFalloffType::Constant; break; case EFalloffType::Linear: default: - x300_falloffType = EFalloffType::Linear; + x32c_falloffType = EFalloffType::Linear; break; case EFalloffType::Quadratic: - x300_falloffType = EFalloffType::Quadratic; + x32c_falloffType = EFalloffType::Quadratic; break; } } - if (x225_26_LINE) + if (x26c_31_LINE) { CUVElement* texr = desc->x54_x40_TEXR.get(); boo::ITexture* tex = nullptr; if (texr) tex = texr->GetValueTexture(0).GetObj()->GetBooTexture(); - int maxVerts = (x70_MAXP == 0 ? 256 : x70_MAXP); + int maxVerts = (x90_MAXP == 0 ? 256 : x90_MAXP); m_lineRenderer.reset(new CLineRenderer(CLineRenderer::EPrimitiveMode::Lines, maxVerts * 2, tex, x224_26_AAPH)); } else { m_shaderClass = CElementGenShaders::GetShaderClass(*this); - size_t maxInsts = x224_29_MBLR ? (m_maxMBSP * x70_MAXP) : x70_MAXP; + size_t maxInsts = x224_29_MBLR ? (m_maxMBSP * x90_MAXP) : x90_MAXP; maxInsts = (maxInsts == 0 ? 256 : maxInsts); m_gfxToken = CGraphics::CommitResources([&](boo::IGraphicsDataFactory::Context& ctx) -> bool { @@ -494,7 +508,7 @@ void CElementGen::Update(double t) bool CElementGen::InternalUpdate(double dt) { - CGlobalRandom gr(x230_randState); + CGlobalRandom gr(x27c_randState); CGenDescription* desc = x1c_genDesc.GetObj(); double dt1 = 1.0 / 60.0; @@ -533,7 +547,7 @@ bool CElementGen::InternalUpdate(double dt) CRealElement* grteElem = desc->x2c_x20_GRTE.get(); if (grteElem->GetValue(x50_curFrame, grte)) { - x2c_particleLists.clear(); + x30_particleLists.clear(); return true; } @@ -542,16 +556,16 @@ bool CElementGen::InternalUpdate(double dt) int genCount = floorf(x6c_generatorRemainder); x6c_generatorRemainder = x6c_generatorRemainder - genCount; - if (!x68_particleEmission || x50_curFrame >= x214_PSLT) + if (!x68_particleEmission || x50_curFrame >= x268_PSLT) genCount = 0; CIntElement* maxpElem = desc->x28_x1c_MAXP.get(); if (maxpElem) - maxpElem->GetValue(x50_curFrame, x70_MAXP); + maxpElem->GetValue(x50_curFrame, x90_MAXP); UpdateExistingParticles(); - CParticleGlobals::SetParticleLifetime(x214_PSLT); + CParticleGlobals::SetParticleLifetime(x268_PSLT); bool oldBoolVal = s_inCreateNewParticles; s_inCreateNewParticles = true; CreateNewParticles(genCount); @@ -560,7 +574,7 @@ bool CElementGen::InternalUpdate(double dt) UpdatePSTranslationAndOrientation(); UpdateChildParticleSystems(1 / 60.0); - if (x2dc_lightType != LightType::None) + if (x308_lightType != LightType::None) UpdateLightParameters(); ++frameUpdateCount; @@ -598,8 +612,8 @@ void CElementGen::UpdateExistingParticles() x208_activeParticleCount = 0; CParticleGlobals::SetEmitterTime(x50_curFrame); - for (std::vector::iterator p = x2c_particleLists.begin(); - p != x2c_particleLists.end();) + for (std::vector::iterator p = x30_particleLists.begin(); + p != x30_particleLists.end();) { CElementGen::CParticle& particle = g_StaticParticleList[p->x0_partIdx]; g_currentParticle = &particle; @@ -607,21 +621,21 @@ void CElementGen::UpdateExistingParticles() if (particle.x0_endFrame < x50_curFrame) { g_StaticFreeList[++g_FreeIndex] = p->x0_partIdx; - if (p+1 == x2c_particleLists.end()) + if (p+1 == x30_particleLists.end()) { - x2c_particleLists.pop_back(); + x30_particleLists.pop_back(); break; } else { - *p = *(x2c_particleLists.end()-1); + *p = *(x30_particleLists.end()-1); if (x28_orientType == EModelOrientationType::One) { - size_t i = p - x2c_particleLists.begin(); - x3c_parentMatrices[i] = x3c_parentMatrices[x2c_particleLists.size()-1]; + size_t i = p - x30_particleLists.begin(); + x60_parentMatrices[i] = x60_parentMatrices[x30_particleLists.size()-1]; } - x2c_particleLists.pop_back(); - if (p != x2c_particleLists.end()) + x30_particleLists.pop_back(); + if (p != x30_particleLists.end()) if (particle.x0_endFrame < x50_curFrame) continue; } @@ -706,7 +720,7 @@ void CElementGen::UpdateExistingParticles() } } - if (x225_26_LINE) + if (x26c_31_LINE) { CRealElement* leng = desc->x20_x14_LENG.get(); if (leng) @@ -743,13 +757,13 @@ void CElementGen::CreateNewParticles(int count) if (!g_StaticListInitialized) Initialize(); - if (!count || x2c_particleLists.size() >= x70_MAXP) + if (!count || x30_particleLists.size() >= x90_MAXP) return; - if (count + x2c_particleLists.size() > x70_MAXP) - count = x70_MAXP - x2c_particleLists.size(); - CGlobalRandom gr(x230_randState); - x2c_particleLists.reserve(x70_MAXP); + if (count + x30_particleLists.size() > x90_MAXP) + count = x90_MAXP - x30_particleLists.size(); + CGlobalRandom gr(x27c_randState); + x30_particleLists.reserve(x90_MAXP); for (int i=0 ; iGetValue(x210_curEmitterFrame, particle.x4_pos, particle.x1c_vel); zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation; zeus::CVector3f compXf2 = x178_orientation * particle.x4_pos; - particle.x4_pos = compXf1 + compXf2 + x94_POFS; + particle.x4_pos = compXf1 + compXf2 + xf4_POFS; particle.x1c_vel = x178_orientation * particle.x1c_vel; } else { zeus::CVector3f compXf1 = (xdc_globalScaleTransformInverse * x148_localScaleTransformInverse) * x7c_translation; - particle.x4_pos = compXf1 + x94_POFS; + particle.x4_pos = compXf1 + xf4_POFS; particle.x1c_vel.zeroOut(); } particle.x10_prevPos = particle.x4_pos; - if (x225_26_LINE) + if (x26c_31_LINE) { CRealElement* leng = desc->x20_x14_LENG.get(); if (leng) @@ -834,8 +848,8 @@ void CElementGen::UpdatePSTranslationAndOrientation() { CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x230_randState); - if (x214_PSLT < x50_curFrame) + CGlobalRandom gr(x27c_randState); + if (x268_PSLT < x50_curFrame) return; /* Removed from retail @@ -871,15 +885,15 @@ void CElementGen::UpdatePSTranslationAndOrientation() CVectorElement* pofs = desc->x18_xc_POFS.get(); if (pofs) - pofs->GetValue(x50_curFrame, x94_POFS); + pofs->GetValue(x50_curFrame, xf4_POFS); CVectorElement* sspo = desc->xe8_xd4_SSPO.get(); if (sspo) - sspo->GetValue(x50_curFrame, x274_SSPO); + sspo->GetValue(x50_curFrame, x2b0_SSPO); CVectorElement* sepo = desc->xfc_xe8_SEPO.get(); if (sepo) - sspo->GetValue(x50_curFrame, x294_SEPO); + sspo->GetValue(x50_curFrame, x2c0_SEPO); } CElementGen* CElementGen::ConstructChildParticleSystem(const TToken& desc) @@ -901,9 +915,9 @@ void CElementGen::UpdateChildParticleSystems(double dt) { CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x230_randState); + CGlobalRandom gr(x27c_randState); SChildGeneratorDesc& icts = desc->x8c_x78_ICTS; - if (icts.m_found && x64_prevFrame != x50_curFrame && x244_CSSD == x50_curFrame) + if (icts.m_found && x64_prevFrame != x50_curFrame && x2a0_CSSD == x50_curFrame) { int ncsyVal = 1; CIntElement* ncsy = desc->x9c_x88_NCSY.get(); @@ -913,47 +927,47 @@ void CElementGen::UpdateChildParticleSystems(double dt) CGenDescription* ictsDesc = icts.m_token.GetObj(); if (!(x226_enableOPTS && ictsDesc->x45_31_x32_25_OPTS)) { - x234_activePartChildren.reserve(ncsyVal + x234_activePartChildren.size()); + x290_activePartChildren.reserve(ncsyVal + x290_activePartChildren.size()); for (int i=0 ; ixb8_xa4_IITS; - if (iits.m_found && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT && - x68_particleEmission == 1 && x50_curFrame >= x258_SISY && - ((x50_curFrame - x258_SISY) % x25c_PISY) == 0) + if (iits.m_found && x64_prevFrame != x50_curFrame && x50_curFrame < x268_PSLT && + x68_particleEmission == 1 && x50_curFrame >= x2a4_SISY && + ((x50_curFrame - x2a4_SISY) % x2a8_PISY) == 0) { CGenDescription* iitsDesc = iits.m_token.GetObj(); if (!(x226_enableOPTS && iitsDesc->x45_31_x32_25_OPTS)) { CElementGen* chGen = ConstructChildParticleSystem(iits.m_token); - x234_activePartChildren.emplace_back(chGen); + x290_activePartChildren.emplace_back(chGen); } } CSpawnSystemKeyframeData* kssm = desc->xd0_xbc_KSSM.get(); - if (kssm && x64_prevFrame != x50_curFrame && x50_curFrame < x214_PSLT) + if (kssm && x64_prevFrame != x50_curFrame && x50_curFrame < x268_PSLT) { std::vector& systems = kssm->GetSpawnedSystemsAtFrame(x50_curFrame); - x234_activePartChildren.reserve(x234_activePartChildren.size() + systems.size()); + x290_activePartChildren.reserve(x290_activePartChildren.size() + systems.size()); for (CSpawnSystemKeyframeData::CSpawnSystemKeyframeInfo& system : systems) { TLockedToken& token = system.GetToken(); if (!(x226_enableOPTS && token.GetObj()->x45_31_x32_25_OPTS)) { CElementGen* chGen = ConstructChildParticleSystem(token); - x234_activePartChildren.emplace_back(chGen); + x290_activePartChildren.emplace_back(chGen); } } } SSwooshGeneratorDesc& sswh = desc->xd4_xc0_SSWH; - if (sswh.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x270_SSSD) + if (sswh.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x2ac_SSSD) { CParticleSwoosh* sswhGen = new CParticleSwoosh(sswh.m_token, 0); sswhGen->SetGlobalTranslation(x88_globalTranslation); @@ -965,7 +979,7 @@ void CElementGen::UpdateChildParticleSystems(double dt) } SElectricGeneratorDesc& selc = desc->xec_xd8_SELC; - if (selc.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x290_SESD) + if (selc.m_found && x64_prevFrame != x50_curFrame && x50_curFrame == x2bc_SESD) { CParticleElectric* selcGen = new CParticleElectric(selc.m_token); selcGen->SetGlobalTranslation(x88_globalTranslation); @@ -976,7 +990,7 @@ void CElementGen::UpdateChildParticleSystems(double dt) x280_elscChildren.emplace_back(selcGen); } - for (auto p = x234_activePartChildren.begin() ; p != x234_activePartChildren.end() ;) + for (auto p = x290_activePartChildren.begin() ; p != x290_activePartChildren.end() ;) { std::unique_ptr& ch = *p; @@ -989,7 +1003,7 @@ void CElementGen::UpdateChildParticleSystems(double dt) ch->Update(dt); if (ch->IsSystemDeletable()) { - p = x234_activePartChildren.erase(p); + p = x290_activePartChildren.erase(p); continue; } @@ -1000,9 +1014,9 @@ void CElementGen::UpdateChildParticleSystems(double dt) { std::unique_ptr& ch = *p; - if (x214_PSLT <= x50_curFrame) + if (x268_PSLT <= x50_curFrame) { - if (x214_PSLT == x50_curFrame && x64_prevFrame != x50_curFrame) + if (x268_PSLT == x50_curFrame && x64_prevFrame != x50_curFrame) { ch->SetTranslation(x7c_translation); ch->SetOrientation(x178_orientation); @@ -1023,9 +1037,9 @@ void CElementGen::UpdateChildParticleSystems(double dt) { std::unique_ptr& ch = *p; - if ((x50_curFrame == x270_SSSD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) + if ((x50_curFrame == x2ac_SSSD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) { - zeus::CVector3f trans = x7c_translation + x274_SSPO; + zeus::CVector3f trans = x7c_translation + x2b0_SSPO; ch->SetTranslation(trans); ch->SetOrientation(x178_orientation); } @@ -1044,9 +1058,9 @@ void CElementGen::UpdateChildParticleSystems(double dt) { std::unique_ptr& ch = *p; - if ((x50_curFrame == x290_SESD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) + if ((x50_curFrame == x2bc_SESD || x224_24_translationDirty) && x64_prevFrame != x50_curFrame) { - zeus::CVector3f trans = x7c_translation + x294_SEPO; + zeus::CVector3f trans = x7c_translation + x2c0_SEPO; ch->SetTranslation(trans); ch->SetOrientation(x178_orientation); } @@ -1076,7 +1090,7 @@ void CElementGen::UpdateLightParameters() if (lint) lint->GetValue(x50_curFrame, x2e4_LINT); - switch (x2dc_lightType) + switch (x308_lightType) { default: case LightType::None: @@ -1091,7 +1105,7 @@ void CElementGen::UpdateLightParameters() if (lfor) lfor->GetValue(x50_curFrame, x304_LFOR); - if (x2dc_lightType == LightType::Spot) + if (x308_lightType == LightType::Spot) { CRealElement* lsla = desc->x11c_x108_LSLA.get(); if (lsla) @@ -1100,7 +1114,7 @@ void CElementGen::UpdateLightParameters() } case LightType::Directional: { - if (x2dc_lightType != LightType::Custom) + if (x308_lightType != LightType::Custom) { CVectorElement* ldir = desc->x110_xfc_LDIR.get(); if (ldir) @@ -1114,7 +1128,7 @@ u32 CElementGen::GetParticleCountAllInternal() const { u32 ret = x208_activeParticleCount; - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ret += ch->GetParticleCountAll(); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -1125,8 +1139,8 @@ u32 CElementGen::GetParticleCountAllInternal() const void CElementGen::EndLifetime() { - x214_PSLT = 0; - for (std::unique_ptr& ch : x234_activePartChildren) + x268_PSLT = 0; + for (std::unique_ptr& ch : x290_activePartChildren) ch->EndLifetime(); for (std::unique_ptr& ch : x248_finishPartChildren) ch->EndLifetime(); @@ -1152,7 +1166,7 @@ void CElementGen::BuildParticleSystemBounds() zeus::CAABox aabb; bool accumulated = false; - for (std::unique_ptr& ch : x234_activePartChildren) + for (std::unique_ptr& ch : x290_activePartChildren) { auto chBounds = ch->GetBounds(); if (chBounds) @@ -1212,7 +1226,7 @@ void CElementGen::BuildParticleSystemBounds() u32 CElementGen::GetSystemCount() { u32 ret = 0; - for (const std::unique_ptr& child : x234_activePartChildren) + for (const std::unique_ptr& child : x290_activePartChildren) ret += child->GetSystemCount(); for (const std::unique_ptr& child : x248_finishPartChildren) @@ -1231,10 +1245,10 @@ void CElementGen::Render() x22c_backupLightActive = CGraphics::g_LightActive; CGraphics::DisableAllLights(); - for (std::unique_ptr& child : x234_activePartChildren) + for (std::unique_ptr& child : x290_activePartChildren) child->Render(); - if (x214_PSLT <= x50_curFrame) + if (x268_PSLT <= x50_curFrame) for (std::unique_ptr& child : x248_finishPartChildren) child->Render(); @@ -1244,13 +1258,13 @@ void CElementGen::Render() for (std::unique_ptr& child : x280_elscChildren) child->Render(); - if (x2c_particleLists.size()) + if (x30_particleLists.size()) { SParticleModel& pmdl = desc->x5c_x48_PMDL; if (pmdl.m_found || desc->x45_24_x31_26_PMUS) RenderModels(); - if (x225_26_LINE) + if (x26c_31_LINE) RenderLines(); else RenderParticles(); @@ -1265,7 +1279,7 @@ void CElementGen::RenderModels() if (x225_29_modelsUseLights) CGraphics::SetLightState(x22c_backupLightActive); - CGlobalRandom gr(x230_randState); + CGlobalRandom gr(x27c_randState); SUVElementSet uvs = {0.f, 0.f, 1.f, 1.f}; CUVElement* texr = desc->x54_x40_TEXR.get(); @@ -1296,7 +1310,7 @@ void CElementGen::RenderModels() if (texr) { - CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; + CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx]; int partFrame = x50_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex->Load(0, CTexture::EClampMode::One); @@ -1338,8 +1352,8 @@ void CElementGen::RenderModels() zeus::CColor col = {1.f, 1.f, 1.f, 1.f}; zeus::CVector3f pmopVec; - auto matrixIt = x3c_parentMatrices.begin(); - for (CParticleListItem& item : x2c_particleLists) + auto matrixIt = x60_parentMatrices.begin(); + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; g_currentParticle = &particle; @@ -1454,7 +1468,7 @@ void CElementGen::RenderModels() void CElementGen::RenderLines() { CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x230_randState); + CGlobalRandom gr(x27c_randState); zeus::CTransform systemViewPointMatrix(CGraphics::g_ViewMatrix); systemViewPointMatrix.origin.zeroOut(); @@ -1488,7 +1502,7 @@ void CElementGen::RenderLines() zeus::CColor moduColor = zeus::CColor::skWhite; if (texr) { - CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; + CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx]; int partFrame = x50_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex->Load(0, CTexture::EClampMode::One); @@ -1515,7 +1529,7 @@ void CElementGen::RenderLines() m_lineRenderer->Reset(); - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; g_currentParticle = &particle; @@ -1536,7 +1550,7 @@ void CElementGen::RenderLines() texr->GetValueUV(partFrame, uvs); zeus::CVector3f dVec = particle.x4_pos - particle.x10_prevPos; - if (x225_27_FXLL) + if (x26d_24_FXLL) if (dVec.magSquared() >= 0.f) dVec.normalize(); @@ -1564,7 +1578,7 @@ void CElementGen::RenderLines() void CElementGen::RenderParticles() { CGenDescription* desc = x1c_genDesc.GetObj(); - CGlobalRandom gr(x230_randState); + CGlobalRandom gr(x27c_randState); CUVElement* texr = desc->x54_x40_TEXR.get(); CUVElement* tind = desc->x58_x44_TIND.get(); @@ -1608,7 +1622,7 @@ void CElementGen::RenderParticles() if (texr) { - CParticle& target = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; + CParticle& target = g_StaticParticleList[x30_particleLists[0].x0_partIdx]; int partFrame = x50_curFrame - target.x28_startFrame; cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex->Load(0, CTexture::EClampMode::One); @@ -1628,13 +1642,13 @@ void CElementGen::RenderParticles() if (desc->x44_28_x30_28_SORT) { - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos); } - std::sort(x2c_particleLists.begin(), x2c_particleLists.end(), + std::sort(x30_particleLists.begin(), x30_particleLists.end(), [](const CParticleListItem& a, const CParticleListItem& b) -> bool {return a.x4_viewPoint[1] >= b.x4_viewPoint[1];}); } @@ -1657,17 +1671,17 @@ void CElementGen::RenderParticles() { case CElementGenShaders::EShaderClass::Tex: g_instTexData.clear(); - g_instTexData.reserve(x2c_particleLists.size()); + g_instTexData.reserve(x30_particleLists.size()); break; case CElementGenShaders::EShaderClass::NoTex: g_instNoTexData.clear(); - g_instNoTexData.reserve(x2c_particleLists.size()); + g_instNoTexData.reserve(x30_particleLists.size()); break; default: Log.report(logvisor::Fatal, "unexpected particle shader class"); break; } - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; g_currentParticle = &particle; @@ -1788,18 +1802,18 @@ void CElementGen::RenderParticles() { case CElementGenShaders::EShaderClass::Tex: g_instTexData.clear(); - g_instTexData.reserve(x2c_particleLists.size() * mbspVal); + g_instTexData.reserve(x30_particleLists.size() * mbspVal); break; case CElementGenShaders::EShaderClass::NoTex: g_instNoTexData.clear(); - g_instNoTexData.reserve(x2c_particleLists.size() * mbspVal); + g_instNoTexData.reserve(x30_particleLists.size() * mbspVal); break; default: Log.report(logvisor::Fatal, "unexpected particle shader class"); break; } float mbspFac = 1.f / float(mbspVal); - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; g_currentParticle = &particle; @@ -1956,7 +1970,7 @@ void CElementGen::RenderParticlesIndirectTexture() } CUVElement* texr = desc->x54_x40_TEXR.get(); - CParticle& firstParticle = g_StaticParticleList[x2c_particleLists[0].x0_partIdx]; + CParticle& firstParticle = g_StaticParticleList[x30_particleLists[0].x0_partIdx]; int partFrame = x50_curFrame - firstParticle.x28_startFrame; CTexture* cachedTex = texr->GetValueTexture(partFrame).GetObj(); cachedTex->Load(0, CTexture::EClampMode::One); @@ -1977,21 +1991,21 @@ void CElementGen::RenderParticlesIndirectTexture() if (desc->x44_28_x30_28_SORT) { - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; item.x4_viewPoint = systemCameraMatrix * ((particle.x4_pos - particle.x10_prevPos) * x60_timeDeltaScale + particle.x10_prevPos); } - std::sort(x2c_particleLists.begin(), x2c_particleLists.end(), + std::sort(x30_particleLists.begin(), x30_particleLists.end(), [](const CParticleListItem& a, const CParticleListItem& b) -> bool {return a.x4_viewPoint[1] >= b.x4_viewPoint[1];}); } g_instIndTexData.clear(); - g_instIndTexData.reserve(x2c_particleLists.size()); + g_instIndTexData.reserve(x30_particleLists.size()); - for (CParticleListItem& item : x2c_particleLists) + for (CParticleListItem& item : x30_particleLists) { CParticle& particle = g_StaticParticleList[item.x0_partIdx]; g_currentParticle = &particle; @@ -2066,7 +2080,7 @@ void CElementGen::SetOrientation(const zeus::CTransform& orientation) x178_orientation = orientation; x1a8_orientationInverse = x178_orientation.inverse(); - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetOrientation(orientation); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2083,24 +2097,24 @@ void CElementGen::SetTranslation(const zeus::CVector3f& translation) { x7c_translation = translation; - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetTranslation(translation); for (const std::unique_ptr& ch : x248_finishPartChildren) ch->SetTranslation(translation); for (const std::unique_ptr& ch : x260_swhcChildren) - ch->SetTranslation(translation + x274_SSPO); + ch->SetTranslation(translation + x2b0_SSPO); for (const std::unique_ptr& ch : x280_elscChildren) - ch->SetTranslation(translation + x294_SEPO); + ch->SetTranslation(translation + x2c0_SEPO); } void CElementGen::SetGlobalOrientation(const zeus::CTransform& rotation) { x1d8_globalOrientation.setRotation(rotation); - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetGlobalOrientation(x1d8_globalOrientation); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2114,7 +2128,7 @@ void CElementGen::SetGlobalTranslation(const zeus::CVector3f& translation) { x88_globalTranslation = translation; - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetGlobalTranslation(translation); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2133,7 +2147,7 @@ void CElementGen::SetGlobalScale(const zeus::CVector3f& scale) xac_globalScaleTransform = zeus::CTransform::Scale(scale); xdc_globalScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetGlobalScale(scale); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2152,7 +2166,7 @@ void CElementGen::SetLocalScale(const zeus::CVector3f& scale) x118_localScaleTransform = zeus::CTransform::Scale(scale); x148_localScaleTransformInverse = zeus::CTransform::Scale(zeus::CVector3f::skOne / scale); - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetLocalScale(scale); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2163,7 +2177,7 @@ void CElementGen::SetParticleEmission(bool enabled) { x68_particleEmission = enabled; - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetParticleEmission(enabled); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2180,7 +2194,7 @@ void CElementGen::SetModulationColor(const zeus::CColor& color) { x30c_moduColor = color; - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->SetModulationColor(color); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2225,7 +2239,7 @@ const zeus::CColor& CElementGen::GetModulationColor() const bool CElementGen::IsSystemDeletable() const { - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) if (!ch->IsSystemDeletable()) return false; @@ -2241,7 +2255,7 @@ bool CElementGen::IsSystemDeletable() const if (!ch->IsSystemDeletable()) return false; - if (x214_PSLT < x50_curFrame && x208_activeParticleCount == 0) + if (x268_PSLT < x50_curFrame && x208_activeParticleCount == 0) return true; return false; @@ -2262,12 +2276,12 @@ u32 CElementGen::GetParticleCount() const bool CElementGen::SystemHasLight() const { - return x2dc_lightType != LightType::None; + return x308_lightType != LightType::None; } CLight CElementGen::GetLight() const { - switch (x2dc_lightType) + switch (x308_lightType) { case LightType::Directional: return CLight::BuildDirectional(x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT); @@ -2275,9 +2289,9 @@ CLight CElementGen::GetLight() const return CLight::BuildSpot(x2e8_LOFF, x2f4_LDIR.normalized(), x2e0_LCLR * x2e4_LINT, x308_LSLA); default: { - float quad = x300_falloffType == EFalloffType::Quadratic ? x304_LFOR : 0.f; - float linear = x300_falloffType == EFalloffType::Linear ? x304_LFOR : 0.f; - float constant = x300_falloffType == EFalloffType::Constant ? 1.f : 0.f; + float quad = x32c_falloffType == EFalloffType::Quadratic ? x304_LFOR : 0.f; + float linear = x32c_falloffType == EFalloffType::Linear ? x304_LFOR : 0.f; + float constant = x32c_falloffType == EFalloffType::Constant ? 1.f : 0.f; return CLight::BuildCustom(x2e8_LOFF, {1.f, 0.f, 0.f}, x2e0_LCLR, constant, linear, quad, x2e4_LINT, 0.f, 0.f); } @@ -2291,16 +2305,16 @@ bool CElementGen::GetParticleEmission() const void CElementGen::DestroyParticles() { - for (CParticleListItem& p : x2c_particleLists) + for (CParticleListItem& p : x30_particleLists) { g_StaticFreeList[++g_FreeIndex] = p.x0_partIdx; g_StaticParticleList[p.x0_partIdx].x0_endFrame = -1; } - x2c_particleLists.clear(); - x3c_parentMatrices.clear(); + x30_particleLists.clear(); + x60_parentMatrices.clear(); - for (const std::unique_ptr& ch : x234_activePartChildren) + for (const std::unique_ptr& ch : x290_activePartChildren) ch->DestroyParticles(); for (const std::unique_ptr& ch : x248_finishPartChildren) @@ -2309,9 +2323,9 @@ void CElementGen::DestroyParticles() void CElementGen::Reset() { - x2c_particleLists.clear(); - x3c_parentMatrices.clear(); - x234_activePartChildren.clear();; + x30_particleLists.clear(); + x60_parentMatrices.clear(); + x290_activePartChildren.clear(); x248_finishPartChildren.clear(); x280_elscChildren.clear(); x260_swhcChildren.clear(); diff --git a/Runtime/Particle/CElementGen.hpp b/Runtime/Particle/CElementGen.hpp index 8270dc48b..ac5bc451d 100644 --- a/Runtime/Particle/CElementGen.hpp +++ b/Runtime/Particle/CElementGen.hpp @@ -78,8 +78,8 @@ private: friend class CElementGenShaders; TLockedToken x1c_genDesc; EModelOrientationType x28_orientType; - std::vector x2c_particleLists; - std::vector x3c_parentMatrices; + std::vector x30_particleLists; + std::vector x60_parentMatrices; u32 x4c_internalStartFrame = 0; u32 x50_curFrame = 0; double x58_curSeconds = 0.f; @@ -87,12 +87,12 @@ private: u32 x64_prevFrame = -1; bool x68_particleEmission = true; float x6c_generatorRemainder = 0.f; - int x70_MAXP = 0; - u16 x74_randomSeed = 99; + int x90_MAXP = 0; + u16 x94_randomSeed = 99; float x78_generatorRate = 1.f; zeus::CVector3f x7c_translation; zeus::CVector3f x88_globalTranslation; - zeus::CVector3f x94_POFS; + zeus::CVector3f xf4_POFS; zeus::CVector3f xa0_globalScale = {1.f, 1.f, 1.f}; zeus::CTransform xac_globalScaleTransform = zeus::CTransform::Identity(); zeus::CTransform xdc_globalScaleTransformInverse = zeus::CTransform::Identity(); @@ -105,7 +105,7 @@ private: u32 x208_activeParticleCount = 0; u32 x20c_recursiveParticleCount = 0; u32 x210_curEmitterFrame = 0; - int x214_PSLT = 90;//0x7fffff; + int x268_PSLT = 90;//0x7fffff; zeus::CVector3f x218_PSIV; bool x224_24_translationDirty = false; bool x224_25_LIT_; @@ -117,38 +117,48 @@ private: bool x224_31_VMD2; bool x225_24_VMD3; bool x225_25_VMD4; - bool x225_26_LINE; - bool x225_27_FXLL; bool x225_28_warmedUp = false; bool x225_29_modelsUseLights = false; bool x226_enableOPTS; int x228_MBSP = 0; int m_maxMBSP = 0; + + union + { + struct + { + bool x26c_24_ : 1; + bool x26c_31_LINE : 1; + bool x26d_24_FXLL : 1; + }; + u32 _dummy = 0; + }; + ERglLightBits x22c_backupLightActive = ERglLightBits::None; - CRandom16 x230_randState; - std::vector> x234_activePartChildren; - int x244_CSSD = 0; + CRandom16 x27c_randState; + std::vector> x290_activePartChildren; + int x2a0_CSSD = 0; std::vector> x248_finishPartChildren; - int x258_SISY = 16; - int x25c_PISY = 16; + int x2a4_SISY = 16; + int x2a8_PISY = 16; u32 x260_cumulativeParticles = 0; /* Retail */ std::vector> x260_swhcChildren; - int x270_SSSD = 0; - zeus::CVector3f x274_SSPO; + int x2ac_SSSD = 0; + zeus::CVector3f x2b0_SSPO; std::vector> x280_elscChildren; - int x290_SESD = 0; - zeus::CVector3f x294_SEPO; + int x2bc_SESD = 0; + zeus::CVector3f x2c0_SEPO; float x2a0 = 0.f; float x2a4 = 0.f; zeus::CVector3f x2a8_aabbMin; zeus::CVector3f x2b4_aabbMax; float x2c0_maxSize = 0.f; zeus::CAABox x2c4_systemBounds = zeus::CAABox::skInvertedBox; - LightType x2dc_lightType; + LightType x308_lightType; zeus::CColor x2e0_LCLR = zeus::CColor::skWhite; float x2e4_LINT = 1.f; zeus::CVector3f x2e8_LOFF; zeus::CVector3f x2f4_LDIR = {1.f, 0.f, 0.f}; - EFalloffType x300_falloffType = EFalloffType::Linear; + EFalloffType x32c_falloffType = EFalloffType::Linear; float x304_LFOR = 1.f; float x308_LSLA = 45.f; zeus::CColor x30c_moduColor = {1.f, 1.f, 1.f, 1.f}; @@ -185,7 +195,7 @@ public: else x78_generatorRate = 0.0f; - for (std::unique_ptr& child : x234_activePartChildren) + for (std::unique_ptr& child : x290_activePartChildren) child->SetGeneratorRateScalar(x78_generatorRate); for (std::unique_ptr& child : x248_finishPartChildren) @@ -241,6 +251,8 @@ public: bool GetParticleEmission() const; void DestroyParticles(); void Reset(); + size_t GetNumActiveChildParticles() const { return x290_activePartChildren.size(); } + CElementGen& GetActiveChildParticle(size_t idx) const { return *x290_activePartChildren[idx]; } static void SetMoveRedToAlphaBuffer(bool); }; diff --git a/specter b/specter index f5f78fdee..2faf7c87e 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit f5f78fdeefd8a0d1a708ca31df8dc2cb2adc8482 +Subproject commit 2faf7c87ed0548cd9152de4d1acd0791ba118308