metaforce/Runtime/Graphics/Shaders/CFluidPlaneShader.hpp

240 lines
8.4 KiB
C++

#ifndef CFLUIDPLANESHADER_HPP
#define CFLUIDPLANESHADER_HPP
#include "RetroTypes.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include "CModelShaders.hpp"
#include "boo/graphicsdev/GL.hpp"
#include "boo/graphicsdev/D3D.hpp"
#include "boo/graphicsdev/Metal.hpp"
#include "boo/graphicsdev/Vulkan.hpp"
#include "World/CFluidPlaneManager.hpp"
#include "Graphics/CTexture.hpp"
#include "CToken.hpp"
#include "zeus/CAABox.hpp"
namespace urde
{
struct SFluidPlaneShaderInfo
{
EFluidType m_type;
bool m_hasPatternTex1;
bool m_hasPatternTex2;
bool m_hasColorTex;
bool m_hasBumpMap;
bool m_hasEnvMap;
bool m_hasEnvBumpMap;
bool m_hasLightmap;
bool m_tessellation;
bool m_doubleLightmapBlend;
bool m_additive;
SFluidPlaneShaderInfo(EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex,
bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap,
bool tessellation, bool doubleLightmapBlend, bool additive)
: m_type(type), m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex),
m_hasBumpMap(hasBumpMap), m_hasEnvMap(hasEnvMap), m_hasEnvBumpMap(hasEnvBumpMap), m_hasLightmap(hasLightmap),
m_tessellation(tessellation), m_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive)
{}
};
struct SFluidPlaneDoorShaderInfo
{
bool m_hasPatternTex1;
bool m_hasPatternTex2;
bool m_hasColorTex;
SFluidPlaneDoorShaderInfo(bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex)
: m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex)
{}
};
class CFluidPlaneShader
{
public:
struct Vertex
{
zeus::CVector3f m_pos;
zeus::CVector3f m_norm;
zeus::CVector3f m_binorm;
zeus::CVector3f m_tangent;
zeus::CColor m_color;
Vertex() = default;
Vertex(const zeus::CVector3f& position) : m_pos(position) {}
Vertex(const zeus::CVector3f& position, const zeus::CColor& color)
: m_pos(position), m_color(color) {}
Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal,
const zeus::CColor& color)
: m_pos(position), m_norm(normal), m_color(color) {}
Vertex(const zeus::CVector3f& position, const zeus::CVector3f& normal,
const zeus::CVector3f& binormal, const zeus::CVector3f& tangent,
const zeus::CColor& color)
: m_pos(position), m_norm(normal), m_binorm(binormal), m_tangent(tangent), m_color(color) {}
};
struct PatchVertex
{
zeus::CVector4f m_pos;
float m_outerLevels[4] = {};
float m_innerLevels[4] = {};
};
struct RenderSetupInfo
{
zeus::CMatrix4f texMtxs[6];
zeus::CMatrix4f normMtx;
float indScale = 1.f;
zeus::CColor kColors[4];
std::vector<CLight> lights;
};
private:
struct ShaderPair
{
boo::ObjToken<boo::IShaderPipeline> m_regular;
boo::ObjToken<boo::IShaderPipeline> m_tessellation;
void reset()
{
m_regular.reset();
m_tessellation.reset();
}
};
struct BindingPair
{
boo::ObjToken<boo::IShaderDataBinding> m_regular;
boo::ObjToken<boo::IShaderDataBinding> m_tessellation;
};
class Cache
{
ShaderPair m_cache[1024] = {};
ShaderPair m_doorCache[8] = {};
ShaderPair&
CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; }
ShaderPair&
CacheSlot(const SFluidPlaneDoorShaderInfo& info, int i) { return m_doorCache[i]; }
static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info);
static u16 MakeCacheKey(const SFluidPlaneDoorShaderInfo& info);
public:
template<class T>
ShaderPair GetOrBuildShader(const T& info);
void Clear();
};
static Cache _cache;
struct Ripple
{
zeus::CVector4f center; // time, distFalloff
zeus::CVector4f params; // amplitude, lookupPhase, lookupTime
};
struct Uniform
{
zeus::CMatrix4f m_mv;
zeus::CMatrix4f m_mvNorm;
zeus::CMatrix4f m_proj;
zeus::CMatrix4f m_texMtxs[6];
Ripple m_ripple[20];
zeus::CVector4f m_colorMul;
zeus::CVector4f m_pad[3]; // rippleNormResolution, Pad out to 1280 bytes
CModelShaders::LightingUniform m_lighting;
zeus::CVector3f m_pad2; // Pad out to 768 bytes
};
TLockedToken<CTexture> m_patternTex1;
TLockedToken<CTexture> m_patternTex2;
TLockedToken<CTexture> m_colorTex;
TLockedToken<CTexture> m_bumpMap;
TLockedToken<CTexture> m_envMap;
TLockedToken<CTexture> m_envBumpMap;
TLockedToken<CTexture> m_lightmap;
boo::ObjToken<boo::ITextureS> m_rippleMap;
boo::ObjToken<boo::IGraphicsBufferD> m_vbo;
boo::ObjToken<boo::IGraphicsBufferD> m_pvbo;
boo::ObjToken<boo::IGraphicsBufferD> m_uniBuf;
BindingPair m_dataBind;
int m_lastBind = -1;
#if BOO_HAS_GL
static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static ShaderPair BuildShader(boo::GLDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
BindingPair BuildBinding(boo::GLDataFactory::Context& ctx, const ShaderPair& pipeline);
#endif
#if _WIN32
static ShaderPair BuildShader(boo::D3DDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static ShaderPair BuildShader(boo::D3DDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
BindingPair BuildBinding(boo::D3DDataFactory::Context& ctx, const ShaderPair& pipeline);
#endif
#if BOO_HAS_METAL
static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static ShaderPair BuildShader(boo::MetalDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
BindingPair BuildBinding(boo::MetalDataFactory::Context& ctx, const ShaderPair& pipeline);
#endif
#if BOO_HAS_VULKAN
static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static ShaderPair BuildShader(boo::VulkanDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
BindingPair BuildBinding(boo::VulkanDataFactory::Context& ctx, const ShaderPair& pipeline);
#endif
template <class F> static void _Shutdown();
void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount);
public:
CFluidPlaneShader(EFluidType type,
const TLockedToken<CTexture>& patternTex1,
const TLockedToken<CTexture>& patternTex2,
const TLockedToken<CTexture>& colorTex,
const TLockedToken<CTexture>& bumpMap,
const TLockedToken<CTexture>& envMap,
const TLockedToken<CTexture>& envBumpMap,
const TLockedToken<CTexture>& lightmap,
const boo::ObjToken<boo::ITextureS>& rippleMap,
bool doubleLightmapBlend, bool additive, u32 maxVertCount);
CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
const TLockedToken<CTexture>& patternTex2,
const TLockedToken<CTexture>& colorTex,
u32 maxVertCount);
void prepareDraw(const RenderSetupInfo& info);
void prepareDraw(const RenderSetupInfo& info,
const zeus::CVector3f& waterCenter,
const CRippleManager& rippleManager,
const zeus::CColor& colorMul,
float rippleNormResolution);
void bindRegular()
{
if (m_lastBind != 0)
{
CGraphics::SetShaderDataBinding(m_dataBind.m_regular);
m_lastBind = 0;
}
}
bool bindTessellation()
{
if (m_lastBind != 1)
{
CGraphics::SetShaderDataBinding(m_dataBind.m_tessellation);
m_lastBind = 1;
}
return true;
}
void doneDrawing() { m_lastBind = -1; }
void loadVerts(const std::vector<Vertex>& verts, const std::vector<PatchVertex>& pVerts);
static void Shutdown();
};
}
#endif // CFLUIDPLANESHADER_HPP