text: #pragma once
  
  #include <array>
  #include <cstdint>
  #include <memory>
  
  #include "DataSpec/DNAMP1/CMDLMaterials.hpp"
  
  #include "Runtime/Graphics/CGraphics.hpp"
  
  #include <zeus/CColor.hpp>
  #include <zeus/CVector3f.hpp>
  #include <zeus/CVector4f.hpp>
  
  #define URDE_MAX_LIGHTS 8
  
  namespace hecl::Backend {
  class ShaderTag;
  }
  
  namespace urde {
  class CLight;
  
  enum class EExtendedShader : uint8_t {
    Flat,
    Lighting,
    ThermalModel,
    ThermalModelNoZTestNoZWrite,
    ThermalStatic,
    ThermalStaticNoZWrite,
    ForcedAlpha,
    ForcedAdditive,
    SolidColor,
    SolidColorAdditive,
    SolidColorFrontfaceCullLEqualAlphaOnly,
    SolidColorFrontfaceCullAlwaysAlphaOnly, // No Z-write or test
    SolidColorBackfaceCullLEqualAlphaOnly,
    SolidColorBackfaceCullGreaterAlphaOnly, // No Z-write
    MorphBallShadow,
    WorldShadow,
    ForcedAlphaNoCull,
    ForcedAdditiveNoCull,
    ForcedAlphaNoZWrite,
    ForcedAdditiveNoZWrite,
    ForcedAlphaNoCullNoZWrite,
    ForcedAdditiveNoCullNoZWrite,
    DepthGEqualNoZWrite,
    Disintegrate,
    ForcedAdditiveNoZWriteDepthGreater,
    ThermalCold,
    LightingAlphaWrite,
    LightingAlphaWriteNoZTestNoZWrite,
    LightingCubeReflection,
    LightingCubeReflectionWorldShadow,
    MAX
  };
  
  class CModelShaders {
    friend class CModel;
  
  public:
    struct Light {
      zeus::CVector3f pos;
      zeus::CVector3f dir;
      zeus::CColor color = zeus::skClear;
      std::array<float, 4> linAtt{1.f, 0.f, 0.f};
      std::array<float, 4> angAtt{1.f, 0.f, 0.f};
    };
  
    struct LightingUniform {
      std::array<Light, URDE_MAX_LIGHTS> lights;
      zeus::CColor ambient;
      std::array<zeus::CColor, 3> colorRegs;
      zeus::CColor mulColor;
      zeus::CColor addColor;
      CGraphics::CFogState fog;
  
      void ActivateLights(const std::vector<CLight>& lts);
    };
  
    struct ThermalUniform {
      zeus::CColor mulColor;
      zeus::CColor addColor;
    };
  
    struct SolidUniform {
      zeus::CColor solidColor;
    };
  
    struct MBShadowUniform {
      zeus::CVector4f shadowUp;
      float shadowId;
    };
  
    struct OneTextureUniform {
      zeus::CColor addColor;
      CGraphics::CFogState fog;
    };
  
    static void Initialize();
    static void Shutdown();
  
    using ShaderPipelinesData = std::array<boo::ObjToken<boo::IShaderPipeline>, size_t(EExtendedShader::MAX)>;
    using ShaderPipelines = std::shared_ptr<ShaderPipelinesData>;
  
    using Material = DataSpec::DNAMP1::HMDLMaterialSet::Material;
    static ShaderPipelines BuildExtendedShader(const hecl::Backend::ShaderTag& tag, const Material& material);
  
  private:
    static std::unordered_map<uint64_t, ShaderPipelines> g_ShaderPipelines;
  };
  
  } // namespace urde
  