mirror of https://github.com/AxioDL/metaforce.git
Implement CFluidPlaneDoor and CScriptDamageableTrigger
This commit is contained in:
parent
02f8f77b57
commit
086ff76474
|
@ -2,7 +2,7 @@
|
|||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="ClangTidyInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="clangTidyChecks" value="*,-cert-env33-c,-cppcoreguidelines-no-malloc,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-union-access,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-memset,google-runtime-operator,-llvm-*,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-misc-bool-pointer-implicit-conversion,-misc-unused-parameters,-modernize-use-using,-safety-no-assembler,-clang-diagnostic-*,-clang-analyzer-*,-cert-flp30-c" />
|
||||
<option name="clangTidyChecks" value="*,-cert-env33-c,-cppcoreguidelines-no-malloc,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-type-const-cast,-cppcoreguidelines-pro-type-cstyle-cast,-cppcoreguidelines-pro-type-union-access,-google-*,google-default-arguments,google-explicit-constructor,google-runtime-member-string-references,google-runtime-memset,google-runtime-operator,-llvm-*,-readability-simplify-boolean-expr,-readability-braces-around-statements,-readability-identifier-naming,-readability-function-size,-misc-bool-pointer-implicit-conversion,-misc-unused-parameters,-modernize-use-using,-safety-no-assembler,-clang-diagnostic-*,-clang-analyzer-*,-cert-flp30-c,-cppcoreguidelines-pro-type-vararg" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
|
|
|
@ -15,6 +15,9 @@ struct ITweakGame : ITweak
|
|||
virtual float GetWavecapIntensityNormal() const = 0;
|
||||
virtual float GetWavecapIntensityPoison() const = 0;
|
||||
virtual float GetWavecapIntensityLava() const = 0;
|
||||
virtual float GetRippleIntensityNormal() const = 0;
|
||||
virtual float GetRippleIntensityPoison() const = 0;
|
||||
virtual float GetRippleIntensityLava() const = 0;
|
||||
virtual float GetFluidEnvBumpScale() const = 0;
|
||||
virtual float GetHardModeDamageMultiplier() const = 0;
|
||||
virtual float GetHardModeWeaponMultiplier() const = 0;
|
||||
|
|
|
@ -17,38 +17,38 @@ struct DamageableTrigger : IScriptObject
|
|||
Value<atVec3f> volume;
|
||||
HealthInfo healthInfo;
|
||||
DamageVulnerability damageVulnerabilty;
|
||||
Value<atUint32> unknown1;
|
||||
UniqueID32 texture1;
|
||||
UniqueID32 texture2;
|
||||
UniqueID32 texture3;
|
||||
Value<atUint32> faceFlag;
|
||||
UniqueID32 patternTex1;
|
||||
UniqueID32 patternTex2;
|
||||
UniqueID32 colorTex;
|
||||
Value<bool> lockOn;
|
||||
Value<bool> active;
|
||||
VisorParameters visorParameters;
|
||||
|
||||
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
|
||||
{
|
||||
if (texture1)
|
||||
if (patternTex1)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture1);
|
||||
ent->name = name + "_texture1";
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex1);
|
||||
ent->name = name + "_patternTex1";
|
||||
}
|
||||
if (texture2)
|
||||
if (patternTex2)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture2);
|
||||
ent->name = name + "_texture2";
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternTex2);
|
||||
ent->name = name + "_patternTex2";
|
||||
}
|
||||
if (texture3)
|
||||
if (colorTex)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(texture3);
|
||||
ent->name = name + "_texture3";
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorTex);
|
||||
ent->name = name + "_colorTex";
|
||||
}
|
||||
}
|
||||
|
||||
void gatherDependencies(std::vector<hecl::ProjectPath>& pathsOut) const
|
||||
{
|
||||
g_curSpec->flattenDependencies(texture1, pathsOut);
|
||||
g_curSpec->flattenDependencies(texture2, pathsOut);
|
||||
g_curSpec->flattenDependencies(texture3, pathsOut);
|
||||
g_curSpec->flattenDependencies(patternTex1, pathsOut);
|
||||
g_curSpec->flattenDependencies(patternTex2, pathsOut);
|
||||
g_curSpec->flattenDependencies(colorTex, pathsOut);
|
||||
}
|
||||
|
||||
zeus::CAABox getVISIAABB(hecl::BlenderToken& btok) const
|
||||
|
|
|
@ -84,7 +84,7 @@ struct Water : IScriptObject
|
|||
Value<float> fogBias;
|
||||
Value<float> fogMagnitude;
|
||||
Value<float> fogSpeed;
|
||||
Value<atVec4f> fogColor; // CColor
|
||||
Value<atVec4f> fogColor;
|
||||
UniqueID32 lightmap;
|
||||
Value<float> unitsPerLightmapTexel;
|
||||
Value<float> alphaInTime;
|
||||
|
@ -116,52 +116,52 @@ struct Water : IScriptObject
|
|||
if (patternMap1)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap1);
|
||||
ent->name = name + "_tex1";
|
||||
ent->name = name + "_patternMap1";
|
||||
}
|
||||
if (patternMap2)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(patternMap2);
|
||||
ent->name = name + "_tex2";
|
||||
ent->name = name + "_patternMap2";
|
||||
}
|
||||
if (colorMap)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(colorMap);
|
||||
ent->name = name + "_tex3";
|
||||
ent->name = name + "_colorMap";
|
||||
}
|
||||
if (bumpMap)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(bumpMap);
|
||||
ent->name = name + "_tex4";
|
||||
ent->name = name + "_bumpMap";
|
||||
}
|
||||
if (envMap)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envMap);
|
||||
ent->name = name + "_tex5";
|
||||
ent->name = name + "_envMap";
|
||||
}
|
||||
if (envBumpMap)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(envBumpMap);
|
||||
ent->name = name + "_tex6";
|
||||
ent->name = name + "_envBumpMap";
|
||||
}
|
||||
if (lightmap)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(lightmap);
|
||||
ent->name = name + "_tex34";
|
||||
ent->name = name + "_lightmap";
|
||||
}
|
||||
if (splashParticle1)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle1);
|
||||
ent->name = name + "_part1";
|
||||
ent->name = name + "_splashParticle1";
|
||||
}
|
||||
if (splashParticle2)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle2);
|
||||
ent->name = name + "_part2";
|
||||
ent->name = name + "_splashParticle2";
|
||||
}
|
||||
if (splashParticle3)
|
||||
{
|
||||
PAK::Entry* ent = (PAK::Entry*)pakRouter.lookupEntry(splashParticle3);
|
||||
ent->name = name + "_part3";
|
||||
ent->name = name + "_splashParticle3";
|
||||
}
|
||||
if (particle4)
|
||||
{
|
||||
|
|
|
@ -23,9 +23,9 @@ struct CTweakGame : ITweakGame
|
|||
Value<float> x34_wavecapIntensityNormal;
|
||||
Value<float> x38_wavecapIntensityPoison;
|
||||
Value<float> x3c_wavecapIntensityLava;
|
||||
Value<float> x40_unknown10;
|
||||
Value<float> x44_unknown11;
|
||||
Value<float> x48_unknown12;
|
||||
Value<float> x40_rippleIntensityNormal;
|
||||
Value<float> x44_rippleIntentityPoison;
|
||||
Value<float> x48_rippleIntensityLava;
|
||||
Value<float> x4c_fluidEnvBumpScale;
|
||||
Value<float> x50_unknown14;
|
||||
Value<float> x54_unknown15;
|
||||
|
@ -41,6 +41,9 @@ struct CTweakGame : ITweakGame
|
|||
float GetWavecapIntensityNormal() const { return x34_wavecapIntensityNormal; }
|
||||
float GetWavecapIntensityPoison() const { return x38_wavecapIntensityPoison; }
|
||||
float GetWavecapIntensityLava() const { return x3c_wavecapIntensityLava; }
|
||||
float GetRippleIntensityNormal() const { return x40_rippleIntensityNormal; }
|
||||
float GetRippleIntensityPoison() const { return x44_rippleIntentityPoison; }
|
||||
float GetRippleIntensityLava() const { return x48_rippleIntensityLava; }
|
||||
float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; }
|
||||
float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
|
||||
float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }
|
||||
|
|
|
@ -1576,7 +1576,7 @@ void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVec
|
|||
{
|
||||
float bombMag = powerBomb ? 1.f : 0.75f;
|
||||
float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * rippleFactor * 0.25f);
|
||||
water->GetFluidPlane().Ripple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
}
|
||||
if (!powerBomb)
|
||||
x87c_fluidPlaneManager->CreateSplash(damager.GetUniqueId(), *this, *water, hitPos, rippleFactor, true);
|
||||
|
@ -1594,7 +1594,7 @@ void CStateManager::TestBombHittingWater(const CActor& damager, const zeus::CVec
|
|||
{
|
||||
// Not blocked by static geometry
|
||||
float mag = 0.6f * bombMag + 0.4f * bombMag * std::sin(2.f * M_PIF * -delta / bombMag * 0.25f);
|
||||
water->GetFluidPlane().Ripple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
water->GetFluidPlane().AddRipple(mag, damager.GetUniqueId(), hitPos, *water, *this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,10 +74,25 @@ u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
|
|||
return ret;
|
||||
}
|
||||
|
||||
boo::IShaderPipeline* CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneShaderInfo& info)
|
||||
u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
u16 ret = 0;
|
||||
|
||||
if (info.m_hasPatternTex1)
|
||||
ret |= 1 << 0;
|
||||
if (info.m_hasPatternTex2)
|
||||
ret |= 1 << 1;
|
||||
if (info.m_hasColorTex)
|
||||
ret |= 1 << 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
boo::IShaderPipeline* CFluidPlaneShader::Cache::GetOrBuildShader(const T& info)
|
||||
{
|
||||
u16 key = MakeCacheKey(info);
|
||||
auto& slot = m_cache[key];
|
||||
auto& slot = CacheSlot(info, key);
|
||||
if (slot.second != nullptr)
|
||||
return slot.second;
|
||||
|
||||
|
@ -116,6 +131,60 @@ boo::IShaderPipeline* CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPla
|
|||
return slot.second;
|
||||
}
|
||||
|
||||
template boo::IShaderPipeline*
|
||||
CFluidPlaneShader::Cache::GetOrBuildShader<SFluidPlaneShaderInfo>(const SFluidPlaneShaderInfo& info);
|
||||
template boo::IShaderPipeline*
|
||||
CFluidPlaneShader::Cache::GetOrBuildShader<SFluidPlaneDoorShaderInfo>(const SFluidPlaneDoorShaderInfo& info);
|
||||
|
||||
void CFluidPlaneShader::Cache::Clear()
|
||||
{
|
||||
for (auto& p : m_cache)
|
||||
{
|
||||
p.first.doDestroy();
|
||||
p.second = nullptr;
|
||||
}
|
||||
for (auto& p : m_doorCache)
|
||||
{
|
||||
p.first.doDestroy();
|
||||
p.second = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CFluidPlaneShader::PrepareBinding(boo::IShaderPipeline* pipeline, u32 maxVertCount, bool door)
|
||||
{
|
||||
m_gfxTok = CGraphics::CommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1);
|
||||
|
||||
switch (ctx.platform())
|
||||
{
|
||||
case boo::IGraphicsDataFactory::Platform::OpenGL:
|
||||
m_dataBind = BuildBinding(static_cast<boo::GLDataFactory::Context&>(ctx), pipeline, door);
|
||||
break;
|
||||
#if _WIN32
|
||||
case boo::IGraphicsDataFactory::Platform::D3D11:
|
||||
case boo::IGraphicsDataFactory::Platform::D3D12:
|
||||
m_dataBind = BuildBinding(static_cast<boo::ID3DDataFactory::Context&>(ctx), pipeline, door);
|
||||
break;
|
||||
#endif
|
||||
#if BOO_HAS_METAL
|
||||
case boo::IGraphicsDataFactory::Platform::Metal:
|
||||
m_dataBind = BuildBinding(static_cast<boo::MetalDataFactory::Context&>(ctx), pipeline, door);
|
||||
break;
|
||||
#endif
|
||||
#if BOO_HAS_VULKAN
|
||||
case boo::IGraphicsDataFactory::Platform::Vulkan:
|
||||
m_dataBind = BuildBinding(static_cast<boo::VulkanDataFactory::Context&>(ctx), pipeline, door);
|
||||
break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
|
||||
|
@ -143,54 +212,37 @@ CFluidPlaneShader::CFluidPlaneShader(CFluidPlane::EFluidType type,
|
|||
m_lightmap.operator bool(),
|
||||
doubleLightmapBlend, additive);
|
||||
boo::IShaderPipeline* pipeline = _cache.GetOrBuildShader(shaderInfo);
|
||||
|
||||
m_gfxTok = CGraphics::CommitResources(
|
||||
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
m_vbo = ctx.newDynamicBuffer(boo::BufferUse::Vertex, sizeof(Vertex), maxVertCount);
|
||||
m_uniBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, 1024, 1);
|
||||
|
||||
switch (ctx.platform())
|
||||
{
|
||||
case boo::IGraphicsDataFactory::Platform::OpenGL:
|
||||
m_dataBind = BuildBinding(static_cast<boo::GLDataFactory::Context&>(ctx), pipeline);
|
||||
break;
|
||||
#if _WIN32
|
||||
case boo::IGraphicsDataFactory::Platform::D3D11:
|
||||
case boo::IGraphicsDataFactory::Platform::D3D12:
|
||||
m_dataBind = BuildBinding(static_cast<boo::ID3DDataFactory::Context&>(ctx), pipeline);
|
||||
break;
|
||||
#endif
|
||||
#if BOO_HAS_METAL
|
||||
case boo::IGraphicsDataFactory::Platform::Metal:
|
||||
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);
|
||||
break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
PrepareBinding(pipeline, maxVertCount, false);
|
||||
}
|
||||
|
||||
void CFluidPlaneShader::prepareDraw(const zeus::CMatrix4f* texMtxs, const zeus::CMatrix4f& normMtx, float indScale,
|
||||
const std::vector<CLight>& lights, const zeus::CColor* kColors)
|
||||
CFluidPlaneShader::CFluidPlaneShader(const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
|
||||
u32 maxVertCount)
|
||||
: m_patternTex1(patternTex1),
|
||||
m_patternTex2(patternTex2),
|
||||
m_colorTex(colorTex)
|
||||
{
|
||||
SFluidPlaneDoorShaderInfo shaderInfo(m_patternTex1.operator bool(),
|
||||
m_patternTex2.operator bool(),
|
||||
m_colorTex.operator bool());
|
||||
boo::IShaderPipeline* pipeline = _cache.GetOrBuildShader(shaderInfo);
|
||||
PrepareBinding(pipeline, maxVertCount, true);
|
||||
}
|
||||
|
||||
void CFluidPlaneShader::prepareDraw(const RenderSetupInfo& info)
|
||||
{
|
||||
Uniform& uni = *reinterpret_cast<Uniform*>(m_uniBuf->map(sizeof(Uniform)));
|
||||
uni.m_mv = CGraphics::g_GXModelView.toMatrix4f();
|
||||
uni.m_mvNorm = normMtx;
|
||||
uni.m_mvNorm = info.normMtx;
|
||||
uni.m_proj = CGraphics::GetPerspectiveProjectionMatrix(true);
|
||||
for (int i=0 ; i<6 ; ++i)
|
||||
uni.m_texMtxs[i] = texMtxs[i];
|
||||
uni.m_lighting.ActivateLights(lights);
|
||||
uni.m_texMtxs[i] = info.texMtxs[i];
|
||||
uni.m_lighting.ActivateLights(info.lights);
|
||||
for (int i=0 ; i<3 ; ++i)
|
||||
uni.m_lighting.colorRegs[i] = kColors[i];
|
||||
uni.m_lighting.mulColor = kColors[3];
|
||||
uni.m_lighting.fog.m_rangeScale = indScale;
|
||||
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();
|
||||
CGraphics::SetShaderDataBinding(m_dataBind);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,17 @@ struct SFluidPlaneShaderInfo
|
|||
{}
|
||||
};
|
||||
|
||||
struct SFluidPlaneDoorShaderInfo
|
||||
{
|
||||
bool m_hasPatternTex1;
|
||||
bool m_hasPatternTex2;
|
||||
bool m_hasColorTex;
|
||||
|
||||
SFluidPlaneDoorShaderInfo(bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex)
|
||||
: m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex)
|
||||
{}
|
||||
};
|
||||
|
||||
class CFluidPlaneShader
|
||||
{
|
||||
public:
|
||||
|
@ -59,13 +70,30 @@ public:
|
|||
: m_pos(position), m_norm(normal), m_binorm(binormal), m_tangent(tangent), m_color(color) {}
|
||||
};
|
||||
|
||||
struct RenderSetupInfo
|
||||
{
|
||||
zeus::CMatrix4f texMtxs[6];
|
||||
zeus::CMatrix4f normMtx;
|
||||
float indScale = 1.f;
|
||||
zeus::CColor kColors[4];
|
||||
std::vector<CLight> lights;
|
||||
};
|
||||
|
||||
private:
|
||||
class Cache
|
||||
{
|
||||
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*> m_cache[1024] = {};
|
||||
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*> m_doorCache[8] = {};
|
||||
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*>&
|
||||
CacheSlot(const SFluidPlaneShaderInfo& info, int i) { return m_cache[i]; }
|
||||
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*>&
|
||||
CacheSlot(const SFluidPlaneDoorShaderInfo& info, int i) { return m_doorCache[i]; }
|
||||
static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info);
|
||||
static u16 MakeCacheKey(const SFluidPlaneDoorShaderInfo& info);
|
||||
public:
|
||||
boo::IShaderPipeline* GetOrBuildShader(const SFluidPlaneShaderInfo& info);
|
||||
template<class T>
|
||||
boo::IShaderPipeline* GetOrBuildShader(const T& info);
|
||||
void Clear();
|
||||
};
|
||||
static Cache _cache;
|
||||
|
||||
|
@ -91,20 +119,25 @@ private:
|
|||
boo::IShaderDataBinding* m_dataBind;
|
||||
|
||||
static boo::IShaderPipeline* BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::GLDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
|
||||
static boo::IShaderPipeline* BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::GLDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door);
|
||||
#if _WIN32
|
||||
static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::ID3DDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
|
||||
static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::ID3DDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door);
|
||||
#endif
|
||||
#if BOO_HAS_METAL
|
||||
static boo::IShaderPipeline* BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::MetalDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
|
||||
static boo::IShaderPipeline* BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::MetalDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door);
|
||||
#endif
|
||||
#if BOO_HAS_VULKAN
|
||||
static boo::IShaderPipeline* BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::VulkanDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
|
||||
static boo::IShaderPipeline* BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info);
|
||||
boo::IShaderDataBinding* BuildBinding(boo::VulkanDataFactory::Context& ctx, boo::IShaderPipeline* pipeline, bool door);
|
||||
#endif
|
||||
|
||||
void PrepareBinding(boo::IShaderPipeline* pipeline, u32 maxVertCount, bool door);
|
||||
public:
|
||||
CFluidPlaneShader(CFluidPlane::EFluidType type,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
|
||||
|
@ -115,9 +148,14 @@ public:
|
|||
const std::experimental::optional<TLockedToken<CTexture>>& envBumpMap,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& lightmap,
|
||||
bool doubleLightmapBlend, bool additive, u32 maxVertCount);
|
||||
void prepareDraw(const zeus::CMatrix4f* texMtxs, const zeus::CMatrix4f& normMtx, float indScale,
|
||||
const std::vector<CLight>& lights, const zeus::CColor* kColors);
|
||||
CFluidPlaneShader(const std::experimental::optional<TLockedToken<CTexture>>& patternTex1,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& patternTex2,
|
||||
const std::experimental::optional<TLockedToken<CTexture>>& colorTex,
|
||||
u32 maxVertCount);
|
||||
void prepareDraw(const RenderSetupInfo& info);
|
||||
void loadVerts(const std::vector<Vertex>& verts);
|
||||
|
||||
static void Shutdown() { _cache.Clear(); }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -115,6 +115,28 @@ BOO_GLSL_BINDING_HEAD
|
|||
"%s" // Combiner expression here
|
||||
"}\n";
|
||||
|
||||
static const char* FSDoor =
|
||||
"#version 330\n"
|
||||
BOO_GLSL_BINDING_HEAD
|
||||
"\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) in VertToFrag vtf;\n"
|
||||
"layout(location=0) out vec4 colorOut;\n"
|
||||
"%s" // Textures here
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"%s" // Combiner expression here
|
||||
"}\n";
|
||||
|
||||
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[7],
|
||||
const SFluidPlaneShaderInfo& info)
|
||||
{
|
||||
|
@ -442,6 +464,51 @@ static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTe
|
|||
finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
|
||||
}
|
||||
|
||||
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[3],
|
||||
const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
std::string additionalTCGs;
|
||||
std::string textures;
|
||||
std::string combiner;
|
||||
|
||||
if (info.m_hasPatternTex1)
|
||||
{
|
||||
texNames[nextTex] = "patternTex1";
|
||||
textures += hecl::Format("TBINDING%d uniform sampler2D patternTex1;\n", nextTex++);
|
||||
}
|
||||
if (info.m_hasPatternTex2)
|
||||
{
|
||||
texNames[nextTex] = "patternTex2";
|
||||
textures += hecl::Format("TBINDING%d uniform sampler2D patternTex2;\n", nextTex++);
|
||||
}
|
||||
if (info.m_hasColorTex)
|
||||
{
|
||||
texNames[nextTex] = "colorTex";
|
||||
textures += hecl::Format("TBINDING%d uniform sampler2D colorTex;\n", nextTex++);
|
||||
}
|
||||
|
||||
// Tex0 * kColor0 * Tex1 + Tex2
|
||||
if (info.m_hasPatternTex1 && info.m_hasPatternTex2)
|
||||
{
|
||||
combiner += " colorOut = texture(patternTex1, vtf.uvs[0]) * kColor0 *\n"
|
||||
" texture(patternTex2, vtf.uvs[1]);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
combiner += " colorOut = vec4(0.0);\n";
|
||||
}
|
||||
|
||||
if (info.m_hasColorTex)
|
||||
{
|
||||
combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n";
|
||||
}
|
||||
|
||||
combiner += " colorOut.a = kColor0.a;\n";
|
||||
|
||||
finalVS = hecl::Format(VS, additionalTCGs.c_str());
|
||||
finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str());
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
|
||||
{
|
||||
|
@ -457,6 +524,20 @@ CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPla
|
|||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
int nextTex = 0;
|
||||
const char* texNames[3] = {};
|
||||
std::string finalVS, finalFS;
|
||||
_BuildShader(finalVS, finalFS, nextTex, texNames, info);
|
||||
const char* uniNames[] = {"FluidPlaneUniform"};
|
||||
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), size_t(nextTex), texNames, 1, uniNames,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
|
||||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
#if BOO_HAS_VULKAN
|
||||
static boo::IVertexFormat* s_vtxFmt = nullptr;
|
||||
|
||||
|
@ -486,10 +567,36 @@ CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFlui
|
|||
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
|
||||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
if (s_vtxFmt == nullptr)
|
||||
{
|
||||
boo::VertexElementDescriptor elements[] =
|
||||
{
|
||||
{nullptr, nullptr, boo::VertexSemantic::Position4},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Color}
|
||||
};
|
||||
s_vtxFmt = ctx.newVertexFormat(5, elements);
|
||||
}
|
||||
|
||||
int nextTex = 0;
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx,
|
||||
boo::IShaderPipeline* pipeline)
|
||||
boo::IShaderPipeline* pipeline, bool door)
|
||||
{
|
||||
boo::VertexElementDescriptor elements[] =
|
||||
{
|
||||
|
@ -521,13 +628,13 @@ boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Con
|
|||
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
|
||||
if (m_lightmap)
|
||||
texs[texCount++] = (*m_lightmap)->GetBooTexture();
|
||||
return ctx.newShaderDataBinding(pipeline, vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
|
||||
ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
return ctx.newShaderDataBinding(pipeline, vtxFmt, m_vbo, nullptr, nullptr, door ? 1 : 3,
|
||||
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
}
|
||||
|
||||
#if BOO_HAS_VULKAN
|
||||
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory::Context& ctx,
|
||||
boo::IShaderPipeline* pipeline)
|
||||
boo::IShaderPipeline* pipeline, bool door)
|
||||
{
|
||||
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||
|
@ -550,8 +657,8 @@ boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory:
|
|||
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
|
||||
if (m_lightmap)
|
||||
texs[texCount++] = (*m_lightmap)->GetBooTexture();
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
|
||||
ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, door ? 1 : 3,
|
||||
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -119,6 +119,27 @@ static const char* FS =
|
|||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSDoor =
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" float4 pos : SV_Position;\n"
|
||||
" float4 mvPos : POSITION;\n"
|
||||
" float4 mvNorm : NORMAL;\n"
|
||||
" float4 mvBinorm : BINORMAL;\n"
|
||||
" float4 mvTangent : TANGENT;\n"
|
||||
" float4 color : COLOR;\n"
|
||||
" float2 uvs[7] : UV;\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"SamplerState samp : register(s0);\n"
|
||||
"%s" // Textures here
|
||||
"float4 main(in VertToFrag vtf)\n"
|
||||
"{\n"
|
||||
" float4 colorOut;\n"
|
||||
"%s" // Combiner expression here
|
||||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
|
||||
{
|
||||
|
@ -198,12 +219,12 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
// Output reg 2
|
||||
// KColor 3
|
||||
// Tex * K2 + Lighting
|
||||
combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
|
||||
combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// mix(Tex * K2, Tex, K3) + Lighting
|
||||
combiner += " lighting += lightMapTexel * lu.kColor2;\n";
|
||||
combiner += " lighting += lightMapTexel * kColor2;\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,7 +245,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
if (info.m_hasPatternTex2)
|
||||
{
|
||||
if (info.m_hasPatternTex1)
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n"
|
||||
" patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
else
|
||||
combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
|
@ -239,7 +260,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
{
|
||||
// Make previous stage indirect, mtx0
|
||||
combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
|
||||
" float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
|
||||
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
|
||||
combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||
}
|
||||
else if (info.m_hasEnvMap)
|
||||
|
@ -253,8 +274,8 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
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(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
|
||||
combiner += hecl::Format(" colorOut = mix(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), lu.kColor1);\n",
|
||||
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
|
||||
combiner += hecl::Format(" colorOut = mix(colorOut, envMap.Sample(samp, indUvs + vtf.uvs[%d]), kColor1);\n",
|
||||
envMapUv);
|
||||
}
|
||||
else if (info.m_hasColorTex)
|
||||
|
@ -279,12 +300,12 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
// Output reg 2
|
||||
// KColor 3
|
||||
// Tex * K2 + Lighting
|
||||
combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
|
||||
combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// mix(Tex * K2, Tex, K3) + Lighting
|
||||
combiner += " lighting += lightMapTexel * lu.kColor2;\n";
|
||||
combiner += " lighting += lightMapTexel * kColor2;\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -305,7 +326,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
if (info.m_hasPatternTex2)
|
||||
{
|
||||
if (info.m_hasPatternTex1)
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + lighting) *\n"
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + lighting) *\n"
|
||||
" patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
else
|
||||
combiner += " colorOut = lighting * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
|
@ -321,7 +342,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
{
|
||||
// Make previous stage indirect, mtx0
|
||||
combiner += hecl::Format(" float2 indUvs = (envBumpMap.Sample(samp, vtf.uvs[%d]).ra - float2(0.5, 0.5)) *\n"
|
||||
" float2(lu.fog.indScale, -lu.fog.indScale);", envBumpMapUv);
|
||||
" float2(fog.indScale, -fog.indScale);", envBumpMapUv);
|
||||
combiner += " colorOut += colorTex.Sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||
}
|
||||
else
|
||||
|
@ -350,7 +371,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
if (info.m_hasPatternTex2)
|
||||
{
|
||||
if (info.m_hasPatternTex1)
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
|
||||
" patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
else
|
||||
combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
|
@ -408,7 +429,7 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
if (info.m_hasPatternTex2)
|
||||
{
|
||||
if (info.m_hasPatternTex1)
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * lu.kColor0 + vtf.color) *\n"
|
||||
combiner += " colorOut = (patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
|
||||
" patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
else
|
||||
combiner += " colorOut = vtf.color * patternTex2.Sample(samp, vtf.uvs[1]) + vtf.color;\n";
|
||||
|
@ -445,8 +466,63 @@ CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidP
|
|||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
if (s_vtxFmt == nullptr)
|
||||
{
|
||||
boo::VertexElementDescriptor elements[] =
|
||||
{
|
||||
{nullptr, nullptr, boo::VertexSemantic::Position4},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Color}
|
||||
};
|
||||
s_vtxFmt = ctx.newVertexFormat(5, elements);
|
||||
}
|
||||
|
||||
std::string additionalTCGs;
|
||||
std::string textures;
|
||||
std::string combiner;
|
||||
int nextTex = 0;
|
||||
|
||||
if (info.m_hasPatternTex1)
|
||||
textures += hecl::Format("Texture2D patternTex1 : register(t%d)\n", nextTex++);
|
||||
if (info.m_hasPatternTex2)
|
||||
textures += hecl::Format("Texture2D patternTex2 : register(t%d)\n", nextTex++);
|
||||
if (info.m_hasColorTex)
|
||||
textures += hecl::Format("Texture2D colorTex : register(t%d)\n", nextTex++);
|
||||
|
||||
// Tex0 * kColor0 * Tex1 + Tex2
|
||||
if (info.m_hasPatternTex1 && info.m_hasPatternTex2)
|
||||
{
|
||||
combiner += " colorOut = patternTex1.Sample(samp, vtf.uvs[0]) * kColor0 *\n"
|
||||
" patternTex2.Sample(samp, vtf.uvs[1]);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
combiner += " colorOut = float4(0.0);\n";
|
||||
}
|
||||
|
||||
if (info.m_hasColorTex)
|
||||
{
|
||||
combiner += " colorOut += colorTex.Sample(samp, vtf.uvs[2]);\n";
|
||||
}
|
||||
|
||||
combiner += " colorOut.a = kColor0.a;\n";
|
||||
|
||||
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str());
|
||||
std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str());
|
||||
|
||||
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), nullptr, nullptr, nullptr, s_vtxFmt,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
|
||||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::ID3DDataFactory::Context& ctx,
|
||||
boo::IShaderPipeline* pipeline)
|
||||
boo::IShaderPipeline* pipeline, bool door)
|
||||
{
|
||||
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||
|
@ -469,8 +545,8 @@ boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::ID3DDataFactory::C
|
|||
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
|
||||
if (m_lightmap)
|
||||
texs[texCount++] = (*m_lightmap)->GetBooTexture();
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
|
||||
ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, door ? 1 : 3,
|
||||
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -125,6 +125,29 @@ static const char* FS =
|
|||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
static const char* FSDoor =
|
||||
"#include <metal_stdlib>\n"
|
||||
"using namespace metal;\n"
|
||||
"constexpr sampler samp(address::repeat, filter::linear);\n"
|
||||
"\n"
|
||||
"struct VertToFrag\n"
|
||||
"{\n"
|
||||
" float4 pos : [[ position ]];\n"
|
||||
" float4 mvPos;\n"
|
||||
" float4 mvNorm;\n"
|
||||
" float4 mvBinorm;\n"
|
||||
" float4 mvTangent;\n"
|
||||
" float4 color;\n"
|
||||
" float2 uvs[7];\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"fragment float4 fmain(VertToFrag vtf [[ stage_in ]]%s)\n" // Textures here
|
||||
"{\n"
|
||||
" float4 colorOut;\n"
|
||||
"%s" // Combiner expression here
|
||||
" return colorOut;\n"
|
||||
"}\n";
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
|
||||
{
|
||||
|
@ -451,8 +474,63 @@ CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluid
|
|||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderPipeline*
|
||||
CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneDoorShaderInfo& info)
|
||||
{
|
||||
if (s_vtxFmt == nullptr)
|
||||
{
|
||||
boo::VertexElementDescriptor elements[] =
|
||||
{
|
||||
{nullptr, nullptr, boo::VertexSemantic::Position4},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 0},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 1},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Normal4, 2},
|
||||
{nullptr, nullptr, boo::VertexSemantic::Color}
|
||||
};
|
||||
s_vtxFmt = ctx.newVertexFormat(5, elements);
|
||||
}
|
||||
|
||||
std::string additionalTCGs;
|
||||
std::string textures;
|
||||
std::string combiner;
|
||||
int nextTex = 0;
|
||||
|
||||
if (info.m_hasPatternTex1)
|
||||
textures += hecl::Format(",\ntexture2d<float> patternTex1 [[ texture(%d) ]]", nextTex++);
|
||||
if (info.m_hasPatternTex2)
|
||||
textures += hecl::Format(",\ntexture2d<float> patternTex2 [[ texture(%d) ]]", nextTex++);
|
||||
if (info.m_hasColorTex)
|
||||
textures += hecl::Format(",\ntexture2d<float> colorTex [[ texture(%d) ]]", nextTex++);
|
||||
|
||||
// Tex0 * kColor0 * Tex1 + Tex2
|
||||
if (info.m_hasPatternTex1 && info.m_hasPatternTex2)
|
||||
{
|
||||
combiner += " colorOut = patternTex1.sample(samp, vtf.uvs[0]) * lu.kColor0 *\n"
|
||||
" patternTex2.sample(samp, vtf.uvs[1]);\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
combiner += " colorOut = float4(0.0);\n";
|
||||
}
|
||||
|
||||
if (info.m_hasColorTex)
|
||||
{
|
||||
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n";
|
||||
}
|
||||
|
||||
combiner += " colorOut.a = kColor0.a;\n";
|
||||
|
||||
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str());
|
||||
std::string finalFS = hecl::Format(FSDoor, textures.c_str(), combiner.c_str());
|
||||
|
||||
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt, CGraphics::g_ViewportSamples,
|
||||
boo::BlendFactor::SrcAlpha, boo::BlendFactor::InvSrcAlpha,
|
||||
boo::Primitive::TriStrips, boo::ZTest::LEqual, false, true, false,
|
||||
boo::CullMode::None);
|
||||
}
|
||||
|
||||
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx,
|
||||
boo::IShaderPipeline* pipeline)
|
||||
boo::IShaderPipeline* pipeline, bool door)
|
||||
{
|
||||
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||
|
@ -475,8 +553,8 @@ boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::
|
|||
texs[texCount++] = (*m_envBumpMap)->GetBooTexture();
|
||||
if (m_lightmap)
|
||||
texs[texCount++] = (*m_lightmap)->GetBooTexture();
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, 1, ubufs, ubufStages, ubufOffs,
|
||||
ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
return ctx.newShaderDataBinding(pipeline, s_vtxFmt, m_vbo, nullptr, nullptr, door ? 1 : 3,
|
||||
ubufs, ubufStages, ubufOffs, ubufSizes, texCount, texs, nullptr, nullptr);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "Graphics/Shaders/CPhazonSuitFilter.hpp"
|
||||
#include "Graphics/Shaders/CScanLinesFilter.hpp"
|
||||
#include "Graphics/Shaders/CRandomStaticFilter.hpp"
|
||||
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
|
||||
#include "Character/CCharLayoutInfo.hpp"
|
||||
#include "Audio/CStreamAudioManager.hpp"
|
||||
#include "CGBASupport.hpp"
|
||||
|
@ -369,6 +370,7 @@ void CMain::Shutdown()
|
|||
TMultiBlendShader<CTextSupportShader>::Shutdown();
|
||||
TMultiBlendShader<CScanLinesFilter>::Shutdown();
|
||||
TMultiBlendShader<CRandomStaticFilter>::Shutdown();
|
||||
CFluidPlaneShader::Shutdown();
|
||||
}
|
||||
|
||||
boo::IWindow* CMain::GetMainWindow() const
|
||||
|
|
|
@ -79,9 +79,9 @@ protected:
|
|||
public:
|
||||
enum class EFluidState
|
||||
{
|
||||
Zero,
|
||||
One,
|
||||
Two
|
||||
EnteredFluid,
|
||||
InFluid,
|
||||
LeftFluid
|
||||
};
|
||||
|
||||
enum class EScanState
|
||||
|
@ -180,6 +180,7 @@ public:
|
|||
float GetAverageAnimVelocity(int anim) const;
|
||||
u8 GetTargetableVisorFlags() const { return xe6_31_targetableVisorFlags; }
|
||||
bool GetIsTargetable() const { return xe7_31_targetable; }
|
||||
void SetDrawFlags(const CModelFlags& flags) { xb4_drawFlags = flags; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include <Runtime/GameGlobalObjects.hpp>
|
||||
#include "CFluidPlane.hpp"
|
||||
#include "CSimplePool.hpp"
|
||||
#include "CRipple.hpp"
|
||||
#include "CScriptWater.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -18,14 +21,67 @@ CFluidPlane::CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId te
|
|||
x30_texColor.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), texColor}));
|
||||
}
|
||||
|
||||
void CFluidPlane::Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||
float CFluidPlane::ProjectRippleVelocity(float baseI, float velDot) const
|
||||
{
|
||||
float tmp = 0.5f * baseI * velDot * velDot;
|
||||
if (tmp != 0.f)
|
||||
tmp = std::sqrt(tmp);
|
||||
if (tmp >= 160.f)
|
||||
return 1.f;
|
||||
return tmp / 160.f;
|
||||
}
|
||||
|
||||
float CFluidPlane::CalculateRippleIntensity(float baseI) const
|
||||
{
|
||||
float mul;
|
||||
switch (x44_fluidType)
|
||||
{
|
||||
case EFluidType::NormalWater:
|
||||
mul = g_tweakGame->GetRippleIntensityNormal();
|
||||
break;
|
||||
case EFluidType::PoisonWater:
|
||||
mul = g_tweakGame->GetRippleIntensityPoison();
|
||||
break;
|
||||
case EFluidType::Lava:
|
||||
mul = g_tweakGame->GetRippleIntensityLava();
|
||||
break;
|
||||
case EFluidType::Three:
|
||||
case EFluidType::Four:
|
||||
mul = 0.8f;
|
||||
break;
|
||||
case EFluidType::Five:
|
||||
mul = 1.f;
|
||||
break;
|
||||
}
|
||||
|
||||
return zeus::clamp(0.f, baseI * mul * (1.f - x48_rippleIntensity + 0.5f), 1.f);
|
||||
}
|
||||
|
||||
void CFluidPlane::AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
CScriptWater& water, CStateManager& mgr)
|
||||
{
|
||||
if (!water.CanRippleAtPoint(center))
|
||||
return;
|
||||
|
||||
mag = CalculateRippleIntensity(mag);
|
||||
mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, mag));
|
||||
}
|
||||
|
||||
void CFluidPlane::Update()
|
||||
void CFluidPlane::AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr,
|
||||
const zeus::CVector3f& upVec)
|
||||
{
|
||||
if (!water.CanRippleAtPoint(center))
|
||||
return;
|
||||
|
||||
intensity = CalculateRippleIntensity(ProjectRippleVelocity(intensity, upVec.dot(velocity)));
|
||||
mgr.GetFluidPlaneManager()->RippleManager().AddRipple(CRipple(rippler, center, intensity));
|
||||
}
|
||||
|
||||
void CFluidPlane::AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr)
|
||||
{
|
||||
if (!water.CanRippleAtPoint(ripple.GetCenter()))
|
||||
return;
|
||||
mgr.GetFluidPlaneManager()->RippleManager().AddRipple(ripple);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ class CFluidUVMotion;
|
|||
class CRippleManager;
|
||||
class CScriptWater;
|
||||
class CStateManager;
|
||||
class CRipple;
|
||||
class CFluidPlane
|
||||
{
|
||||
public:
|
||||
|
@ -38,17 +39,28 @@ protected:
|
|||
EFluidType x44_fluidType;
|
||||
float x48_rippleIntensity;
|
||||
CFluidUVMotion x4c_uvMotion;
|
||||
float ProjectRippleVelocity(float baseI, float velDot) const;
|
||||
float CalculateRippleIntensity(float baseI) const;
|
||||
public:
|
||||
CFluidPlane(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, float alpha,
|
||||
EFluidType fluidType, float rippleIntensity, const CFluidUVMotion& motion);
|
||||
|
||||
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||
// Called by CPlayer, CMorphBall, CWeapon, CPuddleSpore, CMagdolite
|
||||
virtual void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
CScriptWater& water, CStateManager& mgr);
|
||||
virtual void Update();
|
||||
|
||||
// Called by CAi
|
||||
virtual void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr,
|
||||
const zeus::CVector3f& upVec);
|
||||
|
||||
virtual void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr);
|
||||
|
||||
virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
|
||||
|
||||
float GetAlpha() const { return x40_alpha; }
|
||||
EFluidType GetFluidType() const { return x44_fluidType; }
|
||||
const CFluidUVMotion& GetUVMotion() const { return x4c_uvMotion; }
|
||||
|
|
|
@ -43,9 +43,9 @@ CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freq
|
|||
}
|
||||
}
|
||||
|
||||
CFluidPlaneCPU::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,
|
||||
CFluidPlaneCPU::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,
|
||||
|
@ -114,11 +114,11 @@ static const float* InitializeSineWave()
|
|||
|
||||
#define kEnableWaterBumpMaps true
|
||||
|
||||
CFluidPlaneCPU::RenderSetupInfo
|
||||
CFluidPlaneShader::RenderSetupInfo
|
||||
CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb, const CScriptWater* water) const
|
||||
{
|
||||
RenderSetupInfo out;
|
||||
CFluidPlaneShader::RenderSetupInfo out;
|
||||
|
||||
float uvT = mgr.GetFluidPlaneManager()->GetUVT();
|
||||
bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps;
|
||||
|
@ -283,110 +283,6 @@ CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float alpha, const zeus::C
|
|||
return out;
|
||||
}
|
||||
|
||||
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};
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
int CFluidPlaneCPURender::numTilesInHField;
|
||||
int CFluidPlaneCPURender::numSubdivisionsInTile;
|
||||
int CFluidPlaneCPURender::numSubdivisionsInHField;
|
||||
|
@ -963,7 +859,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
|
|||
func(curTileX, curTileY + info.x18_rippleResolution, heights[curYDiv+1][i+v]);
|
||||
curTileX += info.x18_rippleResolution;
|
||||
}
|
||||
CGraphics::DrawArray(start, 4);
|
||||
CGraphics::DrawArray(start, vOut.size() - start);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1040,7 +936,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
|
|||
default:
|
||||
break;
|
||||
}
|
||||
CGraphics::DrawArray(start, 4);
|
||||
CGraphics::DrawArray(start, vOut.size() - start);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1145,7 +1041,7 @@ static void RenderStripWithRipples(float curY, const CFluidPlaneCPURender::SHFie
|
|||
}
|
||||
}
|
||||
|
||||
static void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
|
||||
void RenderPatch(const CFluidPlaneCPURender::SPatchInfo& info,
|
||||
const CFluidPlaneCPURender::SHFieldSample (&heights)[45][45],
|
||||
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut)
|
||||
|
@ -1367,7 +1263,7 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
|
|||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
|
||||
{
|
||||
TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(waterId);
|
||||
RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
|
||||
CFluidPlaneShader::RenderSetupInfo setupInfo = RenderSetup(mgr, alpha, xf, areaXf, aabb, water.GetPtr());
|
||||
|
||||
CFluidPlaneCPURender::NormalMode normalMode;
|
||||
if (xb0_bumpMap && kEnableWaterBumpMaps)
|
||||
|
@ -1435,8 +1331,7 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
|
|||
u32 patchDimY = (water && water->GetPatchDimensionY()) ? water->GetPatchDimensionY() : 128;
|
||||
|
||||
m_verts.clear();
|
||||
m_shader->prepareDraw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale,
|
||||
setupInfo.lights, setupInfo.kColors);
|
||||
m_shader->prepareDraw(setupInfo);
|
||||
|
||||
u32 tileY = 0;
|
||||
float curY = aabb.min.y;
|
||||
|
@ -1496,9 +1391,4 @@ void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::C
|
|||
m_shader->loadVerts(m_verts);
|
||||
}
|
||||
|
||||
void CFluidPlaneCPU::RenderCleanup() const
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,15 +61,6 @@ class CFluidPlaneCPU : public CFluidPlane
|
|||
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
|
||||
mutable bool m_cachedDoubleLightmapBlend;
|
||||
mutable bool m_cachedAdditive;
|
||||
|
||||
struct RenderSetupInfo
|
||||
{
|
||||
zeus::CMatrix4f texMtxs[6];
|
||||
zeus::CMatrix4f normMtx;
|
||||
float indScale = 1.f;
|
||||
zeus::CColor kColors[4];
|
||||
std::vector<CLight> lights;
|
||||
};
|
||||
public:
|
||||
CFluidPlaneCPU(CAssetId texPattern1, CAssetId texPattern2, CAssetId texColor, CAssetId bumpMap, CAssetId envMap, CAssetId envBumpMap,
|
||||
CAssetId lightMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions,
|
||||
|
@ -81,14 +72,13 @@ public:
|
|||
void CreateRipple(const CRipple& ripple, CStateManager& mgr);
|
||||
void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
|
||||
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const;
|
||||
RenderSetupInfo RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf,
|
||||
CFluidPlaneShader::RenderSetupInfo RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb,
|
||||
const CScriptWater* water) const;
|
||||
void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
|
||||
void RenderCleanup() const;
|
||||
float GetReflectionBlend() const { return x114_reflectionBlend; }
|
||||
float GetSpecularMax() const { return x110_specularMax; }
|
||||
float GetSpecularMin() const { return x10c_specularMin; }
|
||||
|
@ -111,6 +101,116 @@ public:
|
|||
float GetOOTurbulenceSpeed() const { return x120_turbulence.GetOOSpeed(); }
|
||||
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)[45][45],
|
||||
const u8 (&flags)[9][9], bool noRipples, bool flagIs1,
|
||||
std::vector<CFluidPlaneShader::Vertex>& vOut);
|
||||
|
||||
}
|
||||
|
||||
#endif // __URDE_CFLUIDPLANECPU_HPP__
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
#include "CFluidPlaneDoor.hpp"
|
||||
#include "CFluidPlaneCPU.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
CFluidPlaneDoor::CFluidPlaneDoor(CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, float tileSize,
|
||||
u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||
const CFluidUVMotion& uvMotion)
|
||||
: CFluidPlane(patternTex1, patternTex2, colorTex, alpha, fluidType, 0.5f, uvMotion), xa0_tileSize(tileSize),
|
||||
xa4_tileSubdivisions(tileSubdivisions & ~0x1), xa8_rippleResolution(xa0_tileSize / float(xa4_tileSubdivisions))
|
||||
{}
|
||||
|
||||
CFluidPlaneShader::RenderSetupInfo
|
||||
CFluidPlaneDoor::RenderSetup(const CStateManager& mgr, float alpha, const zeus::CTransform& xf,
|
||||
const zeus::CAABox& aabb, bool noNormals) const
|
||||
{
|
||||
CFluidPlaneShader::RenderSetupInfo out;
|
||||
|
||||
float uvT = mgr.GetFluidPlaneManager()->GetUVT();
|
||||
CGraphics::SetModelMatrix(xf);
|
||||
|
||||
float fluidUVs[3][2];
|
||||
x4c_uvMotion.CalculateFluidTextureOffset(uvT, fluidUVs);
|
||||
|
||||
out.texMtxs[0][0][0] = out.texMtxs[0][1][1] = x4c_uvMotion.GetFluidLayers()[1].GetUVScale();
|
||||
out.texMtxs[0][3][0] = fluidUVs[1][0];
|
||||
out.texMtxs[0][3][1] = fluidUVs[1][1];
|
||||
|
||||
out.texMtxs[1][0][0] = out.texMtxs[1][1][1] = x4c_uvMotion.GetFluidLayers()[2].GetUVScale();
|
||||
out.texMtxs[1][3][0] = fluidUVs[2][0];
|
||||
out.texMtxs[1][3][1] = fluidUVs[2][1];
|
||||
|
||||
out.texMtxs[2][0][0] = out.texMtxs[2][1][1] = x4c_uvMotion.GetFluidLayers()[0].GetUVScale();
|
||||
out.texMtxs[2][3][0] = fluidUVs[0][0];
|
||||
out.texMtxs[2][3][1] = fluidUVs[0][1];
|
||||
|
||||
out.kColors[0] = zeus::CColor(1.f, alpha);
|
||||
|
||||
if (!m_shader)
|
||||
{
|
||||
auto gridDimX = u32((xa0_tileSize + aabb.max.x - aabb.min.x - 0.01f) / xa0_tileSize);
|
||||
auto gridDimY = u32((xa0_tileSize + aabb.max.y - aabb.min.y - 0.01f) / xa0_tileSize);
|
||||
u32 gridCellCount = (gridDimX + 1) * (gridDimY + 1);
|
||||
u32 maxVerts = gridCellCount * ((std::max(2, xa4_tileSubdivisions) * 4 + 2) * 4);
|
||||
m_shader.emplace(x10_texPattern1, x20_texPattern2, x30_texColor, maxVerts);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void CFluidPlaneDoor::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
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;
|
||||
zeus::CVector2f centerPlane(aabb.center().x, aabb.center().y);
|
||||
float patchSize = xa8_rippleResolution * CFluidPlaneCPURender::numSubdivisionsInHField;
|
||||
float ooSubdivSize = 1.f / xa8_rippleResolution;
|
||||
|
||||
m_verts.clear();
|
||||
m_shader->prepareDraw(setupInfo);
|
||||
|
||||
for (float curX = aabb.min.x ; curX < aabb.max.x ; curX += patchSize)
|
||||
{
|
||||
float remSubdivsX = (aabb.max.x - curX) * ooSubdivSize;
|
||||
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));
|
||||
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),
|
||||
aabb2.max, xf.origin, xa8_rippleResolution,
|
||||
xa0_tileSize, 0.f,
|
||||
CFluidPlaneCPURender::numSubdivisionsInHField,
|
||||
CFluidPlaneCPURender::NormalMode::None,
|
||||
0, 0, 0, 0, 0, 0, 0, nullptr);
|
||||
|
||||
CFluidPlaneCPURender::SHFieldSample heights[45][45];
|
||||
u8 flags[9][9] = {};
|
||||
|
||||
RenderPatch(patchInfo, heights, flags, true, true, m_verts);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_shader->loadVerts(m_verts);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,12 +1,37 @@
|
|||
#ifndef __URDE_CFLUIDPLANEDOOR_HPP__
|
||||
#define __URDE_CFLUIDPLANEDOOR_HPP__
|
||||
|
||||
#include "CFluidPlane.hpp
|
||||
#include "CFluidPlane.hpp"
|
||||
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class CFluidPlaneDoor : public CFluidPlane
|
||||
{
|
||||
float xa0_tileSize;
|
||||
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;
|
||||
public:
|
||||
CFluidPlaneDoor(CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, float tileSize, u32 tileSubdivisions,
|
||||
EFluidType fluidType, float alpha, const CFluidUVMotion& uvMotion);
|
||||
void AddRipple(float mag, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
CScriptWater& water, CStateManager& mgr) {}
|
||||
void AddRipple(float intensity, TUniqueId rippler, const zeus::CVector3f& center,
|
||||
const zeus::CVector3f& velocity, const CScriptWater& water, CStateManager& mgr,
|
||||
const zeus::CVector3f& upVec) {}
|
||||
void AddRipple(const CRipple& ripple, const CScriptWater& water, CStateManager& mgr) {}
|
||||
|
||||
void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||
const zeus::CTransform& areaXf, bool noNormals, const zeus::CFrustum& frustum,
|
||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
const zeus::CVector3f& pos, float factor, bool);
|
||||
rstl::reserved_vector<CSplashRecord, 32>& SplashRecords() { return x18_splashes; }
|
||||
const CRippleManager& GetRippleManager() const { return x0_rippleManager; }
|
||||
CRippleManager& RippleManager() { return x0_rippleManager; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -214,7 +214,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
|||
if (x2f8_morphTransState == EPlayerMorphBallState::Morphed)
|
||||
{
|
||||
x768_morphball->FluidFXThink(state, water, mgr);
|
||||
if (state == EFluidState::One)
|
||||
if (state == EFluidState::InFluid)
|
||||
x9c5_30_ = true;
|
||||
}
|
||||
else if (x2f8_morphTransState != EPlayerMorphBallState::Unmorphed)
|
||||
|
@ -224,7 +224,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
|||
zeus::CVector3f position(x34_transform.origin);
|
||||
position.z = water.GetTriggerBoundsWR().max.z;
|
||||
mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.1f,
|
||||
state == EFluidState::Zero);
|
||||
state == EFluidState::EnteredFluid);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -236,7 +236,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
|||
posOffset = posOffset.normalized() * zeus::CVector3f(1.2f, 1.2f, 0.f);
|
||||
switch (state)
|
||||
{
|
||||
case EFluidState::Zero:
|
||||
case EFluidState::EnteredFluid:
|
||||
{
|
||||
bool doSplash = true;
|
||||
if (x4fc_ > 12.5f)
|
||||
|
@ -260,18 +260,18 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
|||
}
|
||||
break;
|
||||
}
|
||||
case EFluidState::One:
|
||||
case EFluidState::InFluid:
|
||||
{
|
||||
if (x138_velocity.magnitude() > 1.f &&
|
||||
mgr.GetFluidPlaneManager()->GetLastRippleDeltaTime(x8_uid) >= 0.2f)
|
||||
{
|
||||
zeus::CVector3f position(x34_transform.origin);
|
||||
position.z = water.GetTriggerBoundsWR().max.z;
|
||||
water.GetFluidPlane().Ripple(0.5f, x8_uid, position, water, mgr);
|
||||
water.GetFluidPlane().AddRipple(0.5f, x8_uid, position, water, mgr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EFluidState::Two:
|
||||
case EFluidState::LeftFluid:
|
||||
{
|
||||
zeus::CVector3f position = x34_transform.origin + posOffset;
|
||||
position.z = water.GetTriggerBoundsWR().max.z;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#include "CScriptDamageableTrigger.hpp"
|
||||
#include "CActorParameters.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "CWorld.hpp"
|
||||
#include "CScriptActor.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -22,14 +25,52 @@ CMaterialList MakeDamageableTriggerMaterial(CScriptDamageableTrigger::ECanOrbit
|
|||
|
||||
|
||||
CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, const std::string& name, const CEntityInfo& info,
|
||||
const zeus::CVector3f& position, const zeus::CVector3f& extent, const CHealthInfo&,
|
||||
const CDamageVulnerability&, u32, CAssetId, CAssetId, CAssetId,
|
||||
CScriptDamageableTrigger::ECanOrbit canOrbit, bool active, const CVisorParameters& vParams)
|
||||
const zeus::CVector3f& position, const zeus::CVector3f& extent,
|
||||
const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
|
||||
u32 faceFlag, CAssetId patternTex1, CAssetId patternTex2,
|
||||
CAssetId colorTex, ECanOrbit canOrbit, bool active,
|
||||
const CVisorParameters& vParams)
|
||||
: CActor(uid, active, name, info, zeus::CTransform::Translate(position), CModelData::CModelDataNull(),
|
||||
MakeDamageableTriggerMaterial(canOrbit), MakeDamageableTriggerActorParms(CActorParameters::None(), vParams),
|
||||
kInvalidUniqueId),
|
||||
x14c_bounds(-extent * 0.5f, extent * 0.5f)
|
||||
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))
|
||||
{
|
||||
x300_28_canOrbit = canOrbit == ECanOrbit::Orbit;
|
||||
if (x1dc_faceFlag & 0x1)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.max.y, 0.f);
|
||||
x1e4_faceDir = zeus::CTransform::RotateX(-M_PIF / 2.f);
|
||||
}
|
||||
else if (x1dc_faceFlag & 0x2)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.min.y, 0.f);
|
||||
x1e4_faceDir = zeus::CTransform::RotateX(M_PIF / 2.f);
|
||||
}
|
||||
else if (x1dc_faceFlag & 0x4)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(x14c_bounds.min.x, 0.f, 0.f);
|
||||
x1e4_faceDir = zeus::CTransform::RotateY(-M_PIF / 2.f);
|
||||
}
|
||||
else if (x1dc_faceFlag & 0x8)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(x14c_bounds.max.x, 0.f, 0.f);
|
||||
x1e4_faceDir = zeus::CTransform::RotateY(M_PIF / 2.f);
|
||||
}
|
||||
else if (x1dc_faceFlag & 0x10)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.max.z);
|
||||
x1e4_faceDir = zeus::CTransform::Identity();
|
||||
}
|
||||
else if (x1dc_faceFlag & 0x20)
|
||||
{
|
||||
x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.min.z);
|
||||
x1e4_faceDir = zeus::CTransform::RotateY(M_PIF);
|
||||
}
|
||||
|
||||
x214_faceDirInv = x1e4_faceDir.inverse();
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::Accept(IVisitor& visitor)
|
||||
|
@ -37,4 +78,160 @@ void CScriptDamageableTrigger::Accept(IVisitor& visitor)
|
|||
visitor.Visit(this);
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case EScriptObjectMessage::Deactivate:
|
||||
if (x30_24_active && x300_25_alphaOut)
|
||||
return;
|
||||
case EScriptObjectMessage::Activate:
|
||||
if (!x30_24_active || x300_25_alphaOut)
|
||||
{
|
||||
x250_alphaTimer = 0.f;
|
||||
x16c_hInfo = x164_origHInfo;
|
||||
x300_25_alphaOut = false;
|
||||
if (x300_28_canOrbit)
|
||||
AddMaterial(EMaterialTypes::Orbit, mgr);
|
||||
SetLinkedObjectAlpha(0.f, mgr);
|
||||
x1e0_alpha = 0.f;
|
||||
}
|
||||
break;
|
||||
case EScriptObjectMessage::Damage:
|
||||
if (x300_27_invulnerable)
|
||||
x16c_hInfo = x164_origHInfo;
|
||||
break;
|
||||
case EScriptObjectMessage::Increment:
|
||||
x300_27_invulnerable = true;
|
||||
break;
|
||||
case EScriptObjectMessage::Decrement:
|
||||
x300_27_invulnerable = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CActor::AcceptScriptMsg(msg, sender, mgr);
|
||||
}
|
||||
|
||||
EWeaponCollisionResponseTypes
|
||||
CScriptDamageableTrigger::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
const CWeaponMode& weapMode, int) const
|
||||
{
|
||||
return x174_dVuln.WeaponHurts(weapMode, false) ? EWeaponCollisionResponseTypes::Unknown13 :
|
||||
EWeaponCollisionResponseTypes::Unknown15;
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::Render(const CStateManager& mgr) const
|
||||
{
|
||||
if (x30_24_active && x1dc_faceFlag != 0 && std::fabs(x1e0_alpha) >= 0.00001f)
|
||||
{
|
||||
zeus::CAABox aabb = x14c_bounds.getTransformedAABox(x214_faceDirInv);
|
||||
zeus::CTransform xf = x34_transform * zeus::CTransform::Translate(x244_faceTranslate) * x1e4_faceDir;
|
||||
x254_fluidPlane.Render(mgr, x1e0_alpha, aabb, xf, zeus::CTransform::Identity(), false,
|
||||
xe8_frustum, {}, kInvalidUniqueId, nullptr, 0, 0, zeus::CVector3f::skZero);
|
||||
}
|
||||
|
||||
CActor::Render(mgr);
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const
|
||||
{
|
||||
if (x300_26_outOfFrustum)
|
||||
return;
|
||||
EnsureRendered(mgr, GetTranslation() - x244_faceTranslate, GetSortingBounds(mgr));
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
|
||||
{
|
||||
x300_26_outOfFrustum = !frustum.aabbFrustumTest(x14c_bounds.getTransformedAABox(x34_transform));
|
||||
if (!x300_26_outOfFrustum)
|
||||
{
|
||||
xe8_frustum = frustum;
|
||||
CActor::PreRender(mgr, frustum);
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::SetLinkedObjectAlpha(float a, CStateManager& mgr)
|
||||
{
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
if (conn.x0_state != EScriptObjectState::MaxReached ||
|
||||
conn.x4_msg != EScriptObjectMessage::Activate)
|
||||
continue;
|
||||
if (TCastToPtr<CScriptActor> act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId)))
|
||||
{
|
||||
if (!act->GetActive())
|
||||
act->SetActive(true);
|
||||
act->SetDrawFlags(CModelFlags(5, 0, 3, zeus::CColor(1.f, a)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float CScriptDamageableTrigger::GetPuddleAlphaScale() const
|
||||
{
|
||||
if (x250_alphaTimer <= 0.75f)
|
||||
{
|
||||
if (x300_25_alphaOut)
|
||||
return 1.f - x250_alphaTimer / 0.75f;
|
||||
return x250_alphaTimer / 0.75f;
|
||||
}
|
||||
|
||||
if (x300_25_alphaOut)
|
||||
return 0.f;
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
void CScriptDamageableTrigger::Think(float dt, CStateManager& mgr)
|
||||
{
|
||||
if (!x30_24_active)
|
||||
return;
|
||||
|
||||
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId);
|
||||
CGameArea::EOcclusionState occState =
|
||||
area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded;
|
||||
x300_24_notOccluded = occState == CGameArea::EOcclusionState::Visible;
|
||||
|
||||
if (x300_25_alphaOut)
|
||||
{
|
||||
if (x250_alphaTimer >= 0.75f)
|
||||
{
|
||||
SetActive(false);
|
||||
for (const SConnection& conn : x20_conns)
|
||||
{
|
||||
if (conn.x0_state != EScriptObjectState::MaxReached ||
|
||||
conn.x4_msg != EScriptObjectMessage::Activate)
|
||||
continue;
|
||||
if (TCastToPtr<CScriptActor> act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId)))
|
||||
act->SetActive(false);
|
||||
}
|
||||
|
||||
SetLinkedObjectAlpha(0.f, mgr);
|
||||
x300_25_alphaOut = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x16c_hInfo.GetHP() <= 0.f && x30_24_active)
|
||||
{
|
||||
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None);
|
||||
RemoveMaterial(EMaterialTypes::Orbit, mgr);
|
||||
x300_25_alphaOut = true;
|
||||
x250_alphaTimer = 0.f;
|
||||
}
|
||||
if (x250_alphaTimer <= 0.75f)
|
||||
x250_alphaTimer += dt;
|
||||
float objAlpha = GetPuddleAlphaScale();
|
||||
x1e0_alpha = 0.2f * objAlpha;
|
||||
SetLinkedObjectAlpha(objAlpha, mgr);
|
||||
}
|
||||
}
|
||||
|
||||
rstl::optional_object<zeus::CAABox> CScriptDamageableTrigger::GetTouchBounds() const
|
||||
{
|
||||
if (!x30_24_active || !x300_24_notOccluded)
|
||||
return {};
|
||||
return {zeus::CAABox(x14c_bounds.min + GetTranslation(), x14c_bounds.max + GetTranslation())};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
#define CSCRIPTDAMAGEABLETRIGGER_HPP
|
||||
|
||||
#include "CActor.hpp"
|
||||
#include "CFluidPlaneDoor.hpp"
|
||||
#include "CHealthInfo.hpp"
|
||||
#include "CDamageVulnerability.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -15,13 +18,51 @@ public:
|
|||
Orbit,
|
||||
};
|
||||
|
||||
zeus::CFrustum xe8_frustum;
|
||||
zeus::CAABox x14c_bounds;
|
||||
CHealthInfo x164_origHInfo;
|
||||
CHealthInfo x16c_hInfo;
|
||||
CDamageVulnerability x174_dVuln;
|
||||
u32 x1dc_faceFlag;
|
||||
float x1e0_alpha = 1.f;
|
||||
zeus::CTransform x1e4_faceDir;
|
||||
zeus::CTransform x214_faceDirInv;
|
||||
zeus::CVector3f x244_faceTranslate;
|
||||
float x250_alphaTimer = 0.f;
|
||||
CFluidPlaneDoor x254_fluidPlane;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x300_24_notOccluded : 1;
|
||||
bool x300_25_alphaOut : 1;
|
||||
bool x300_26_outOfFrustum : 1;
|
||||
bool x300_27_invulnerable : 1;
|
||||
bool x300_28_canOrbit : 1;
|
||||
};
|
||||
u32 _dummy = 0;
|
||||
};
|
||||
void SetLinkedObjectAlpha(float a, CStateManager& mgr);
|
||||
float GetPuddleAlphaScale() const;
|
||||
public:
|
||||
CScriptDamageableTrigger(TUniqueId, const std::string&, const CEntityInfo&, const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
const CHealthInfo&, const CDamageVulnerability&, u32, CAssetId, CAssetId, CAssetId, ECanOrbit, bool,
|
||||
const CVisorParameters&);
|
||||
CScriptDamageableTrigger(TUniqueId uid, const std::string& name, const CEntityInfo& info,
|
||||
const zeus::CVector3f& position, const zeus::CVector3f& extent,
|
||||
const CHealthInfo& hInfo, const CDamageVulnerability& dVuln,
|
||||
u32 faceFlag, CAssetId patternTex1, CAssetId patternTex2,
|
||||
CAssetId colorTex, ECanOrbit canOrbit, bool active,
|
||||
const CVisorParameters& vParams);
|
||||
|
||||
void Accept(IVisitor& visitor);
|
||||
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
|
||||
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
const CWeaponMode&, int) const;
|
||||
void Render(const CStateManager& mgr) const;
|
||||
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const;
|
||||
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum);
|
||||
const CDamageVulnerability* GetDamageVulnerability() const { return &x174_dVuln; }
|
||||
CHealthInfo* HealthInfo() { return &x16c_hInfo; }
|
||||
void Think(float, CStateManager&);
|
||||
rstl::optional_object<zeus::CAABox> GetTouchBounds() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -231,7 +231,41 @@ void CScriptWater::SetupGridClipping(CStateManager& mgr, int computeVerts)
|
|||
|
||||
void CScriptWater::UpdateSplashInhabitants(CStateManager& mgr)
|
||||
{
|
||||
// TODO: Do
|
||||
for (auto it = x1fc_waterInhabitants.begin() ; it != x1fc_waterInhabitants.end() ;)
|
||||
{
|
||||
auto& inhab = *it;
|
||||
TCastToPtr<CActor> act = mgr.ObjectById(inhab.first);
|
||||
bool intersects = false;
|
||||
if (act)
|
||||
{
|
||||
if (auto tb = act->GetTouchBounds())
|
||||
{
|
||||
zeus::CAABox thisTb = GetTriggerBoundsWR();
|
||||
if (tb->min.z <= thisTb.max.z && tb->max.z >= thisTb.max.z)
|
||||
intersects = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (act && inhab.second)
|
||||
{
|
||||
if (intersects)
|
||||
act->FluidFXThink(EFluidState::InFluid, *this, mgr);
|
||||
mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::UpdateSplashInhabitant);
|
||||
inhab.second = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
it = x1fc_waterInhabitants.erase(it);
|
||||
if (act)
|
||||
{
|
||||
if (intersects)
|
||||
act->FluidFXThink(EFluidState::LeftFluid, *this, mgr);
|
||||
mgr.SendScriptMsg(act.GetPtr(), GetUniqueId(), EScriptObjectMessage::RemoveSplashInhabitant);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void CScriptWater::Think(float dt, CStateManager& mgr)
|
||||
|
@ -486,7 +520,7 @@ void CScriptWater::Touch(CActor& otherAct, CStateManager& mgr)
|
|||
x1fc_waterInhabitants.emplace_back(otherAct.GetUniqueId(), true);
|
||||
float triggerMaxZ = GetTriggerBoundsWR().max.z;
|
||||
if (touchBounds->min.z <= triggerMaxZ && touchBounds->max.z >= triggerMaxZ)
|
||||
otherAct.FluidFXThink(EFluidState::Zero, *this, mgr);
|
||||
otherAct.FluidFXThink(EFluidState::EnteredFluid, *this, mgr);
|
||||
|
||||
mgr.SendScriptMsg(&otherAct, x8_uid, EScriptObjectMessage::AddSplashInhabitant);
|
||||
}
|
||||
|
@ -510,11 +544,7 @@ zeus::CAABox CScriptWater::GetSortingBounds(const CStateManager& mgr) const
|
|||
}
|
||||
|
||||
EWeaponCollisionResponseTypes CScriptWater::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
<<<<<<< HEAD
|
||||
CWeaponMode&, int)
|
||||
=======
|
||||
const CWeaponMode&, int) const
|
||||
>>>>>>> 11d4aad746973443508adbff80b9da9eb0b4c60c
|
||||
{
|
||||
return EWeaponCollisionResponseTypes::Water;
|
||||
}
|
||||
|
@ -566,4 +596,20 @@ const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr
|
|||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CScriptWater::CanRippleAtPoint(const zeus::CVector3f& point) const
|
||||
{
|
||||
if (!x2d8_tileIntersects)
|
||||
return true;
|
||||
|
||||
auto xTile = int((point.x - GetTriggerBoundsOR().min.x) / x2c0_tileSize);
|
||||
if (xTile < 0 || xTile >= x2c4_gridDimX)
|
||||
return false;
|
||||
|
||||
auto yTile = int((point.y - GetTriggerBoundsOR().min.y) / x2c0_tileSize);
|
||||
if (xTile < 0 || xTile >= x2c8_gridDimY)
|
||||
return false;
|
||||
|
||||
return x2d8_tileIntersects[yTile * x2c4_gridDimX + xTile];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,30 +25,16 @@ private:
|
|||
float x1f4_morphOutTime;
|
||||
float x1f8_morphFactor = 0.f;
|
||||
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
|
||||
<<<<<<< HEAD
|
||||
float x214_fogBias;
|
||||
float x218_fogMagnitude;
|
||||
float x21c_origFogBias;
|
||||
float x220_origFogMagnitude;
|
||||
float x224_fogSpeed;
|
||||
zeus::CColor x228_fogColor;
|
||||
ResId x22c_splashParticle1Id;
|
||||
ResId x230_splashParticle2Id;
|
||||
ResId x234_splashParticle3Id;
|
||||
ResId x238_particle4Id;
|
||||
=======
|
||||
u32 x210_;
|
||||
float x214_;
|
||||
float x218_;
|
||||
float x21c_;
|
||||
float x220_;
|
||||
float x224_;
|
||||
zeus::CColor x228_;
|
||||
CAssetId x22c_splashParticle1Id;
|
||||
CAssetId x230_splashParticle2Id;
|
||||
CAssetId x234_splashParticle3Id;
|
||||
CAssetId x238_particle4Id;
|
||||
>>>>>>> 11d4aad746973443508adbff80b9da9eb0b4c60c
|
||||
std::experimental::optional<TLockedToken<CGenDescription>> x23c_;
|
||||
CAssetId x24c_particle5Id;
|
||||
std::experimental::optional<TLockedToken<CGenDescription>> x250_visorRunoffEffect;
|
||||
|
@ -117,8 +103,8 @@ public:
|
|||
void Touch(CActor &, CStateManager &);
|
||||
void CalculateRenderBounds();
|
||||
zeus::CAABox GetSortingBounds(const CStateManager&) const;
|
||||
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, CWeaponMode&,
|
||||
int);
|
||||
EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
const CWeaponMode&, int) const;
|
||||
|
||||
s16 GetSplashSound(float) const;
|
||||
const std::experimental::optional<TLockedToken<CGenDescription>>& GetSplashEffect(float) const;
|
||||
|
@ -141,6 +127,7 @@ public:
|
|||
u8 GetPatchRenderFlags(int x, int y) const { return x2e0_patchIntersects[y * x2d0_patchDimX + x]; }
|
||||
int GetPatchDimensionX() const { return x2d0_patchDimX; }
|
||||
int GetPatchDimensionY() const { return x2d4_patchDimY; }
|
||||
bool CanRippleAtPoint(const zeus::CVector3f& point) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1111,14 +1111,14 @@ CEntity* ScriptLoader::LoadDamageableTrigger(CStateManager& mgr, CInputStream& i
|
|||
CDamageVulnerability dVuln(in);
|
||||
u32 triggerFlags = in.readUint32Big();
|
||||
triggerFlags = TransformDamagableTriggerFlags(mgr, info.GetAreaId(), triggerFlags);
|
||||
CAssetId w1 = in.readUint32Big();
|
||||
CAssetId w2 = in.readUint32Big();
|
||||
CAssetId w3 = in.readUint32Big();
|
||||
CAssetId patternTex1 = in.readUint32Big();
|
||||
CAssetId patternTex2 = in.readUint32Big();
|
||||
CAssetId colorTex = in.readUint32Big();
|
||||
CScriptDamageableTrigger::ECanOrbit canOrbit = CScriptDamageableTrigger::ECanOrbit(in.readBool());
|
||||
bool active = in.readBool();
|
||||
CVisorParameters vParms = LoadVisorParameters(in);
|
||||
return new CScriptDamageableTrigger(mgr.AllocateUniqueId(), name, info, position, volume, hInfo, dVuln,
|
||||
triggerFlags, w1, w2, w3, canOrbit, active, vParms);
|
||||
triggerFlags, patternTex1, patternTex2, colorTex, canOrbit, active, vParms);
|
||||
}
|
||||
|
||||
CEntity* ScriptLoader::LoadDebris(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||
|
|
Loading…
Reference in New Issue