#pragma once #include #include #include #include #include #include #include "Runtime/CRandom16.hpp" #include "Runtime/rstl.hpp" #include "Runtime/Graphics/CDrawable.hpp" #include "Runtime/Graphics/CDrawablePlaneObject.hpp" #include "Runtime/Graphics/CPVSVisSet.hpp" #include "Runtime/Graphics/CTexture.hpp" #include "Runtime/Graphics/IRenderer.hpp" #include "Runtime/Graphics/Shaders/CFogVolumeFilter.hpp" #include "Runtime/Graphics/Shaders/CFogVolumePlaneShader.hpp" #include "Runtime/Graphics/Shaders/CPhazonSuitFilter.hpp" #include "Runtime/Graphics/Shaders/CSpaceWarpFilter.hpp" #include "Runtime/Graphics/Shaders/CThermalColdFilter.hpp" #include "Runtime/Graphics/Shaders/CThermalHotFilter.hpp" #include "Runtime/World/CGameArea.hpp" #include #include #include #include #include #include #include namespace urde { class CBooModel; class CMemorySys; class CParticleGen; class CTexture; class IFactory; class IObjectStore; class Buckets; enum class EWorldShadowMode { None, WorldOnActorShadow, BallOnWorldShadow, BallOnWorldIds, MAX }; constexpr u32 skBallShadowIdSize = 64; constexpr u32 skReflectionDrawTargetSize = 256; class CBooRenderer final : public IRenderer { friend class CBooModel; friend class CGameArea; friend class CModel; friend class CMorphBallShadow; friend class CWorldTransManager; public: struct ScanlinesVert { hsh::float3 pos; }; struct CAreaListItem { const std::vector* x0_geometry; const CAreaRenderOctTree* x4_octTree; /* originally auto_ptrs of vectors */ std::unordered_map> x8_textures; std::vector x10_models; int x18_areaIdx; /* Per-area octree-word major, light bits minor */ std::vector x1c_lightOctreeWords; const SShader* m_shaderSet; CAreaListItem(const std::vector* geom, const CAreaRenderOctTree* octTree, std::unordered_map>&& textures, std::vector&& models, int areaIdx, const SShader* shaderSet); ~CAreaListItem(); }; struct CFogVolumeListItem { zeus::CTransform x0_transform; zeus::CColor x30_color; zeus::CAABox x34_aabb; TLockedToken x4c_model; // bool x58_b; Optional for model token const CSkinnedModel* x5c_skinnedModel = nullptr; CFogVolumeListItem(const zeus::CTransform& xf, const zeus::CColor& color, const zeus::CAABox& aabb, const TLockedToken* model, const CSkinnedModel* sModel) : x0_transform(xf), x30_color(color), x34_aabb(aabb), x5c_skinnedModel(sModel) { if (model) x4c_model = *model; } }; private: IFactory& x8_factory; IObjectStore& xc_store; TLockedToken m_staticEntropy; // CFont x10_fnt; u32 x18_ = 0; std::list x1c_areaListItems; zeus::CFrustum x44_frustumPlanes; TDrawableCallback xa8_drawableCallback; void* xac_callbackContext; zeus::CPlane xb0_viewPlane = {0.f, 1.f, 0.f, 0.f}; enum class EPVSMode { Mask, PVS, PVSAndMask } xc4_pvsMode = EPVSMode::Mask; std::optional xc8_pvs; u32 xe0_pvsAreaIdx = 0; // boo::ITextureS* xe4_blackTex = nullptr; bool xee_24_ : 1 = true; hsh::owner m_clearTexture; hsh::owner m_blackTexture; hsh::owner m_whiteTexture; std::unordered_map> m_colorTextures; hsh::owner x14c_reflectionTex; // boo::ITextureS* x150_mirrorRamp = nullptr; hsh::owner x1b8_fogVolumeRamp; hsh::owner x220_sphereRamp; TLockedToken m_thermoPaletteTex; hsh::texture2d x288_thermoPalette; TLockedToken m_ballFadeTex; hsh::texture2d m_ballFade; hsh::owner m_ballShadowId; hsh::owner> m_scanLinesEvenVBO; hsh::owner> m_scanLinesOddVBO; CRandom16 x2a8_thermalRand; std::list x2ac_fogVolumes; std::list m_fogVolumePlaneShaders; std::list::iterator m_nextFogVolumePlaneShader; std::list m_fogVolumeFilters; std::list::iterator m_nextFogVolumeFilter; std::list> x2c4_spaceWarps; u32 x2dc_reflectionAge = 2; zeus::CColor x2e0_ = zeus::skWhite; zeus::CVector3f x2e4_ = {0.f, 1.f, 0.f}; CSpaceWarpFilter m_spaceWarpFilter; float x2f0_thermalVisorLevel; zeus::CColor x2f4_thermColor; float x2f8_thermColdScale = 0.f; zeus::CColor x2fc_tevReg1Color = {1.f, 0.f, 1.f, 1.f}; std::optional m_thermColdFilter; std::optional m_thermHotFilter; std::vector x300_dynamicLights; u32 x310_phazonSuitMaskCountdown = 0; // std::unique_ptr x314_phazonSuitMask; CPhazonSuitFilter m_phazonSuitFilter; bool x318_24_refectionDirty : 1 = false; bool x318_25_drawWireframe : 1 = false; bool x318_26_requestRGBA6 : 1 = false; bool x318_27_currentRGBA6 : 1 = false; bool x318_28_disableFog : 1 = false; bool x318_29_thermalVisor : 1 = false; bool x318_30_inAreaDraw : 1 = false; bool x318_31_persistRGBA6 : 1 = false; bool m_thermalHotPass : 1 = false; void GenerateFogVolumeRampTex(); void GenerateSphereRampTex(); void GenerateScanLinesVBO(); void LoadThermoPalette(); void LoadBallFade(); void ActivateLightsForModel(CAreaListItem* item, CBooModel& model); void RenderBucketItems(CAreaListItem* item); void HandleUnsortedModel(CAreaListItem* item, CBooModel& model, const CModelFlags& flags); static void CalcDrawFogFan(const zeus::CPlane* planes, size_t numPlanes, const zeus::CVector3f* verts, size_t numVerts, size_t iteration, size_t level, CFogVolumePlaneShader& fogVol); static void DrawFogSlices(const zeus::CPlane* planes, size_t numPlanes, size_t iteration, const zeus::CVector3f& center, float delta, CFogVolumePlaneShader& fogVol); static void RenderFogVolumeModel(const zeus::CAABox& aabb, const CModel* model, const zeus::CTransform& modelMtx, const zeus::CTransform& viewMtx, const CSkinnedModel* sModel, int pass, 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); ~CBooRenderer() override; void AddWorldSurfaces(CBooModel& model); std::list::iterator FindStaticGeometry(const std::vector*); void AddStaticGeometry(const std::vector* geometry, const CAreaRenderOctTree* octTree, int areaIdx, const SShader* shaderSet) override; void EnablePVS(const CPVSVisSet& set, u32 areaIdx) override; void DisablePVS() override; void UpdateAreaUniforms(int areaIdx, EWorldShadowMode shadowMode = EWorldShadowMode::None, bool activateLights = true, int cubeFace = -1, const CModelFlags* ballShadowFlags = nullptr); void RemoveStaticGeometry(const std::vector*) override; void DrawAreaGeometry(int areaIdx, int mask, int targetMask) override; void DrawUnsortedGeometry(int areaIdx, int mask, int targetMask, bool shadowRender = false) override; void DrawSortedGeometry(int areaIdx, int mask, int targetMask) override; void DrawStaticGeometry(int areaIdx, int mask, int targetMask) override; void DrawModelFlat(const CModel& model, const CModelFlags& flags, bool unsortedOnly) override; void PostRenderFogs() override; void SetModelMatrix(const zeus::CTransform& xf) override; void AddParticleGen(CParticleGen& gen) override; void AddParticleGen(CParticleGen& gen, const zeus::CVector3f& pos, const zeus::CAABox& bounds) override; void AddPlaneObject(void* obj, const zeus::CAABox& aabb, const zeus::CPlane& plane, int type) override; void AddDrawable(void* obj, const zeus::CVector3f& pos, const zeus::CAABox& aabb, int mode, EDrawableSorting sorting) override; void SetDrawableCallback(TDrawableCallback cb, void* ctx) override; void SetWorldViewpoint(const zeus::CTransform& xf) override; void SetPerspective(float fovy, float width, float height, float znear, float zfar) override; void SetPerspective(float fovy, float aspect, float znear, float zfar) override; std::pair SetViewportOrtho(bool centered, float znear, float zfar) override; void SetClippingPlanes(const zeus::CFrustum& frustum) override; void SetViewport(int left, int bottom, int width, int height) override; void SetDepthReadWrite(bool test, bool write) override { CGraphics::SetDepthWriteMode(test, ERglEnum::LEqual, write); } void SetBlendMode_AdditiveAlpha() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::One, ERglLogicOp::Clear); } void SetBlendMode_AlphaBlended() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcAlpha, ERglBlendFactor::InvSrcAlpha, ERglLogicOp::Clear); } void SetBlendMode_NoColorWrite() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::Zero, ERglBlendFactor::One, ERglLogicOp::Clear); } void SetBlendMode_ColorMultiply() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::Zero, ERglBlendFactor::SrcColor, ERglLogicOp::Clear); } void SetBlendMode_InvertDst() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::InvSrcColor, ERglBlendFactor::Zero, ERglLogicOp::Clear); } void SetBlendMode_InvertSrc() override { CGraphics::SetBlendMode(ERglBlendMode::Logic, ERglBlendFactor::One, ERglBlendFactor::Zero, ERglLogicOp::InvCopy); } void SetBlendMode_Replace() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::Zero, ERglLogicOp::Clear); } void SetBlendMode_AdditiveDestColor() override { CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::SrcColor, ERglBlendFactor::One, ERglLogicOp::Clear); } void SetDebugOption(EDebugOption, int) override; void BeginScene() override; void EndScene() override; // void BeginPrimitive(EPrimitiveType, int); // void BeginLines(int); // void BeginLineStrip(int); // void BeginTriangles(int); // void BeginTriangleStrip(int); // void BeginTriangleFan(int); // void PrimVertex(const zeus::CVector3f&); // void PrimNormal(const zeus::CVector3f&); // void PrimColor(float, float, float, float); // void PrimColor(const zeus::CColor&); // void EndPrimitive(); void SetAmbientColor(const zeus::CColor& color) override; void DrawString(const char* string, int, int) override; u32 GetFPS() override; void CacheReflection(TReflectionCallback cb, void* ctx, bool clearAfter) override; void DrawSpaceWarp(const zeus::CVector3f& pt, float strength) override; void DrawThermalModel(const CModel& model, const zeus::CColor& multCol, const zeus::CColor& addCol) override; void DrawXRayOutline(const zeus::CAABox&) override; void SetWireframeFlags(int flags) override; void SetWorldFog(ERglFogMode mode, float startz, float endz, const zeus::CColor& color) override; void RenderFogVolume(const zeus::CColor& color, const zeus::CAABox& aabb, const TLockedToken* model, const CSkinnedModel* sModel) override; void SetThermal(bool thermal, float level, const zeus::CColor& color) override; void SetThermalColdScale(float scale) override; void DoThermalBlendCold() override; void DoThermalBlendHot() override; u32 GetStaticWorldDataSize() override; void PrepareDynamicLights(const std::vector& lights) override; void SetGXRegister1Color(const zeus::CColor& color) override; void SetWorldLightFadeLevel(float level) override; void SetWorldLightMultiplyColor(const zeus::CColor& col) override; 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); hsh::texture2d GetThermoPalette() const { return x288_thermoPalette; } hsh::texture2d GetFogRampTex() const { return x1b8_fogVolumeRamp.get(); } hsh::texture2d GetRandomStaticEntropyTex() const { return m_staticEntropy->GetBooTexture(); } auto GetScanLinesEvenVBO() const { return m_scanLinesEvenVBO.get(); } auto GetScanLinesOddVBO() const { return m_scanLinesOddVBO.get(); } hsh::texture2d GetClearTexture() const { return m_clearTexture.get(); } hsh::texture2d GetBlackTexture() const { return m_blackTexture.get(); } hsh::texture2d GetWhiteTexture() const { return m_whiteTexture.get(); } hsh::texture2d GetColorTexture(const zeus::CColor& color); static void BindMainDrawTarget() { CGraphics::g_SpareTexture.attach(); } void BindReflectionDrawTarget() { x14c_reflectionTex.attach(); } void BindBallShadowIdTarget() { m_ballShadowId.attach(); } void ResolveBallShadowIdTarget() { m_ballShadowId.resolve_color_binding(0, hsh::rect2d({0, 0}, {skBallShadowIdSize, skBallShadowIdSize}), false); } void FindOverlappingWorldModels(std::vector& modelBits, const zeus::CAABox& aabb) const; int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb); void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector& modelBits, const zeus::CAABox& aabb, float alpha); bool IsThermalVisorActive() const { return x318_29_thermalVisor; } bool IsThermalVisorHotPass() const { return m_thermalHotPass; } bool IsInAreaDraw() const { return x318_30_inAreaDraw; } }; } // namespace urde