mirror of https://github.com/AxioDL/metaforce.git
326 lines
15 KiB
C++
326 lines
15 KiB
C++
#pragma once
|
|
|
|
#include <functional>
|
|
#include <list>
|
|
#include <optional>
|
|
#include <unordered_map>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#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 <zeus/CAABox.hpp>
|
|
#include <zeus/CColor.hpp>
|
|
#include <zeus/CFrustum.hpp>
|
|
#include <zeus/CPlane.hpp>
|
|
#include <zeus/CRectangle.hpp>
|
|
#include <zeus/CTransform.hpp>
|
|
#include <zeus/CVector3f.hpp>
|
|
|
|
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<CMetroidModelInstance>* x0_geometry;
|
|
const CAreaRenderOctTree* x4_octTree;
|
|
/* originally auto_ptrs of vectors */
|
|
std::unordered_map<CAssetId, TCachedToken<CTexture>> x8_textures;
|
|
std::vector<CBooModel*> x10_models;
|
|
int x18_areaIdx;
|
|
/* Per-area octree-word major, light bits minor */
|
|
std::vector<u32> x1c_lightOctreeWords;
|
|
const SShader* m_shaderSet;
|
|
|
|
CAreaListItem(const std::vector<CMetroidModelInstance>* geom, const CAreaRenderOctTree* octTree,
|
|
std::unordered_map<CAssetId, TCachedToken<CTexture>>&& textures, std::vector<CBooModel*>&& models,
|
|
int areaIdx, const SShader* shaderSet);
|
|
~CAreaListItem();
|
|
};
|
|
|
|
struct CFogVolumeListItem {
|
|
zeus::CTransform x0_transform;
|
|
zeus::CColor x30_color;
|
|
zeus::CAABox x34_aabb;
|
|
TLockedToken<CModel> 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<CModel>* 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<CTexture> m_staticEntropy;
|
|
// CFont x10_fnt;
|
|
u32 x18_ = 0;
|
|
std::list<CAreaListItem> 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<CPVSVisSet> xc8_pvs;
|
|
u32 xe0_pvsAreaIdx = 0;
|
|
|
|
// boo::ITextureS* xe4_blackTex = nullptr;
|
|
bool xee_24_ : 1 = true;
|
|
|
|
hsh::owner<hsh::texture2d> m_clearTexture;
|
|
hsh::owner<hsh::texture2d> m_blackTexture;
|
|
hsh::owner<hsh::texture2d> m_whiteTexture;
|
|
std::unordered_map<zeus::CColor, hsh::owner<hsh::texture2d>> m_colorTextures;
|
|
|
|
hsh::owner<hsh::render_texture2d> x14c_reflectionTex;
|
|
// boo::ITextureS* x150_mirrorRamp = nullptr;
|
|
hsh::owner<hsh::texture2d> x1b8_fogVolumeRamp;
|
|
hsh::owner<hsh::texture2d> x220_sphereRamp;
|
|
TLockedToken<CTexture> m_thermoPaletteTex;
|
|
hsh::texture2d x288_thermoPalette;
|
|
TLockedToken<CTexture> m_ballFadeTex;
|
|
hsh::texture2d m_ballFade;
|
|
hsh::owner<hsh::render_texture2d> m_ballShadowId;
|
|
|
|
hsh::owner<hsh::vertex_buffer<ScanlinesVert>> m_scanLinesEvenVBO;
|
|
hsh::owner<hsh::vertex_buffer<ScanlinesVert>> m_scanLinesOddVBO;
|
|
|
|
CRandom16 x2a8_thermalRand;
|
|
std::list<CFogVolumeListItem> x2ac_fogVolumes;
|
|
std::list<CFogVolumePlaneShader> m_fogVolumePlaneShaders;
|
|
std::list<CFogVolumePlaneShader>::iterator m_nextFogVolumePlaneShader;
|
|
std::list<CFogVolumeFilter> m_fogVolumeFilters;
|
|
std::list<CFogVolumeFilter>::iterator m_nextFogVolumeFilter;
|
|
std::list<std::pair<zeus::CVector3f, float>> 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<CThermalColdFilter> m_thermColdFilter;
|
|
std::optional<CThermalHotFilter> m_thermHotFilter;
|
|
|
|
std::vector<CLight> x300_dynamicLights;
|
|
|
|
u32 x310_phazonSuitMaskCountdown = 0;
|
|
// std::unique_ptr<CTexture> 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<CTexture>& indTex);
|
|
|
|
public:
|
|
CBooRenderer(IObjectStore& store, IFactory& resFac);
|
|
~CBooRenderer() override;
|
|
|
|
void AddWorldSurfaces(CBooModel& model);
|
|
|
|
std::list<CAreaListItem>::iterator FindStaticGeometry(const std::vector<CMetroidModelInstance>*);
|
|
void AddStaticGeometry(const std::vector<CMetroidModelInstance>* 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<CMetroidModelInstance>*) 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<zeus::CVector2f, zeus::CVector2f> 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<CModel>* 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<CLight>& 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<CTexture>& 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<u32>& modelBits, const zeus::CAABox& aabb) const;
|
|
int DrawOverlappingWorldModelIDs(int alphaVal, const std::vector<u32>& modelBits, const zeus::CAABox& aabb);
|
|
void DrawOverlappingWorldModelShadows(int alphaVal, const std::vector<u32>& 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
|