#ifndef CFLUIDPLANESHADER_HPP #define CFLUIDPLANESHADER_HPP #include "RetroTypes.hpp" #include "boo/graphicsdev/IGraphicsDataFactory.hpp" #include "Runtime/World/CFluidPlane.hpp" #include "CModelShaders.hpp" #include "boo/graphicsdev/GL.hpp" #include "boo/graphicsdev/D3D.hpp" #include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Vulkan.hpp" namespace urde { struct SFluidPlaneShaderInfo { CFluidPlane::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_doubleLightmapBlend; bool m_additive; SFluidPlaneShaderInfo(CFluidPlane::EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex, bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap, 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_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 RenderSetupInfo { zeus::CMatrix4f texMtxs[6]; zeus::CMatrix4f normMtx; float indScale = 1.f; zeus::CColor kColors[4]; std::vector lights; }; private: class Cache { boo::ObjToken m_cache[1024] = {}; boo::ObjToken m_doorCache[8] = {}; boo::ObjToken& CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; } boo::ObjToken& CacheSlot(const SFluidPlaneDoorShaderInfo& info, int i) { return m_doorCache[i]; } static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info); static u16 MakeCacheKey(const SFluidPlaneDoorShaderInfo& info); public: template boo::ObjToken GetOrBuildShader(const T& info); void Clear(); }; static Cache _cache; struct Uniform { zeus::CMatrix4f m_mv; zeus::CMatrix4f m_mvNorm; zeus::CMatrix4f m_proj; zeus::CMatrix4f m_texMtxs[9]; // Pad out to 768 bytes CModelShaders::LightingUniform m_lighting; }; std::experimental::optional> m_patternTex1; std::experimental::optional> m_patternTex2; std::experimental::optional> m_colorTex; std::experimental::optional> m_bumpMap; std::experimental::optional> m_envMap; std::experimental::optional> m_envBumpMap; std::experimental::optional> m_lightmap; boo::ObjToken m_vbo; boo::ObjToken m_uniBuf; boo::ObjToken m_dataBind; static boo::ObjToken BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); static boo::ObjToken BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); boo::ObjToken BuildBinding(boo::GLDataFactory::Context& ctx, const boo::ObjToken& pipeline, bool door); #if _WIN32 static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); boo::IShaderDataBinding* BuildBinding(boo::ID3DDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door); #endif #if BOO_HAS_METAL static boo::ObjToken BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); static boo::ObjToken BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); boo::ObjToken BuildBinding(boo::MetalDataFactory::Context& ctx, const boo::ObjToken& pipeline, bool door); #endif #if BOO_HAS_VULKAN static boo::IShaderPipeline* BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info); static boo::IShaderPipeline* BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info); boo::IShaderDataBinding* BuildBinding(boo::VulkanDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door); #endif void PrepareBinding(const boo::ObjToken& pipeline, u32 maxVertCount, bool door); public: CFluidPlaneShader(CFluidPlane::EFluidType type, const std::experimental::optional>& patternTex1, const std::experimental::optional>& patternTex2, const std::experimental::optional>& colorTex, const std::experimental::optional>& bumpMap, const std::experimental::optional>& envMap, const std::experimental::optional>& envBumpMap, const std::experimental::optional>& lightmap, bool doubleLightmapBlend, bool additive, u32 maxVertCount); CFluidPlaneShader(const std::experimental::optional>& patternTex1, const std::experimental::optional>& patternTex2, const std::experimental::optional>& colorTex, u32 maxVertCount); void prepareDraw(const RenderSetupInfo& info); void loadVerts(const std::vector& verts); static void Shutdown() { _cache.Clear(); } }; } #endif // CFLUIDPLANESHADER_HPP