mirror of https://github.com/AxioDL/metaforce.git
Initial CFluidPlane implementation
This commit is contained in:
parent
5590e2f27a
commit
3650a58a1e
|
@ -1,4 +1,4 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
<component name="CMakeWorkspace" IGNORE_OUTSIDE_FILES="true" PROJECT_DIR="$PROJECT_DIR$" />
|
||||||
</project>
|
</project>
|
|
@ -12,6 +12,7 @@ struct ITweakGame : ITweak
|
||||||
virtual bool GetSplashScreensDisabled() const = 0;
|
virtual bool GetSplashScreensDisabled() const = 0;
|
||||||
virtual float GetFirstPersonFOV() const = 0;
|
virtual float GetFirstPersonFOV() const = 0;
|
||||||
virtual float GetPressStartDelay() const = 0;
|
virtual float GetPressStartDelay() const = 0;
|
||||||
|
virtual float GetFluidEnvBumpScale() const = 0;
|
||||||
virtual float GetHardModeDamageMultiplier() const = 0;
|
virtual float GetHardModeDamageMultiplier() const = 0;
|
||||||
virtual float GetHardModeWeaponMultiplier() const = 0;
|
virtual float GetHardModeWeaponMultiplier() const = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct CTweakGame : ITweakGame
|
||||||
Value<float> x40_unknown10;
|
Value<float> x40_unknown10;
|
||||||
Value<float> x44_unknown11;
|
Value<float> x44_unknown11;
|
||||||
Value<float> x48_unknown12;
|
Value<float> x48_unknown12;
|
||||||
Value<float> x4c_unknown13;
|
Value<float> x4c_fluidEnvBumpScale;
|
||||||
Value<float> x50_unknown14;
|
Value<float> x50_unknown14;
|
||||||
Value<float> x54_unknown15;
|
Value<float> x54_unknown15;
|
||||||
Value<float> x58_unknown16;
|
Value<float> x58_unknown16;
|
||||||
|
@ -38,6 +38,7 @@ struct CTweakGame : ITweakGame
|
||||||
virtual bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; }
|
virtual bool GetSplashScreensDisabled() const { return x2b_splashScreensDisabled; }
|
||||||
virtual float GetFirstPersonFOV() const { return x24_fov; }
|
virtual float GetFirstPersonFOV() const { return x24_fov; }
|
||||||
virtual float GetPressStartDelay() const { return x30_presStartDelay; }
|
virtual float GetPressStartDelay() const { return x30_presStartDelay; }
|
||||||
|
virtual float GetFluidEnvBumpScale() const { return x4c_fluidEnvBumpScale; }
|
||||||
virtual float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
|
virtual float GetHardModeDamageMultiplier() const { return x60_hardmodeDamageMult; }
|
||||||
virtual float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }
|
virtual float GetHardModeWeaponMultiplier() const { return x64_hardmodeWeaponMult; }
|
||||||
CTweakGame() = default;
|
CTweakGame() = default;
|
||||||
|
|
|
@ -1055,7 +1055,7 @@ void CStateManager::SendScriptMsg(TUniqueId src, TEditorId dest, EScriptObjectMe
|
||||||
{
|
{
|
||||||
CEntity* ent = ObjectById(src);
|
CEntity* ent = ObjectById(src);
|
||||||
auto search = GetIdListForScript(dest);
|
auto search = GetIdListForScript(dest);
|
||||||
if (ent && search.first != x890_scriptIdMap.cend() && search.second != x890_scriptIdMap.cend())
|
if (ent && search.first != x890_scriptIdMap.cend())
|
||||||
{
|
{
|
||||||
for (auto it = search.first; it != search.second; ++it)
|
for (auto it = search.first; it != search.second; ++it)
|
||||||
{
|
{
|
||||||
|
@ -1137,7 +1137,10 @@ TUniqueId CStateManager::GetIdForScript(TEditorId id) const
|
||||||
std::pair<std::multimap<TEditorId, TUniqueId>::const_iterator, std::multimap<TEditorId, TUniqueId>::const_iterator>
|
std::pair<std::multimap<TEditorId, TUniqueId>::const_iterator, std::multimap<TEditorId, TUniqueId>::const_iterator>
|
||||||
CStateManager::GetIdListForScript(TEditorId id) const
|
CStateManager::GetIdListForScript(TEditorId id) const
|
||||||
{
|
{
|
||||||
return x890_scriptIdMap.equal_range(id);
|
auto ret = x890_scriptIdMap.equal_range(id);
|
||||||
|
if (ret.first->first != id)
|
||||||
|
ret.first = x890_scriptIdMap.cend();
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStateManager::LoadScriptObjects(TAreaId aid, CInputStream& in, std::vector<TEditorId>& idsOut)
|
void CStateManager::LoadScriptObjects(TAreaId aid, CInputStream& in, std::vector<TEditorId>& idsOut)
|
||||||
|
|
|
@ -315,6 +315,7 @@ public:
|
||||||
std::pair<std::multimap<TEditorId, TUniqueId>::const_iterator,
|
std::pair<std::multimap<TEditorId, TUniqueId>::const_iterator,
|
||||||
std::multimap<TEditorId, TUniqueId>::const_iterator>
|
std::multimap<TEditorId, TUniqueId>::const_iterator>
|
||||||
GetIdListForScript(TEditorId) const;
|
GetIdListForScript(TEditorId) const;
|
||||||
|
std::multimap<TEditorId, TUniqueId>::const_iterator GetIdListEnd() const { return x890_scriptIdMap.cend(); };
|
||||||
void LoadScriptObjects(TAreaId, CInputStream& in, std::vector<TEditorId>& idsOut);
|
void LoadScriptObjects(TAreaId, CInputStream& in, std::vector<TEditorId>& idsOut);
|
||||||
void InitializeScriptObjects(const std::vector<TEditorId>& objIds);
|
void InitializeScriptObjects(const std::vector<TEditorId>& objIds);
|
||||||
std::pair<TEditorId, TUniqueId> LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in);
|
std::pair<TEditorId, TUniqueId> LoadScriptObject(TAreaId, EScriptObjectType, u32, CInputStream& in);
|
||||||
|
|
|
@ -503,19 +503,9 @@ void CActorLights::BuildDynamicLightList(const CStateManager& mgr, const zeus::C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CActorLights::ActivateLights(CBooModel& model) const
|
std::vector<CLight> CActorLights::BuildLightVector() const
|
||||||
{
|
{
|
||||||
std::vector<CLight> lights;
|
std::vector<CLight> lights;
|
||||||
if (x298_28_inArea)
|
|
||||||
{
|
|
||||||
if (!x298_26_hasAreaLights || !x299_26_)
|
|
||||||
{
|
|
||||||
g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
|
|
||||||
model.ActivateLights(lights);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x288_ambientColor));
|
lights.push_back(CLight::BuildLocalAmbient(zeus::CVector3f::skZero, x288_ambientColor));
|
||||||
|
|
||||||
if (x0_areaLights.size())
|
if (x0_areaLights.size())
|
||||||
|
@ -538,6 +528,24 @@ void CActorLights::ActivateLights(CBooModel& model) const
|
||||||
for (const CLight& light : x144_dynamicLights)
|
for (const CLight& light : x144_dynamicLights)
|
||||||
lights.push_back(light);
|
lights.push_back(light);
|
||||||
|
|
||||||
|
return lights;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CActorLights::ActivateLights(CBooModel& model) const
|
||||||
|
{
|
||||||
|
std::vector<CLight> lights;
|
||||||
|
|
||||||
|
if (x298_28_inArea)
|
||||||
|
{
|
||||||
|
if (!x298_26_hasAreaLights || !x299_26_)
|
||||||
|
{
|
||||||
|
g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
|
||||||
|
model.ActivateLights(lights);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lights = BuildLightVector();
|
||||||
model.ActivateLights(lights);
|
model.ActivateLights(lights);
|
||||||
|
|
||||||
if (x298_31_disableWorldLights)
|
if (x298_31_disableWorldLights)
|
||||||
|
|
|
@ -71,6 +71,7 @@ public:
|
||||||
void BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
void BuildFaceLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
||||||
bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
bool BuildAreaLightList(const CStateManager& mgr, const CGameArea& area, const zeus::CAABox& aabb);
|
||||||
void BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb);
|
void BuildDynamicLightList(const CStateManager& mgr, const zeus::CAABox& aabb);
|
||||||
|
std::vector<CLight> BuildLightVector() const;
|
||||||
void ActivateLights(CBooModel& model) const;
|
void ActivateLights(CBooModel& model) const;
|
||||||
void SetCastShadows(bool v) { x298_25_castShadows = v; }
|
void SetCastShadows(bool v) { x298_25_castShadows = v; }
|
||||||
void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; }
|
void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; }
|
||||||
|
|
|
@ -19,7 +19,8 @@ if(WIN32)
|
||||||
Shaders/CScanLinesFilterHLSL.cpp
|
Shaders/CScanLinesFilterHLSL.cpp
|
||||||
Shaders/CRandomStaticFilterHLSL.cpp
|
Shaders/CRandomStaticFilterHLSL.cpp
|
||||||
Shaders/CElementGenShadersHLSL.cpp
|
Shaders/CElementGenShadersHLSL.cpp
|
||||||
Shaders/CParticleSwooshShadersHLSL.cpp)
|
Shaders/CParticleSwooshShadersHLSL.cpp
|
||||||
|
Shaders/CFluidPlaneShaderHLSL.cpp)
|
||||||
elseif(BOO_HAS_METAL)
|
elseif(BOO_HAS_METAL)
|
||||||
set(PLAT_SRCS
|
set(PLAT_SRCS
|
||||||
Shaders/CLineRendererShadersMetal.cpp
|
Shaders/CLineRendererShadersMetal.cpp
|
||||||
|
@ -41,7 +42,8 @@ elseif(BOO_HAS_METAL)
|
||||||
Shaders/CScanLinesFilterMetal.cpp
|
Shaders/CScanLinesFilterMetal.cpp
|
||||||
Shaders/CRandomStaticFilterMetal.cpp
|
Shaders/CRandomStaticFilterMetal.cpp
|
||||||
Shaders/CElementGenShadersMetal.cpp
|
Shaders/CElementGenShadersMetal.cpp
|
||||||
Shaders/CParticleSwooshShadersMetal.cpp)
|
Shaders/CParticleSwooshShadersMetal.cpp
|
||||||
|
Shaders/CFluidPlaneShaderMetal.cpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(GRAPHICS_SOURCES
|
set(GRAPHICS_SOURCES
|
||||||
|
@ -85,6 +87,7 @@ set(GRAPHICS_SOURCES
|
||||||
Shaders/CRandomStaticFilter.hpp Shaders/CRandomStaticFilter.cpp Shaders/CRandomStaticFilterGLSL.cpp
|
Shaders/CRandomStaticFilter.hpp Shaders/CRandomStaticFilter.cpp Shaders/CRandomStaticFilterGLSL.cpp
|
||||||
Shaders/CElementGenShaders.hpp Shaders/CElementGenShaders.cpp Shaders/CElementGenShadersGLSL.cpp
|
Shaders/CElementGenShaders.hpp Shaders/CElementGenShaders.cpp Shaders/CElementGenShadersGLSL.cpp
|
||||||
Shaders/CParticleSwooshShaders.hpp Shaders/CParticleSwooshShaders.cpp Shaders/CParticleSwooshShadersGLSL.cpp
|
Shaders/CParticleSwooshShaders.hpp Shaders/CParticleSwooshShaders.cpp Shaders/CParticleSwooshShadersGLSL.cpp
|
||||||
|
Shaders/CFluidPlaneShader.hpp Shaders/CFluidPlaneShader.cpp Shaders/CFluidPlaneShaderGLSL.cpp
|
||||||
${PLAT_SRCS})
|
${PLAT_SRCS})
|
||||||
|
|
||||||
runtime_add_list(Graphics GRAPHICS_SOURCES)
|
runtime_add_list(Graphics GRAPHICS_SOURCES)
|
||||||
|
|
|
@ -390,50 +390,7 @@ void CBooModel::MakeTexturesFromMats(std::vector<TCachedToken<CTexture>>& toksOu
|
||||||
|
|
||||||
void CBooModel::ActivateLights(const std::vector<CLight>& lights)
|
void CBooModel::ActivateLights(const std::vector<CLight>& lights)
|
||||||
{
|
{
|
||||||
m_lightingData.ambient = zeus::CColor::skBlack;
|
m_lightingData.ActivateLights(lights);
|
||||||
size_t curLight = 0;
|
|
||||||
|
|
||||||
for (const CLight& light : lights)
|
|
||||||
{
|
|
||||||
switch (light.x1c_type)
|
|
||||||
{
|
|
||||||
case ELightType::LocalAmbient:
|
|
||||||
m_lightingData.ambient += light.x18_color;
|
|
||||||
break;
|
|
||||||
case ELightType::Point:
|
|
||||||
case ELightType::Spot:
|
|
||||||
case ELightType::Custom:
|
|
||||||
case ELightType::Directional:
|
|
||||||
{
|
|
||||||
if (curLight >= URDE_MAX_LIGHTS)
|
|
||||||
continue;
|
|
||||||
CModelShaders::Light& lightOut = m_lightingData.lights[curLight++];
|
|
||||||
lightOut.pos = CGraphics::g_CameraMatrix * light.x0_pos;
|
|
||||||
lightOut.dir = CGraphics::g_CameraMatrix.basis * light.xc_dir;
|
|
||||||
lightOut.dir.normalize();
|
|
||||||
lightOut.color = light.x18_color;
|
|
||||||
lightOut.linAtt[0] = light.x24_distC;
|
|
||||||
lightOut.linAtt[1] = light.x28_distL;
|
|
||||||
lightOut.linAtt[2] = light.x2c_distQ;
|
|
||||||
lightOut.angAtt[0] = light.x30_angleC;
|
|
||||||
lightOut.angAtt[1] = light.x34_angleL;
|
|
||||||
lightOut.angAtt[2] = light.x38_angleQ;
|
|
||||||
|
|
||||||
if (light.x1c_type == ELightType::Directional)
|
|
||||||
lightOut.pos = (-lightOut.dir) * 1048576.f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (; curLight<URDE_MAX_LIGHTS ; ++curLight)
|
|
||||||
{
|
|
||||||
CModelShaders::Light& lightOut = m_lightingData.lights[curLight];
|
|
||||||
lightOut.color = zeus::CColor::skClear;
|
|
||||||
lightOut.linAtt[0] = 1.f;
|
|
||||||
lightOut.angAtt[0] = 1.f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBooModel::DisableAllLights()
|
void CBooModel::DisableAllLights()
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
#include "CFluidPlaneShader.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
CFluidPlaneShader::Cache CFluidPlaneShader::_cache = {};
|
||||||
|
|
||||||
|
u16 CFluidPlaneShader::Cache::MakeCacheKey(const SFluidPlaneShaderInfo& info)
|
||||||
|
{
|
||||||
|
u16 ret = 0;
|
||||||
|
|
||||||
|
switch (info.m_type)
|
||||||
|
{
|
||||||
|
case CFluidPlane::EFluidType::NormalWater:
|
||||||
|
case CFluidPlane::EFluidType::Three:
|
||||||
|
case CFluidPlane::EFluidType::Four:
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
ret |= 1 << 2;
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
ret |= 1 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!info.m_hasEnvMap && info.m_hasEnvBumpMap)
|
||||||
|
ret |= 1 << 4;
|
||||||
|
|
||||||
|
if (info.m_hasEnvMap)
|
||||||
|
ret |= 1 << 5;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::PoisonWater:
|
||||||
|
ret |= 1;
|
||||||
|
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
ret |= 1 << 2;
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
ret |= 1 << 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
ret |= 1 << 4;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Lava:
|
||||||
|
ret |= 2;
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
ret |= 1 << 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Five:
|
||||||
|
ret |= 3;
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
ret |= 1 << 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
ret |= 1 << 6;
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
ret |= 1 << 7;
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
ret |= 1 << 8;
|
||||||
|
|
||||||
|
if (info.m_additive)
|
||||||
|
ret |= 1 << 9;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
boo::IShaderPipeline* CFluidPlaneShader::Cache::GetOrBuildShader(const SFluidPlaneShaderInfo& info)
|
||||||
|
{
|
||||||
|
u16 key = MakeCacheKey(info);
|
||||||
|
auto& slot = m_cache[key];
|
||||||
|
if (slot.second != nullptr)
|
||||||
|
return slot.second;
|
||||||
|
|
||||||
|
if (CGraphics::g_BooFactory == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
slot.first = CGraphics::CommitResources(
|
||||||
|
[&](boo::IGraphicsDataFactory::Context& ctx)
|
||||||
|
{
|
||||||
|
switch (ctx.platform())
|
||||||
|
{
|
||||||
|
case boo::IGraphicsDataFactory::Platform::OpenGL:
|
||||||
|
slot.second = BuildShader(static_cast<boo::GLDataFactory::Context&>(ctx), info);
|
||||||
|
break;
|
||||||
|
#if _WIN32
|
||||||
|
case boo::IGraphicsDataFactory::Platform::D3D11:
|
||||||
|
case boo::IGraphicsDataFactory::Platform::D3D12:
|
||||||
|
slot.second = BuildShader(static_cast<boo::ID3DDataFactory::Context&>(ctx), info);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if BOO_HAS_METAL
|
||||||
|
case boo::IGraphicsDataFactory::Platform::Metal:
|
||||||
|
slot.second = BuildShader(static_cast<boo::MetalDataFactory::Context&>(ctx), info);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
#if BOO_HAS_VULKAN
|
||||||
|
case boo::IGraphicsDataFactory::Platform::Vulkan:
|
||||||
|
slot.second = BuildShader(static_cast<boo::VulkanDataFactory::Context&>(ctx), info);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
return slot.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
bool doubleLightmapBlend, bool additive)
|
||||||
|
: m_patternTex1(patternTex1),
|
||||||
|
m_patternTex2(patternTex2),
|
||||||
|
m_colorTex(colorTex),
|
||||||
|
m_bumpMap(bumpMap),
|
||||||
|
m_envMap(envMap),
|
||||||
|
m_envBumpMap(envBumpMap),
|
||||||
|
m_lightmap(lightmap)
|
||||||
|
{
|
||||||
|
SFluidPlaneShaderInfo shaderInfo(type,
|
||||||
|
m_patternTex1.operator bool(),
|
||||||
|
m_patternTex2.operator bool(),
|
||||||
|
m_colorTex.operator bool(),
|
||||||
|
m_bumpMap.operator bool(),
|
||||||
|
m_envMap.operator bool(),
|
||||||
|
m_envBumpMap.operator bool(),
|
||||||
|
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), 999); // TODO: Figure out how many
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFluidPlaneShader::draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
|
||||||
|
const std::vector<CLight>& lights, const zeus::CColor kColors[4])
|
||||||
|
{
|
||||||
|
Uniform& uni = *reinterpret_cast<Uniform*>(m_uniBuf->map(sizeof(Uniform)));
|
||||||
|
uni.m_mv = CGraphics::g_GXModelView.toMatrix4f();
|
||||||
|
uni.m_mvNorm = 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);
|
||||||
|
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;
|
||||||
|
m_uniBuf->unmap();
|
||||||
|
CGraphics::SetShaderDataBinding(m_dataBind);
|
||||||
|
CGraphics::DrawArray(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,110 @@
|
||||||
|
#ifndef CFLUIDPLANESHADER_HPP
|
||||||
|
#define CFLUIDPLANESHADER_HPP
|
||||||
|
|
||||||
|
#include "RetroTypes.hpp"
|
||||||
|
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
|
||||||
|
#include "Runtime/World/CFluidPlane.hpp"
|
||||||
|
#include "CModelShaders.hpp"
|
||||||
|
#include "boo/graphicsdev/GL.hpp"
|
||||||
|
#include "boo/graphicsdev/D3D.hpp"
|
||||||
|
#include "boo/graphicsdev/Metal.hpp"
|
||||||
|
#include "boo/graphicsdev/Vulkan.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SFluidPlaneShaderInfo
|
||||||
|
{
|
||||||
|
CFluidPlane::EFluidType m_type;
|
||||||
|
bool m_hasPatternTex1;
|
||||||
|
bool m_hasPatternTex2;
|
||||||
|
bool m_hasColorTex;
|
||||||
|
bool m_hasBumpMap;
|
||||||
|
bool m_hasEnvMap;
|
||||||
|
bool m_hasEnvBumpMap;
|
||||||
|
bool m_hasLightmap;
|
||||||
|
bool m_doubleLightmapBlend;
|
||||||
|
bool m_additive;
|
||||||
|
|
||||||
|
SFluidPlaneShaderInfo(CFluidPlane::EFluidType type, bool hasPatternTex1, bool hasPatternTex2, bool hasColorTex,
|
||||||
|
bool hasBumpMap, bool hasEnvMap, bool hasEnvBumpMap, bool hasLightmap,
|
||||||
|
bool doubleLightmapBlend, bool additive)
|
||||||
|
: m_type(type), m_hasPatternTex1(hasPatternTex1), m_hasPatternTex2(hasPatternTex2), m_hasColorTex(hasColorTex),
|
||||||
|
m_hasBumpMap(hasBumpMap), m_hasEnvMap(hasEnvMap), m_hasEnvBumpMap(hasEnvBumpMap), m_hasLightmap(hasLightmap),
|
||||||
|
m_doubleLightmapBlend(doubleLightmapBlend), m_additive(additive)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFluidPlaneShader
|
||||||
|
{
|
||||||
|
class Cache
|
||||||
|
{
|
||||||
|
std::pair<boo::GraphicsDataToken, boo::IShaderPipeline*> m_cache[1024] = {};
|
||||||
|
static u16 MakeCacheKey(const SFluidPlaneShaderInfo& info);
|
||||||
|
public:
|
||||||
|
boo::IShaderPipeline* GetOrBuildShader(const SFluidPlaneShaderInfo& info);
|
||||||
|
};
|
||||||
|
static Cache _cache;
|
||||||
|
|
||||||
|
struct Vertex
|
||||||
|
{
|
||||||
|
zeus::CVector3f m_pos;
|
||||||
|
zeus::CVector3f m_norm;
|
||||||
|
zeus::CVector3f m_binorm;
|
||||||
|
zeus::CVector3f m_tangent;
|
||||||
|
zeus::CColor m_color;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Uniform
|
||||||
|
{
|
||||||
|
zeus::CMatrix4f m_mv;
|
||||||
|
zeus::CMatrix4f m_mvNorm;
|
||||||
|
zeus::CMatrix4f m_proj;
|
||||||
|
zeus::CMatrix4f m_texMtxs[9]; // Pad out to 768 bytes
|
||||||
|
CModelShaders::LightingUniform m_lighting;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::experimental::optional<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;
|
||||||
|
boo::GraphicsDataToken m_gfxTok;
|
||||||
|
boo::IGraphicsBufferD* m_vbo;
|
||||||
|
boo::IGraphicsBufferD* m_uniBuf;
|
||||||
|
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);
|
||||||
|
#if _WIN32
|
||||||
|
static boo::IShaderPipeline* BuildShader(boo::ID3DDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info);
|
||||||
|
boo::IShaderDataBinding* BuildBinding(boo::ID3DDataFactory::Context& ctx, boo::IShaderPipeline* pipeline);
|
||||||
|
#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);
|
||||||
|
#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);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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,
|
||||||
|
bool doubleLightmapBlend, bool additive);
|
||||||
|
void draw(const zeus::CMatrix4f texMtxs[6], const zeus::CMatrix4f& normMtx, float indScale,
|
||||||
|
const std::vector<CLight>& lights, const zeus::CColor kColors[4]);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CFLUIDPLANESHADER_HPP
|
|
@ -0,0 +1,559 @@
|
||||||
|
#include "CFluidPlaneShader.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
static const char* VS =
|
||||||
|
"#version 330\n"
|
||||||
|
BOO_GLSL_BINDING_HEAD
|
||||||
|
"layout(location=0) in vec4 posIn;\n"
|
||||||
|
"layout(location=1) in vec4 normalIn;\n"
|
||||||
|
"layout(location=2) in vec4 binormalIn;\n"
|
||||||
|
"layout(location=3) in vec4 tangentIn;\n"
|
||||||
|
"layout(location=4) in vec4 colorIn;\n"
|
||||||
|
"\n"
|
||||||
|
"UBINDING0 uniform FluidPlaneUniform\n"
|
||||||
|
"{\n"
|
||||||
|
" mat4 mv;\n"
|
||||||
|
" mat4 mvNorm;\n"
|
||||||
|
" mat4 proj;\n"
|
||||||
|
" mat4 texMtxs[6];\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) out VertToFrag vtf;\n"
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vtf.mvPos = mv * vec4(posIn.xyz, 1.0);\n"
|
||||||
|
" gl_Position = proj * vtf.mvPos;\n"
|
||||||
|
" vtf.mvNorm = mvNorm * normalIn;\n"
|
||||||
|
" vtf.mvBinorm = mvNorm * binormalIn;\n"
|
||||||
|
" vtf.mvTangent = mvNorm * tangentIn;\n"
|
||||||
|
" vtf.color = colorIn;\n"
|
||||||
|
" vtf.uvs[0] = (texMtxs[0] * posIn).xy;\n"
|
||||||
|
" vtf.uvs[1] = (texMtxs[1] * posIn).xy;\n"
|
||||||
|
" vtf.uvs[2] = (texMtxs[2] * posIn).xy;\n"
|
||||||
|
"%s" // Additional TCGs here
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* FS =
|
||||||
|
"#version 330\n"
|
||||||
|
BOO_GLSL_BINDING_HEAD
|
||||||
|
"\n"
|
||||||
|
"struct Light\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 pos;\n"
|
||||||
|
" vec4 dir;\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
" vec4 linAtt;\n"
|
||||||
|
" vec4 angAtt;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct Fog\n" // Reappropriated for indirect texture scaling
|
||||||
|
"{\n"
|
||||||
|
" vec4 color;\n"
|
||||||
|
" float indScale;\n"
|
||||||
|
" float start;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"UBINDING2 uniform LightingUniform\n"
|
||||||
|
"{\n"
|
||||||
|
" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n"
|
||||||
|
" vec4 ambient;\n"
|
||||||
|
" vec4 kColor0;\n"
|
||||||
|
" vec4 kColor1;\n"
|
||||||
|
" vec4 kColor2;\n"
|
||||||
|
" vec4 kColor3;\n"
|
||||||
|
" Fog fog;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"vec4 LightingFunc(vec4 mvPosIn, vec4 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"
|
||||||
|
" 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"
|
||||||
|
" lights[i].linAtt[1] * dist +\n"
|
||||||
|
" lights[i].linAtt[0]);\n"
|
||||||
|
" 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"
|
||||||
|
" }\n"
|
||||||
|
" \n"
|
||||||
|
" return clamp(ret, vec4(0.0,0.0,0.0,0.0), vec4(1.0,1.0,1.0,1.0));\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) in VertToFrag vtf;\n"
|
||||||
|
"layout(location=0) out vec4 colorOut;\n"
|
||||||
|
"%s" // Textures here
|
||||||
|
"void main()\n"
|
||||||
|
"{\n"
|
||||||
|
" vec4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
|
||||||
|
"%s" // Combiner expression here
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static void _BuildShader(std::string& finalVS, std::string& finalFS, int& nextTex, const char* texNames[7],
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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++);
|
||||||
|
}
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
texNames[nextTex] = "bumpMap";
|
||||||
|
textures += hecl::Format("TBINDING%d uniform sampler2D bumpMap;\n", nextTex++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvMap)
|
||||||
|
{
|
||||||
|
texNames[nextTex] = "envMap";
|
||||||
|
textures += hecl::Format("TBINDING%d uniform sampler2D envMap;\n", nextTex++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
texNames[nextTex] = "envBumpMap";
|
||||||
|
textures += hecl::Format("TBINDING%d uniform sampler2D envBumpMap;\n", nextTex++);
|
||||||
|
}
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
texNames[nextTex] = "lightMap";
|
||||||
|
textures += hecl::Format("TBINDING%d uniform sampler2D lightMap;\n", nextTex++);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
bumpMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[0] * posIn).xy;\n", nextTCG++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
envBumpMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[3] * posIn).xy;\n", nextTCG++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvMap)
|
||||||
|
{
|
||||||
|
envMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * posIn).xy;\n", nextTCG++, nextMtx++);
|
||||||
|
}
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
lightmapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (texMtxs[%d] * posIn).xy;\n", nextTCG++, nextMtx++);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info.m_type)
|
||||||
|
{
|
||||||
|
case CFluidPlane::EFluidType::NormalWater:
|
||||||
|
case CFluidPlane::EFluidType::Three:
|
||||||
|
case CFluidPlane::EFluidType::Four:
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
|
||||||
|
// 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 2
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
{
|
||||||
|
// 1: Tex4TCG2, Tex4, GX_COLOR1A1
|
||||||
|
// C2, TEX, KONST, RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 3
|
||||||
|
// Tex * K2 + Lighting
|
||||||
|
combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mix(Tex * K2, Tex, K3) + Lighting
|
||||||
|
combiner += " lighting += lightMapTexel * kColor2;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next: Tex0TCG, Tex0, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// Next: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// Next: Tex2TCG, Tex2, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, hasTex4 ? C2 : RAS, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n"
|
||||||
|
" texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
else
|
||||||
|
combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
else if (info.m_hasEnvMap)
|
||||||
|
{
|
||||||
|
// Next: envTCG, envTex, NULL
|
||||||
|
// PREV, TEX, KONST, ZERO
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 1
|
||||||
|
|
||||||
|
// Make previous stage indirect, mtx0
|
||||||
|
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",
|
||||||
|
envMapUv);
|
||||||
|
}
|
||||||
|
else if (info.m_hasColorTex)
|
||||||
|
{
|
||||||
|
combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::PoisonWater:
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
combiner += hecl::Format(" vec4 lightMapTexel = texture(lightMap, vtf.uvs[%d]);\n", lightmapUv);
|
||||||
|
// 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 2
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
{
|
||||||
|
// 1: Tex4TCG2, Tex4, GX_COLOR1A1
|
||||||
|
// C2, TEX, KONST, RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 3
|
||||||
|
// Tex * K2 + Lighting
|
||||||
|
combiner += " lighting += mix(lightMapTexel * kColor2, lightMapTexel, kColor3);\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mix(Tex * K2, Tex, K3) + Lighting
|
||||||
|
combiner += " lighting += lightMapTexel * kColor2;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next: Tex0TCG, Tex0, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// Next: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// Next: Tex2TCG, Tex2, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, hasTex4 ? C2 : RAS, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + lighting) *\n"
|
||||||
|
" texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
else
|
||||||
|
combiner += " colorOut = lighting * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
{
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
combiner += " colorOut += texture(colorTex, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut += texture(colorTex, vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Lava:
|
||||||
|
// 0: Tex0TCG, Tex0, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// 1: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// 2: Tex2TCG, Tex2, NULL
|
||||||
|
// ZERO, TEX, ONE, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
|
||||||
|
" texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
else
|
||||||
|
combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n";
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
// 3: bumpMapTCG, bumpMap, NULL
|
||||||
|
// ZERO, TEX, ONE, HALF
|
||||||
|
// Output reg 0, no clamp, no bias
|
||||||
|
|
||||||
|
// 4: bumpMapTCG2, bumpMap, NULL
|
||||||
|
// ZERO, TEX, ONE, C0
|
||||||
|
// Output reg 0, subtract, clamp, no bias
|
||||||
|
|
||||||
|
combiner += " vec3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
|
||||||
|
" float lx = dot(vtf.mvTangent, lightVec);\n"
|
||||||
|
" float ly = dot(vtf.mvBinorm, lightVec);\n";
|
||||||
|
combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n"
|
||||||
|
" vec4 emboss2 = texture(bumpMap, vtf.uvs[%d] + vec2(lx, ly));\n",
|
||||||
|
bumpMapUv, bumpMapUv);
|
||||||
|
|
||||||
|
// 5: NULL, NULL, NULL
|
||||||
|
// ZERO, PREV, C0, ZERO
|
||||||
|
// Output reg prev, scale 2, clamp
|
||||||
|
|
||||||
|
// colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0
|
||||||
|
combiner += "colorOut *= clamp((emboss1 + vec4(0.5) - emboss2) * vec4(2.0), vec4(0.0), vec4(1.0));\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Five:
|
||||||
|
// 0: Tex0TCG, Tex0, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// 1: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// 2: Tex2TCG, Tex2, NULL
|
||||||
|
// ZERO, TEX, ONE, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (texture(patternTex1, vtf.uvs[0]) * kColor0 + vtf.color) *\n"
|
||||||
|
" texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
else
|
||||||
|
combiner += " colorOut = vtf.color * texture(patternTex2, vtf.uvs[1]) + vtf.color;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
combiner += " colorOut += texture(colorTex, vtf.uvs[2]);\n";
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
// 3: bumpMapTCG, bumpMap, NULL
|
||||||
|
// ZERO, TEX, PREV, ZERO
|
||||||
|
// Output reg prev, scale 2
|
||||||
|
combiner += hecl::Format(" vec4 emboss1 = texture(bumpMap, vtf.uvs[%d]) + vec4(0.5);\n", bumpMapUv);
|
||||||
|
combiner += "colorOut *= emboss1 * vec4(2.0);\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
combiner += " colorOut.a = kColor0.a;\n";
|
||||||
|
|
||||||
|
finalVS = hecl::Format(VS, additionalTCGs.c_str());
|
||||||
|
finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
boo::IShaderPipeline*
|
||||||
|
CFluidPlaneShader::BuildShader(boo::GLDataFactory::Context& ctx, const SFluidPlaneShaderInfo& info)
|
||||||
|
{
|
||||||
|
int nextTex = 0;
|
||||||
|
const char* texNames[7] = {};
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BOO_HAS_VULKAN
|
||||||
|
static boo::IVertexFormat* s_vtxFmt = nullptr;
|
||||||
|
|
||||||
|
boo::IShaderPipeline*
|
||||||
|
CFluidPlaneShader::BuildShader(boo::VulkanDataFactory::Context& ctx, const SFluidPlaneShaderInfo& 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[7] = {};
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::GLDataFactory::Context& ctx,
|
||||||
|
boo::IShaderPipeline* pipeline)
|
||||||
|
{
|
||||||
|
boo::VertexElementDescriptor elements[] =
|
||||||
|
{
|
||||||
|
{m_vbo, nullptr, boo::VertexSemantic::Position4},
|
||||||
|
{m_vbo, nullptr, boo::VertexSemantic::Normal4, 0},
|
||||||
|
{m_vbo, nullptr, boo::VertexSemantic::Normal4, 1},
|
||||||
|
{m_vbo, nullptr, boo::VertexSemantic::Normal4, 2},
|
||||||
|
{m_vbo, nullptr, boo::VertexSemantic::Color}
|
||||||
|
};
|
||||||
|
boo::IVertexFormat* vtxFmt = ctx.newVertexFormat(5, elements);
|
||||||
|
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||||
|
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||||
|
boo::PipelineStage::Fragment };
|
||||||
|
size_t ubufOffs[] = {0, 0, 768};
|
||||||
|
size_t ubufSizes[] = {768, 768, 256};
|
||||||
|
size_t texCount = 0;
|
||||||
|
boo::ITexture* texs[7] = {};
|
||||||
|
if (m_patternTex1)
|
||||||
|
texs[texCount++] = (*m_patternTex1)->GetBooTexture();
|
||||||
|
if (m_patternTex2)
|
||||||
|
texs[texCount++] = (*m_patternTex2)->GetBooTexture();
|
||||||
|
if (m_colorTex)
|
||||||
|
texs[texCount++] = (*m_colorTex)->GetBooTexture();
|
||||||
|
if (m_bumpMap)
|
||||||
|
texs[texCount++] = (*m_bumpMap)->GetBooTexture();
|
||||||
|
if (m_envMap)
|
||||||
|
texs[texCount++] = (*m_envMap)->GetBooTexture();
|
||||||
|
if (m_envBumpMap)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if BOO_HAS_VULKAN
|
||||||
|
boo::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::VulkanDataFactory::Context& ctx,
|
||||||
|
boo::IShaderPipeline* pipeline)
|
||||||
|
{
|
||||||
|
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||||
|
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||||
|
boo::PipelineStage::Fragment };
|
||||||
|
size_t ubufOffs[] = {0, 0, 768};
|
||||||
|
size_t ubufSizes[] = {768, 768, 256};
|
||||||
|
size_t texCount = 0;
|
||||||
|
boo::ITexture* texs[7] = {};
|
||||||
|
if (m_patternTex1)
|
||||||
|
texs[texCount++] = (*m_patternTex1)->GetBooTexture();
|
||||||
|
if (m_patternTex2)
|
||||||
|
texs[texCount++] = (*m_patternTex2)->GetBooTexture();
|
||||||
|
if (m_colorTex)
|
||||||
|
texs[texCount++] = (*m_colorTex)->GetBooTexture();
|
||||||
|
if (m_bumpMap)
|
||||||
|
texs[texCount++] = (*m_bumpMap)->GetBooTexture();
|
||||||
|
if (m_envMap)
|
||||||
|
texs[texCount++] = (*m_envMap)->GetBooTexture();
|
||||||
|
if (m_envBumpMap)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
//
|
||||||
|
// Created by Jack Andersen on 8/6/17.
|
||||||
|
//
|
||||||
|
|
|
@ -0,0 +1,480 @@
|
||||||
|
#include "CFluidPlaneShader.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
static boo::IVertexFormat* s_vtxFmt = nullptr;
|
||||||
|
|
||||||
|
static const char* VS =
|
||||||
|
"#include <metal_stdlib>\n"
|
||||||
|
"using namespace metal;\n"
|
||||||
|
"struct VertData\n"
|
||||||
|
"{\n"
|
||||||
|
" float4 posIn [[ attribute(0) ]];\n"
|
||||||
|
" float4 normalIn [[ attribute(1) ]];\n"
|
||||||
|
" float4 binormalIn [[ attribute(2) ]];\n"
|
||||||
|
" float4 tangentIn [[ attribute(3) ]];\n"
|
||||||
|
" float4 colorIn [[ attribute(4) ]];\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"UBINDING0 uniform FluidPlaneUniform\n"
|
||||||
|
"{\n"
|
||||||
|
" float4x4 mv;\n"
|
||||||
|
" float4x4 mvNorm;\n"
|
||||||
|
" float4x4 proj;\n"
|
||||||
|
" float4x4 texMtxs[6];\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"struct VertToFrag\n"
|
||||||
|
"{\n"
|
||||||
|
" float4 mvPos;\n"
|
||||||
|
" float4 mvNorm;\n"
|
||||||
|
" float4 mvBinorm;\n"
|
||||||
|
" float4 mvTangent;\n"
|
||||||
|
" float4 color;\n"
|
||||||
|
" float2 uvs[7];\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"vertex VertToFrag vmain(VertData v [[ stage_in ]],\n"
|
||||||
|
" constant FluidPlaneUniform& fu [[ buffer(2) ]])\n"
|
||||||
|
"{\n"
|
||||||
|
" VertToFrag vtf;\n"
|
||||||
|
" vtf.mvPos = fu.mv * float4(v.posIn.xyz, 1.0);\n"
|
||||||
|
" gl_Position = fu.proj * vtf.mvPos;\n"
|
||||||
|
" vtf.mvNorm = fu.mvNorm * v.normalIn;\n"
|
||||||
|
" vtf.mvBinorm = fu.mvNorm * v.binormalIn;\n"
|
||||||
|
" vtf.mvTangent = fu.mvNorm * v.tangentIn;\n"
|
||||||
|
" vtf.color = v.colorIn;\n"
|
||||||
|
" vtf.uvs[0] = (fu.texMtxs[0] * v.posIn).xy;\n"
|
||||||
|
" vtf.uvs[1] = (fu.texMtxs[1] * v.posIn).xy;\n"
|
||||||
|
" vtf.uvs[2] = (fu.texMtxs[2] * v.posIn).xy;\n"
|
||||||
|
"%s" // Additional TCGs here
|
||||||
|
" return vtf;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
static const char* FS =
|
||||||
|
"#include <metal_stdlib>\n"
|
||||||
|
"using namespace metal;\n"
|
||||||
|
"constexpr sampler samp(address::repeat, filter::linear);\n"
|
||||||
|
"\n"
|
||||||
|
"struct Light\n"
|
||||||
|
"{\n"
|
||||||
|
" float4 pos;\n"
|
||||||
|
" float4 dir;\n"
|
||||||
|
" float4 color;\n"
|
||||||
|
" float4 linAtt;\n"
|
||||||
|
" float4 angAtt;\n"
|
||||||
|
"};\n"
|
||||||
|
"struct Fog\n" // Reappropriated for indirect texture scaling
|
||||||
|
"{\n"
|
||||||
|
" float4 color;\n"
|
||||||
|
" float indScale;\n"
|
||||||
|
" float start;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"struct LightingUniform\n"
|
||||||
|
"{\n"
|
||||||
|
" Light lights[" _XSTR(URDE_MAX_LIGHTS) "];\n"
|
||||||
|
" float4 ambient;\n"
|
||||||
|
" float4 kColor0;\n"
|
||||||
|
" float4 kColor1;\n"
|
||||||
|
" float4 kColor2;\n"
|
||||||
|
" float4 kColor3;\n"
|
||||||
|
" Fog fog;\n"
|
||||||
|
"};\n"
|
||||||
|
"\n"
|
||||||
|
"static float4 LightingFunc(float4 mvPosIn, float4 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"
|
||||||
|
" 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"
|
||||||
|
" lights[i].linAtt[1] * dist +\n"
|
||||||
|
" lights[i].linAtt[0]);\n"
|
||||||
|
" 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"
|
||||||
|
" }\n"
|
||||||
|
" \n"
|
||||||
|
" return clamp(ret, float4(0.0,0.0,0.0,0.0), float4(1.0,1.0,1.0,1.0));\n"
|
||||||
|
"}\n"
|
||||||
|
"\n"
|
||||||
|
"struct VertToFrag\n"
|
||||||
|
"{\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 ]],\n"
|
||||||
|
" constant LightingUniform& lu [[ buffer(4) ]]%s)\n" // Textures here
|
||||||
|
"{\n"
|
||||||
|
" float4 lighting = LightingFunc(vtf.mvPos, normalize(vtf.mvNorm));\n"
|
||||||
|
" float4 colorOut;\n"
|
||||||
|
"%s" // Combiner expression here
|
||||||
|
" return colorOut;\n"
|
||||||
|
"}\n";
|
||||||
|
|
||||||
|
boo::IShaderPipeline*
|
||||||
|
CFluidPlaneShader::BuildShader(boo::MetalDataFactory::Context& ctx, const SFluidPlaneShaderInfo& 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;
|
||||||
|
int nextTCG = 3;
|
||||||
|
int nextMtx = 4;
|
||||||
|
int bumpMapUv, envBumpMapUv, envMapUv, lightmapUv;
|
||||||
|
|
||||||
|
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++);
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
textures += hecl::Format(",\ntexture2d<float> bumpMap [[ texture(%d) ]]", nextTex++);
|
||||||
|
if (info.m_hasEnvMap)
|
||||||
|
textures += hecl::Format(",\ntexture2d<float> envMap [[ texture(%d) ]]", nextTex++);
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
textures += hecl::Format(",\ntexture2d<float> envBumpMap [[ texture(%d) ]]", nextTex++);
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
textures += hecl::Format(",\ntexture2d<float> lightMap [[ texture(%d) ]]", nextTex++);
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
bumpMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[0] * v.posIn).xy;\n", nextTCG++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
envBumpMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[3] * v.posIn).xy;\n", nextTCG++);
|
||||||
|
}
|
||||||
|
if (info.m_hasEnvMap)
|
||||||
|
{
|
||||||
|
envMapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++);
|
||||||
|
}
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
lightmapUv = nextTCG;
|
||||||
|
additionalTCGs += hecl::Format(" vtf.uvs[%d] = (fu.texMtxs[%d] * v.posIn).xy;\n", nextTCG++, nextMtx++);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (info.m_type)
|
||||||
|
{
|
||||||
|
case CFluidPlane::EFluidType::NormalWater:
|
||||||
|
case CFluidPlane::EFluidType::Three:
|
||||||
|
case CFluidPlane::EFluidType::Four:
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv);
|
||||||
|
// 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 2
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
{
|
||||||
|
// 1: Tex4TCG2, Tex4, GX_COLOR1A1
|
||||||
|
// C2, TEX, KONST, RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 3
|
||||||
|
// Tex * K2 + Lighting
|
||||||
|
combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mix(Tex * K2, Tex, K3) + Lighting
|
||||||
|
combiner += " lighting += lightMapTexel * lu.kColor2;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next: Tex0TCG, Tex0, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// Next: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// Next: Tex2TCG, Tex2, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, hasTex4 ? C2 : RAS, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.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";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (info.m_hasColorTex && !info.m_hasEnvMap && info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
else if (info.m_hasEnvMap)
|
||||||
|
{
|
||||||
|
// Next: envTCG, envTex, NULL
|
||||||
|
// PREV, TEX, KONST, ZERO
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 1
|
||||||
|
|
||||||
|
// Make previous stage indirect, mtx0
|
||||||
|
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",
|
||||||
|
envMapUv);
|
||||||
|
}
|
||||||
|
else if (info.m_hasColorTex)
|
||||||
|
{
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::PoisonWater:
|
||||||
|
if (info.m_hasLightmap)
|
||||||
|
{
|
||||||
|
combiner += hecl::Format(" float4 lightMapTexel = lightMap.sample(samp, vtf.uvs[%d]);\n", lightmapUv);
|
||||||
|
// 0: Tex4TCG, Tex4, doubleLightmapBlend ? NULL : GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, doubleLightmapBlend ? ZERO : RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 2
|
||||||
|
if (info.m_doubleLightmapBlend)
|
||||||
|
{
|
||||||
|
// 1: Tex4TCG2, Tex4, GX_COLOR1A1
|
||||||
|
// C2, TEX, KONST, RAS
|
||||||
|
// Output reg 2
|
||||||
|
// KColor 3
|
||||||
|
// Tex * K2 + Lighting
|
||||||
|
combiner += " lighting += mix(lightMapTexel * lu.kColor2, lightMapTexel, lu.kColor3);\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// mix(Tex * K2, Tex, K3) + Lighting
|
||||||
|
combiner += " lighting += lightMapTexel * lu.kColor2;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next: Tex0TCG, Tex0, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// Next: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// Next: Tex2TCG, Tex2, GX_COLOR1A1
|
||||||
|
// ZERO, TEX, hasTex4 ? C2 : RAS, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + Lighting) * Tex1 + VertColor + Tex2 * Lighting
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.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";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
{
|
||||||
|
if (info.m_hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
// 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);
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, indUvs + vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]) * lighting;\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Lava:
|
||||||
|
// 0: Tex0TCG, Tex0, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// 1: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// 2: Tex2TCG, Tex2, NULL
|
||||||
|
// ZERO, TEX, ONE, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.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";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n";
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
// 3: bumpMapTCG, bumpMap, NULL
|
||||||
|
// ZERO, TEX, ONE, HALF
|
||||||
|
// Output reg 0, no clamp, no bias
|
||||||
|
|
||||||
|
// 4: bumpMapTCG2, bumpMap, NULL
|
||||||
|
// ZERO, TEX, ONE, C0
|
||||||
|
// Output reg 0, subtract, clamp, no bias
|
||||||
|
|
||||||
|
combiner += " float3 lightVec = lights[3].pos.xyz - vtf.mvPos.xyz;\n"
|
||||||
|
" float lx = dot(vtf.mvTangent.xyz, lightVec);\n"
|
||||||
|
" float ly = dot(vtf.mvBinorm.xyz, lightVec);\n";
|
||||||
|
combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n"
|
||||||
|
" float4 emboss2 = bumpMap.sample(samp, vtf.uvs[%d] + float2(lx, ly));\n",
|
||||||
|
bumpMapUv, bumpMapUv);
|
||||||
|
|
||||||
|
// 5: NULL, NULL, NULL
|
||||||
|
// ZERO, PREV, C0, ZERO
|
||||||
|
// Output reg prev, scale 2, clamp
|
||||||
|
|
||||||
|
// colorOut * clamp(emboss1 + 0.5 - emboss2, 0.0, 1.0) * 2.0
|
||||||
|
combiner += "colorOut *= clamp((emboss1 + float4(0.5) - emboss2) * float4(2.0), float4(0.0), float4(1.0));\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CFluidPlane::EFluidType::Five:
|
||||||
|
// 0: Tex0TCG, Tex0, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, KONST, RAS
|
||||||
|
// Output reg prev
|
||||||
|
// KColor 0
|
||||||
|
|
||||||
|
// 1: Tex1TCG, Tex1, GX_COLOR0A0
|
||||||
|
// ZERO, TEX, PREV, RAS
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// 2: Tex2TCG, Tex2, NULL
|
||||||
|
// ZERO, TEX, ONE, PREV
|
||||||
|
// Output reg prev
|
||||||
|
|
||||||
|
// (Tex0 * kColor0 + VertColor) * Tex1 + VertColor + Tex2
|
||||||
|
if (info.m_hasPatternTex2)
|
||||||
|
{
|
||||||
|
if (info.m_hasPatternTex1)
|
||||||
|
combiner += " colorOut = (patternTex1.sample(samp, vtf.uvs[0]) * lu.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";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
combiner += " colorOut = vtf.color;\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.m_hasColorTex)
|
||||||
|
combiner += " colorOut += colorTex.sample(samp, vtf.uvs[2]);\n";
|
||||||
|
|
||||||
|
if (info.m_hasBumpMap)
|
||||||
|
{
|
||||||
|
// 3: bumpMapTCG, bumpMap, NULL
|
||||||
|
// ZERO, TEX, PREV, ZERO
|
||||||
|
// Output reg prev, scale 2
|
||||||
|
combiner += hecl::Format(" float4 emboss1 = bumpMap.sample(samp, vtf.uvs[%d]) + float4(0.5);\n", bumpMapUv);
|
||||||
|
combiner += "colorOut *= emboss1 * float4(2.0);\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
combiner += " colorOut.a = kColor0.a;\n";
|
||||||
|
|
||||||
|
std::string finalVS = hecl::Format(VS, additionalTCGs.c_str());
|
||||||
|
std::string finalFS = hecl::Format(FS, textures.c_str(), combiner.c_str());
|
||||||
|
|
||||||
|
return ctx.newShaderPipeline(finalVS.c_str(), finalFS.c_str(), s_vtxFmt, CGraphics::g_ViewportSamples,
|
||||||
|
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::IShaderDataBinding* CFluidPlaneShader::BuildBinding(boo::MetalDataFactory::Context& ctx,
|
||||||
|
boo::IShaderPipeline* pipeline)
|
||||||
|
{
|
||||||
|
boo::IGraphicsBuffer* ubufs[] = { m_uniBuf, m_uniBuf, m_uniBuf };
|
||||||
|
boo::PipelineStage ubufStages[] = { boo::PipelineStage::Vertex, boo::PipelineStage::Vertex,
|
||||||
|
boo::PipelineStage::Fragment };
|
||||||
|
size_t ubufOffs[] = {0, 0, 768};
|
||||||
|
size_t ubufSizes[] = {768, 768, 256};
|
||||||
|
size_t texCount = 0;
|
||||||
|
boo::ITexture* texs[7] = {};
|
||||||
|
if (m_patternTex1)
|
||||||
|
texs[texCount++] = (*m_patternTex1)->GetBooTexture();
|
||||||
|
if (m_patternTex2)
|
||||||
|
texs[texCount++] = (*m_patternTex2)->GetBooTexture();
|
||||||
|
if (m_colorTex)
|
||||||
|
texs[texCount++] = (*m_colorTex)->GetBooTexture();
|
||||||
|
if (m_bumpMap)
|
||||||
|
texs[texCount++] = (*m_bumpMap)->GetBooTexture();
|
||||||
|
if (m_envMap)
|
||||||
|
texs[texCount++] = (*m_envMap)->GetBooTexture();
|
||||||
|
if (m_envBumpMap)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,10 +1,58 @@
|
||||||
#include "CModelShaders.hpp"
|
#include "CModelShaders.hpp"
|
||||||
|
#include "Graphics/CLight.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
|
||||||
std::experimental::optional<CModelShaders> CModelShaders::g_ModelShaders;
|
std::experimental::optional<CModelShaders> CModelShaders::g_ModelShaders;
|
||||||
|
|
||||||
|
void CModelShaders::LightingUniform::ActivateLights(const std::vector<CLight>& lts)
|
||||||
|
{
|
||||||
|
ambient = zeus::CColor::skBlack;
|
||||||
|
size_t curLight = 0;
|
||||||
|
|
||||||
|
for (const CLight& light : lts)
|
||||||
|
{
|
||||||
|
switch (light.GetType())
|
||||||
|
{
|
||||||
|
case ELightType::LocalAmbient:
|
||||||
|
ambient += light.GetColor();
|
||||||
|
break;
|
||||||
|
case ELightType::Point:
|
||||||
|
case ELightType::Spot:
|
||||||
|
case ELightType::Custom:
|
||||||
|
case ELightType::Directional:
|
||||||
|
{
|
||||||
|
if (curLight >= URDE_MAX_LIGHTS)
|
||||||
|
continue;
|
||||||
|
CModelShaders::Light& lightOut = lights[curLight++];
|
||||||
|
lightOut.pos = CGraphics::g_CameraMatrix * light.GetPosition();
|
||||||
|
lightOut.dir = CGraphics::g_CameraMatrix.basis * light.GetDirection();
|
||||||
|
lightOut.dir.normalize();
|
||||||
|
lightOut.color = light.GetColor();
|
||||||
|
lightOut.linAtt[0] = light.GetAttenuationConstant();
|
||||||
|
lightOut.linAtt[1] = light.GetAttenuationLinear();
|
||||||
|
lightOut.linAtt[2] = light.GetAttenuationQuadratic();
|
||||||
|
lightOut.angAtt[0] = light.GetAngleAttenuationConstant();
|
||||||
|
lightOut.angAtt[1] = light.GetAngleAttenuationLinear();
|
||||||
|
lightOut.angAtt[2] = light.GetAngleAttenuationQuadratic();
|
||||||
|
|
||||||
|
if (light.GetType() == ELightType::Directional)
|
||||||
|
lightOut.pos = (-lightOut.dir) * 1048576.f;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; curLight<URDE_MAX_LIGHTS ; ++curLight)
|
||||||
|
{
|
||||||
|
CModelShaders::Light& lightOut = lights[curLight];
|
||||||
|
lightOut.color = zeus::CColor::skClear;
|
||||||
|
lightOut.linAtt[0] = 1.f;
|
||||||
|
lightOut.angAtt[0] = 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
hecl::Runtime::ShaderCacheExtensions
|
hecl::Runtime::ShaderCacheExtensions
|
||||||
CModelShaders::GetShaderExtensions(boo::IGraphicsDataFactory::Platform plat)
|
CModelShaders::GetShaderExtensions(boo::IGraphicsDataFactory::Platform plat)
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#include "zeus/CColor.hpp"
|
#include "zeus/CColor.hpp"
|
||||||
#include "Graphics/CGraphics.hpp"
|
#include "Graphics/CGraphics.hpp"
|
||||||
|
|
||||||
#define URDE_MAX_LIGHTS 16
|
#define URDE_MAX_LIGHTS 8
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -55,6 +55,8 @@ public:
|
||||||
zeus::CColor colorRegs[3];
|
zeus::CColor colorRegs[3];
|
||||||
zeus::CColor mulColor;
|
zeus::CColor mulColor;
|
||||||
CGraphics::CFogState fog;
|
CGraphics::CFogState fog;
|
||||||
|
|
||||||
|
void ActivateLights(const std::vector<CLight>& lts);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ThermalUniform
|
struct ThermalUniform
|
||||||
|
|
|
@ -170,6 +170,7 @@ public:
|
||||||
bool translateId);
|
bool translateId);
|
||||||
SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool);
|
SAdvancementDeltas UpdateAnimation(float, CStateManager&, bool);
|
||||||
void SetActorLights(std::unique_ptr<CActorLights>);
|
void SetActorLights(std::unique_ptr<CActorLights>);
|
||||||
|
const CActorLights* GetActorLights() const { return x90_actorLights.get(); }
|
||||||
bool CanDrawStatic() const;
|
bool CanDrawStatic() const;
|
||||||
bool GetE7_29() const { return xe7_29_; }
|
bool GetE7_29() const { return xe7_29_; }
|
||||||
const CScannableObjectInfo* GetScannableObjectInfo() const;
|
const CScannableObjectInfo* GetScannableObjectInfo() const;
|
||||||
|
|
|
@ -19,15 +19,15 @@ class CFluidPlane
|
||||||
public:
|
public:
|
||||||
enum class EFluidType
|
enum class EFluidType
|
||||||
{
|
{
|
||||||
Zero,
|
NormalWater,
|
||||||
One,
|
PoisonWater,
|
||||||
Two,
|
Lava,
|
||||||
Three,
|
Three,
|
||||||
Four,
|
Four,
|
||||||
Five
|
Five
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
ResId x4_texPattern1Id;
|
ResId x4_texPattern1Id;
|
||||||
ResId x8_texPattern2Id;
|
ResId x8_texPattern2Id;
|
||||||
ResId xc_texColorId;
|
ResId xc_texColorId;
|
||||||
|
@ -45,7 +45,7 @@ public:
|
||||||
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
virtual void Ripple(float mag, TUniqueId rippler, const zeus::CVector3f& pos,
|
||||||
CScriptWater& water, CStateManager& mgr);
|
CScriptWater& water, CStateManager& mgr);
|
||||||
virtual void Update();
|
virtual void Update();
|
||||||
virtual void Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
virtual void Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||||
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
|
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const {}
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
#include "CFluidPlaneCPU.hpp"
|
#include "CFluidPlaneCPU.hpp"
|
||||||
#include "CSimplePool.hpp"
|
#include "CSimplePool.hpp"
|
||||||
#include "GameGlobalObjects.hpp"
|
#include "GameGlobalObjects.hpp"
|
||||||
|
#include "CFluidPlaneManager.hpp"
|
||||||
|
#include "CStateManager.hpp"
|
||||||
|
#include "CWorld.hpp"
|
||||||
|
#include "World/CScriptWater.hpp"
|
||||||
|
#include "TCastTo.hpp"
|
||||||
|
|
||||||
#define kTableSize 2048
|
#define kTableSize 2048
|
||||||
|
|
||||||
|
@ -38,19 +43,20 @@ CFluidPlaneCPU::CTurbulence::CTurbulence(float speed, float distance, float freq
|
||||||
}
|
}
|
||||||
|
|
||||||
CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap,
|
CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap,
|
||||||
ResId envBumpMap, ResId unkMap, float f1, float tileSize, u32 tileSubdivisions,
|
ResId envBumpMap, ResId unkMap, float unitsPerLightmapTexel, float tileSize,
|
||||||
EFluidType fluidType, float alpha, const zeus::CVector3f& bumpLightDir, float bumpScale,
|
u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||||
const CFluidUVMotion& mot, float turbSpeed, float turbDistance, float turbFreqMax,
|
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot,
|
||||||
float turbFreqMin, float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax,
|
float turbSpeed, float turbDistance, float turbFreqMax, float turbFreqMin,
|
||||||
float turbAmplitudeMin, float specularMin, float specularMax, float reflectionBlend,
|
float turbPhaseMax, float turbPhaseMin, float turbAmplitudeMax, float turbAmplitudeMin,
|
||||||
float reflectionSize, float fluidPlaneF2)
|
float specularMin, float specularMax, float reflectionBlend, float reflectionSize,
|
||||||
|
float fluidPlaneF2)
|
||||||
: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot),
|
: CFluidPlane(texPattern1, texPattern2, texColor, alpha, fluidType, fluidPlaneF2, mot),
|
||||||
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(unkMap),
|
xa0_texIdBumpMap(bumpMap), xa4_texIdEnvMap(envMap), xa8_texIdEnvBumpMap(envBumpMap), xac_texId4(unkMap),
|
||||||
xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
|
xf0_bumpLightDir(bumpLightDir), xfc_bumpScale(bumpScale), x100_tileSize(tileSize),
|
||||||
x104_tileSubdivisions(tileSubdivisions & ~0x1),
|
x104_tileSubdivisions(tileSubdivisions & ~0x1),
|
||||||
x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)),
|
x108_rippleResolution(x100_tileSize / float(x104_tileSubdivisions)),
|
||||||
x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend),
|
x10c_specularMin(specularMin), x110_specularMax(specularMax), x114_reflectionBlend(reflectionBlend),
|
||||||
x118_reflectionSize(reflectionSize), x11c_f1(f1),
|
x118_reflectionSize(reflectionSize), x11c_unitsPerLightmapTexel(unitsPerLightmapTexel),
|
||||||
x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
|
x120_turbulence(turbSpeed, turbDistance, turbFreqMax, turbFreqMin, turbPhaseMax,
|
||||||
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin)
|
turbPhaseMin, turbAmplitudeMax, turbAmplitudeMin)
|
||||||
{
|
{
|
||||||
|
@ -61,7 +67,7 @@ CFluidPlaneCPU::CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texCo
|
||||||
if (g_ResFactory->GetResourceTypeById(xa8_texIdEnvBumpMap) == FOURCC('TXTR'))
|
if (g_ResFactory->GetResourceTypeById(xa8_texIdEnvBumpMap) == FOURCC('TXTR'))
|
||||||
xd0_envBumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa8_texIdEnvBumpMap}));
|
xd0_envBumpMap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xa8_texIdEnvBumpMap}));
|
||||||
if (g_ResFactory->GetResourceTypeById(xac_texId4) == FOURCC('TXTR'))
|
if (g_ResFactory->GetResourceTypeById(xac_texId4) == FOURCC('TXTR'))
|
||||||
xe0_tex4.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}));
|
xe0_lightmap.emplace(g_SimplePool->GetObj(SObjectTag{FOURCC('TXTR'), xac_texId4}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
|
void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
|
||||||
|
@ -69,18 +75,228 @@ void CFluidPlaneCPU::CreateRipple(const CRipple& ripple, CStateManager& mgr)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFluidPlaneCPU::RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf,
|
void CFluidPlaneCPU::CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
|
||||||
const zeus::CTransform& areaXf, const zeus::CAABox& aabb, CScriptWater* water) const
|
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const
|
||||||
{
|
{
|
||||||
|
int width = GetLightMap().GetWidth();
|
||||||
|
int height = GetLightMap().GetHeight();
|
||||||
|
|
||||||
|
zeus::CTransform toLocal = areaXf.getRotation().inverse();
|
||||||
|
zeus::CAABox areaLocalAABB = aabb.getTransformedAABox(toLocal);
|
||||||
|
float f26 = (areaLocalAABB.max.x - areaLocalAABB.min.x) / (width * x11c_unitsPerLightmapTexel);
|
||||||
|
float f25 = (areaLocalAABB.max.y - areaLocalAABB.min.y) / (height * x11c_unitsPerLightmapTexel);
|
||||||
|
float f24 = (1.f + std::fmod(areaLocalAABB.min.x + xf.origin.x, x11c_unitsPerLightmapTexel)) / width;
|
||||||
|
float f23 = (2.f - std::fmod(areaLocalAABB.max.x + xf.origin.x, x11c_unitsPerLightmapTexel)) / width;
|
||||||
|
float f29 = (1.f + std::fmod(areaLocalAABB.min.y + xf.origin.y, x11c_unitsPerLightmapTexel)) / height;
|
||||||
|
float f6 = (2.f - std::fmod(areaLocalAABB.max.y + xf.origin.y, x11c_unitsPerLightmapTexel)) / height;
|
||||||
|
|
||||||
|
float scaleX = (f26 - f24 - f23) / (areaLocalAABB.max.x - areaLocalAABB.min.x);
|
||||||
|
float scaleY = -(f25 - f29 - f6) / (areaLocalAABB.max.y - areaLocalAABB.min.y);
|
||||||
|
float offX = f24 + f26 * -areaLocalAABB.min.x / (areaLocalAABB.max.x - areaLocalAABB.min.x);
|
||||||
|
float offY = f25 * areaLocalAABB.min.y / (areaLocalAABB.max.y - areaLocalAABB.min.y) - f6;
|
||||||
|
mtxOut = (zeus::CTransform(zeus::CMatrix3f(zeus::CVector3f(scaleX, scaleY, 0.f)),
|
||||||
|
zeus::CVector3f(offX, offY, 0.f)) * toLocal).toMatrix4f();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFluidPlaneCPU::Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
#define kEnableWaterBumpMaps true
|
||||||
|
|
||||||
|
CFluidPlaneCPU::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;
|
||||||
|
|
||||||
|
float uvT = mgr.GetFluidPlaneManager()->GetUVT();
|
||||||
|
bool hasBumpMap = HasBumpMap() && kEnableWaterBumpMaps;
|
||||||
|
bool doubleLightmapBlend = false;
|
||||||
|
bool hasEnvMap = mgr.GetCameraManager()->GetFluidCounter() == 0 && HasEnvMap();
|
||||||
|
bool hasEnvBumpMap = HasEnvBumpMap();
|
||||||
|
CGraphics::SetModelMatrix(xf);
|
||||||
|
|
||||||
|
if (hasBumpMap)
|
||||||
|
{
|
||||||
|
// Build 50% grey directional light with xf0_bumpLightDir and load into LIGHT_3
|
||||||
|
// Light 3 in channel 1
|
||||||
|
// Vertex colors in channel 0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Normal light mask in channel 1
|
||||||
|
// Vertex colors in channel 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x10_texPattern1)
|
||||||
|
{
|
||||||
|
// Load into 0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load black tex into 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x20_texPattern2)
|
||||||
|
{
|
||||||
|
// Load into 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load black tex into 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x30_texColor)
|
||||||
|
{
|
||||||
|
// Load into 2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Load black tex into 2
|
||||||
|
}
|
||||||
|
|
||||||
|
int curTex = 3;
|
||||||
|
int bumpMapId;
|
||||||
|
int envMapId;
|
||||||
|
int envBumpMapId;
|
||||||
|
int lightmapId;
|
||||||
|
|
||||||
|
if (hasBumpMap)
|
||||||
|
{
|
||||||
|
// Load into next
|
||||||
|
bumpMapId = curTex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasEnvMap)
|
||||||
|
{
|
||||||
|
// Load into next
|
||||||
|
envMapId = curTex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
// Load into next
|
||||||
|
envBumpMapId = curTex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
|
||||||
|
// Load normal mtx 0 with
|
||||||
|
out.normMtx =
|
||||||
|
(zeus::CTransform::Scale(xfc_bumpScale) * CGraphics::g_ViewMatrix.getRotation().inverse()).toMatrix4f();
|
||||||
|
|
||||||
|
// Setup TCGs
|
||||||
|
int nextTexMtx = 3;
|
||||||
|
|
||||||
|
if (hasEnvBumpMap)
|
||||||
|
{
|
||||||
|
float pttScale;
|
||||||
|
if (hasEnvMap)
|
||||||
|
pttScale = 0.5f * (1.f - x118_reflectionSize);
|
||||||
|
else
|
||||||
|
pttScale = g_tweakGame->GetFluidEnvBumpScale() * x4c_uvMotion.GetFluidLayers()[0].GetUVScale();
|
||||||
|
|
||||||
|
// Load GX_TEXMTX3 with identity
|
||||||
|
zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++];
|
||||||
|
// Load GX_PTTEXMTX0 with scale of pttScale
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_NRM, GX_TEXMTX3, true, GX_PTTEXMTX0
|
||||||
|
|
||||||
|
out.indScale = 0.5f * (hasEnvMap ? x118_reflectionSize : 1.f);
|
||||||
|
// Load ind mtx with scale of (indScale, -indScale)
|
||||||
|
// Load envBumpMap into ind stage 0 with previous TCG
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasEnvMap)
|
||||||
|
{
|
||||||
|
float scale = std::max(aabb.max.x - aabb.min.x, aabb.max.y - aabb.min.y);
|
||||||
|
zeus::CMatrix4f& texMtx = out.texMtxs[nextTexMtx++];
|
||||||
|
texMtx[0][0] = texMtx[1][1] = 1.f / scale;
|
||||||
|
zeus::CVector3f center = aabb.center();
|
||||||
|
texMtx[3][0] = 0.5f + -center.x / scale;
|
||||||
|
texMtx[3][1] = 0.5f + -center.y / scale;
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasLightMap())
|
||||||
|
{
|
||||||
|
float lowLightBlend = 1.f;
|
||||||
|
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId());
|
||||||
|
float lightLevel = area->GetPostConstructed()->x1128_worldLightingLevel;
|
||||||
|
const CScriptWater* nextWater = water->GetNextConnectedWater(mgr);
|
||||||
|
if (std::fabs(water->GetLightmapDoubleBlendFactor()) < 0.00001f || !nextWater ||
|
||||||
|
!nextWater->GetFluidPlane().HasLightMap())
|
||||||
|
{
|
||||||
|
lightmapId = curTex;
|
||||||
|
// Load lightmap
|
||||||
|
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||||
|
}
|
||||||
|
else if (nextWater && nextWater->GetFluidPlane().HasLightMap())
|
||||||
|
{
|
||||||
|
if (std::fabs(water->GetLightmapDoubleBlendFactor() - 1.f) < 0.00001f)
|
||||||
|
{
|
||||||
|
lightmapId = curTex;
|
||||||
|
// Load lightmap
|
||||||
|
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lightmapId = curTex;
|
||||||
|
// Load lightmap
|
||||||
|
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||||
|
// Load lightmap
|
||||||
|
CalculateLightmapMatrix(areaXf, xf, aabb, out.texMtxs[nextTexMtx++]);
|
||||||
|
// Next: GX_TG_MTX2x4 GX_TG_POS, mtxNext, false, GX_PTIDENTITY
|
||||||
|
|
||||||
|
float lum = lightLevel * water->GetLightmapDoubleBlendFactor();
|
||||||
|
out.kColors[3] = zeus::CColor(lum, 1.f);
|
||||||
|
lowLightBlend = (1.f - water->GetLightmapDoubleBlendFactor()) / (1.f - lum);
|
||||||
|
doubleLightmapBlend = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.kColors[2] = zeus::CColor(lowLightBlend * lightLevel, 1.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float waterPlaneOrthoDot = xf.transposeRotate(zeus::CVector3f::skUp).
|
||||||
|
dot(CGraphics::g_ViewMatrix.inverse().transposeRotate(zeus::CVector3f::skForward));
|
||||||
|
if (waterPlaneOrthoDot < 0.f)
|
||||||
|
waterPlaneOrthoDot = -waterPlaneOrthoDot;
|
||||||
|
|
||||||
|
out.kColors[0] =
|
||||||
|
zeus::CColor((1.f - waterPlaneOrthoDot) * (x110_specularMax - x10c_specularMin) + x10c_specularMin, alpha);
|
||||||
|
out.kColors[1] = zeus::CColor(x114_reflectionBlend, 1.f);
|
||||||
|
|
||||||
|
// TODO: Detect parameter changes and rebuild if needed
|
||||||
|
if (!m_shader)
|
||||||
|
m_shader.emplace(x44_fluidType,
|
||||||
|
x10_texPattern1, x20_texPattern2, x30_texColor, xb0_bumpMap, xc0_envMap, xd0_envBumpMap,
|
||||||
|
xe0_lightmap, doubleLightmapBlend, mgr.GetParticleFlags() == 0);
|
||||||
|
out.lights = water->GetActorLights()->BuildLightVector();
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFluidPlaneCPU::Render(const CStateManager& mgr, float alpha, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
||||||
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const
|
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());
|
||||||
|
m_shader->draw(setupInfo.texMtxs, setupInfo.normMtx, setupInfo.indScale, setupInfo.lights, setupInfo.kColors);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFluidPlaneCPU::RenderCleanup() const
|
void CFluidPlaneCPU::RenderCleanup() const
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "CFluidPlane.hpp"
|
#include "CFluidPlane.hpp"
|
||||||
#include "CRipple.hpp"
|
#include "CRipple.hpp"
|
||||||
|
#include "Graphics/Shaders/CFluidPlaneShader.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -41,7 +42,7 @@ class CFluidPlaneCPU : public CFluidPlane
|
||||||
std::experimental::optional<TLockedToken<CTexture>> xb0_bumpMap;
|
std::experimental::optional<TLockedToken<CTexture>> xb0_bumpMap;
|
||||||
std::experimental::optional<TLockedToken<CTexture>> xc0_envMap;
|
std::experimental::optional<TLockedToken<CTexture>> xc0_envMap;
|
||||||
std::experimental::optional<TLockedToken<CTexture>> xd0_envBumpMap;
|
std::experimental::optional<TLockedToken<CTexture>> xd0_envBumpMap;
|
||||||
std::experimental::optional<TLockedToken<CTexture>> xe0_tex4;
|
std::experimental::optional<TLockedToken<CTexture>> xe0_lightmap;
|
||||||
zeus::CVector3f xf0_bumpLightDir;
|
zeus::CVector3f xf0_bumpLightDir;
|
||||||
float xfc_bumpScale;
|
float xfc_bumpScale;
|
||||||
float x100_tileSize;
|
float x100_tileSize;
|
||||||
|
@ -51,19 +52,32 @@ class CFluidPlaneCPU : public CFluidPlane
|
||||||
float x110_specularMax;
|
float x110_specularMax;
|
||||||
float x114_reflectionBlend;
|
float x114_reflectionBlend;
|
||||||
float x118_reflectionSize;
|
float x118_reflectionSize;
|
||||||
float x11c_f1;
|
float x11c_unitsPerLightmapTexel;
|
||||||
CTurbulence x120_turbulence;
|
CTurbulence x120_turbulence;
|
||||||
|
mutable std::experimental::optional<CFluidPlaneShader> m_shader;
|
||||||
|
|
||||||
|
struct RenderSetupInfo
|
||||||
|
{
|
||||||
|
zeus::CMatrix4f texMtxs[6];
|
||||||
|
zeus::CMatrix4f normMtx;
|
||||||
|
float indScale = 1.f;
|
||||||
|
zeus::CColor kColors[4];
|
||||||
|
std::vector<CLight> lights;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap,
|
CFluidPlaneCPU(ResId texPattern1, ResId texPattern2, ResId texColor, ResId bumpMap, ResId envMap, ResId envBumpMap,
|
||||||
ResId unkMap, float f1, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
ResId unkMap, float unitsPerLightmapTexel, float tileSize, u32 tileSubdivisions, EFluidType fluidType, float alpha,
|
||||||
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot, float turbSpeed,
|
const zeus::CVector3f& bumpLightDir, float bumpScale, const CFluidUVMotion& mot, float turbSpeed,
|
||||||
float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin,
|
float turbDistance, float turbFreqMax, float turbFreqMin, float turbPhaseMax, float turbPhaseMin,
|
||||||
float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax,
|
float turbAmplitudeMax, float turbAmplitudeMin, float specularMin, float specularMax,
|
||||||
float reflectionBlend, float reflectionSize, float fluidPlaneF2);
|
float reflectionBlend, float reflectionSize, float fluidPlaneF2);
|
||||||
void CreateRipple(const CRipple& ripple, CStateManager& mgr);
|
void CreateRipple(const CRipple& ripple, CStateManager& mgr);
|
||||||
void RenderSetup(const CStateManager& mgr, float, const zeus::CTransform& xf, const zeus::CTransform& areaXf,
|
void CalculateLightmapMatrix(const zeus::CTransform& areaXf, const zeus::CTransform& xf,
|
||||||
const zeus::CAABox& aabb, CScriptWater* water) const;
|
const zeus::CAABox& aabb, zeus::CMatrix4f& mtxOut) const;
|
||||||
void Render(const CStateManager& mgr, const zeus::CAABox& aabb, const zeus::CTransform& xf,
|
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 noSubdiv, const zeus::CFrustum& frustum,
|
const zeus::CTransform& areaXf, bool noSubdiv, const zeus::CFrustum& frustum,
|
||||||
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
const std::experimental::optional<CRippleManager>& rippleManager, TUniqueId waterId,
|
||||||
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
|
const bool* gridFlags, u32 gridDimX, u32 gridDimY, const zeus::CVector3f& areaCenter) const;
|
||||||
|
@ -79,6 +93,8 @@ public:
|
||||||
const CTexture& GetEnvMap() const { return **xc0_envMap; }
|
const CTexture& GetEnvMap() const { return **xc0_envMap; }
|
||||||
bool HasEnvBumpMap() const { return xd0_envBumpMap.operator bool(); }
|
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 zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; }
|
const zeus::CVector3f& GetBumpLightDir() const { return xf0_bumpLightDir; }
|
||||||
float GetTileSize() const { return x100_tileSize; }
|
float GetTileSize() const { return x100_tileSize; }
|
||||||
u32 GetTileSubdivisions() const { return x104_tileSubdivisions; }
|
u32 GetTileSubdivisions() const { return x104_tileSubdivisions; }
|
||||||
|
|
|
@ -8,7 +8,8 @@ CFluidPlaneManager::CFluidProfile CFluidPlaneManager::sProfile = {};
|
||||||
CFluidPlaneManager::CFluidPlaneManager()
|
CFluidPlaneManager::CFluidPlaneManager()
|
||||||
: x0_rippleManager(20, 0.5f)
|
: x0_rippleManager(20, 0.5f)
|
||||||
{
|
{
|
||||||
|
sProfile.Clear();
|
||||||
|
SetupRippleMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFluidPlaneManager::CFluidProfile::Clear()
|
void CFluidPlaneManager::CFluidProfile::Clear()
|
||||||
|
@ -43,4 +44,56 @@ void CFluidPlaneManager::CreateSplash(TUniqueId splasher, CStateManager& mgr, co
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 CFluidPlaneManager::RippleValues[64][64] = {};
|
||||||
|
u8 CFluidPlaneManager::RippleMins[64] = {};
|
||||||
|
u8 CFluidPlaneManager::RippleMaxs[64] = {};
|
||||||
|
|
||||||
|
void CFluidPlaneManager::SetupRippleMap()
|
||||||
|
{
|
||||||
|
float curX = 0.f;
|
||||||
|
for (int i=0 ; i<64 ; ++i)
|
||||||
|
{
|
||||||
|
float curY = 0.f;
|
||||||
|
float minY = 1.f;
|
||||||
|
float maxY = 0.f;
|
||||||
|
for (int j=0 ; j<64 ; ++j)
|
||||||
|
{
|
||||||
|
float rVal = 1.f - curY;
|
||||||
|
float minX = curY;
|
||||||
|
float maxX = 1.25f * (0.25f * rVal + 0.1f) + curY;
|
||||||
|
if (curY < 0.f)
|
||||||
|
minX = 0.f;
|
||||||
|
else if (maxX > 1.f)
|
||||||
|
maxX = 1.f;
|
||||||
|
|
||||||
|
float val = 0.f;
|
||||||
|
if (curX >= minX && curX <= maxX)
|
||||||
|
{
|
||||||
|
float t = (curX - minX) / (maxX - minX);
|
||||||
|
if (t < 0.4f)
|
||||||
|
val = 2.5f * t;
|
||||||
|
else if (t > 0.75f)
|
||||||
|
val = 4.f * (1.f - t);
|
||||||
|
else
|
||||||
|
val = 1.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto valA = u8(std::max(int(255.f * val * rVal * rVal) - 1, 0));
|
||||||
|
RippleValues[i][j] = valA;
|
||||||
|
if (valA != 0 && curY < minY)
|
||||||
|
minY = curY;
|
||||||
|
if (valA != 0 && curY > maxY)
|
||||||
|
maxY = curY;
|
||||||
|
|
||||||
|
curY += (1.f / 63.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto valB = u8(std::max(int(255.f * minY) - 1, 0));
|
||||||
|
auto valC = u8(std::min(int(255.f * maxY) + 1, 255));
|
||||||
|
RippleMins[i] = valB;
|
||||||
|
RippleMaxs[i] = valC;
|
||||||
|
curX += (1.f / 63.f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,23 +11,43 @@ class CScriptWater;
|
||||||
|
|
||||||
class CFluidPlaneManager
|
class CFluidPlaneManager
|
||||||
{
|
{
|
||||||
|
class CSplashRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CSplashRecord(TUniqueId id);
|
||||||
|
void SetTime(float t);
|
||||||
|
float GetTime() const;
|
||||||
|
TUniqueId GetUniqueId() const;
|
||||||
|
};
|
||||||
|
|
||||||
CRippleManager x0_rippleManager;
|
CRippleManager x0_rippleManager;
|
||||||
bool x121_;
|
rstl::reserved_vector<CSplashRecord, 32> x18_splashes;
|
||||||
|
float x11c_uvT = 0.f;
|
||||||
|
bool x120_ = false;
|
||||||
|
bool x121_ = false;
|
||||||
|
|
||||||
class CFluidProfile
|
class CFluidProfile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Clear();
|
void Clear();
|
||||||
};
|
};
|
||||||
static CFluidProfile sProfile;
|
static CFluidProfile sProfile;
|
||||||
|
static void SetupRippleMap();
|
||||||
public:
|
public:
|
||||||
|
static u8 RippleValues[64][64];
|
||||||
|
static u8 RippleMins[64];
|
||||||
|
static u8 RippleMaxs[64];
|
||||||
|
|
||||||
CFluidPlaneManager();
|
CFluidPlaneManager();
|
||||||
void StartFrame(bool);
|
void StartFrame(bool);
|
||||||
void EndFrame() { x121_ = false; }
|
void EndFrame() { x121_ = false; }
|
||||||
void Update(float dt);
|
void Update(float dt);
|
||||||
|
float GetUVT() const { return x11c_uvT; }
|
||||||
float GetLastRippleDeltaTime(TUniqueId rippler) const;
|
float GetLastRippleDeltaTime(TUniqueId rippler) const;
|
||||||
float GetLastSplashDeltaTime(TUniqueId splasher) const;
|
float GetLastSplashDeltaTime(TUniqueId splasher) const;
|
||||||
void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
|
void CreateSplash(TUniqueId splasher, CStateManager& mgr, const CScriptWater& water,
|
||||||
const zeus::CVector3f& pos, float factor, bool);
|
const zeus::CVector3f& pos, float factor, bool);
|
||||||
|
rstl::reserved_vector<CSplashRecord, 32>& SplashRecords() { return x18_splashes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ CFluidUVMotion::CFluidUVMotion(float a, float b, const CFluidUVMotion::SFluidLay
|
||||||
CFluidUVMotion::CFluidUVMotion(float, float)
|
CFluidUVMotion::CFluidUVMotion(float, float)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2])
|
void CFluidUVMotion::CalculateFluidTextureOffset(float f31, float offsets[3][2]) const
|
||||||
{
|
{
|
||||||
float f28 = (f31 * x4c_) * zeus::fastCosF(x50_);
|
float f28 = (f31 * x4c_) * zeus::fastCosF(x50_);
|
||||||
float f29 = (f31 * x4c_) / zeus::fastSinF(x50_);
|
float f29 = (f31 * x4c_) / zeus::fastSinF(x50_);
|
||||||
|
|
|
@ -22,14 +22,16 @@ public:
|
||||||
float x4_a = 0.16666667f;
|
float x4_a = 0.16666667f;
|
||||||
float x8_b = 0.f;
|
float x8_b = 0.f;
|
||||||
float xc_c = 1.f;
|
float xc_c = 1.f;
|
||||||
float x10_d = 5.f;
|
float x10_uvMul = 5.f;
|
||||||
float x14_envNormalScale = 0.2f;
|
float x14_uvScale = 0.2f;
|
||||||
|
|
||||||
SFluidLayerMotion() = default;
|
SFluidLayerMotion() = default;
|
||||||
SFluidLayerMotion(EFluidUVMotion motion, float a, float b, float c, float d)
|
SFluidLayerMotion(EFluidUVMotion motion, float a, float b, float c, float uvMul)
|
||||||
: x0_motion(motion), x4_a(1.f / a), x8_b(b), xc_c(c), x10_d(d), x14_envNormalScale(1.f / d)
|
: x0_motion(motion), x4_a(1.f / a), x8_b(b), xc_c(c), x10_uvMul(uvMul), x14_uvScale(1.f / uvMul)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float GetUVScale() const { return x14_uvScale; }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -43,7 +45,7 @@ public:
|
||||||
const rstl::reserved_vector<SFluidLayerMotion, 3>& GetFluidLayers() const { return x0_fluidLayers; }
|
const rstl::reserved_vector<SFluidLayerMotion, 3>& GetFluidLayers() const { return x0_fluidLayers; }
|
||||||
void GetOrientation() const;
|
void GetOrientation() const;
|
||||||
void GetOOTimeToWrapTexPage() const;
|
void GetOOTimeToWrapTexPage() const;
|
||||||
void CalculateFluidTextureOffset(float, float[3][2]);
|
void CalculateFluidTextureOffset(float, float[3][2]) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // __URDE_CFLUIDUVMOTION_HPP__
|
#endif // __URDE_CFLUIDUVMOTION_HPP__
|
||||||
|
|
|
@ -252,7 +252,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
|
||||||
zeus::CVector3f position = x34_transform.origin + posOffset;
|
zeus::CVector3f position = x34_transform.origin + posOffset;
|
||||||
position.z = water.GetTriggerBoundsWR().max.z;
|
position.z = water.GetTriggerBoundsWR().max.z;
|
||||||
mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true);
|
mgr.GetFluidPlaneManager()->CreateSplash(x8_uid, mgr, water, position, 0.3f, true);
|
||||||
if (water.GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::Zero)
|
if (water.GetFluidPlane().GetFluidType() == CFluidPlane::EFluidType::NormalWater)
|
||||||
{
|
{
|
||||||
float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f;
|
float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f;
|
||||||
mgr.GetEnvFxManager()->SetXB54(10.f * std::max(1.f, velMag));
|
mgr.GetEnvFxManager()->SetXB54(10.f * std::max(1.f, velMag));
|
||||||
|
@ -1710,14 +1710,14 @@ void CPlayer::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CState
|
||||||
{
|
{
|
||||||
switch (water->GetFluidPlane().GetFluidType())
|
switch (water->GetFluidPlane().GetFluidType())
|
||||||
{
|
{
|
||||||
case CFluidPlane::EFluidType::Zero:
|
case CFluidPlane::EFluidType::NormalWater:
|
||||||
x2b0_ = 0;
|
x2b0_ = 0;
|
||||||
break;
|
break;
|
||||||
case CFluidPlane::EFluidType::Two:
|
case CFluidPlane::EFluidType::Lava:
|
||||||
case CFluidPlane::EFluidType::Five:
|
case CFluidPlane::EFluidType::Five:
|
||||||
x2ac_surfaceRestraint = ESurfaceRestraints::Fluid2Or5;
|
x2ac_surfaceRestraint = ESurfaceRestraints::Fluid2Or5;
|
||||||
break;
|
break;
|
||||||
case CFluidPlane::EFluidType::One:
|
case CFluidPlane::EFluidType::PoisonWater:
|
||||||
x2b0_ = 0;
|
x2b0_ = 0;
|
||||||
break;
|
break;
|
||||||
case CFluidPlane::EFluidType::Three:
|
case CFluidPlane::EFluidType::Three:
|
||||||
|
@ -4399,7 +4399,7 @@ void CPlayer::UpdateSubmerged(CStateManager& mgr)
|
||||||
x828_waterLevelOnPlayer =
|
x828_waterLevelOnPlayer =
|
||||||
-(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z);
|
-(zeus::CVector3f::skUp.dot(x34_transform.origin) - water->GetTriggerBoundsWR().max.z);
|
||||||
CFluidPlane::EFluidType fluidType = water->GetFluidPlane().GetFluidType();
|
CFluidPlane::EFluidType fluidType = water->GetFluidPlane().GetFluidType();
|
||||||
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Two || fluidType == CFluidPlane::EFluidType::Five);
|
x82c_inLava = (fluidType == CFluidPlane::EFluidType::Lava || fluidType == CFluidPlane::EFluidType::Five);
|
||||||
CheckSubmerged();
|
CheckSubmerged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include "CScriptWater.hpp"
|
#include "CScriptWater.hpp"
|
||||||
#include "CStateManager.hpp"
|
#include "CStateManager.hpp"
|
||||||
|
#include "TCastTo.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -87,4 +88,18 @@ u32 CScriptWater::GetSplashIndex(float dt) const
|
||||||
u32 idx = dt * 3.f;
|
u32 idx = dt * 3.f;
|
||||||
return (idx < 3 ? idx : idx - 1);
|
return (idx < 3 ? idx : idx - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CScriptWater* CScriptWater::GetNextConnectedWater(const CStateManager& mgr) const
|
||||||
|
{
|
||||||
|
for (const SConnection& conn : x20_conns)
|
||||||
|
{
|
||||||
|
if (conn.x0_state != EScriptObjectState::Play || conn.x4_msg != EScriptObjectMessage::Activate)
|
||||||
|
continue;
|
||||||
|
auto its = mgr.GetIdListForScript(conn.x8_objId);
|
||||||
|
if (its.first != mgr.GetIdListEnd())
|
||||||
|
if (TCastToConstPtr<CScriptWater> water = mgr.GetObjectById(its.first->second))
|
||||||
|
return water.GetPtr();
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ private:
|
||||||
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
|
std::unique_ptr<CFluidPlaneCPU> x1b4_fluidPlane;
|
||||||
zeus::CVector3f x1b8_;
|
zeus::CVector3f x1b8_;
|
||||||
float x1f4_;
|
float x1f4_;
|
||||||
float x1f8_ = 0.f;
|
float x1f8_lightmapDoubleBlendFactor = 0.f;
|
||||||
zeus::CVector3f x1d4_;
|
zeus::CVector3f x1d4_;
|
||||||
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
|
std::list<std::pair<TUniqueId, bool>> x1fc_waterInhabitants;
|
||||||
u32 x210_;
|
u32 x210_;
|
||||||
|
@ -97,6 +97,8 @@ public:
|
||||||
const std::experimental::optional<TLockedToken<CGenDescription>>& GetVisorRunoffEffect() const
|
const std::experimental::optional<TLockedToken<CGenDescription>>& GetVisorRunoffEffect() const
|
||||||
{ return x250_visorRunoffEffect; }
|
{ return x250_visorRunoffEffect; }
|
||||||
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
|
u16 GetVisorRunoffSfx() const { return x262_visorRunoffSfx; }
|
||||||
|
const CScriptWater* GetNextConnectedWater(const CStateManager& mgr) const;
|
||||||
|
float GetLightmapDoubleBlendFactor() const { return x1f8_lightmapDoubleBlendFactor; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue