Implement CFluidPlaneGPU for GPU-computed water ripples

This commit is contained in:
Jack Andersen 2018-06-06 18:43:26 -10:00
parent e63102e180
commit ac424ff9eb
31 changed files with 1651 additions and 1060 deletions

View File

@ -62,7 +62,7 @@ struct Water : IScriptObject
Value<float> turbulenceAmplitudeMax;
Value<float> turbulenceAmplitudeMin;
Value<atVec4f> splashColor;
Value<atVec4f> unkColor;
Value<atVec4f> insideFogColor;
UniqueID32 splashParticle1;
UniqueID32 splashParticle2;
UniqueID32 splashParticle3;

View File

@ -590,12 +590,12 @@ void CCameraManager::UpdateFog(float dt, CStateManager& mgr)
{
zeus::CVector2f zRange(GetCurrentCamera(mgr)->GetNearClipDistance(),
CalculateFogDensity(mgr, water.GetPtr()));
x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, water->GetFogColor(), zRange);
x3c_fog.SetFogExplicit(ERglFogMode::PerspExp, water->GetInsideFogColor(), zRange);
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal)
mgr.GetCameraFilterPass(4).DisableFilter(0.f);
else
mgr.GetCameraFilterPass(4).SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen,
0.f, water->GetFogColor(), {});
0.f, water->GetInsideFogColor(), {});
}
xa0_26_inWater = true;
}

View File

@ -1,4 +1,6 @@
#include "CFluidPlaneShader.hpp"
#include "World/CRipple.hpp"
#include "World/CRippleManager.hpp"
namespace urde
{
@ -11,9 +13,9 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
switch (info.m_type)
{
case CFluidPlane::EFluidType::NormalWater:
case CFluidPlane::EFluidType::PhazonFluid:
case CFluidPlane::EFluidType::Four:
case EFluidType::NormalWater:
case EFluidType::PhazonFluid:
case EFluidType::Four:
if (info.m_hasLightmap)
{
ret |= 1 << 2;
@ -29,7 +31,7 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
break;
case CFluidPlane::EFluidType::PoisonWater:
case EFluidType::PoisonWater:
ret |= 1;
if (info.m_hasLightmap)
@ -44,7 +46,7 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
break;
case CFluidPlane::EFluidType::Lava:
case EFluidType::Lava:
ret |= 2;
if (info.m_hasBumpMap)
@ -52,7 +54,7 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
break;
case CFluidPlane::EFluidType::ThickLava:
case EFluidType::ThickLava:
ret |= 3;
if (info.m_hasBumpMap)
@ -89,15 +91,15 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneDoorShaderInfo& info
}
template<class T>
boo::ObjToken<boo::IShaderPipeline> CFluidPlaneShader::Cache::GetOrBuildShader(const T& info)
CFluidPlaneShader::ShaderPair CFluidPlaneShader::Cache::GetOrBuildShader(const T& info)
{
u16 key = MakeCacheKey(info);
auto& slot = CacheSlot(info, key);
if (slot)
if (slot.m_regular)
return slot;
if (CGraphics::g_BooFactory == nullptr)
return nullptr;
return {};
CGraphics::CommitResources(
[&](boo::IGraphicsDataFactory::Context& ctx)
@ -132,9 +134,9 @@ boo::ObjToken<boo::IShaderPipeline> CFluidPlaneShader::Cache::GetOrBuildShader(c
return slot;
}
template boo::ObjToken<boo::IShaderPipeline>
template CFluidPlaneShader::ShaderPair
CFluidPlaneShader::Cache::GetOrBuildShader<SFluidPlaneShaderInfo>(const SFluidPlaneShaderInfo& info);
template boo::ObjToken<boo::IShaderPipeline>
template CFluidPlaneShader::ShaderPair
CFluidPlaneShader::Cache::GetOrBuildShader<SFluidPlaneDoorShaderInfo>(const SFluidPlaneDoorShaderInfo& info);
void CFluidPlaneShader::Cache::Clear()
@ -145,34 +147,36 @@ void CFluidPlaneShader::Cache::Clear()
p.reset();
}
void CFluidPlaneShader::PrepareBinding(const boo::ObjToken<boo::IShaderPipeline>& pipeline, u32 maxVertCount, bool door)
void CFluidPlaneShader::PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount)
{
CGraphics::CommitResources(
[&](boo::IGraphicsDataFactory::Context& ctx)
{
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
if (pipeline.m_tessellation)
m_pvbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(PatchVertex), maxVertCount);
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(Uniform), 1);
switch (ctx.platform())
{
#if BOO_HAS_GL
case boo::IGraphicsDataFactory::Platform::OpenGL:
m_dataBind = BuildBinding(static_cast<boo::GLDataFactory::Context&>(ctx), pipeline, door);
m_dataBind = BuildBinding(static_cast<boo::GLDataFactory::Context&>(ctx), pipeline);
break;
#endif
#if _WIN32
case boo::IGraphicsDataFactory::Platform::D3D11:
m_dataBind = BuildBinding(static_cast<boo::D3DDataFactory::Context&>(ctx), pipeline, door);
m_dataBind = BuildBinding(static_cast<boo::D3DDataFactory::Context&>(ctx), pipeline);
break;
#endif
#if BOO_HAS_METAL
case boo::IGraphicsDataFactory::Platform::Metal:
m_dataBind = BuildBinding(static_cast<boo::MetalDataFactory::Context&>(ctx), pipeline, door);
m_dataBind = BuildBinding(static_cast<boo::MetalDataFactory::Context&>(ctx), pipeline);
break;
#endif
#if BOO_HAS_VULKAN
case boo::IGraphicsDataFactory::Platform::Vulkan:
m_dataBind = BuildBinding(static_cast<boo::VulkanDataFactory::Context&>(ctx), pipeline, door);
m_dataBind = BuildBinding(static_cast<boo::VulkanDataFactory::Context&>(ctx), pipeline);
break;
#endif
default: break;
@ -210,14 +214,15 @@ void CFluidPlaneShader::Shutdown()
}
}
CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
const std::experimental::optional<TLockedToken<CTexture>>& bumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& envMap,
const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
CFluidPlaneShader::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)
: m_patternTex1(patternTex1),
m_patternTex2(patternTex2),
@ -225,7 +230,8 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
m_bumpMap(bumpMap),
m_envMap(envMap),
m_envBumpMap(envBumpMap),
m_lightmap(lightmap)
m_lightmap(lightmap),
m_rippleMap(rippleMap)
{
SFluidPlaneShaderInfo shaderInfo(type,
m_patternTex1.operator bool(),
@ -235,14 +241,15 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
m_envMap.operator bool(),
m_envBumpMap.operator bool(),
m_lightmap.operator bool(),
m_rippleMap.operator bool(),
doubleLightmapBlend, additive);
boo::ObjToken<boo::IShaderPipeline> pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount, false);
ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount);
}
CFluidPlaneShader::CFluidPlaneShader(const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
CFluidPlaneShader::CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
const TLockedToken<CTexture>& patternTex2,
const TLockedToken<CTexture>& colorTex,
u32 maxVertCount)
: m_patternTex1(patternTex1),
m_patternTex2(patternTex2),
@ -251,8 +258,8 @@ CFluidPlaneShader::CFluidPlaneShader(const std::experimental::optional<TLockedTo
SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(),
m_patternTex2.operator bool(),
m_colorTex.operator bool());
boo::ObjToken<boo::IShaderPipeline> pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount, true);
ShaderPair pipeline = _cache.GetOrBuildShader(shaderInfo);
PrepareBinding(pipeline, maxVertCount);
}
void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info)
@ -269,12 +276,56 @@ void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info)
uni.m_lighting.mulColor = info.kColors[3];
uni.m_lighting.fog.m_rangeScale = info.indScale;
m_uniBuf->unmap();
CGraphics::SetShaderDataBinding(m_dataBind);
}
void CFluidPlaneShader::loadVerts(const std::vector<Vertex>& verts)
void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info,
const zeus::CVector3f& waterCenter,
const CRippleManager& rippleManager,
const zeus::CColor& colorMul,
float rippleNormResolution)
{
Uniform& uni = *reinterpret_cast<Uniform*>(m_uniBuf->map(sizeof(Uniform)));
uni.m_mv = CGraphics::g_GXModelView.toMatrix4f();
uni.m_mvNorm = info.normMtx;
uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true);
for (int i=0 ; i<6 ; ++i)
uni.m_texMtxs[i] = info.texMtxs[i];
int i = 0;
for (const CRipple& ripple : rippleManager.GetRipples())
{
assert(i < 20 && "Too many ripples");
Ripple& rOut = uni.m_ripple[i++];
if (ripple.GetTime() >= ripple.GetTimeFalloff())
{
rOut.center.zeroOut();
rOut.params.zeroOut();
continue;
}
zeus::CVector3f localPos = ripple.GetCenter() - waterCenter;
rOut.center.x = localPos.x;
rOut.center.y = localPos.y;
rOut.center.z = ripple.GetTime() * ripple.GetOOTimeFalloff();
rOut.center.w = ripple.GetOODistanceFalloff();
rOut.params.x = ripple.GetAmplitude();
rOut.params.y = ripple.GetPhase();
rOut.params.z = (1.f - ripple.GetTime() * ripple.GetOOTimeFalloff() *
ripple.GetOOTimeFalloff()) * ripple.GetFrequency();
}
uni.m_colorMul = colorMul;
uni.m_pad[0].x = rippleNormResolution;
uni.m_lighting.ActivateLights(info.lights);
for (i=0 ; i<3 ; ++i)
uni.m_lighting.colorRegs[i] = info.kColors[i];
uni.m_lighting.mulColor = info.kColors[3];
uni.m_lighting.fog.m_rangeScale = info.indScale;
m_uniBuf->unmap();
}
void CFluidPlaneShader::loadVerts(const std::vector<Vertex>& verts, const std::vector<PatchVertex>& pVerts)
{
m_vbo->load(verts.data(), verts.size() * sizeof(Vertex));
if (m_pvbo)
m_pvbo->load(pVerts.data(), pVerts.size() * sizeof(PatchVertex));
}
}

View File

@ -3,19 +3,22 @@
#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"
#include "World/CFluidPlaneManager.hpp"
#include "Graphics/CTexture.hpp"
#include "CToken.hpp"
#include "zeus/CAABox.hpp"
namespace urde
{
struct SFluidPlaneShaderInfo
{
CFluidPlane::EFluidType m_type;
EFluidType m_type;
bool m_hasPatternTex1;
bool m_hasPatternTex2;
bool m_hasColorTex;
@ -23,15 +26,16 @@ struct SFluidPlaneShaderInfo
bool m_hasEnvMap;
bool m_hasEnvBumpMap;
bool m_hasLightmap;
bool m_tessellation;
bool m_doubleLightmapBlend;
bool m_additive;
SFluidPlaneShaderInfo(CFluidPlane::EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex,
SFluidPlaneShaderInfo(EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex,
bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap,
bool doubleLightmapBlend, bool additive)
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_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive)
m_tessellation(tessellation), m_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive)
{}
};
@ -70,6 +74,13 @@ public:
: 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];
@ -80,96 +91,145 @@ public:
};
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
{
boo::ObjToken<boo::IShaderPipeline> m_cache[1024] = {};
boo::ObjToken<boo::IShaderPipeline> m_doorCache[8] = {};
boo::ObjToken<boo::IShaderPipeline>&
ShaderPair m_cache[1024] = {};
ShaderPair m_doorCache[8] = {};
ShaderPair&
CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; }
boo::ObjToken<boo::IShaderPipeline>&
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>
boo::ObjToken<boo::IShaderPipeline> GetOrBuildShader(const T& info);
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[9]; // Pad out to 768 bytes
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_pad; // Pad out to 768 bytes
zeus::CVector3f m_pad2; // Pad out to 768 bytes
};
std::experimental::optional<TLockedToken<CTexture>> m_patternTex1;
std::experimental::optional<TLockedToken<CTexture>> m_patternTex2;
std::experimental::optional<TLockedToken<CTexture>> m_colorTex;
std::experimental::optional<TLockedToken<CTexture>> m_bumpMap;
std::experimental::optional<TLockedToken<CTexture>> m_envMap;
std::experimental::optional<TLockedToken<CTexture>> m_envBumpMap;
std::experimental::optional<TLockedToken<CTexture>> m_lightmap;
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;
boo::ObjToken<boo::IShaderDataBinding> m_dataBind;
BindingPair m_dataBind;
int m_lastBind = -1;
#if BOO_HAS_GL
static boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::GLDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::GLDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
boo::ObjToken<boo::IShaderDataBinding> BuildBinding(boo::GLDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door);
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 boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::D3DDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::D3DDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
boo::ObjToken<boo::IShaderDataBinding> BuildBinding(boo::D3DDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door);
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 boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::MetalDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::MetalDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
boo::ObjToken<boo::IShaderDataBinding> BuildBinding(boo::MetalDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door);
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 boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::VulkanDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info);
static boo::ObjToken<boo::IShaderPipeline> BuildShader(boo::VulkanDataFactory::Context& ctx,
const SFluidPlaneDoorShaderInfo& info);
boo::ObjToken<boo::IShaderDataBinding> BuildBinding(boo::VulkanDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door);
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 boo::ObjToken<boo::IShaderPipeline>& pipeline, u32 maxVertCount, bool door);
void PrepareBinding(const ShaderPair& pipeline, u32 maxVertCount);
public:
CFluidPlaneShader(CFluidPlane::EFluidType type,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
const std::experimental::optional<TLockedToken<CTexture>>& bumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& envMap,
const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap,
const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
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 std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
CFluidPlaneShader(const TLockedToken<CTexture>& patternTex1,
const TLockedToken<CTexture>& patternTex2,
const TLockedToken<CTexture>& colorTex,
u32 maxVertCount);
void prepareDraw(const RenderSetupInfo& info);
void loadVerts(const std::vector<Vertex>& verts);
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();
};

View File

@ -39,13 +39,145 @@ BOO_GLSL_BINDING_HEAD
" vtf.mvNorm = mvNorm * normalIn;\n"
" vtf.mvBinorm = mvNorm * binormalIn;\n"
" vtf.mvTangent = mvNorm * tangentIn;\n"
" vtf.color = colorIn;\n"
" vtf.color = vec4(colorIn.xyz, 1.0);\n"
" vtf.uvs[0] = (texMtxs[0] * pos).xy;\n"
" vtf.uvs[1] = (texMtxs[1] * pos).xy;\n"
" vtf.uvs[2] = (texMtxs[2] * pos).xy;\n"
"%s" // Additional TCGs here
"}\n";
static const char* TessVS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"\n"
"layout(location=0) in vec4 posIn;\n"
"layout(location=1) in vec4 outerLevelsIn;\n"
"layout(location=2) in vec2 innerLevelsIn;\n"
"\n"
"struct VertToControl\n"
"{\n"
" vec4 minMaxPos;\n"
" vec4 outerLevels;\n"
" vec2 innerLevels;\n"
"};\n"
"\n"
"SBINDING(0) out VertToControl vtc;\n"
"\n"
"void main()\n"
"{\n"
" vtc.minMaxPos = posIn;\n"
" vtc.outerLevels = outerLevelsIn;\n"
" vtc.innerLevels = innerLevelsIn;\n"
"}\n";
static const char* TessCS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"#extension GL_ARB_tessellation_shader: enable\n"
"layout(vertices = 1) out;\n"
"\n"
"struct VertToControl\n"
"{\n"
" vec4 minMaxPos;\n"
" vec4 outerLevels;\n"
" vec2 innerLevels;\n"
"};\n"
"\n"
"SBINDING(0) in VertToControl vtc[];\n"
"SBINDING(0) patch out vec4 minMaxPos;\n"
"\n"
"void main()\n"
"{\n"
" minMaxPos = vtc[gl_InvocationID].minMaxPos;\n"
" for (int i=0 ; i<4 ; ++i)\n"
" gl_TessLevelOuter[i] = vtc[gl_InvocationID].outerLevels[i];\n"
" for (int i=0 ; i<2 ; ++i)\n"
" gl_TessLevelInner[i] = vtc[gl_InvocationID].innerLevels[i];\n"
"}";
static const char* TessES =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"#extension GL_ARB_tessellation_shader: enable\n"
"layout(quads, equal_spacing) in;\n"
"\n"
"struct Ripple\n"
"{\n"
" vec4 center; // time, distFalloff\n"
" vec4 params; // amplitude, lookupPhase, lookupTime\n"
"};\n"
"\n"
"UBINDING0 uniform FluidPlaneUniform\n"
"{\n"
" mat4 mv;\n"
" mat4 mvNorm;\n"
" mat4 proj;\n"
" mat4 texMtxs[6];\n"
" Ripple ripples[20];\n"
" vec4 colorMul;\n"
" float rippleNormResolution;\n"
"};\n"
"\n"
"struct VertToFrag\n"
"{\n"
" vec4 mvPos;\n"
" vec4 mvNorm;\n"
" vec4 mvBinorm;\n"
" vec4 mvTangent;\n"
" vec4 color;\n"
" vec2 uvs[7];\n"
"};\n"
"\n"
"SBINDING(0) patch in vec4 minMaxPos;\n"
"SBINDING(0) out VertToFrag vtf;\n"
"\n"
"TBINDING%d uniform sampler2D RippleMap;\n"
"\n"
"const float PI_X2 = 6.283185307179586;\n"
"\n"
"void ApplyRipple(in Ripple ripple, in vec2 pos, inout float height)\n"
"{\n"
" float dist = length(ripple.center.xy - pos);\n"
" float rippleV = texture(RippleMap, vec2(dist * ripple.center.w, ripple.center.z)).r;\n"
" height += rippleV * ripple.params.x * sin((dist * ripple.params.y + ripple.params.z) * PI_X2);\n"
"}\n"
"\n"
"void main()\n"
"{\n"
" vec2 posIn = vec2(mix(minMaxPos.x, minMaxPos.z, gl_TessCoord.x),\n"
" mix(minMaxPos.y, minMaxPos.w, gl_TessCoord.y));\n"
" float height = 0.0;\n"
" float upHeight = 0.0;\n"
" float downHeight = 0.0;\n"
" float rightHeight = 0.0;\n"
" float leftHeight = 0.0;\n"
" for (int i=0 ; i<20 ; ++i)\n"
" {\n"
" ApplyRipple(ripples[i], posIn, height);\n"
" ApplyRipple(ripples[i], posIn + vec2(0.0, rippleNormResolution), upHeight);\n"
" ApplyRipple(ripples[i], posIn - vec2(0.0, rippleNormResolution), downHeight);\n"
" ApplyRipple(ripples[i], posIn + vec2(rippleNormResolution, 0.0), rightHeight);\n"
" ApplyRipple(ripples[i], posIn - vec2(rippleNormResolution, 0.0), leftHeight);\n"
" }\n"
" vec4 normalIn = vec4(normalize(vec3((leftHeight - rightHeight),\n"
" (downHeight - upHeight),\n"
" rippleNormResolution)), 1.0);\n"
" vec4 binormalIn = vec4(normalIn.x, normalIn.z, -normalIn.y, 1.0);\n"
" vec4 tangentIn = vec4(normalIn.z, normalIn.y, -normalIn.x, 1.0);\n"
" vec4 pos = vec4(posIn, height, 1.0);\n"
" vtf.mvPos = mv * pos;\n"
" gl_Position = proj * vtf.mvPos;\n"
" vtf.mvNorm = mvNorm * normalIn;\n"
" vtf.mvBinorm = mvNorm * binormalIn;\n"
" vtf.mvTangent = mvNorm * tangentIn;\n"
" vtf.color = max(height, 0.0) * colorMul;\n"
" vtf.color.a = 1.0;\n"
" vtf.uvs[0] = (texMtxs[0] * pos).xy;\n"
" vtf.uvs[1] = (texMtxs[1] * pos).xy;\n"
" vtf.uvs[2] = (texMtxs[2] * pos).xy;\n"
"%s\n" // Additional TCGs here
"}\n";
static const char* FS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
@ -60,7 +192,7 @@ BOO_GLSL_BINDING_HEAD
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" vec4 color;\n"
" float indScale;\n"
" float start;\n"
@ -77,13 +209,13 @@ BOO_GLSL_BINDING_HEAD
" Fog fog;\n"
"};\n"
"\n"
"vec4 LightingFunc(vec4 mvPosIn, vec4 mvNormIn)\n"
"vec4 LightingFunc(vec3 mvPosIn, vec3 mvNormIn)\n"
"{\n"
" vec4 ret = ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" vec3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" vec3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -92,10 +224,10 @@ BOO_GLSL_BINDING_HEAD
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0);\n"
" }\n"
" \n"
" return clamp(ret, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\n"
" return ret;\n"
"}\n"
"\n"
"struct VertToFrag\n"
@ -113,7 +245,7 @@ BOO_GLSL_BINDING_HEAD
"%s" // Textures here
"void main()\n"
"{\n"
" vec4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
" vec4 lighting = LightingFunc(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n"
"%s" // Combiner expression here
"}\n";
@ -131,7 +263,7 @@ BOO_GLSL_BINDING_HEAD
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" vec4 color;\n"
" float indScale;\n"
" float start;\n"
@ -166,14 +298,12 @@ BOO_GLSL_BINDING_HEAD
"%s" // Combiner expression here
"}\n";
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[7],
const SFluidPlaneShaderInfo& info)
static void _BuildFragShader(std::string& finalFS, int& nextTex, const char* texNames[8],
const SFluidPlaneShaderInfo& info)
{
std::string additionalTCGs;
std::string textures;
std::string combiner;
int nextTCG = 3;
int nextMtx = 4;
int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv;
if (info.m_hasPatternTex1)
@ -214,30 +344,26 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
if (info.m_hasBumpMap)
{
bumpMapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * pos).xy;\n", nextTCG++);
bumpMapUv = nextTCG++;
}
if (info.m_hasEnvBumpMap)
{
envBumpMapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * vec4(normalize(normalIn.xyz), 1.0)).xy;\n", nextTCG++);
envBumpMapUv = nextTCG++;
}
if (info.m_hasEnvMap)
{
envMapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++);
envMapUv = nextTCG++;
}
if (info.m_hasLightmap)
{
lightmapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++);
}
switch (info.m_type)
{
case CFluidPlane::EFluidType::NormalWater:
case CFluidPlane::EFluidType::PhazonFluid:
case CFluidPlane::EFluidType::Four:
case EFluidType::NormalWater:
case EFluidType::PhazonFluid:
case EFluidType::Four:
if (info.m_hasLightmap)
{
combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
@ -293,7 +419,7 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
" vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
" vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
}
else if (info.m_hasEnvMap)
@ -307,8 +433,8 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
if (info.m_hasColorTex)
combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
" vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
combiner += hecl::Format(" colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[%d]), kColor1);\n",
" vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += hecl::Format(" colorOut = mix(colorOut, texture(envMap, indUvs + vtf.uvs[%d]), kColor1);\n",
envMapUv);
}
else if (info.m_hasColorTex)
@ -318,7 +444,7 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
break;
case CFluidPlane::EFluidType::PoisonWater:
case EFluidType::PoisonWater:
if (info.m_hasLightmap)
{
combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
@ -375,7 +501,7 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" vec2 indUvs = (texture(envBumpMap, vtf.uvs[%d]).ra - vec2(0.5, 0.5)) *\n"
" vec2(fog.indScale, -fog.indScale);", envBumpMapUv);
" vec2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
}
else
@ -386,7 +512,7 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
break;
case CFluidPlane::EFluidType::Lava:
case EFluidType::Lava:
// 0: Tex0TCG, Tex0, GX_COLOR0A0
// ZERO, TEX, KONST, RAS
// Output reg prev
@ -444,7 +570,7 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
break;
case CFluidPlane::EFluidType::ThickLava:
case EFluidType::ThickLava:
// 0: Tex0TCG, Tex0, GX_COLOR0A0
// ZERO, TEX, KONST, RAS
// Output reg prev
@ -489,17 +615,66 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
combiner += " colorOut.a = kColor0.a;\n";
char *finalVSs, *finalFSs;
asprintf(&finalVSs, VS, additionalTCGs.c_str());
char *finalFSs;
asprintf(&finalFSs, FS, textures.c_str(), combiner.c_str());
finalVS = finalVSs;
finalFS = finalFSs;
free(finalVSs);
free(finalFSs);
}
static std::string _BuildAdditionalTCGs(const SFluidPlaneShaderInfo& info)
{
std::string additionalTCGs;
int nextTCG = 3;
int nextMtx = 4;
if (info.m_hasBumpMap)
{
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * pos).xy;\n", nextTCG++);
}
if (info.m_hasEnvBumpMap)
{
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * vec4(normalIn.xyz, 1.0)).xy;\n", nextTCG++);
}
if (info.m_hasEnvMap)
{
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG++, nextMtx++);
}
if (info.m_hasLightmap)
{
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * pos).xy;\n", nextTCG, nextMtx);
}
return additionalTCGs;
}
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[8],
const SFluidPlaneShaderInfo& info)
{
std::string additionalTCGs = _BuildAdditionalTCGs(info);
char *finalVSs;
asprintf(&finalVSs, VS, additionalTCGs.c_str());
finalVS = finalVSs;
free(finalVSs);
_BuildFragShader(finalFS, nextTex, texNames, info);
}
static void _BuildTessellationShader(std::string& finalTessES, int& nextTex, const char* texNames[8],
const SFluidPlaneShaderInfo& info)
{
std::string additionalTCGs = _BuildAdditionalTCGs(info);
texNames[nextTex] = "RippleMap";
char *finalESs;
asprintf(&finalESs, TessES, nextTex, additionalTCGs.c_str());
finalTessES = finalESs;
free(finalESs);
++nextTex;
}
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[3],
const SFluidPlaneDoorShaderInfo& info)
{
@ -552,22 +727,36 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
free(finalFSs);
}
boo::ObjToken<boo::IShaderPipeline>
CFluidPlaneShader::ShaderPair
CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
{
int nextTex = 0;
const char* texNames[7] = {};
const char* texNames[8] = {};
std::string finalVS, finalFS;
_BuildShader(finalVS, finalFS, nextTex, texNames, info);
const char* uniNames[] = {"FluidPlaneUniform", "FluidPlaneUniform", "LightingUniform"};
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), size_t(nextTex), texNames, 3, uniNames,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
auto regular = ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(),
size_t(nextTex), texNames, 3, uniNames,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
boo::ObjToken<boo::IShaderPipeline> tessellation;
if (info.m_tessellation)
{
std::string finalTessES;
_BuildTessellationShader(finalTessES, nextTex, texNames, info);
tessellation = ctx.newTessellationShaderPipeline(
TessVS, finalFS.c_str(), TessCS, finalTessES.c_str(),
size_t(nextTex), texNames, 3, uniNames,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
1, boo::ZTest::LEqual, false, true, false, boo::CullMode::None);
}
return {regular, tessellation};
}
boo::ObjToken<boo::IShaderPipeline>
CFluidPlaneShader::ShaderPair
CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
{
int nextTex = 0;
@ -575,10 +764,10 @@ CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPla
std::string finalVS, finalFS;
_BuildShader(finalVS, finalFS, nextTex, texNames, info);
const char* uniNames[] = {"FluidPlaneUniform", "FluidPlaneUniform", "LightingUniform"};
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), size_t(nextTex), texNames, 3, uniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
return {ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), size_t(nextTex), texNames, 3, uniNames,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None), {}};
}
template <>
@ -586,9 +775,11 @@ void CFluidPlaneShader::_Shutdown<boo::GLDataFactory>() {}
#if BOO_HAS_VULKAN
static boo::ObjToken<boo::IVertexFormat> s_vtxFmt;
static boo::ObjToken<boo::IVertexFormat> s_vtxFmtTess;
boo::ObjToken<boo::IShaderPipeline>
CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
CFluidPlaneShader::ShaderPair
CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx,
const SFluidPlaneShaderInfo& info)
{
if (!s_vtxFmt)
{
@ -604,17 +795,40 @@ CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFlui
}
int nextTex = 0;
const char* texNames[7] = {};
const char* texNames[8] = {};
std::string finalVS, finalFS;
_BuildShader(finalVS, finalFS, nextTex, texNames, info);
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
auto regular = ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
boo::ObjToken<boo::IShaderPipeline> tessellation;
if (info.m_tessellation)
{
if (!s_vtxFmtTess)
{
boo::VertexElementDescriptor elements[] =
{
{nullptr, nullptr, boo::VertexSemantic::Position4},
{nullptr, nullptr, boo::VertexSemantic::UV4, 0},
{nullptr, nullptr, boo::VertexSemantic::UV4, 1}
};
s_vtxFmtTess = ctx.newVertexFormat(3, elements);
}
std::string finalTessES;
_BuildTessellationShader(finalTessES, nextTex, texNames, info);
tessellation = ctx.newTessellationShaderPipeline(
TessVS, finalFS.c_str(), TessCS, finalTessES.c_str(), s_vtxFmtTess,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::SrcAlpha,
info.m_additive ? boo::BlendFactor::One : boo::BlendFactor::InvSrcAlpha,
1, boo::ZTest::LEqual, false, true, false, boo::CullMode::None);
}
return {regular, tessellation};
}
boo::ObjToken<boo::IShaderPipeline>
CFluidPlaneShader::ShaderPair
CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
{
if (!s_vtxFmt)
@ -634,23 +848,24 @@ CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFlui
const char* texNames[3] = {};
std::string finalVS, finalFS;
_BuildShader(finalVS, finalFS, nextTex, texNames, info);
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
auto regular = ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt,
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
boo::CullMode::None);
return {regular, {}};
}
template <>
void CFluidPlaneShader::_Shutdown<boo::VulkanDataFactory>()
{
s_vtxFmt.reset();
s_vtxFmtTess.reset();
}
#endif
boo::ObjToken<boo::IShaderDataBinding>
CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door)
CFluidPlaneShader::BindingPair
CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx, const ShaderPair& pipeline)
{
boo::VertexElementDescriptor elements[] =
{
@ -664,56 +879,79 @@ CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx,
boo::ObjToken<boo::IGraphicsBuffer> ubufs[] = { m_uniBuf.get(), m_uniBuf.get(), m_uniBuf.get() };
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
boo::PipelineStage::Fragment };
size_t ubufOffs[] = {0, 0, 768};
size_t ubufSizes[] = {768, 768, sizeof(CModelShaders::LightingUniform)};
size_t ubufOffs[] = {0, 0, 1280};
size_t ubufSizes[] = {1280, 1280, sizeof(CModelShaders::LightingUniform)};
size_t texCount = 0;
boo::ObjToken<boo::ITexture> texs[7];
if (m_patternTex1)
texs[texCount++] = (*m_patternTex1)->GetBooTexture();
texs[texCount++] = m_patternTex1->GetBooTexture();
if (m_patternTex2)
texs[texCount++] = (*m_patternTex2)->GetBooTexture();
texs[texCount++] = m_patternTex2->GetBooTexture();
if (m_colorTex)
texs[texCount++] = (*m_colorTex)->GetBooTexture();
texs[texCount++] = m_colorTex->GetBooTexture();
if (m_bumpMap)
texs[texCount++] = (*m_bumpMap)->GetBooTexture();
texs[texCount++] = m_bumpMap->GetBooTexture();
if (m_envMap)
texs[texCount++] = (*m_envMap)->GetBooTexture();
texs[texCount++] = m_envMap->GetBooTexture();
if (m_envBumpMap)
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
texs[texCount++] = m_envBumpMap->GetBooTexture();
if (m_lightmap)
texs[texCount++] = (*m_lightmap)->GetBooTexture();
return ctx.newShaderDataBinding(pipeline, vtxFmt, m_vbo.get(), nullptr, nullptr, 3,
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
texs[texCount++] = m_lightmap->GetBooTexture();
auto regular = ctx.newShaderDataBinding(pipeline.m_regular, vtxFmt, m_vbo.get(), nullptr, nullptr, 3,
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
boo::ObjToken<boo::IShaderDataBinding> tessellation;
if (pipeline.m_tessellation)
{
boo::VertexElementDescriptor tessElements[] =
{
{m_pvbo.get(), nullptr, boo::VertexSemantic::Position4},
{m_pvbo.get(), nullptr, boo::VertexSemantic::UV4, 0},
{m_pvbo.get(), nullptr, boo::VertexSemantic::UV4, 1}
};
boo::ObjToken<boo::IVertexFormat> vtxFmtTess = ctx.newVertexFormat(3, tessElements);
texs[texCount++] = m_rippleMap.get();
tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, vtxFmtTess, m_pvbo.get(), nullptr, nullptr, 3,
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
}
return {regular, tessellation};
}
#if BOO_HAS_VULKAN
boo::ObjToken<boo::IShaderDataBinding>
CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& pipeline, bool door)
CFluidPlaneShader::BindingPair
CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory::Context& ctx, const ShaderPair& pipeline)
{
boo::ObjToken<boo::IGraphicsBuffer> ubufs[] = { m_uniBuf.get(), m_uniBuf.get(), m_uniBuf.get() };
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
boo::PipelineStage::Fragment };
size_t ubufOffs[] = {0, 0, 768};
size_t ubufSizes[] = {768, 768, sizeof(CModelShaders::LightingUniform)};
size_t ubufOffs[] = {0, 0, 1280};
size_t ubufSizes[] = {1280, 1280, sizeof(CModelShaders::LightingUniform)};
size_t texCount = 0;
boo::ObjToken<boo::ITexture> texs[7] = {};
if (m_patternTex1)
texs[texCount++] = (*m_patternTex1)->GetBooTexture();
texs[texCount++] = m_patternTex1->GetBooTexture();
if (m_patternTex2)
texs[texCount++] = (*m_patternTex2)->GetBooTexture();
texs[texCount++] = m_patternTex2->GetBooTexture();
if (m_colorTex)
texs[texCount++] = (*m_colorTex)->GetBooTexture();
texs[texCount++] = m_colorTex->GetBooTexture();
if (m_bumpMap)
texs[texCount++] = (*m_bumpMap)->GetBooTexture();
texs[texCount++] = m_bumpMap->GetBooTexture();
if (m_envMap)
texs[texCount++] = (*m_envMap)->GetBooTexture();
texs[texCount++] = m_envMap->GetBooTexture();
if (m_envBumpMap)
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
texs[texCount++] = m_envBumpMap->GetBooTexture();
if (m_lightmap)
texs[texCount++] = (*m_lightmap)->GetBooTexture();
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo.get(), nullptr, nullptr, 3,
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
texs[texCount++] = m_lightmap->GetBooTexture();
auto regular = ctx.newShaderDataBinding(pipeline.m_regular, s_vtxFmt, m_vbo.get(), nullptr, nullptr,
3, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
boo::ObjToken<boo::IShaderDataBinding> tessellation;
if (pipeline.m_tessellation)
{
texs[texCount++] = m_rippleMap.get();
tessellation = ctx.newShaderDataBinding(pipeline.m_tessellation, s_vtxFmtTess, m_pvbo.get(), nullptr, nullptr,
3, ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
}
return {regular, tessellation};
}
#endif

View File

@ -62,7 +62,7 @@ static const char* FS =
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float indScale;\n"
" float start;\n"
@ -79,13 +79,13 @@ static const char* FS =
" Fog fog;\n"
"};\n"
"\n"
"static float4 LightingFunc(float4 mvPosIn, float4 mvNormIn)\n"
"static float4 LightingFunc(float3 mvPosIn, float3 mvNormIn)\n"
"{\n"
" float4 ret = ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -94,10 +94,10 @@ static const char* FS =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0);\n"
" }\n"
" \n"
" return clamp(ret, float4(0.0,0.0,0.0,0.0), float4(1.0,1.0,1.0,1.0));\n"
" return ret;\n"
"}\n"
"\n"
"struct VertToFrag\n"
@ -115,7 +115,7 @@ static const char* FS =
"%s" // Textures here
"float4 main(in VertToFrag vtf) : SV_Target0\n"
"{\n"
" float4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
" float4 lighting = LightingFunc(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n"
" float4 colorOut;\n"
"%s" // Combiner expression here
" return colorOut;\n"
@ -132,7 +132,7 @@ static const char* FSDoor =
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float indScale;\n"
" float start;\n"
@ -215,7 +215,7 @@ CFluidPlaneShader::BuildShader(boo::D3DDataFactory::Context& ctx, const SFluidPl
if (info.m_hasEnvBumpMap)
{
envBumpMapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(normalize(v.normalIn.xyz), 1.0)).xy;\n", nextTCG++);
additionalTCGs += hecl::Format(" vtf.uvs[%d] = mul(texMtxs[3], float4(v.normalIn.xyz, 1.0)).xy;\n", nextTCG++);
}
if (info.m_hasEnvMap)
{
@ -288,7 +288,7 @@ CFluidPlaneShader::BuildShader(boo::D3DDataFactory::Context& ctx, const SFluidPl
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
" float2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
}
else if (info.m_hasEnvMap)
@ -302,7 +302,7 @@ CFluidPlaneShader::BuildShader(boo::D3DDataFactory::Context& ctx, const SFluidPl
if (info.m_hasColorTex)
combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]) * lighting;\n";
combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
" float2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += hecl::Format(" colorOut = mix(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), kColor1);\n",
envMapUv);
}
@ -370,7 +370,7 @@ CFluidPlaneShader::BuildShader(boo::D3DDataFactory::Context& ctx, const SFluidPl
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
" float2(fog.indScale, -fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
}
else

View File

@ -74,7 +74,7 @@ static const char* FS =
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float indScale;\n"
" float start;\n"
@ -91,13 +91,13 @@ static const char* FS =
" Fog fog;\n"
"};\n"
"\n"
"static float4 LightingFunc(float4 mvPosIn, float4 mvNormIn)\n"
"static float4 LightingFunc(float3 mvPosIn, float3 mvNormIn)\n"
"{\n"
" float4 ret = ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -106,10 +106,10 @@ static const char* FS =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0);\n"
" }\n"
" \n"
" return clamp(ret, float4(0.0,0.0,0.0,0.0), float4(1.0,1.0,1.0,1.0));\n"
" return ret;\n"
"}\n"
"\n"
"struct VertToFrag\n"
@ -133,7 +133,7 @@ static const char* FS =
" sampler samp [[ sampler(0) ]],\n"
" constant LightingUniform& lu [[ buffer(4) ]]%s)\n" // Textures here
"{\n"
" float4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
" float4 lighting = LightingFunc(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n"
" float4 colorOut;\n"
"%s" // Combiner expression here
" return colorOut;\n"
@ -153,7 +153,7 @@ static const char* FSDoor =
"};\n"
"struct Fog\n" // Reappropriated for indirect texture scaling
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float indScale;\n"
" float start;\n"
@ -243,7 +243,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasEnvBumpMap)
{
envBumpMapUv = nextTCG;
additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[3] * float4(normalize(v.normalIn.xyz), 1.0)).xy;\n", nextTCG++);
additionalTCGs += hecl::Format(" vtf.uv%d = (fu.texMtxs[3] * float4(v.normalIn.xyz, 1.0)).xy;\n", nextTCG++);
}
if (info.m_hasEnvMap)
{
@ -316,7 +316,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n"
" float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
" float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n";
}
else if (info.m_hasEnvMap)
@ -330,7 +330,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
if (info.m_hasColorTex)
combiner += " colorOut += colorTex.sample(samp, vtf.uv2) * lighting;\n";
combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n"
" float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
" float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv);
combiner += hecl::Format(" colorOut = mix(colorOut, envMap.sample(samp, indUvs + vtf.uv%d), lu.kColor1);\n",
envMapUv);
}
@ -398,7 +398,7 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
{
// Make previous stage indirect, mtx0
combiner += hecl::Format(" float2 indUvs = (envBumpMap.sample(samp, vtf.uv%d).ra - float2(0.5, 0.5)) *\n"
" float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
" float2(lu.fog.indScale, -lu.fog.indScale);\n", envBumpMapUv);
combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uv2) * lighting;\n";
}
else

View File

@ -15,7 +15,7 @@ static const char* LightingGLSL =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" vec4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -32,13 +32,13 @@ static const char* LightingGLSL =
" Fog fog;\n"
"};\n"
"\n"
"vec4 LightingFunc(vec4 mvPosIn, vec4 mvNormIn)\n"
"vec4 LightingFunc(vec3 mvPosIn, vec3 mvNormIn)\n"
"{\n"
" vec4 ret = ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" vec3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" vec3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -47,7 +47,7 @@ static const char* LightingGLSL =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0);\n"
" }\n"
" \n"
" return ret;\n"
@ -64,7 +64,7 @@ static const char* LightingShadowGLSL =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" vec4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -81,14 +81,14 @@ static const char* LightingShadowGLSL =
" Fog fog;\n"
"};\n"
"\n"
"vec4 LightingShadowFunc(vec4 mvPosIn, vec4 mvNormIn)\n"
"vec4 LightingShadowFunc(vec3 mvPosIn, vec3 mvNormIn)\n"
"{\n"
" vec2 shadowUV = vtf.extTcgs[0];\n"
" shadowUV.y = 1.0 - shadowUV.y;\n"
" \n"
" vec4 ret = ambient;\n"
" \n"
" vec3 delta = mvPosIn.xyz - lights[0].pos.xyz;\n"
" vec3 delta = mvPosIn - lights[0].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[0].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[0].linAtt[2] * dist * dist +\n"
@ -97,12 +97,12 @@ static const char* LightingShadowGLSL =
" float angAtt = lights[0].angAtt[2] * angDot * angDot +\n"
" lights[0].angAtt[1] * angDot +\n"
" lights[0].angAtt[0];\n"
" ret += lights[0].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0) *\n"
" ret += lights[0].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0) *\n"
" texture(extTex7, shadowUV).r;\n"
" \n"
" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" vec3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" vec3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = clamp(dot(normalize(delta), lights[i].dir.xyz), 0.0, 1.0);\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -111,7 +111,7 @@ static const char* LightingShadowGLSL =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn.xyz), 0.0, 1.0);\n"
" ret += lights[i].color * clamp(angAtt, 0.0, 1.0) * att * clamp(dot(normalize(-delta), mvNormIn), 0.0, 1.0);\n"
" }\n"
" \n"
" return ret;\n"

View File

@ -14,7 +14,7 @@ static const char* LightingHLSL =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -31,13 +31,13 @@ static const char* LightingHLSL =
" Fog fog;\n"
"};\n"
"\n"
"static float4 LightingFunc(float4 mvPosIn, float4 mvNormIn, in VertToFrag vtf)\n"
"static float4 LightingFunc(float3 mvPosIn, float3 mvNormIn, in VertToFrag vtf)\n"
"{\n"
" float4 ret = ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lights[i].dir.xyz));\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -46,7 +46,7 @@ static const char* LightingHLSL =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz));\n"
" ret += lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n"
" }\n"
" \n"
" return ret;\n"
@ -63,7 +63,7 @@ static const char* LightingShadowHLSL =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -80,11 +80,11 @@ static const char* LightingShadowHLSL =
" Fog fog;\n"
"};\n"
"\n"
"static float4 LightingShadowFunc(float4 mvPosIn, float4 mvNormIn, in VertToFrag vtf)\n"
"static float4 LightingShadowFunc(float3 mvPosIn, float3 mvNormIn, in VertToFrag vtf)\n"
"{\n"
" float4 ret = ambient;\n"
" \n"
" float3 delta = mvPosIn.xyz - lights[0].pos.xyz;\n"
" float3 delta = mvPosIn - lights[0].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lights[0].dir.xyz));\n"
" float att = 1.0 / (lights[0].linAtt[2] * dist * dist +\n"
@ -93,12 +93,12 @@ static const char* LightingShadowHLSL =
" float angAtt = lights[0].angAtt[2] * angDot * angDot +\n"
" lights[0].angAtt[1] * angDot +\n"
" lights[0].angAtt[0];\n"
" ret += lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz)) *\n"
" ret += lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn)) *\n"
" extTex7.Sample(clampSamp, vtf.extTcgs[0]).r;\n"
" \n"
" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lights[i].dir.xyz));\n"
" float att = 1.0 / (lights[i].linAtt[2] * dist * dist +\n"
@ -107,7 +107,7 @@ static const char* LightingShadowHLSL =
" float angAtt = lights[i].angAtt[2] * angDot * angDot +\n"
" lights[i].angAtt[1] * angDot +\n"
" lights[i].angAtt[0];\n"
" ret += lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz));\n"
" ret += lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n"
" }\n"
" \n"
" return ret;\n"

View File

@ -14,7 +14,7 @@ static const char* LightingMetal =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -31,13 +31,13 @@ static const char* LightingMetal =
" Fog fog;\n"
"};\n"
"\n"
"static float4 LightingFunc(constant LightingUniform& lu, float4 mvPosIn, float4 mvNormIn, thread VertToFrag& vtf)\n"
"static float4 LightingFunc(constant LightingUniform& lu, float3 mvPosIn, float3 mvNormIn, thread VertToFrag& vtf)\n"
"{\n"
" float4 ret = lu.ambient;\n"
" \n"
" for (int i=0 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lu.lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lu.lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lu.lights[i].dir.xyz));\n"
" float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist +\n"
@ -46,7 +46,7 @@ static const char* LightingMetal =
" float angAtt = lu.lights[i].angAtt[2] * angDot * angDot +\n"
" lu.lights[i].angAtt[1] * angDot +\n"
" lu.lights[i].angAtt[0];\n"
" ret += lu.lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz));\n"
" ret += lu.lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n"
" }\n"
" \n"
" return ret;\n"
@ -63,7 +63,7 @@ static const char* LightingShadowMetal =
"};\n"
"struct Fog\n"
"{\n"
" uint mode;\n"
" int mode;\n"
" float4 color;\n"
" float rangeScale;\n"
" float start;\n"
@ -80,12 +80,12 @@ static const char* LightingShadowMetal =
" Fog fog;\n"
"};\n"
"\n"
"static float4 EXTLightingShadowFunc(constant LightingUniform& lu, float4 mvPosIn, float4 mvNormIn,\n"
"static float4 EXTLightingShadowFunc(constant LightingUniform& lu, float3 mvPosIn, float3 mvNormIn,\n"
" thread VertToFrag& vtf, sampler samp, sampler clampSamp, texture2d<float> extTex7)\n"
"{\n"
" float4 ret = lu.ambient;\n"
" \n"
" float3 delta = mvPosIn.xyz - lu.lights[0].pos.xyz;\n"
" float3 delta = mvPosIn - lu.lights[0].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lu.lights[0].dir.xyz));\n"
" float att = 1.0 / (lu.lights[0].linAtt[2] * dist * dist +\n"
@ -94,12 +94,12 @@ static const char* LightingShadowMetal =
" float angAtt = lu.lights[0].angAtt[2] * angDot * angDot +\n"
" lu.lights[0].angAtt[1] * angDot +\n"
" lu.lights[0].angAtt[0];\n"
" ret += lu.lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz)) *\n"
" ret += lu.lights[0].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn)) *\n"
" extTex7.sample(clampSamp, vtf.extTcgs0).r;\n"
" \n"
" for (int i=1 ; i<" _XSTR(URDE_MAX_LIGHTS) " ; ++i)\n"
" {\n"
" float3 delta = mvPosIn.xyz - lu.lights[i].pos.xyz;\n"
" float3 delta = mvPosIn - lu.lights[i].pos.xyz;\n"
" float dist = length(delta);\n"
" float angDot = saturate(dot(normalize(delta), lu.lights[i].dir.xyz));\n"
" float att = 1.0 / (lu.lights[i].linAtt[2] * dist * dist +\n"
@ -108,7 +108,7 @@ static const char* LightingShadowMetal =
" float angAtt = lu.lights[i].angAtt[2] * angDot * angDot +\n"
" lu.lights[i].angAtt[1] * angDot +\n"
" lu.lights[i].angAtt[0];\n"
" ret += lu.lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn.xyz));\n"
" ret += lu.lights[i].color * saturate(angAtt) * att * saturate(dot(normalize(-delta), mvNormIn));\n"
" }\n"
" \n"
" return ret;\n"

View File

@ -783,6 +783,7 @@ void CMain::Shutdown()
TMultiBlendShader<CScanLinesFilter>::Shutdown();
TMultiBlendShader<CRandomStaticFilter>::Shutdown();
CFluidPlaneShader::Shutdown();
CFluidPlaneManager::RippleMapTex.reset();
CNESShader::Shutdown();
CGraphics::ShutdownBoo();
ShutdownDiscord();

View File

@ -256,7 +256,7 @@ void CPlayerGun::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CSt
{
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(sender))
{
if (water->GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::PhazonFluid)
if (water->GetFluidPlane().GetFluidType() == EFluidType::PhazonFluid)
{
x835_24_canFirePhazon = true;
x835_25_inPhazonBeam = true;

View File

@ -14,11 +14,11 @@ CFluidPlane::CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId te
x44_fluidType(fluidType), x48_rippleIntensity(rippleIntensity), x4c_uvMotion(motion)
{
if (g_ResFactory->GetResourceTypeById(texPattern1) == FOURCC('TXTR'))
x10_texPattern1.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1}));
x10_texPattern1 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern1});
if (g_ResFactory->GetResourceTypeById(texPattern2) == FOURCC('TXTR'))
x20_texPattern2.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern2}));
x20_texPattern2 = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texPattern2});
if (g_ResFactory->GetResourceTypeById(texColor) == FOURCC('TXTR'))
x30_texColor.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor}));
x30_texColor = g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor});
}
float CFluidPlane::ProjectRippleVelocity(float baseI, float velDot) const
@ -84,4 +84,495 @@ void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CS
return;
mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple);
}
void CFluidPlane::RenderStripWithRipples(float curY,
const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneRender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const
{
m_shader->bindRegular();
int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) /
CFluidPlaneRender::numSubdivisionsInTile;
int endXTile = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) /
CFluidPlaneRender::numSubdivisionsInTile;
int midDiv = CFluidPlaneRender::numSubdivisionsInTile / 2;
float tileMid = info.x18_rippleResolution * midDiv;
float yMin = curY;
float yMid = curY + tileMid;
float curX = info.x4_localMin.x;
int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1);
int xTile = 1;
int tileSpan;
for (int i = 1 ; i < info.x0_xSubdivs - 2 ;
i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan,
xTile += tileSpan, curX += info.x14_tileSize * tileSpan)
{
tileSpan = 1;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell])
continue;
if ((flags[yTile][xTile] & 0x1f) == 0x1f)
{
for (; xTile+tileSpan<=endXTile ; ++tileSpan)
{
if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f)
break;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan])
break;
}
int stripDivCount = tileSpan * CFluidPlaneRender::numSubdivisionsInTile + 1;
int remSubdivs = CFluidPlaneRender::numSubdivisionsInTile;
std::function<void(float x, float y, const CFluidPlaneRender::SHFieldSample& samp)> func;
switch (info.x37_normalMode)
{
case CFluidPlaneRender::NormalMode::None:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height));
};
break;
case CFluidPlaneRender::NormalMode::NoNormals:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info));
};
break;
case CFluidPlaneRender::NormalMode::Normals:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeColor(info));
};
break;
case CFluidPlaneRender::NormalMode::NBT:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
vOut.emplace_back(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info));
};
break;
}
float curTileY = yMin;
int curYDiv = startYDiv;
for (; remSubdivs>0 ; --remSubdivs, ++curYDiv, curTileY+=info.x18_rippleResolution)
{
size_t start = vOut.size();
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
func(curTileX, curTileY, heights[curYDiv][i+v]);
func(curTileX, curTileY + info.x18_rippleResolution, heights[curYDiv+1][i+v]);
curTileX += info.x18_rippleResolution;
}
CGraphics::DrawArray(start, vOut.size() - start);
}
}
else
{
bool r19 = (flags[yTile+1][xTile] & 0x2) != 0; // North
bool r16 = (flags[yTile][xTile-1] & 0x8) != 0; // West
bool r18 = (flags[yTile][xTile+1] & 0x4) != 0; // East
bool r17 = (flags[yTile-1][xTile] & 0x1) != 0; // South
int r6 = (r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1) + 2;
r6 += r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1;
r6 += r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1;
r6 += r16 ? CFluidPlaneRender::numSubdivisionsInTile : 1;
if (r6 == 6 && (info.x37_normalMode == CFluidPlaneRender::NormalMode::Normals ||
info.x37_normalMode == CFluidPlaneRender::NormalMode::NBT))
{
for (; xTile+tileSpan<=endXTile ; ++tileSpan)
{
if ((flags[yTile][xTile+tileSpan] & 0x1f) == 0x1f)
break;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan])
break;
if ((flags[yTile+1][xTile+tileSpan] & 0x2) != 0x0)
break;
if ((flags[yTile][xTile+tileSpan+1] & 0x4) != 0x0)
break;
if ((flags[yTile-1][xTile+tileSpan] & 0x1) != 0x0)
break;
}
int stripDivCount = tileSpan + 1;
size_t start = vOut.size();
switch (info.x37_normalMode)
{
case CFluidPlaneRender::NormalMode::Normals:
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneRender::numSubdivisionsInTile;
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneRender::numSubdivisionsInTile + i;
const CFluidPlaneRender::SHFieldSample& samp0 = heights[curYDiv0][curXDiv];
const CFluidPlaneRender::SHFieldSample& samp1 = heights[curYDiv1][curXDiv];
vOut.emplace_back(zeus::CVector3f(curTileX, yMin, samp0.height),
samp0.MakeNormal(), samp0.MakeColor(info));
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeColor(info));
curTileX += info.x14_tileSize;
}
break;
}
case CFluidPlaneRender::NormalMode::NBT:
{
int curYDiv0 = startYDiv;
int curYDiv1 = startYDiv + CFluidPlaneRender::numSubdivisionsInTile;
float curTileX = curX;
for (int v=0 ; v<stripDivCount ; ++v)
{
int curXDiv = v * CFluidPlaneRender::numSubdivisionsInTile + i;
const CFluidPlaneRender::SHFieldSample& samp0 = heights[curYDiv0][curXDiv];
const CFluidPlaneRender::SHFieldSample& samp1 = heights[curYDiv1][curXDiv];
vOut.emplace_back(zeus::CVector3f(curTileX, yMin, samp0.height),
samp0.MakeNormal(), samp0.MakeBinormal(), samp0.MakeTangent(),
samp0.MakeColor(info));
vOut.emplace_back(zeus::CVector3f(curTileX, yMin + info.x14_tileSize, samp1.height),
samp1.MakeNormal(), samp1.MakeBinormal(), samp1.MakeTangent(),
samp1.MakeColor(info));
curTileX += info.x14_tileSize;
}
break;
}
default:
break;
}
CGraphics::DrawArray(start, vOut.size() - start);
}
else
{
TriFanToStrip<CFluidPlaneShader::Vertex> toStrip(vOut);
std::function<void(float x, float y, const CFluidPlaneRender::SHFieldSample& samp)> func;
switch (info.x37_normalMode)
{
case CFluidPlaneRender::NormalMode::None:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height));
};
break;
case CFluidPlaneRender::NormalMode::NoNormals:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeColor(info));
};
break;
case CFluidPlaneRender::NormalMode::Normals:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeColor(info));
};
break;
case CFluidPlaneRender::NormalMode::NBT:
func = [&](float x, float y, const CFluidPlaneRender::SHFieldSample& samp)
{
toStrip.EmplaceVert(zeus::CVector3f(x, y, samp.height), samp.MakeNormal(),
samp.MakeBinormal(), samp.MakeTangent(), samp.MakeColor(info));
};
break;
}
func(tileMid + curX, yMid, heights[startYDiv+midDiv][i+midDiv]);
int curXDiv = i;
int curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile;
float curTileX = curX;
float curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r19 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv+v];
func(curTileX, curTileY, samp);
curTileX += info.x18_rippleResolution;
}
curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile;
curYDiv = startYDiv + CFluidPlaneRender::numSubdivisionsInTile;
curTileX = curX + info.x14_tileSize;
curTileY = yMin + info.x14_tileSize;
for (int v=0 ; v<(r18 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv-v][curXDiv];
func(curTileX, curTileY, samp);
curTileY -= info.x18_rippleResolution;
}
curXDiv = i + CFluidPlaneRender::numSubdivisionsInTile;
curYDiv = startYDiv;
curTileX = curX + info.x14_tileSize;
curTileY = yMin;
for (int v=0 ; v<(r17 ? CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv-v];
func(curTileX, curTileY, samp);
curTileX -= info.x18_rippleResolution;
}
curXDiv = i;
curYDiv = startYDiv;
curTileX = curX;
curTileY = yMin;
if (r16)
{
for (int v=0 ; v<CFluidPlaneRender::numSubdivisionsInTile+1 ; ++v)
{
const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv+v][curXDiv];
func(curTileX, curTileY, samp);
curTileY += info.x18_rippleResolution;
}
}
else
{
{
const CFluidPlaneRender::SHFieldSample& samp = heights[curYDiv][curXDiv];
func(curTileX, curTileY, samp);
}
curTileY += info.x14_tileSize;
{
const CFluidPlaneRender::SHFieldSample& samp =
heights[curYDiv+CFluidPlaneRender::numSubdivisionsInTile][curXDiv];
func(curTileX, curTileY, samp);
}
}
toStrip.Draw();
}
}
}
}
void CFluidPlane::RenderPatch(const CFluidPlaneRender::SPatchInfo& info,
const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const
{
if (noRipples)
{
m_shader->bindRegular();
float xMin = info.x4_localMin.x;
float yMin = info.x4_localMin.y;
float xMax = info.x18_rippleResolution * (info.x0_xSubdivs - 2) + xMin;
float yMax = info.x18_rippleResolution * (info.x1_ySubdivs - 2) + yMin;
switch (info.x37_normalMode)
{
case CFluidPlaneRender::NormalMode::None:
{
size_t start = vOut.size();
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f));
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f));
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f));
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f));
CGraphics::DrawArray(start, 4);
break;
}
case CFluidPlaneRender::NormalMode::NoNormals:
{
size_t start = vOut.size();
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CColor::skBlack);
CGraphics::DrawArray(start, 4);
break;
}
case CFluidPlaneRender::NormalMode::Normals:
{
int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1;
int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1;
int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX;
yMax = yMin;
for (int curYTile=yTiles ; curYTile>0 ; --curYTile,
yMax += info.x14_tileSize, xTileStart += info.x2a_gridDimX)
{
xMax = xMin;
int nextXTile;
for (int curXTile=0 ; curXTile<xTiles ; curXTile=nextXTile)
{
if (!info.x30_gridFlags || info.x30_gridFlags[xTileStart+curXTile])
{
if (curYTile == yTiles || curYTile == 1 || curXTile == 0 || xTiles - 1 == curXTile)
{
TriFanToStrip<CFluidPlaneShader::Vertex> toStrip(vOut);
toStrip.EmplaceVert(zeus::CVector3f(xMax + 0.5f * info.x14_tileSize,
yMax + 0.5f * info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
float tmp = xMax;
for (int v=0 ; v<((curYTile == 1) ?
CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp += info.x18_rippleResolution;
}
tmp = yMax + info.x14_tileSize;
for (int v=0 ; v<((xTiles - 1 == curXTile) ?
CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
toStrip.EmplaceVert(zeus::CVector3f(xMax + info.x14_tileSize, tmp, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp -= info.x18_rippleResolution;
}
tmp = xMax + info.x14_tileSize;
for (int v=0 ; v<((curYTile == yTiles) ?
CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
toStrip.EmplaceVert(zeus::CVector3f(tmp, yMax, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp -= info.x18_rippleResolution;
}
tmp = yMax;
for (int v=0 ; v<((curXTile == 0) ?
CFluidPlaneRender::numSubdivisionsInTile : 1) ; ++v)
{
toStrip.EmplaceVert(zeus::CVector3f(xMax, tmp, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
tmp += info.x18_rippleResolution;
}
toStrip.EmplaceVert(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
toStrip.Draw();
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
}
else
{
nextXTile = curXTile + 1;
while (nextXTile < xTiles - 1 &&
(!info.x30_gridFlags || info.x30_gridFlags[xTileStart+nextXTile]))
++nextXTile;
size_t start = vOut.size();
for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CColor::skBlack);
xMax += info.x14_tileSize;
}
CGraphics::DrawArray(start, vOut.size() - start);
++nextXTile;
if (nextXTile == xTiles)
{
--nextXTile;
xMax -= info.x14_tileSize;
}
}
}
else
{
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
while (nextXTile < xTiles && !info.x30_gridFlags[xTileStart+nextXTile])
{
xMax += info.x14_tileSize;
++nextXTile;
}
}
}
}
break;
}
case CFluidPlaneRender::NormalMode::NBT:
{
if (flagIs1 || !info.x30_gridFlags)
{
size_t start = vOut.size();
vOut.emplace_back(zeus::CVector3f(xMin, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMin, yMax, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMax, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight, zeus::CColor::skBlack);
CGraphics::DrawArray(start, 4);
}
else
{
int xTiles = (info.x0_xSubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1;
int yTiles = (info.x1_ySubdivs - 3) / CFluidPlaneRender::numSubdivisionsInTile + 1;
int xTileStart = info.x28_tileX + info.x2e_tileY * info.x2a_gridDimX;
for (; yTiles>0 ; --yTiles, yMin += info.x14_tileSize, xTileStart += info.x2a_gridDimX)
{
xMax = xMin;
int nextXTile;
for (int curXTile=0 ; curXTile<xTiles ; curXTile=nextXTile)
{
if (info.x30_gridFlags[xTileStart+curXTile])
{
nextXTile = curXTile + 1;
int tile = xTileStart + nextXTile;
while (nextXTile < xTiles && info.x30_gridFlags[tile])
{
++nextXTile;
++tile;
}
size_t start = vOut.size();
for (int v = 0 ; v < nextXTile - curXTile + 1 ; ++v)
{
vOut.emplace_back(zeus::CVector3f(xMax, yMin, 0.f), zeus::CVector3f::skUp,
zeus::CVector3f::skForward, zeus::CVector3f::skRight,
zeus::CColor::skBlack);
vOut.emplace_back(zeus::CVector3f(xMax, yMin + info.x14_tileSize, 0.f),
zeus::CVector3f::skUp, zeus::CVector3f::skForward,
zeus::CVector3f::skRight, zeus::CColor::skBlack);
xMax += info.x14_tileSize;
}
CGraphics::DrawArray(start, vOut.size() - start);
}
else
{
nextXTile = curXTile + 1;
xMax += info.x14_tileSize;
int tile = xTileStart + nextXTile;
while (nextXTile < xTiles && !info.x30_gridFlags[tile])
{
xMax += info.x14_tileSize;
++nextXTile;
++tile;
}
}
}
}
}
break;
}
}
}
else
{
float curY = info.x4_localMin.y;
for (int startYDiv=1 ; startYDiv<info.x1_ySubdivs-2 ;
startYDiv += CFluidPlaneRender::numSubdivisionsInTile, curY += info.x14_tileSize)
RenderStripWithRipples(curY, heights, flags, startYDiv, info, vOut, pvOut);
}
}
}

View File

@ -7,6 +7,7 @@
#include "CFluidUVMotion.hpp"
#include "zeus/CAABox.hpp"
#include "zeus/CFrustum.hpp"
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
namespace urde
{
@ -15,33 +16,145 @@ class CRippleManager;
class CScriptWater;
class CStateManager;
class CRipple;
class CFluidPlane
class CFluidPlaneRender
{
public:
enum class EFluidType
enum class NormalMode
{
NormalWater,
PoisonWater,
Lava,
PhazonFluid,
Four,
ThickLava
None,
NoNormals,
Normals,
NBT
};
static int numTilesInHField;
static int numSubdivisionsInTile;
static int numSubdivisionsInHField;
struct SPatchInfo
{
u8 x0_xSubdivs, x1_ySubdivs;
zeus::CVector2f x4_localMin, xc_globalMin;
float x14_tileSize;
float x18_rippleResolution;
float x1c_tileHypRadius;
float x20_ooTileSize;
float x24_ooRippleResolution;
u16 x28_tileX;
u16 x2a_gridDimX;
u16 x2c_gridDimY;
u16 x2e_tileY;
const bool* x30_gridFlags;
u8 x34_redShift;
u8 x35_greenShift;
u8 x36_blueShift;
NormalMode x37_normalMode;
float x38_wavecapIntensityScale;
public:
SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos,
float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField,
NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX,
u32 gridDimY, u32 tileY, const bool* gridFlags)
{
x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
float tileHypRadius = tileSize * tileSize * 2 * 0.25f;
x4_localMin.x = localMin.x;
x4_localMin.y = localMin.y;
xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y);
x14_tileSize = tileSize;
x18_rippleResolution = rippleResolution;
if (tileHypRadius != 0.f)
tileHypRadius = std::sqrt(tileHypRadius);
x1c_tileHypRadius = tileHypRadius;
x20_ooTileSize = 1.f / x14_tileSize;
x24_ooRippleResolution = 1.f / x18_rippleResolution;
x28_tileX = u16(tileX);
x2a_gridDimX = u16(gridDimX);
x2c_gridDimY = u16(gridDimY);
x2e_tileY = u16(tileY);
x30_gridFlags = gridFlags;
x34_redShift = u8(redShift);
x35_greenShift = u8(greenShift);
x36_blueShift = u8(blueShift);
x37_normalMode = normalMode;
x38_wavecapIntensityScale = wavecapIntensityScale;
}
};
struct SRippleInfo
{
const CRipple& x0_ripple;
int x4_fromX;
int x8_toX;
int xc_fromY;
int x10_toY;
int x14_gfromX;
int x18_gtoX;
int x1c_gfromY;
int x20_gtoY;
public:
SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY)
: x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {}
};
struct SHFieldSample
{
float height;
s8 nx;
s8 ny;
s8 nz;
u8 wavecapIntensity;
zeus::CVector3f MakeNormal() const { return zeus::CVector3f{nx / 63.f, ny / 63.f, nz / 63.f}.normalized(); }
zeus::CVector3f MakeBinormal() const { return zeus::CVector3f{nx / 63.f, nz / 63.f, -ny / 63.f}.normalized(); }
zeus::CVector3f MakeTangent() const { return zeus::CVector3f{nz / 63.f, ny / 63.f, -nx / 63.f}.normalized(); }
zeus::CColor MakeColor(const CFluidPlaneRender::SPatchInfo& info) const
{
return {(wavecapIntensity >> info.x34_redShift) / 255.f,
(wavecapIntensity >> info.x35_greenShift) / 255.f,
(wavecapIntensity >> info.x36_blueShift) / 255.f};
}
};
};
class CFluidPlane
{
protected:
CAssetId x4_texPattern1Id;
CAssetId x8_texPattern2Id;
CAssetId xc_texColorId;
std::experimental::optional<TLockedToken<CTexture>> x10_texPattern1;
std::experimental::optional<TLockedToken<CTexture>> x20_texPattern2;
std::experimental::optional<TLockedToken<CTexture>> x30_texColor;
TLockedToken<CTexture> x10_texPattern1;
TLockedToken<CTexture> x20_texPattern2;
TLockedToken<CTexture> x30_texColor;
float x40_alpha;
EFluidType x44_fluidType;
float x48_rippleIntensity;
CFluidUVMotion x4c_uvMotion;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::vector<CFluidPlaneShader::PatchVertex> m_pVerts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
float ProjectRippleVelocity(float baseI, float velDot) const;
float CalculateRippleIntensity(float baseI) const;
virtual void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneRender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const;
void RenderPatch(const CFluidPlaneRender::SPatchInfo& info,
const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const;
public:
virtual ~CFluidPlane() = default;
CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, float alpha,
EFluidType fluidType, float rippleIntensity, const CFluidUVMotion& motion);
@ -64,11 +177,11 @@ public:
float GetAlpha() const { return x40_alpha; }
EFluidType GetFluidType() const { return x44_fluidType; }
const CFluidUVMotion& GetUVMotion() const { return x4c_uvMotion; }
const CTexture& GetColorTexture() const { return **x30_texColor; }
const CTexture& GetColorTexture() const { return *x30_texColor; }
bool HasColorTexture() const { return x30_texColor.operator bool(); }
const CTexture& GetTexturePattern1() const { return **x10_texPattern1; }
const CTexture& GetTexturePattern1() const { return *x10_texPattern1; }
bool HasTexturePattern1() const { return x10_texPattern1.operator bool(); }
const CTexture& GetTexturePattern2() const { return **x20_texPattern2; }
const CTexture& GetTexturePattern2() const { return *x20_texPattern2; }
bool HasTexturePattern2() const { return x20_texPattern2.operator bool(); }
};
}

File diff suppressed because it is too large Load Diff

View File

@ -3,13 +3,14 @@
#include "CFluidPlane.hpp"
#include "CRipple.hpp"
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
namespace urde
{
class CFluidUVMotion;
class CFluidPlaneCPU final : public CFluidPlane
class CFluidPlaneCPU : public CFluidPlane
{
protected:
class CTurbulence
{
float x0_speed;
@ -39,10 +40,10 @@ class CFluidPlaneCPU final : public CFluidPlane
CAssetId xa4_texIdEnvMap;
CAssetId xa8_texIdEnvBumpMap;
CAssetId xac_texId4;
std::experimental::optional<TLockedToken<CTexture>> xb0_bumpMap;
std::experimental::optional<TLockedToken<CTexture>> xc0_envMap;
std::experimental::optional<TLockedToken<CTexture>> xd0_envBumpMap;
std::experimental::optional<TLockedToken<CTexture>> xe0_lightmap;
TLockedToken<CTexture> xb0_bumpMap;
TLockedToken<CTexture> xc0_envMap;
TLockedToken<CTexture> xd0_envBumpMap;
TLockedToken<CTexture> xe0_lightmap;
zeus::CVector3f xf0_bumpLightDir;
float xfc_bumpScale;
float x100_tileSize;
@ -56,16 +57,41 @@ class CFluidPlaneCPU final : public CFluidPlane
CTurbulence x120_turbulence;
u32 m_maxVertCount;
bool m_tessellation = false;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
mutable bool m_cachedDoubleLightmapBlend;
mutable bool m_cachedAdditive;
static bool PrepareRipple(const CRipple& ripple, const CFluidPlaneRender::SPatchInfo& info,
CFluidPlaneRender::SRippleInfo& rippleOut);
void ApplyTurbulence(float t, CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], const float sineWave[256],
const CFluidPlaneRender::SPatchInfo& info,
const zeus::CVector3f& areaCenter) const;
void ApplyRipple(const CFluidPlaneRender::SRippleInfo& rippleInfo,
CFluidPlaneRender::SHFieldSample (&heights)[46][46],
u8 (&flags)[9][9], const float sineWave[256],
const CFluidPlaneRender::SPatchInfo& info) const;
void ApplyRipples(const rstl::reserved_vector<CFluidPlaneRender::SRippleInfo, 32>& rippleInfos,
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const float sineWave[256], const CFluidPlaneRender::SPatchInfo& info) const;
static void UpdatePatchNoNormals(CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9],
const CFluidPlaneRender::SPatchInfo& info);
static void UpdatePatchWithNormals(CFluidPlaneRender::SHFieldSample (& heights)[46][46],
const u8 (& flags)[9][9],
const CFluidPlaneRender::SPatchInfo& info);
bool UpdatePatch(float time, const CFluidPlaneRender::SPatchInfo& info,
CFluidPlaneRender::SHFieldSample (&heights)[46][46], u8 (&flags)[9][9],
const zeus::CVector3f& areaCenter,
const std::experimental::optional<CRippleManager>& rippleManager,
int fromX, int toX, int fromY, int toY) const;
public:
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap,
CAssetId lightMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions,
EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, float bumpScale,
const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap,
CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, float tileSize,
u32 tileSubdivisions, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir,
float bumpScale, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
float reflectionSize, float rippleIntensity, u32 maxVertCount);
@ -85,13 +111,13 @@ public:
float GetReflectionSize() const { return x118_reflectionSize; }
float GetBumpScale() const { return xfc_bumpScale; }
bool HasBumpMap() const { return xb0_bumpMap.operator bool(); }
const CTexture& GetBumpMap() const { return **xb0_bumpMap; }
const CTexture& GetBumpMap() const { return *xb0_bumpMap; }
bool HasEnvMap() const { return xc0_envMap.operator bool(); }
const CTexture& GetEnvMap() const { return **xc0_envMap; }
const CTexture& GetEnvMap() const { return *xc0_envMap; }
bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); }
const CTexture& GetEnvBumpMap() const { return **xd0_envBumpMap; }
const CTexture& GetEnvBumpMap() const { return *xd0_envBumpMap; }
bool HasLightMap() const { return xe0_lightmap.operator bool(); }
const CTexture& GetLightMap() const { return **xe0_lightmap; }
const CTexture& GetLightMap() const { return *xe0_lightmap; }
const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; }
float GetTileSize() const { return x100_tileSize; }
int GetTileSubdivisions() const { return x104_tileSubdivisions; }
@ -102,115 +128,6 @@ public:
bool HasTurbulence() const { return x120_turbulence.HasTurbulence(); }
};
class CFluidPlaneCPURender
{
public:
enum class NormalMode
{
None,
NoNormals,
Normals,
NBT
};
static int numTilesInHField;
static int numSubdivisionsInTile;
static int numSubdivisionsInHField;
struct SPatchInfo
{
u8 x0_xSubdivs, x1_ySubdivs;
zeus::CVector2f x4_localMin, xc_globalMin;
float x14_tileSize;
float x18_rippleResolution;
float x1c_tileHypRadius;
float x20_ooTileSize;
float x24_ooRippleResolution;
u16 x28_tileX;
u16 x2a_gridDimX;
u16 x2c_gridDimY;
u16 x2e_tileY;
const bool* x30_gridFlags;
u8 x34_redShift;
u8 x35_greenShift;
u8 x36_blueShift;
NormalMode x37_normalMode;
float x38_wavecapIntensityScale;
public:
SPatchInfo(const zeus::CVector3f& localMin, const zeus::CVector3f& localMax, const zeus::CVector3f& pos,
float rippleResolution, float tileSize, float wavecapIntensityScale, int numSubdivisionsInHField,
NormalMode normalMode, int redShift, int greenShift, int blueShift, u32 tileX, u32 gridDimX,
u32 gridDimY, u32 tileY, const bool* gridFlags)
{
x0_xSubdivs = std::min(s16((localMax.x - localMin.x) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
x1_ySubdivs = std::min(s16((localMax.y - localMin.y) / rippleResolution + 1.f - FLT_EPSILON) + 2,
numSubdivisionsInHField + 2);
float tileHypRadius = tileSize * tileSize * 2 * 0.25f;
x4_localMin.x = localMin.x;
x4_localMin.y = localMin.y;
xc_globalMin = x4_localMin + zeus::CVector2f(pos.x, pos.y);
x14_tileSize = tileSize;
x18_rippleResolution = rippleResolution;
if (tileHypRadius != 0.f)
tileHypRadius = std::sqrt(tileHypRadius);
x1c_tileHypRadius = tileHypRadius;
x20_ooTileSize = 1.f / x14_tileSize;
x24_ooRippleResolution = 1.f / x18_rippleResolution;
x28_tileX = u16(tileX);
x2a_gridDimX = u16(gridDimX);
x2c_gridDimY = u16(gridDimY);
x2e_tileY = u16(tileY);
x30_gridFlags = gridFlags;
x34_redShift = u8(redShift);
x35_greenShift = u8(greenShift);
x36_blueShift = u8(blueShift);
x37_normalMode = normalMode;
x38_wavecapIntensityScale = wavecapIntensityScale;
}
};
struct SRippleInfo
{
const CRipple& x0_ripple;
int x4_fromX;
int x8_toX;
int xc_fromY;
int x10_toY;
int x14_gfromX;
int x18_gtoX;
int x1c_gfromY;
int x20_gtoY;
public:
SRippleInfo(const CRipple& ripple, int fromX, int toX, int fromY, int toY)
: x0_ripple(ripple), x14_gfromX(fromX), x18_gtoX(toX), x1c_gfromY(fromY), x20_gtoY(toY) {}
};
struct SHFieldSample
{
float height;
s8 nx;
s8 ny;
s8 nz;
u8 wavecapIntensity;
zeus::CVector3f MakeNormal() const { return {nx / 63.f, ny / 63.f, nz / 63.f}; }
zeus::CVector3f MakeBinormal() const { return {nx / 63.f, nz / 63.f, -ny / 63.f}; }
zeus::CVector3f MakeTangent() const { return {nz / 63.f, ny / 63.f, -nx / 63.f}; }
zeus::CColor MakeColor(const CFluidPlaneCPURender::SPatchInfo& info) const
{
return {(wavecapIntensity >> info.x34_redShift) / 255.f,
(wavecapIntensity >> info.x35_greenShift) / 255.f,
(wavecapIntensity >> info.x36_blueShift) / 255.f};
}
};
};
void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
const CFluidPlaneCPURender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
std::vector<CFluidPlaneShader::Vertex>& vOut);
}
#endif // __URDE_CFLUIDPLANECPU_HPP__

View File

@ -52,7 +52,7 @@ CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, const zeus::
/* Used to be part of locked cache
* These are too big for stack allocation */
static CFluidPlaneCPURender::SHFieldSample lc_heights[46][46] = {};
static CFluidPlaneRender::SHFieldSample lc_heights[46][46] = {};
static u8 lc_flags[9][9] = {};
void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
@ -61,14 +61,15 @@ void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
{
CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, aabb, noNormals);
CFluidPlaneCPURender::numSubdivisionsInTile = xa4_tileSubdivisions;
CFluidPlaneCPURender::numTilesInHField = 42 / xa4_tileSubdivisions;
CFluidPlaneCPURender::numSubdivisionsInHField = CFluidPlaneCPURender::numTilesInHField * xa4_tileSubdivisions;
CFluidPlaneRender::numSubdivisionsInTile = xa4_tileSubdivisions;
CFluidPlaneRender::numTilesInHField = 42 / xa4_tileSubdivisions;
CFluidPlaneRender::numSubdivisionsInHField = CFluidPlaneRender::numTilesInHField * xa4_tileSubdivisions;
zeus::CVector2f centerPlane(aabb.center().x, aabb.center().y);
float patchSize = xa8_rippleResolution * CFluidPlaneCPURender::numSubdivisionsInHField;
float patchSize = xa8_rippleResolution * CFluidPlaneRender::numSubdivisionsInHField;
float ooSubdivSize = 1.f / xa8_rippleResolution;
m_verts.clear();
m_pVerts.clear();
m_shader->prepareDraw(setupInfo);
for (float curX = aabb.min.x ; curX < aabb.max.x ; curX += patchSize)
@ -77,26 +78,27 @@ void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::
for (float curY = aabb.min.y ; curY < aabb.max.y ; curY += patchSize)
{
float remSubdivsY = (aabb.max.y - curY) * ooSubdivSize;
int remSubdivsXi = std::min(CFluidPlaneCPURender::numSubdivisionsInHField, int(remSubdivsX));
int remSubdivsYi = std::min(CFluidPlaneCPURender::numSubdivisionsInHField, int(remSubdivsY));
int remSubdivsXi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsX));
int remSubdivsYi = std::min(CFluidPlaneRender::numSubdivisionsInHField, int(remSubdivsY));
zeus::CAABox aabb2(aabb.min, zeus::CVector3f(xa8_rippleResolution * remSubdivsXi + curX,
xa8_rippleResolution * remSubdivsYi + curY,
aabb.max.z));
if (frustum.aabbFrustumTest(aabb2.getTransformedAABox(xf)))
{
CFluidPlaneCPURender::SPatchInfo patchInfo(zeus::CVector3f(curX, curY, aabb.min.z),
CFluidPlaneRender::SPatchInfo patchInfo(zeus::CVector3f(curX, curY, aabb.min.z),
aabb2.max, xf.origin, xa8_rippleResolution,
xa0_tileSize, 0.f,
CFluidPlaneCPURender::numSubdivisionsInHField,
CFluidPlaneCPURender::NormalMode::None,
CFluidPlaneRender::numSubdivisionsInHField,
CFluidPlaneRender::NormalMode::None,
0, 0, 0, 0, 0, 0, 0, nullptr);
RenderPatch(patchInfo, lc_heights, lc_flags, true, true, m_verts);
RenderPatch(patchInfo, lc_heights, lc_flags, true, true, m_verts, m_pVerts);
}
}
}
m_shader->loadVerts(m_verts);
m_shader->loadVerts(m_verts, m_pVerts);
m_shader->doneDrawing();
}
}

View File

@ -12,9 +12,6 @@ class CFluidPlaneDoor final : public CFluidPlane
int xa4_tileSubdivisions;
float xa8_rippleResolution;
mutable std::vector<CFluidPlaneShader::Vertex> m_verts;
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
CFluidPlaneShader::RenderSetupInfo
RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf,
const zeus::CAABox& aabb, bool noNormals) const;

View File

@ -0,0 +1,93 @@
#include "CFluidPlaneGPU.hpp"
namespace urde
{
CFluidPlaneGPU::CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap,
CAssetId envMap, CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel,
float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot,
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin,
float specularMin, float specularMax, float reflectionBlend, float reflectionSize,
float rippleIntensity, u32 maxVertCount)
: CFluidPlaneCPU(texPattern1, texPattern2, texColor, bumpMap, envMap, envBumpMap, lightMap, unitsPerLightmapTexel,
tileSize, tileSubdivisions, fluidType, alpha, bumpLightDir, bumpScale, mot, turbSpeed, turbDistance,
turbFreqMax, turbFreqMin, turbPhaseMax, turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin,
specularMin, specularMax, reflectionBlend, reflectionSize, rippleIntensity, maxVertCount)
{
m_tessellation = true;
}
void CFluidPlaneGPU::RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneRender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const
{
m_shader->bindTessellation();
int yTile = (startYDiv + CFluidPlaneRender::numSubdivisionsInTile - 1) /
CFluidPlaneRender::numSubdivisionsInTile;
int endXTile = (info.x0_xSubdivs + CFluidPlaneRender::numSubdivisionsInTile - 4) /
CFluidPlaneRender::numSubdivisionsInTile;
float yMin = curY;
float subdivF = CFluidPlaneRender::numSubdivisionsInTile;
float curX = info.x4_localMin.x;
int gridCell = info.x28_tileX + info.x2a_gridDimX * (info.x2e_tileY + yTile - 1);
int xTile = 1;
int tileSpan;
for (int i = 1 ; i < info.x0_xSubdivs - 2 ;
i += CFluidPlaneRender::numSubdivisionsInTile * tileSpan, gridCell += tileSpan,
xTile += tileSpan, curX += info.x14_tileSize * tileSpan)
{
tileSpan = 1;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell])
continue;
CFluidPlaneShader::PatchVertex pv;
size_t start = pvOut.size();
if ((flags[yTile][xTile] & 0x1f) == 0x1f)
{
for (; xTile+tileSpan<=endXTile ; ++tileSpan)
{
if ((flags[yTile][xTile+tileSpan] & 0x1f) != 0x1f)
break;
if (info.x30_gridFlags && !info.x30_gridFlags[gridCell+tileSpan])
break;
}
std::fill(std::begin(pv.m_outerLevels), std::end(pv.m_outerLevels), subdivF);
std::fill(std::begin(pv.m_innerLevels), std::end(pv.m_innerLevels), subdivF);
}
else
{
bool r19 = (flags[yTile+1][xTile] & 0x2) != 0; // North
bool r16 = (flags[yTile][xTile-1] & 0x8) != 0; // West
bool r18 = (flags[yTile][xTile+1] & 0x4) != 0; // East
bool r17 = (flags[yTile-1][xTile] & 0x1) != 0; // South
pv.m_outerLevels[0] = r16 ? subdivF : 1.f;
pv.m_outerLevels[1] = r17 ? subdivF : 1.f;
pv.m_outerLevels[2] = r18 ? subdivF : 1.f;
pv.m_outerLevels[3] = r19 ? subdivF : 1.f;
std::fill(std::begin(pv.m_innerLevels), std::end(pv.m_innerLevels), subdivF);
}
float curTileY = yMin;
float curTileX = curX;
for (int t=0 ; t<tileSpan ; ++t)
{
pv.m_pos = zeus::CVector4f(curTileX, curTileY, curTileX + info.x14_tileSize, curTileY + info.x14_tileSize);
pvOut.push_back(pv);
curTileX += info.x14_tileSize;
}
CGraphics::DrawArray(start, pvOut.size() - start);
}
}
}

View File

@ -0,0 +1,29 @@
#ifndef __URDE_CFLUIDPLANEGPU_HPP__
#define __URDE_CFLUIDPLANEGPU_HPP__
#include "CFluidPlaneCPU.hpp"
namespace urde
{
class CFluidPlaneGPU final : public CFluidPlaneCPU
{
public:
CFluidPlaneGPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap,
CAssetId envBumpMap, CAssetId lightMap, float unitsPerLightmapTexel, float tileSize,
u32 tileSubdivisions, EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir,
float bumpScale, const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
float reflectionSize, float rippleIntensity, u32 maxVertCount);
void RenderStripWithRipples(float curY, const CFluidPlaneRender::SHFieldSample (&heights)[46][46],
const u8 (&flags)[9][9], int startYDiv,
const CFluidPlaneRender::SPatchInfo& info,
std::vector<CFluidPlaneShader::Vertex>& vOut,
std::vector<CFluidPlaneShader::PatchVertex>& pvOut) const;
};
}
#endif // __URDE_CFLUIDPLANEGPU_HPP__

View File

@ -92,12 +92,18 @@ void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, co
}
}
static bool g_RippleMapSetup = false;
u8 CFluidPlaneManager::RippleValues[64][64] = {};
u8 CFluidPlaneManager::RippleMins[64] = {};
u8 CFluidPlaneManager::RippleMaxs[64] = {};
boo::ObjToken<boo::ITextureS> CFluidPlaneManager::RippleMapTex;
void CFluidPlaneManager::SetupRippleMap()
{
if (g_RippleMapSetup)
return;
g_RippleMapSetup = true;
float curX = 0.f;
for (int i=0 ; i<64 ; ++i)
{
@ -142,6 +148,13 @@ void CFluidPlaneManager::SetupRippleMap()
RippleMaxs[i] = valC;
curX += (1.f / 63.f);
}
CGraphics::CommitResources([](boo::IGraphicsDataFactory::Context& ctx)
{
RippleMapTex = ctx.newStaticTexture(64, 64, 1, boo::TextureFormat::I8,
boo::TextureClampMode::ClampToBlack, RippleValues, 64 * 64);
return true;
} BooTrace);
}
}

View File

@ -3,9 +3,21 @@
#include "RetroTypes.hpp"
#include "CRippleManager.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace urde
{
enum class EFluidType
{
NormalWater,
PoisonWater,
Lava,
PhazonFluid,
Four,
ThickLava
};
class CStateManager;
class CScriptWater;
@ -45,6 +57,7 @@ public:
static u8 RippleValues[64][64];
static u8 RippleMins[64];
static u8 RippleMaxs[64];
static boo::ObjToken<boo::ITextureS> RippleMapTex;
CFluidPlaneManager();
void StartFrame(bool);

View File

@ -118,6 +118,7 @@ set(WORLD_SOURCES
CGameLight.hpp CGameLight.cpp
CFluidPlane.hpp CFluidPlane.cpp
CFluidPlaneCPU.hpp CFluidPlaneCPU.cpp
CFluidPlaneGPU.hpp CFluidPlaneGPU.cpp
CFluidPlaneDoor.hpp CFluidPlaneDoor.cpp
CRippleManager.hpp CRippleManager.cpp
CRipple.hpp CRipple.cpp

View File

@ -930,7 +930,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
zeus::CVector3f position = x34_transform.origin + posOffset;
position.z = water.GetTriggerBoundsWR().max.z;
mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true);
if (water.GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::NormalWater)
if (water.GetFluidPlane().GetFluidType() == EFluidType::NormalWater)
{
float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f;
mgr.GetEnvFxManager()->SetXB54(10.f * std::max(1.f, velMag));
@ -2899,17 +2899,17 @@ void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CState
{
switch (water->GetFluidPlane().GetFluidType())
{
case CFluidPlane::EFluidType::NormalWater:
case EFluidType::NormalWater:
x2b0_outOfWaterTicks = 0;
break;
case CFluidPlane::EFluidType::Lava:
case CFluidPlane::EFluidType::ThickLava:
case EFluidType::Lava:
case EFluidType::ThickLava:
x2ac_surfaceRestraint = ESurfaceRestraints::Lava;
break;
case CFluidPlane::EFluidType::PoisonWater:
case EFluidType::PoisonWater:
x2b0_outOfWaterTicks = 0;
break;
case CFluidPlane::EFluidType::PhazonFluid:
case EFluidType::PhazonFluid:
x2ac_surfaceRestraint = ESurfaceRestraints::PhazonFluid;
break;
default: break;
@ -6618,8 +6618,8 @@ void CPlayer::UpdateSubmerged(CStateManager& mgr)
{
x828_distanceUnderWater =
-(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z);
CFluidPlane::EFluidType fluidType = water->GetFluidPlane().GetFluidType();
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Lava || fluidType == CFluidPlane::EFluidType::ThickLava);
EFluidType fluidType = water->GetFluidPlane().GetFluidType();
x82c_inLava = (fluidType == EFluidType::Lava || fluidType == EFluidType::ThickLava);
CheckSubmerged();
}
}

View File

@ -15,8 +15,8 @@ CRipple::CRipple(TUniqueId id, const zeus::CVector3f& center, float intensity)
x14_timeFalloff = 0.5f * tmp + 1.5f;
x18_distFalloff = 4.f * tmp + 8.f;
x1c_frequency = 2.f + tmp;
x20_preAmplitude = 0.15f * tmp + 0.1f;
x24_amplitude = x20_preAmplitude / 255.f;
x20_amplitude = 0.15f * tmp + 0.1f;
x24_lookupAmplitude = x20_amplitude / 255.f;
}
x28_ooTimeFalloff = 1.f / x14_timeFalloff;

View File

@ -15,8 +15,8 @@ private:
float x14_timeFalloff = 2.f;
float x18_distFalloff = 12.f;
float x1c_frequency = 3.f;
float x20_preAmplitude = 0.25f;
float x24_amplitude = 0.00098039221f;
float x20_amplitude = 0.25f;
float x24_lookupAmplitude = 0.00098039221f;
float x28_ooTimeFalloff = 0.f;
float x2c_ooDistFalloff = 0.f;
float x30_ooPhase = 0.f;
@ -32,11 +32,13 @@ public:
float GetTimeFalloff() const { return x14_timeFalloff; }
TUniqueId GetUniqueId() const { return x0_id; }
float GetFrequency() const { return x1c_frequency; }
float GetAmplitude() const { return x24_amplitude; }
float GetAmplitude() const { return x20_amplitude; }
float GetLookupAmplitude() const { return x24_lookupAmplitude; }
float GetOODistanceFalloff() const { return x2c_ooDistFalloff; }
float GetDistanceFalloff() const { return x18_distFalloff; }
const zeus::CVector3f& GetCenter() const { return x8_center; }
float GetOOTimeFalloff() const { return x28_ooTimeFalloff; }
float GetPhase() const { return x34_phase; }
float GetLookupPhase() const { return x38_lookupPhase; }
};
}

View File

@ -36,7 +36,7 @@ CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, std::string_vi
x14c_bounds(-extent * 0.5f, extent * 0.5f),
x164_origHInfo(hInfo), x16c_hInfo(hInfo), x174_dVuln(dVuln), x1dc_faceFlag(faceFlag),
x254_fluidPlane(patternTex1, patternTex2, colorTex, 1.f, 2,
CFluidPlane::EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f))
EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f))
{
x300_28_canOrbit = canOrbit == ECanOrbit::Orbit;
if (x1dc_faceFlag & 0x1)

View File

@ -6,6 +6,7 @@
#include "World/CWorld.hpp"
#include "Graphics/CBooRenderer.hpp"
#include "Camera/CGameCamera.hpp"
#include "CFluidPlaneGPU.hpp"
namespace urde
{
@ -22,10 +23,10 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view n
bool allowRender, CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap,
CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap, CAssetId unusedMap,
const zeus::CVector3f& bumpLightDir, float bumpScale, float morphInTime, float morphOutTime,
bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha,
bool active, EFluidType fluidType, bool b4, float alpha,
const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& unkColor,
float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& insideFogColor,
CAssetId splashParticle1, CAssetId splashParticle2, CAssetId splashParticle3,
CAssetId visorRunoffParticle, CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx,
s32 unmorphVisorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
@ -44,8 +45,8 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view n
x24c_unmorphVisorRunoffParticleId(unmorphVisorRunoffparticle),
x260_visorRunoffSfx(CSfxManager::TranslateSFXID(visorRunoffSfx)),
x262_unmorphVisorRunoffSfx(CSfxManager::TranslateSFXID(unmorphVisorRunoffSfx)),
x2a4_splashColor(splashColor), x2a8_fogColor(unkColor), x2ac_alphaInTime(alphaInTime), x2b0_alphaOutTime(alphaOutTime),
x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f),
x2a4_splashColor(splashColor), x2a8_insideFogColor(insideFogColor), x2ac_alphaInTime(alphaInTime),
x2b0_alphaOutTime(alphaOutTime), x2b4_alphaInRecip((alphaInTime != 0.f) ? 1.f / alphaInTime : 0.f),
x2b8_alphaOutRecip((alphaOutTime != 0.f) ? 1.f / alphaOutTime : 0.f), x2bc_alpha(alpha), x2c0_tileSize(tileSize)
{
zeus::CAABox triggerAABB = GetTriggerBoundsWR();
@ -56,14 +57,25 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view n
x2e8_27_allowRender = allowRender;
x2e8_28_recomputeClipping = true;
x1b4_fluidPlane = std::make_unique<CFluidPlaneCPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap,
lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions,
fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot,
turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin,
specularMax, reflectionBlend, reflectionSize, rippleIntensity,
x2cc_gridCellCount *
((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4));
uint32_t maxPatchSize;
if (CGraphics::g_BooFactory->isTessellationSupported(maxPatchSize))
x1b4_fluidPlane = std::make_unique<CFluidPlaneGPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap,
lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions * 2,
fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot,
turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin,
specularMax, reflectionBlend, reflectionSize, rippleIntensity,
x2cc_gridCellCount *
((std::max(u32(2), tileSubdivisions * 2) * 4 + 2) * 4));
else
x1b4_fluidPlane = std::make_unique<CFluidPlaneCPU>(patternMap1, patternMap2, colorMap, bumpMap, envMap, envBumpMap,
lightmapId, unitsPerLightmapTexel, tileSize, tileSubdivisions,
fluidType, x2bc_alpha, bumpLightDir, bumpScale, uvMot,
turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, specularMin,
specularMax, reflectionBlend, reflectionSize, rippleIntensity,
x2cc_gridCellCount *
((std::max(u32(2), tileSubdivisions) * 4 + 2) * 4));
u32Arr.reset();
x264_splashEffects.resize(3);
if (x22c_splashParticle1Id.IsValid())

View File

@ -43,7 +43,7 @@ private:
rstl::reserved_vector<std::experimental::optional<TLockedToken<CGenDescription>>, 3> x264_splashEffects;
rstl::reserved_vector<u16, 3> x298_splashSounds;
zeus::CColor x2a4_splashColor;
zeus::CColor x2a8_fogColor;
zeus::CColor x2a8_insideFogColor;
float x2ac_alphaInTime;
float x2b0_alphaOutTime;
float x2b4_alphaInRecip;
@ -83,10 +83,10 @@ public:
bool allowRender, CAssetId patternMap1, CAssetId patternMap2, CAssetId colorMap,
CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap, CAssetId unusedMap,
const zeus::CVector3f& bumpLightDir, float bumpScale, float morphInTime, float morphOutTime,
bool active, CFluidPlane::EFluidType fluidType, bool b4, float alpha,
bool active, EFluidType fluidType, bool b4, float alpha,
const CFluidUVMotion& uvMot, float turbSpeed, float turbDistance, float turbFreqMax,
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& unkColor,
float turbAmplitudeMin, const zeus::CColor& splashColor, const zeus::CColor& insideFogColor,
CAssetId splashParticle1, CAssetId splashParticle2, CAssetId splashParticle3,
CAssetId visorRunoffParticle, CAssetId unmorphVisorRunoffparticle, s32 visorRunoffSfx,
s32 unmorphVisorRunoffSfx, s32 splashSfx1, s32 splashSfx2, s32 splashSfx3, float tileSize,
@ -132,7 +132,7 @@ public:
int GetPatchDimensionX() const { return x2d0_patchDimX; }
int GetPatchDimensionY() const { return x2d4_patchDimY; }
bool CanRippleAtPoint(const zeus::CVector3f& point) const;
const zeus::CColor& GetFogColor() const { return x2a8_fogColor; }
const zeus::CColor& GetInsideFogColor() const { return x2a8_insideFogColor; }
};
}

View File

@ -1238,7 +1238,7 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
float morphInTime = in.readFloatBig();
float morphOutTime = in.readFloatBig();
bool active = in.readBool();
auto fluidType = CFluidPlane::EFluidType(in.readUint32Big());
auto fluidType = EFluidType(in.readUint32Big());
bool b4 = in.readBool();
float alpha = in.readFloatBig();
CFluidUVMotion uvMotion = LoadFluidUVMotion(in);
@ -1253,8 +1253,8 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
float turbAmplitudeMin = in.readFloatBig();
zeus::CColor splashColor;
splashColor.readRGBABig(in);
zeus::CColor unkColor;
unkColor.readRGBABig(in);
zeus::CColor insideFogColor;
insideFogColor.readRGBABig(in);
CAssetId splashParticle1 = in.readUint32Big();
CAssetId splashParticle2 = in.readUint32Big();
CAssetId splashParticle3 = in.readUint32Big();
@ -1312,7 +1312,7 @@ CEntity* ScriptLoader::LoadWater(CStateManager& mgr, CInputStream& in, int propC
thermalCold, displaySurface, patternMap1, patternMap2, colorMap, bumpMap, envMap,
envBumpMap, {}, bumpLightDir, bumpScale, morphInTime, morphOutTime, active, fluidType, b4,
alpha, uvMotion, turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, splashColor, unkColor, splashParticle1,
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin, splashColor, insideFogColor, splashParticle1,
splashParticle2, splashParticle3, visorRunoffParticle, unmorphVisorRunoffParticle,
visorRunoffSfx, unmorphVisorRunoffSfx, splashSfx1, splashSfx2, splashSfx3, tileSize,
tileSubdivisions, specularMin, specularMax, reflectionSize, rippleIntensity,

2
hecl

@ -1 +1 @@
Subproject commit 788fa73884d56417d6bc70918983c9d9ac8032b4
Subproject commit c9e057fa6e314257909edcd9758a0628bbc91918