Initially working CEnvFxManager

This commit is contained in:
Jack Andersen 2018-11-01 22:16:16 -10:00
parent 93e9e2f6f1
commit 98c7525176
28 changed files with 1179 additions and 77 deletions

View File

@ -33,6 +33,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn,
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
if (force || cmdlPath.isNone())
{
cmdlPath.makeDirChain(false);
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
return false;
@ -70,6 +71,7 @@ bool ReadANCSToBlender(hecl::blender::Connection& conn,
hecl::ProjectPath cmdlPath = pakRouter.getWorking(cmdlE);
if (force || cmdlPath.isNone())
{
cmdlPath.makeDirChain(false);
if (!conn.createBlend(cmdlPath, hecl::blender::BlendType::Mesh))
return false;

View File

@ -652,6 +652,7 @@ atUint32 ReadGeomSectionsToBlender(hecl::blender::PyOutStream& os,
{
MaterialSet matSet;
matSet.read(reader);
matSet.ensureTexturesExtracted(pakRouter);
GetVertexAttributes(matSet, vertAttribs);
}
}

View File

@ -23,6 +23,25 @@ struct MaterialSet : BigDNA
void addTexture(const UniqueID32& id) {textureIDs.push_back(id); ++textureCount;}
void addMaterialEndOff(atUint32 off) {materialEndOffs.push_back(off); ++materialCount;}
template <class PAKBRIDGE>
void ensureTexturesExtracted(PAKRouter<PAKBRIDGE>& pakRouter) const
{
for (const auto& id : textureIDs)
{
const nod::Node* node;
const PAK::Entry* texEntry = pakRouter.lookupEntry(id, &node);
if (!texEntry)
continue;
hecl::ProjectPath txtrPath = pakRouter.getWorking(texEntry);
if (txtrPath.isNone())
{
txtrPath.makeDirChain(false);
PAKEntryReadStream rs = texEntry->beginReadStream(*node);
TXTR::Extract(rs, txtrPath);
}
}
}
} head;
struct Material : BigDNA
@ -352,6 +371,10 @@ struct MaterialSet : BigDNA
}
}
void ensureTexturesExtracted(PAKRouter<PAKBridge>& pakRouter) const
{
head.ensureTexturesExtracted(pakRouter);
}
};
struct HMDLMaterialSet : BigDNA

View File

@ -71,6 +71,11 @@ struct MaterialSet : BigDNA
{
DNACMDL::ReadMaterialSetToBlender_1_2(os, *this, pakRouter, entry, setIdx);
}
void ensureTexturesExtracted(PAKRouter<PAKBridge>& pakRouter) const
{
head.ensureTexturesExtracted(pakRouter);
}
};
}

View File

@ -198,6 +198,8 @@ struct MaterialSet : BigDNA
{
DNACMDL::ReadMaterialSetToBlender_3(os, *this, pakRouter, entry, setIdx);
}
void ensureTexturesExtracted(PAKRouter<PAKBridge>& pakRouter) const {}
};
}

View File

@ -3,8 +3,8 @@
namespace urde
{
static TLockedToken<std::vector<s16>> mpSfxTranslationTableTok;
std::vector<s16>* CSfxManager::mpSfxTranslationTable = nullptr;
static TLockedToken<std::vector<u16>> mpSfxTranslationTableTok;
std::vector<u16>* CSfxManager::mpSfxTranslationTable = nullptr;
static amuse::EffectReverbHiInfo s_ReverbHiQueued;
static amuse::EffectChorusInfo s_ChorusQueued;
@ -20,12 +20,12 @@ CFactoryFnReturn FAudioTranslationTableFactory(const SObjectTag& tag, CInputStre
const CVParamTransfer& vparms,
CObjectReference* selfRef)
{
std::unique_ptr<std::vector<s16>> obj = std::make_unique<std::vector<s16>>();
std::unique_ptr<std::vector<u16>> obj = std::make_unique<std::vector<u16>>();
u32 count = in.readUint32Big();
obj->reserve(count);
for (u32 i=0 ; i<count ; ++i)
obj->push_back(in.readUint16Big());
return TToken<std::vector<s16>>::GetIObjObjectFor(std::move(obj));
return TToken<std::vector<u16>>::GetIObjObjectFor(std::move(obj));
}
CSfxManager::CSfxChannel CSfxManager::m_channels[4];
@ -379,8 +379,8 @@ u16 CSfxManager::TranslateSFXID(u16 id)
if (index >= mpSfxTranslationTable->size())
return 0;
s16 ret = mpSfxTranslationTable->at(index);
if (ret == -1)
u16 ret = (*mpSfxTranslationTable)[index];
if (ret == 0xffff)
return 0;
return ret;
}
@ -747,7 +747,7 @@ void CSfxManager::Update(float dt)
void CSfxManager::Shutdown()
{
mpSfxTranslationTable = nullptr;
mpSfxTranslationTableTok = TLockedToken<std::vector<s16>>{};
mpSfxTranslationTableTok = TLockedToken<std::vector<u16>>{};
StopAndRemoveAllEmitters();
DisableAuxCallback();
}

View File

@ -11,7 +11,7 @@ namespace urde
class CSfxManager
{
static std::vector<s16>* mpSfxTranslationTable;
static std::vector<u16>* mpSfxTranslationTable;
public:
enum class ESfxChannels

View File

@ -2434,9 +2434,6 @@ void CStateManager::SetCurrentAreaId(TAreaId aid)
x850_world->GetMapWorld()->RecalculateWorldSphere(*x8c0_mapWorldInfo, *x850_world);
}
CEntity* CStateManager::ObjectById(TUniqueId uid) { return GetAllObjectList().GetObjectById(uid); }
const CEntity* CStateManager::GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); }
void CStateManager::AreaUnloaded(TAreaId)
{
// Intentionally empty

View File

@ -361,8 +361,8 @@ public:
void UpdateRoomAcoustics(TAreaId);
TAreaId GetNextAreaId() const { return x8cc_nextAreaId; }
void SetCurrentAreaId(TAreaId);
CEntity* ObjectById(TUniqueId uid);
const CEntity* GetObjectById(TUniqueId uid) const;
CEntity* ObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); }
const CEntity* GetObjectById(TUniqueId uid) const { return GetAllObjectList().GetObjectById(uid); }
void AreaUnloaded(TAreaId);
void PrepareAreaUnload(TAreaId);
void AreaLoaded(TAreaId);

View File

@ -1067,7 +1067,7 @@ void CBooRenderer::AddPlaneObject(const void* obj, const zeus::CAABox& aabb, con
float farDist = xb0_viewPlane.pointToPlaneDist(farPoint);
if (closeDist >= 0.f || farDist >= 0.f)
{
bool zOnly = plane.normal().isZero();
bool zOnly = plane.normal() == zeus::CVector3f::skUp;
bool invert;
if (zOnly)
invert = CGraphics::g_ViewMatrix.origin.z >= plane.d;

View File

@ -9,8 +9,8 @@ enum class EDrawableType : u16
{
WorldSurface,
Particle,
UnsortedCallback,
SortedCallback,
Actor,
SimpleShadow,
Decal
};

View File

@ -43,6 +43,7 @@ set(GRAPHICS_SOURCES
Shaders/CParticleSwooshShaders.hpp Shaders/CParticleSwooshShaders.cpp
Shaders/CFluidPlaneShader.hpp Shaders/CFluidPlaneShader.cpp
Shaders/CAABoxShader.hpp Shaders/CAABoxShader.cpp
Shaders/CWorldShadowShader.hpp Shaders/CWorldShadowShader.cpp)
Shaders/CWorldShadowShader.hpp Shaders/CWorldShadowShader.cpp
Shaders/CEnvFxShaders.hpp Shaders/CEnvFxShaders.cpp)
runtime_add_list(Graphics GRAPHICS_SOURCES)

View File

@ -170,7 +170,7 @@ void CRainSplashGenerator::Update(float dt, CStateManager& mgr)
EEnvFxType neededFx = mgr.GetWorld()->GetNeededEnvFx();
x28_dt = dt;
x48_25_raining = false;
if (neededFx != EEnvFxType::None && mgr.GetEnvFxManager()->GetX24() &&
if (neededFx != EEnvFxType::None && mgr.GetEnvFxManager()->IsSplashActive() &&
mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f && neededFx == EEnvFxType::Rain)
{
UpdateRainSplashes(mgr, mgr.GetEnvFxManager()->GetRainMagnitude(), dt);

View File

@ -0,0 +1,45 @@
#include "CEnvFxShaders.hpp"
#include "hecl/Pipeline.hpp"
#include "World/CEnvFxManager.hpp"
namespace urde
{
boo::ObjToken<boo::IShaderPipeline> CEnvFxShaders::m_snowPipeline;
boo::ObjToken<boo::IShaderPipeline> CEnvFxShaders::m_underwaterPipeline;
void CEnvFxShaders::Initialize()
{
m_snowPipeline = hecl::conv->convert(Shader_CEnvFxSnowShader{});
m_underwaterPipeline = hecl::conv->convert(Shader_CEnvFxUnderwaterShader{});
}
void CEnvFxShaders::Shutdown()
{
m_snowPipeline.reset();
m_underwaterPipeline.reset();
}
void CEnvFxShaders::BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid)
{
auto uBufInfo = grid.m_uniformBuf.getBufferInfo();
auto iBufInfo = grid.m_instBuf.getBufferInfo();
boo::ObjToken<boo::IGraphicsBuffer> uniforms[] = {uBufInfo.first.get(),
fxMgr.m_fogUniformBuf.get()};
size_t ubufOffsets[] = {uBufInfo.second, 0};
size_t ubufSizes[] = {256, 256};
boo::PipelineStage uniformStages[] = {boo::PipelineStage::Vertex, boo::PipelineStage::Fragment};
boo::ObjToken<boo::ITexture> textures[] = {fxMgr.xb74_txtrSnowFlake->GetBooTexture(),
fxMgr.x40_txtrEnvGradient->GetBooTexture()};
grid.m_snowBinding = ctx.newShaderDataBinding(m_snowPipeline, nullptr,
iBufInfo.first.get(), nullptr, 2, uniforms,
uniformStages, ubufOffsets, ubufSizes,
2, textures, nullptr, nullptr, 0, iBufInfo.second);
textures[0] = fxMgr.xc48_underwaterFlake->GetBooTexture();
grid.m_underwaterBinding = ctx.newShaderDataBinding(m_underwaterPipeline, nullptr,
iBufInfo.first.get(), nullptr, 2, uniforms,
uniformStages, ubufOffsets, ubufSizes,
2, textures, nullptr, nullptr, 0, iBufInfo.second);
}
}

View File

@ -0,0 +1,38 @@
#pragma once
#include "Graphics/CGraphics.hpp"
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace urde
{
class CEnvFxManager;
class CEnvFxManagerGrid;
class CEnvFxShaders
{
public:
struct Instance
{
zeus::CVector3f positions[4];
zeus::CColor color;
zeus::CVector2f uvs[4];
};
struct Uniform
{
zeus::CMatrix4f mvp;
zeus::CMatrix4f envMtx;
zeus::CColor moduColor;
};
private:
static boo::ObjToken<boo::IShaderPipeline> m_snowPipeline;
static boo::ObjToken<boo::IShaderPipeline> m_underwaterPipeline;
public:
static void Initialize();
static void Shutdown();
static void BuildShaderDataBinding(boo::IGraphicsDataFactory::Context& ctx,
CEnvFxManager& fxMgr, CEnvFxManagerGrid& grid);
};
}

View File

@ -18,6 +18,7 @@
#include "Graphics/Shaders/CAABoxShader.hpp"
#include "Graphics/Shaders/CWorldShadowShader.hpp"
#include "Graphics/Shaders/CParticleSwooshShaders.hpp"
#include "Graphics/Shaders/CEnvFxShaders.hpp"
#include "NESEmulator/CNESShader.hpp"
#include "Audio/CStreamAudioManager.hpp"
#include "CGBASupport.hpp"
@ -286,6 +287,7 @@ CMain::BooSetter::BooSetter(boo::IGraphicsDataFactory* factory,
CTextSupportShader::Initialize();
CScanLinesFilter::Initialize();
CRandomStaticFilter::Initialize();
CEnvFxShaders::Initialize();
CNESShader::Initialize();
}
@ -942,6 +944,7 @@ void CMain::Shutdown()
CTextSupportShader::Shutdown();
CScanLinesFilter::Shutdown();
CRandomStaticFilter::Shutdown();
CEnvFxShaders::Shutdown();
CFluidPlaneShader::Shutdown();
CFluidPlaneManager::RippleMapTex.reset();
CNESShader::Shutdown();

View File

@ -110,6 +110,7 @@ public:
x4_resFactory->LoadOriginalIDs(*xcc_simplePool);
LoadStringTable();
m_renderer.reset(AllocateRenderer(*xcc_simplePool, *x4_resFactory));
CEnvFxManager::Initialize();
CScriptMazeNode::LoadMazeSeeds();
}

View File

@ -1,47 +1,656 @@
#include "CEnvFxManager.hpp"
#include "Graphics/CTexture.hpp"
#include "CActor.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "CRandom16.hpp"
#include "CStateManager.hpp"
#include "TCastTo.hpp"
#include "CHUDBillboardEffect.hpp"
#include "World/CWorld.hpp"
#include "World/CPlayer.hpp"
#include "Collision/CGameCollision.hpp"
#include "Collision/CInternalRayCastStructure.hpp"
#include "World/CScriptTrigger.hpp"
#include "World/CScriptWater.hpp"
#include "Graphics/CBooRenderer.hpp"
namespace urde
{
static rstl::reserved_vector<zeus::CVector2f, 256> g_SnowForces;
CEnvFxManagerGrid::CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent,
const std::vector<CVectorFixed8_8>& initialParticles, int reserve,
CEnvFxManager& parent, boo::IGraphicsDataFactory::Context& ctx)
: x4_position(position), xc_extent(extent), x1c_particles(initialParticles),
m_instBuf(parent.m_instPool.allocateBlock(CGraphics::g_BooFactory, reserve)),
m_uniformBuf(parent.m_uniformPool.allocateBlock(CGraphics::g_BooFactory)),
m_lineRenderer(ctx, CLineRenderer::EPrimitiveMode::Lines, reserve * 2,
parent.x40_txtrEnvGradient->GetBooTexture(), true, true)
{
x1c_particles.reserve(reserve);
CEnvFxShaders::BuildShaderDataBinding(ctx, parent, *this);
}
CEnvFxManager::CEnvFxManager()
{
x40_txtrEnvGradient = g_SimplePool->GetObj("TXTR_EnvGradient");
x40_txtrEnvGradient->GetBooTexture()->setClampMode(boo::TextureClampMode::ClampToEdge);
xb58_envRainSplash = g_SimplePool->GetObj("PART_EnvRainSplash");
xb74_txtrSnowFlake = g_SimplePool->GetObj("TXTR_SnowFlake");
xc48_underwaterFlake = g_SimplePool->GetObj("TXTR_UnderwaterFlake");
CRandom16 random(0);
CGraphics::CommitResources([this](boo::IGraphicsDataFactory::Context& ctx)
{
m_fogUniformBuf = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(CGraphics::g_Fog), 1);
for (int i = 0; i < 8; ++i)
for (int j = 0; j < 8; ++j)
x50_grids.emplace_back(zeus::CVector2i{j * 2048, i * 2048}, zeus::CVector2i{2048, 2048},
std::vector<CVectorFixed8_8>{}, 171, *this, ctx);
return true;
} BooTrace);
for (int i = 0; i < 16; ++i)
xb84_snowZDeltas.emplace_back(0.f, 0.f, random.Range(-2.f, -4.f));
}
void CEnvFxManager::Update(float, const CStateManager&)
void CEnvFxManager::SetSplashEffectRate(float rate, const CStateManager& mgr)
{
if (TCastToPtr<CHUDBillboardEffect> splashEffect = mgr.ObjectById(xb68_envRainSplashId))
if (splashEffect->GetX104_26())
splashEffect->GetParticleGen()->SetGeneratorRate(rate);
}
/* Used to be MIDI scale */
static float CalcRainVolume(float f)
{
if (f < 0.1f)
return (f / 0.1f * 74.f) / 127.f;
else
return (f / 0.9f * 21.f + 74.f) / 127.f;
}
/* Used to be MIDI scale */
static float CalcRainPitch(float f)
{
return f - 1.f;
}
void CEnvFxManager::UpdateRainSounds(const CStateManager& mgr)
{
if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain)
{
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
float rainVol = CalcRainVolume(x30_fxDensity);
if (!xb6a_rainSoundActive)
{
xb6c_leftRainSound = CSfxManager::AddEmitter(SFXsfx09F0,
zeus::CVector3f::skZero, zeus::CVector3f::skZero,
false, true, 0xff, kInvalidAreaId);
xb70_rightRainSound = CSfxManager::AddEmitter(SFXsfx09F1,
zeus::CVector3f::skZero, zeus::CVector3f::skZero,
false, true, 0xff, kInvalidAreaId);
xb6a_rainSoundActive = true;
}
CSfxManager::UpdateEmitter(xb6c_leftRainSound, camXf.origin - camXf.basis[0], camXf.basis[0], rainVol);
CSfxManager::UpdateEmitter(xb70_rightRainSound, camXf.origin + camXf.basis[0], -camXf.basis[0], rainVol);
float rainPitch = CalcRainPitch(x30_fxDensity);
CSfxManager::PitchBend(xb6c_leftRainSound, rainPitch);
CSfxManager::PitchBend(xb70_rightRainSound, rainPitch);
}
else if (xb6a_rainSoundActive)
{
CSfxManager::RemoveEmitter(xb6c_leftRainSound);
CSfxManager::RemoveEmitter(xb70_rightRainSound);
xb6a_rainSoundActive = false;
}
}
zeus::CVector3f CEnvFxManager::GetParticleBoundsToWorldScale() const
{
return (x0_particleBounds.max - x0_particleBounds.min) / 127.f;
}
zeus::CTransform CEnvFxManager::GetParticleBoundsToWorldTransform() const
{
return zeus::CTransform::Translate(x18_focusCellPosition)
* zeus::CTransform::Translate(zeus::CVector3f(-31.75f))
* zeus::CTransform::Scale(GetParticleBoundsToWorldScale());
}
void CEnvFxManager::UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf)
{
EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx();
if (xb68_envRainSplashId != kInvalidUniqueId)
if (TCastToPtr<CHUDBillboardEffect> splashEffect = mgr.ObjectById(xb68_envRainSplashId))
mgr.SetActorAreaId(*splashEffect, mgr.GetNextAreaId());
float camUpness = camXf.basis[1].dot(zeus::CVector3f::skUp);
float splashRateFactor;
if (x24_enableSplash)
splashRateFactor = std::max(0.f, camUpness) * x30_fxDensity;
else
splashRateFactor = 0.f;
float forwardRateFactor = 0.f;
if (x24_enableSplash && camUpness >= -0.1f)
{
zeus::CVector3f pRelVel = mgr.GetPlayer().GetTransform().transposeRotate(mgr.GetPlayer().GetVelocity());
if (pRelVel.canBeNormalized())
{
float velMag = pRelVel.magnitude();
zeus::CVector3f normRelVel = pRelVel * (1.f / velMag);
forwardRateFactor = std::min(velMag / 60.f, 1.f) * normRelVel.dot(zeus::CVector3f::skForward);
}
}
float additionalFactor;
if (fxType == EEnvFxType::Rain)
additionalFactor = splashRateFactor + forwardRateFactor;
else
additionalFactor = 0.f;
SetSplashEffectRate(xb54_baseSplashRate + additionalFactor, mgr);
xb54_baseSplashRate = 0.f;
}
void CEnvFxManager::MoveWrapCells(s32 moveX, s32 moveY)
{
if (moveX == 0 && moveY == 0)
return;
bool r5 = std::fabs(moveX) >= 1.f || std::fabs(moveY) >= 1.f;
s32 moveXMaj = moveX << 11;
s32 moveYMaj = moveY << 11;
for (int i = 0; i < 8; ++i)
{
s32 r28 = i - moveY;
for (int j = 0; j < 8; ++j)
{
CEnvFxManagerGrid& grid = x50_grids[i * 8 + j];
s32 r3 = j - moveX;
if (!r5)
{
CEnvFxManagerGrid& otherGrid = x50_grids[r28 * 8 + r3];
grid.x14_block = otherGrid.x14_block;
}
else
{
grid.x0_24_blockDirty = true;
}
grid.x4_position = zeus::CVector2i((moveXMaj + grid.x4_position.x) & 0x3fff,
(moveYMaj + grid.x4_position.y) & 0x3fff);
}
}
}
void CEnvFxManager::CalculateSnowForces(const CVectorFixed8_8& zVec,
rstl::reserved_vector<CVectorFixed8_8, 256>& snowForces,
EEnvFxType type, const zeus::CVector3f& oopbtws, float dt)
{
if (type == EEnvFxType::Snow)
{
CVectorFixed8_8 vecf;
zeus::CVector3f vec;
for (int i = 255; i >= 0; ++i)
{
const zeus::CVector2f& force = g_SnowForces[i];
zeus::CVector3f delta = zeus::CVector3f(force * dt) * oopbtws;
vec += delta;
CVectorFixed8_8 vecf2(vec);
snowForces.push_back(vecf2 - vecf);
vecf = vecf2;
}
for (int i = 0; i < snowForces.size(); ++i)
snowForces[i] = snowForces[i] + zVec + CVectorFixed8_8(xb84_snowZDeltas[i & 0xf] * dt * oopbtws);
}
}
void CEnvFxManager::BuildBlockObjectList(rstl::reserved_vector<TUniqueId, 1024>& list, CStateManager& mgr)
{
for (CEntity* ent : mgr.GetAllObjectList())
{
if (TCastToPtr<CScriptTrigger> trig = ent)
{
if ((trig->GetTriggerFlags() & ETriggerFlags::BlockEnvironmentalEffects) != ETriggerFlags::None)
list.push_back(ent->GetUniqueId());
}
else if (TCastToPtr<CScriptWater> water = ent)
{
list.push_back(ent->GetUniqueId());
}
}
}
void CEnvFxManager::UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, const zeus::CTransform& camXf,
const zeus::CTransform& xf, const zeus::CTransform& invXf)
{
zeus::CVector3f playerPos;
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed)
playerPos = camXf.origin;
else
playerPos = mgr.GetPlayer().GetBallPosition();
zeus::CVector2i localPlayerPos((invXf * playerPos * 256.f).toVec2f());
x2c_lastBlockedGridIdx = -1;
x24_enableSplash = false;
rstl::reserved_vector<TUniqueId, 1024> blockList;
bool blockListBuilt = false;
int blockedGrids = 0;
for (int i = 0; i < x50_grids.size(); ++i)
{
CEnvFxManagerGrid& grid = x50_grids[i];
if (blockedGrids < 8 && grid.x0_24_blockDirty)
{
if (type == EEnvFxType::UnderwaterFlake)
{
grid.x14_block = std::make_pair(true, float(-FLT_MAX));
}
else
{
CMaterialFilter filter =
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid, EMaterialTypes::Trigger},
{EMaterialTypes::ProjectilePassthrough, EMaterialTypes::SeeThrough});
zeus::CVector3f pos = xf * zeus::CVector3f((grid.x4_position + grid.xc_extent * 0).toVec2f() / 256.f) +
zeus::CVector3f::skUp * 500.f;
CRayCastResult result =
CGameCollision::RayStaticIntersection(mgr, pos, zeus::CVector3f::skDown, 1000.f, filter);
if (result.IsValid())
{
if (!blockListBuilt)
{
BuildBlockObjectList(blockList, mgr);
blockListBuilt = true;
}
for (TUniqueId id : blockList)
{
if (TCastToConstPtr<CScriptTrigger> trig = mgr.GetObjectById(id))
{
if (auto tb = trig->GetTouchBounds())
{
CCollidableAABox caabb(*tb, {EMaterialTypes::Trigger});
CRayCastResult result2 =
caabb.CastRayInternal({pos, zeus::CVector3f::skDown, 1000.f, {}, filter});
if (result2.IsValid() && result2.GetT() < result.GetT())
result = result2;
}
}
}
}
++blockedGrids;
grid.x14_block = std::make_pair(result.IsValid(), result.GetPoint().z);
}
grid.x0_24_blockDirty = false;
}
zeus::CVector2i gridEnd = grid.x4_position + grid.xc_extent;
if (localPlayerPos.x >= grid.x4_position.x && localPlayerPos.y >= grid.x4_position.y &&
localPlayerPos.x < gridEnd.x && localPlayerPos.y < gridEnd.y && grid.x14_block.first &&
grid.x14_block.second <= playerPos.z)
{
x24_enableSplash = true;
x2c_lastBlockedGridIdx = i;
}
}
}
void CEnvFxManager::CreateNewParticles(EEnvFxType type)
{
int maxCellParticleCount;
if (type == EEnvFxType::Snow)
maxCellParticleCount = 0x1c98;
else if (type == EEnvFxType::Rain)
maxCellParticleCount = 0x2af8;
else if (type == EEnvFxType::UnderwaterFlake)
maxCellParticleCount = 0x1fd6;
else
maxCellParticleCount = 0;
maxCellParticleCount >>= 6;
int cellParticleCount = maxCellParticleCount * x30_fxDensity;
static u32 seedStash = 0;
CRandom16 random(seedStash);
for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it)
{
if (it->x14_block.first)
{
if (cellParticleCount > it->x1c_particles.size())
{
if (cellParticleCount > it->x1c_particles.capacity())
it->x1c_particles.reserve(maxCellParticleCount);
int remCellParticleCount = cellParticleCount - it->x1c_particles.size();
for (int i = 0; i < remCellParticleCount; ++i)
{
int x = random.Range(0.f, float(it->xc_extent.x));
int y = random.Range(0.f, float(it->xc_extent.y));
int z = 256.f * random.Range(0.f, 63.f);
it->x1c_particles.emplace_back(x, y, z);
}
}
else
{
it->x1c_particles.resize(cellParticleCount);
}
}
}
seedStash = random.GetSeed();
}
void CEnvFxManager::UpdateSnowParticles(const rstl::reserved_vector<CVectorFixed8_8, 256>& snowForces)
{
for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it)
{
int forceIt = int(x28_firstSnowForce);
if (it->x14_block.first)
{
for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit)
{
const CVectorFixed8_8& force = snowForces[forceIt];
forceIt = (forceIt + 1) & 0xff;
*pit = *pit + force;
pit->z = s16(pit->z & 0x3fff);
}
}
}
}
void CEnvFxManager::UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt)
{
s16 deltaZ = zVec.z + s16(-40.f * dt * oopbtws.z * 256.f);
for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it)
for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit)
pit->z = s16((pit->z + deltaZ) & 0x3fff);
}
void CEnvFxManager::UpdateUnderwaterParticles(const CVectorFixed8_8& zVec)
{
for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it)
for (auto pit = it->x1c_particles.rbegin(); pit != it->x1c_particles.rend(); ++pit)
pit->z = s16((pit->z + zVec.z) & 0x3fff);
}
void CEnvFxManager::Update(float dt, CStateManager& mgr)
{
EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx();
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
if (mgr.GetCameraManager()->GetFluidCounter() != 0)
{
x2c_lastBlockedGridIdx = -1;
x24_enableSplash = false;
SetSplashEffectRate(0.f, mgr);
}
UpdateRainSounds(mgr);
UpdateVisorSplash(mgr, dt, camXf);
if (fxType == EEnvFxType::None)
{
for (auto it = x50_grids.rbegin(); it != x50_grids.rend(); ++it)
if (it->x14_block.first)
it->x1c_particles = std::vector<CVectorFixed8_8>();
}
else
{
float densityDelta = x34_targetFxDensity - x30_fxDensity;
float densityDeltaDamper = std::min(std::fabs(densityDelta) / 0.15f, 1.f);
float maxDensityDelta = x38_maxDensityDeltaSpeed / 11000.f * dt;
if (std::fabs(densityDelta) > maxDensityDelta)
densityDelta = (densityDelta > 0.f ? 1.f : -1.f) * maxDensityDelta;
x30_fxDensity += densityDeltaDamper * densityDelta;
zeus::CVector3f pbtws = GetParticleBoundsToWorldScale();
zeus::CVector3f oopbtws = 1.f / pbtws;
zeus::CVector3f forwardPoint = camXf.basis[1] * 23.8125f + camXf.origin;
float modX = std::fmod(forwardPoint.x, 7.9375f);
float modY = std::fmod(forwardPoint.x, 7.9375f);
s32 moveX = (x18_focusCellPosition.x - (forwardPoint.x - modX)) / 7.9375f;
x18_focusCellPosition.x = forwardPoint.x - modX;
s32 moveY = (x18_focusCellPosition.y - (forwardPoint.y - modY)) / 7.9375f;
x18_focusCellPosition.y = forwardPoint.y - modY;
float deltaZ = x18_focusCellPosition.z - forwardPoint.z;
x18_focusCellPosition.z = forwardPoint.z;
MoveWrapCells(moveX, moveY);
CVectorFixed8_8 zVec(oopbtws * zeus::CVector3f(0.f, 0.f, deltaZ));
if (fxType == EEnvFxType::UnderwaterFlake)
zVec.z += s16(256.f * 0.5f * dt);
rstl::reserved_vector<CVectorFixed8_8, 256> snowForces;
CalculateSnowForces(zVec, snowForces, fxType, oopbtws, dt);
zeus::CTransform xf = GetParticleBoundsToWorldTransform();
zeus::CTransform invXf = xf.inverse();
UpdateBlockedGrids(mgr, fxType, camXf, xf, invXf);
CreateNewParticles(fxType);
switch (fxType)
{
case EEnvFxType::Snow:
UpdateSnowParticles(snowForces);
break;
case EEnvFxType::Rain:
UpdateRainParticles(zVec, oopbtws, dt);
break;
case EEnvFxType::UnderwaterFlake:
UpdateUnderwaterParticles(zVec);
break;
default:
break;
}
if (fxType == EEnvFxType::Snow)
x28_firstSnowForce = std::fmod(1.f + x28_firstSnowForce, 256.f);
else
x28_firstSnowForce = std::fmod(0.125f + x28_firstSnowForce, 256.f);
}
}
void CEnvFxManagerGrid::RenderSnowParticles(const zeus::CTransform& camXf) const
{
zeus::CVector3f xVec = 0.2f * camXf.basis[0];
zeus::CVector3f zVec = 0.2f * camXf.basis[2];
}
void CEnvFxManagerGrid::RenderRainParticles(const zeus::CTransform& camXf) const
{
m_lineRenderer.Reset();
float zOffset = 2.f * (1.f - std::fabs(camXf.basis[2].dot(zeus::CVector3f::skUp))) + 1.f;
zeus::CColor color0(1.f, 10.f / 15.f);
for (const auto& particle : x1c_particles)
{
zeus::CVector3f pos0 = particle.toVec3f();
zeus::CVector3f pos1 = pos0;
pos1.z += zOffset;
float uvy0 = pos0.z * 10.f + m_uvyOffset;
float uvy1 = pos1.z * 10.f + m_uvyOffset;
m_lineRenderer.AddVertex(pos0, zeus::CColor::skWhite, 1.f, {0.f, uvy0});
m_lineRenderer.AddVertex(pos1, zeus::CColor::skClear, 1.f, {0.f, uvy1});
}
m_lineRenderer.Render(zeus::CColor(1.f, 0.15f));
}
void CEnvFxManagerGrid::RenderUnderwaterParticles(const zeus::CTransform& camXf) const
{
}
void CEnvFxManager::Render(const CStateManager& mgr)
void CEnvFxManagerGrid::Render(const zeus::CTransform& xf, const zeus::CTransform& invXf,
const zeus::CTransform& camXf, float fxDensity, EEnvFxType fxType,
const CEnvFxManager& parent) const
{
if (!x1c_particles.empty() && x14_block.first)
{
CGraphics::SetModelMatrix(xf * zeus::CTransform::Translate(x4_position.toVec2f() / 256.f));
parent.m_uniformData.mvp =
CGraphics::GetPerspectiveProjectionMatrix(true) *
CGraphics::g_GXModelView.toMatrix4f();
switch (fxType)
{
case EEnvFxType::Snow:
case EEnvFxType::Rain:
{
zeus::CMatrix4f envTexMtx(true);
envTexMtx[2][1] = 10.f;
envTexMtx[3][1] = 0.5f - (invXf * (zeus::CVector3f::skUp * x14_block.second)).z * 10.f;
m_uvyOffset = envTexMtx[3][1];
parent.m_uniformData.envMtx = envTexMtx;
break;
}
default:
break;
}
m_uniformBuf.access() = parent.m_uniformData;
switch (fxType)
{
case EEnvFxType::Snow:
RenderSnowParticles(camXf);
break;
case EEnvFxType::Rain:
RenderRainParticles(camXf);
break;
case EEnvFxType::UnderwaterFlake:
RenderUnderwaterParticles(camXf);
break;
default:
break;
}
}
}
void CEnvFxManager::SetupSnowTevs(const CStateManager& mgr) const
{
mgr.GetCameraManager()->GetCurrentCamera(mgr);
if (mgr.GetCameraManager()->GetFluidCounter() != 0)
{
g_Renderer->SetWorldFog(ERglFogMode::PerspExp, 0.f, 35.f, zeus::CColor::skBlack);
m_uniformData.moduColor = zeus::CColor(1.f, 0.5f);
}
else
{
g_Renderer->SetWorldFog(ERglFogMode::PerspLin, 52.f, 57.f, zeus::CColor::skBlack);
}
// Blend One One
// 2 stages
// xb74_txtrSnowFlake
// Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY
// 0: Standard alpha, map0, tcg0
// Color: Zero, Konst, TexC, Zero
// Alpha: Zero, Konst, TexA, Zero
// x40_txtrEnvGradient
// Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY
// 0: Standard alpha, map0, tcg0
// Color: Zero, TexC, CPrev, Zero
// Alpha: Zero, Zero, Zero, TexA
}
void CEnvFxManager::SetupRainTevs() const
{
// Line-width 1px
// Blend SrcAlpha One
// x40_txtrEnvGradient
// Texcoord0: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY
// 0: Standard alpha, map0, tcg0
// Color: Zero, Zero, Zero, TexC
// Alpha: Zero, RasA, Konst, Zero
// Ras vertex color
// KAlpha 0.15
}
void CEnvFxManager::SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const
{
// Blend SrcAlpha InvSrcAlpha
// xc48_underwaterFlake
// Texcoord0: 2x4, TEX0, GX_IDENTITY, no norm, GX_PTTIDENTITY
// Color: Zero, Zero, Zero, TexC
// Alpha: Zero, Zero, Zero, TexA
float waterTop = FLT_MAX;
for (CEntity* ent : mgr.GetAllObjectList())
if (TCastToPtr<CScriptWater> water = ent)
if (auto tb = water->GetTouchBounds())
waterTop = std::min(waterTop, tb->max.z);
zeus::CVector3f localWaterTop = invXf * (zeus::CVector3f::skUp * waterTop);
zeus::CMatrix4f envTexMtx(true);
envTexMtx[2][1] = -10.f;
envTexMtx[3][1] = localWaterTop.z * -10.f + 0.5f;
// Load into texmtx5
// x40_txtrEnvGradient
// Texcoord1: 2x4, POS, GX_TEXMTX5, no norm, GX_PTTIDENTITY
// MTX: y-scale -10.0 of Z, y-trans -10.0 * ()
// 1: Standard alpha, map1, tcg1
// Color: Zero, One, CPrev, Zero
// Alpha: Zero, TexA, APrev, Zero
// Swap: RGBR
}
void CEnvFxManager::Render(const CStateManager& mgr) const
{
EEnvFxType fxType = mgr.GetWorld()->GetNeededEnvFx();
if (fxType != EEnvFxType::None)
{
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed ||
(mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal &&
(fxType != EEnvFxType::Snow ||
mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::XRay)))
{
// No Cull
// ZTest, No ZWrite
zeus::CTransform xf = GetParticleBoundsToWorldTransform();
zeus::CTransform invXf = xf.inverse();
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
m_uniformData.moduColor = zeus::CColor::skWhite;
switch (fxType)
{
case EEnvFxType::Snow:
SetupSnowTevs(mgr);
break;
case EEnvFxType::Rain:
SetupRainTevs();
break;
case EEnvFxType::UnderwaterFlake:
SetupUnderwaterTevs(invXf, mgr);
break;
default:
break;
}
m_fogUniformBuf->load(&CGraphics::g_Fog, sizeof(CGraphics::g_Fog));
for (const auto& grid : x50_grids)
grid.Render(xf, invXf, camXf, x30_fxDensity, fxType, *this);
// Backface cull
}
}
}
void CEnvFxManager::AsyncLoadResources(CStateManager& mgr)
{
xb68_envRainSplashId = mgr.AllocateUniqueId();
CHUDBillboardEffect* effect =
new CHUDBillboardEffect(xb58_envRainSplash, {}, xb68_envRainSplashId, true, "VisorRainSplashes",
CHUDBillboardEffect::GetNearClipDistance(mgr),
CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::CColor::skWhite,
zeus::CVector3f::skOne, zeus::CVector3f::skZero);
effect->SetX104_27(true);
mgr.AddObject(effect);
}
void CEnvFxManager::SetFxDensity(s32 val, float density)
{
x34_fxDensity = density;
x38_ = val;
x34_targetFxDensity = density;
x38_maxDensityDeltaSpeed = val;
}
void CEnvFxManager::AreaLoaded()
{
for (CEnvFxManagerGrid& grid : x50_grids)
grid.x0_24_ = true;
grid.x0_24_blockDirty = true;
}
void CEnvFxManager::Cleanup()
{
xb68_envRainSplashId = kInvalidUniqueId;
xb6a_ = false;
xb6c_ = 0;
xb70_ = 0;
xb6a_rainSoundActive = false;
xb6c_leftRainSound.reset();
xb70_rightRainSound.reset();
}
void CEnvFxManager::Initialize()
{
const SObjectTag* tag = g_ResFactory->GetResourceIdByName("DUMB_SnowForces");
std::unique_ptr<u8[]> data = g_ResFactory->LoadResourceSync(*tag);
athena::io::MemoryReader r(data.get(), 2048);
for (int i = 0; i < 256; ++i)
g_SnowForces.push_back(r.readVec2fBig());
}
}

View File

@ -4,6 +4,11 @@
#include "CToken.hpp"
#include "zeus/CAABox.hpp"
#include "Particle/CGenDescription.hpp"
#include "Audio/CSfxManager.hpp"
#include "Graphics/Shaders/CEnvFxShaders.hpp"
#include "Graphics/CLineRenderer.hpp"
#include "hecl/VertexBufferPool.hpp"
#include "hecl/UniformBufferPool.hpp"
namespace urde
{
@ -15,7 +20,8 @@ enum class EEnvFxType
{
None,
Snow,
Rain
Rain,
UnderwaterFlake
};
enum class EPhazonType
@ -27,64 +33,132 @@ enum class EPhazonType
class CVectorFixed8_8
{
//u16 x0_[3];
public:
union {
struct
{
s16 x, y, z;
};
s16 v[3];
};
CVectorFixed8_8() { x = y = z = 0; }
CVectorFixed8_8(s16 xi, s16 yi, s16 zi) { x = xi; y = yi; z = zi; }
CVectorFixed8_8(const zeus::CVector3f& vec)
{
x = s16(vec.x * 256.f);
y = s16(vec.y * 256.f);
z = s16(vec.z * 256.f);
}
CVectorFixed8_8 operator+(const CVectorFixed8_8& other) const
{
return {s16(x + other.x), s16(y + other.y), s16(z + other.z)};
}
CVectorFixed8_8 operator-(const CVectorFixed8_8& other) const
{
return {s16(x - other.x), s16(y - other.y), s16(z - other.z)};
}
zeus::CVector3f toVec3f() const
{
return {x / 256.f, y / 256.f, z / 256.f};
}
};
class CEnvFxManagerGrid
{
friend class CEnvFxManager;
bool x0_24_ = true;
zeus::CVector2i x4_;
zeus::CVector2i xc_;
std::pair<bool, float> x14_ = {false, FLT_MAX};
std::vector<CVectorFixed8_8> x1c_;
friend class CEnvFxShaders;
bool x0_24_blockDirty = true;
zeus::CVector2i x4_position; /* 8.8 fixed point */
zeus::CVector2i xc_extent; /* 8.8 fixed point */
std::pair<bool, float> x14_block = {false, FLT_MAX}; /* Blocked-bool, Z-coordinate */
std::vector<CVectorFixed8_8> x1c_particles;
mutable hecl::VertexBufferPool<CEnvFxShaders::Instance>::Token m_instBuf;
mutable hecl::UniformBufferPool<CEnvFxShaders::Uniform>::Token m_uniformBuf;
mutable CLineRenderer m_lineRenderer;
boo::ObjToken<boo::IShaderDataBinding> m_snowBinding;
boo::ObjToken<boo::IShaderDataBinding> m_underwaterBinding;
mutable float m_uvyOffset = 0.f;
void RenderSnowParticles(const zeus::CTransform& camXf) const;
void RenderRainParticles(const zeus::CTransform& camXf) const;
void RenderUnderwaterParticles(const zeus::CTransform& camXf) const;
public:
CEnvFxManagerGrid(const zeus::CVector2i& a, const zeus::CVector2i& b,
const std::vector<CVectorFixed8_8>& vec, int reserve)
: x4_(a), xc_(b), x1c_(vec)
{
x1c_.reserve(reserve);
}
CEnvFxManagerGrid(const zeus::CVector2i& position, const zeus::CVector2i& extent,
const std::vector<CVectorFixed8_8>& initialParticles, int reserve,
CEnvFxManager& parent, boo::IGraphicsDataFactory::Context& ctx);
void Render(const zeus::CTransform& xf, const zeus::CTransform& invXf,
const zeus::CTransform& camXf, float fxDensity, EEnvFxType fxType,
const CEnvFxManager& parent) const;
};
class CEnvFxManager
{
zeus::CAABox x0_ = zeus::CAABox(-63.5, 63.5);
zeus::CVector3f x18_ = zeus::CVector3f::skZero;
bool x24_ = false;
float x28_ = 0.f;
u32 x2c_ = -1;
float x30_rainMagnitude = 0.f;
float x34_fxDensity = 0.f;
float x38_ = 0.f;
u8 x3c = 0;
friend class CEnvFxManagerGrid;
friend class CEnvFxShaders;
zeus::CAABox x0_particleBounds = zeus::CAABox(-63.5f, 63.5f);
zeus::CVector3f x18_focusCellPosition = zeus::CVector3f::skZero;
bool x24_enableSplash = false;
float x28_firstSnowForce = 0.f;
s32 x2c_lastBlockedGridIdx = -1;
float x30_fxDensity = 0.f;
float x34_targetFxDensity = 0.f;
float x38_maxDensityDeltaSpeed = 0.f;
//bool x3c_snowflakeTextureMipBlanked = false; /* Shader simulates this texture mod */
TLockedToken<CTexture> x40_txtrEnvGradient;
rstl::reserved_vector<CEnvFxManagerGrid, 64> x50_grids;
float xb54_;
float xb54_baseSplashRate;
TLockedToken<CGenDescription> xb58_envRainSplash;
bool xb64_ = true;
TUniqueId xb68_envRainSplashId = kInvalidUniqueId;
bool xb6a_ = false;
u32 xb6c_ = 0;
u32 xb70_ = 0;
bool xb6a_rainSoundActive = false;
CSfxHandle xb6c_leftRainSound;
CSfxHandle xb70_rightRainSound;
TLockedToken<CTexture> xb74_txtrSnowFlake;
bool xb80_ = true;
rstl::reserved_vector<zeus::CVector3f, 16> xb84_snowZDeltas;
TLockedToken<CTexture> xc48_underwaterFlake;
bool xc54_ = true;
void SetupSnowTevs();
void SetupRainTevs();
hecl::VertexBufferPool<CEnvFxShaders::Instance> m_instPool;
hecl::UniformBufferPool<CEnvFxShaders::Uniform> m_uniformPool;
mutable CEnvFxShaders::Uniform m_uniformData;
boo::ObjToken<boo::IGraphicsBufferD> m_fogUniformBuf;
void SetSplashEffectRate(float f, const CStateManager& mgr);
void UpdateRainSounds(const CStateManager& mgr);
zeus::CVector3f GetParticleBoundsToWorldScale() const;
zeus::CTransform GetParticleBoundsToWorldTransform() const;
void UpdateVisorSplash(CStateManager& mgr, float dt, const zeus::CTransform& camXf);
void MoveWrapCells(s32, s32);
void CalculateSnowForces(const CVectorFixed8_8& zVec, rstl::reserved_vector<CVectorFixed8_8, 256>& snowForces,
EEnvFxType type, const zeus::CVector3f& oopbtws, float dt);
static void BuildBlockObjectList(rstl::reserved_vector<TUniqueId, 1024>& list, CStateManager& mgr);
void UpdateBlockedGrids(CStateManager& mgr, EEnvFxType type, const zeus::CTransform& camXf,
const zeus::CTransform& xf, const zeus::CTransform& invXf);
void CreateNewParticles(EEnvFxType type);
void UpdateSnowParticles(const rstl::reserved_vector<CVectorFixed8_8, 256>& snowForces);
void UpdateRainParticles(const CVectorFixed8_8& zVec, const zeus::CVector3f& oopbtws, float dt);
void UpdateUnderwaterParticles(const CVectorFixed8_8& zVec);
void SetupSnowTevs(const CStateManager& mgr) const;
void SetupRainTevs() const;
void SetupUnderwaterTevs(const zeus::CTransform& invXf, const CStateManager& mgr) const;
public:
CEnvFxManager();
void AsyncLoadResources(CStateManager& mgr);
void Update(float, const CStateManager&);
void Render(const CStateManager& mgr);
void Update(float, CStateManager& mgr);
void Render(const CStateManager& mgr) const;
void SetFxDensity(s32, float);
void MoveWrapCells(s32, s32);
void GetParticleBoundsToWorldScale() const;
void AreaLoaded();
void SetXB54(float f) { xb54_ = f; }
bool GetX24() const { return x24_; }
float GetRainMagnitude() const { return x30_rainMagnitude; }
void SetSplashRate(float f) { xb54_baseSplashRate = f; }
bool IsSplashActive() const { return x24_enableSplash; }
float GetRainMagnitude() const { return x30_fxDensity; }
void Cleanup();
static void Initialize();
};
}

View File

@ -31,6 +31,9 @@ public:
const zeus::CColor& color, const zeus::CVector3f& v1, const zeus::CVector3f& v2);
~CHUDBillboardEffect();
void Accept(IVisitor& visitor);
bool GetX104_26() const { return x104_26_; }
void SetX104_27(bool b) { x104_27_ = b; }
CParticleGen* GetParticleGen() const { return xe8_generator.get(); }
static float GetNearClipDistance(CStateManager& mgr);
static zeus::CVector3f GetScaleForPOV(CStateManager& mgr);

View File

@ -1258,7 +1258,7 @@ void CMorphBall::UpdateEffects(float dt, CStateManager& mgr)
bool emitRainWake = (x0_player.GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround &&
mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain &&
mgr.GetEnvFxManager()->GetRainMagnitude() > 0.f &&
mgr.GetEnvFxManager()->GetX24());
mgr.GetEnvFxManager()->IsSplashActive());
x1bc8_wakeEffectGens[7]->SetParticleEmission(emitRainWake);
float rainGenRate = std::min(mgr.GetEnvFxManager()->GetRainMagnitude() * 2.f *
x0_player.x4fc_flatMoveSpeed / x0_player.GetBallMaxVelocity(), 1.f);

View File

@ -933,7 +933,7 @@ void CPlayer::FluidFXThink(EFluidState state, CScriptWater& water, CStateManager
if (water.GetFluidPlane().GetFluidType() == EFluidType::NormalWater)
{
float velMag = mgr.GetPlayer().GetVelocity().magnitude() / 10.f;
mgr.GetEnvFxManager()->SetXB54(10.f * std::max(1.f, velMag));
mgr.GetEnvFxManager()->SetSplashRate(10.f * std::max(1.f, velMag));
}
}
break;

View File

@ -147,15 +147,15 @@ void CScriptEffect::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSt
case EScriptObjectMessage::InitializedInArea:
for (const SConnection& conn : x20_conns)
{
if (!(conn.x0_state == EScriptObjectState::Active && conn.x4_msg == EScriptObjectMessage::Deactivate) &&
!(conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Activate))
continue;
auto search = mgr.GetIdListForScript(conn.x8_objId);
for (auto it = search.first; it != search.second; ++it)
if ((conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow) ||
(conn.x0_state == EScriptObjectState::InheritBounds && conn.x4_msg == EScriptObjectMessage::Activate))
{
if (TCastToConstPtr<CScriptTrigger>(mgr.GetObjectById(it->second)))
x13c_triggerId = it->second;
auto search = mgr.GetIdListForScript(conn.x8_objId);
for (auto it = search.first; it != search.second; ++it)
{
if (TCastToConstPtr<CScriptTrigger>(mgr.GetObjectById(it->second)))
x13c_triggerId = it->second;
}
}
}
break;

View File

@ -55,7 +55,7 @@ void CScriptSteam::Think(float dt, CStateManager& mgr)
float distance = (mag >= x164_ ? 0.f : std::cos((1.5707964f * mag) * x168_) * x158_);
mgr.Player()->SetVisorSteam(distance, x15c_alphaInDur, x160_alphaOutDur, x154_texture, x150_);
if (x150_)
mgr.GetEnvFxManager()->SetXB54(2.f * distance);
mgr.GetEnvFxManager()->SetSplashRate(2.f * distance);
}
else
mgr.Player()->SetVisorSteam(0.f, x15c_alphaInDur, x160_alphaOutDur, CAssetId(), x150_);

View File

@ -0,0 +1,297 @@
#shader CEnvFxSnowShader
#instattribute position4 0
#instattribute position4 1
#instattribute position4 2
#instattribute position4 3
#instattribute color
#instattribute uv4 0
#instattribute uv4 1
#instattribute uv4 2
#instattribute uv4 3
#srcfac one
#dstfac one
#primitive tristrips
#depthtest lequal
#depthwrite false
#alphawrite false
#culling none
#vertex glsl
layout(location=0) in vec4 posIn[4];
layout(location=4) in vec4 colorIn;
layout(location=5) in vec4 uvsIn[4];
UBINDING0 uniform EnvFxUniform
{
mat4 mv;
mat4 proj;
mat4 envMtx;
vec4 moduColor;
};
struct VertToFrag
{
vec4 mvPos;
vec4 color;
vec2 uvFlake;
vec2 uvEnv;
};
SBINDING(0) out VertToFrag vtf;
void main()
{
vec4 pos = posIn[gl_VertexID];
vtf.color = colorIn * moduColor;
vtf.uvFlake = uvsIn[gl_VertexID].xy;
vtf.uvEnv = (envMtx * pos).xy;
vtf.mvPos = mv * pos;
gl_Position = proj * vtf.mvPos;
}
#fragment glsl
struct VertToFrag
{
vec4 mvPos;
vec4 color;
vec2 uvFlake;
vec2 uvEnv;
};
SBINDING(0) in VertToFrag vtf;
layout(location=0) out vec4 colorOut;
TBINDING0 uniform sampler2D texFlake;
TBINDING1 uniform sampler2D texEnv;
UBINDING1 uniform FogUniform
{
int mode;
vec4 color;
float rangeScale;
float start;
};
vec4 MainPostFunc(vec4 colorIn)
{
float fogZ, temp;
switch (mode)
{
case 2:
fogZ = (-vtf.mvPos.z - start) * rangeScale;
break;
case 4:
fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - start) * rangeScale);
break;
case 5:
temp = (-vtf.mvPos.z - start) * rangeScale;
fogZ = 1.0 - exp2(-8.0 * temp * temp);
break;
case 6:
fogZ = exp2(-8.0 * (start + vtf.mvPos.z) * rangeScale);
break;
case 7:
temp = (start + vtf.mvPos.z) * rangeScale;
fogZ = exp2(-8.0 * temp * temp);
break;
default:
fogZ = 0.0;
break;
}
return vec4(mix(colorIn, color, clamp(fogZ, 0.0, 1.0)).rgb, colorIn.a);
}
void main()
{
colorOut = MainPostFunc(vtf.color * texture(texFlake, vtf.uvFlake) * texture(texEnv, vtf.uvEnv));
}
#vertex hlsl
struct VertData
{
float4 posIn[4] : POSITION;
float4 colorIn : COLOR;
float4 uvsIn[4] : UV;
};
cbuffer EnvFxUniform : register(b0)
{
float4x4 mv;
float4x4 proj;
float4x4 envMtx;
float4 moduColor;
};
struct VertToFrag
{
float4 position : SV_Position;
float4 mvPos : POSITION;
float4 color : COLOR;
float2 uvFlake : UV0;
float2 uvEnv : UV1;
};
VertToFrag main(in VertData v, in uint vertId : SV_VertexID)
{
VertToFrag vtf;
vtf.color = v.colorIn * moduColor;
vtf.uvFlake = v.uvsIn[vertId].xy;
vtf.uvEnv = mul(envMtx, v.posIn[vertId]).xy;
vtf.mvPos = mul(mv, v.posIn[vertId]);
vtf.position = mul(proj, vtf.mvPos);
return vtf;
}
#fragment hlsl
SamplerState samp : register(s0);
SamplerState sampClamp : register(s3);
Texture2D texFlake : register(t0);
Texture2D texEnv : register(t1);
struct VertToFrag
{
float4 position : SV_Position;
float4 mvPos : POSITION;
float4 color : COLOR;
float2 uvFlake : UV0;
float2 uvEnv : UV1;
};
cbuffer FogUniform : register(b1)
{
int mode;
float4 color;
float rangeScale;
float start;
};
static float4 MainPostFunc(in VertToFrag vtf, float4 colorIn)
{
float fogZ, temp;
switch (mode)
{
case 2:
fogZ = (-vtf.mvPos.z - start) * rangeScale;
break;
case 4:
fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - start) * rangeScale);
break;
case 5:
temp = (-vtf.mvPos.z - start) * rangeScale;
fogZ = 1.0 - exp2(-8.0 * temp * temp);
break;
case 6:
fogZ = exp2(-8.0 * (start + vtf.mvPos.z) * rangeScale);
break;
case 7:
temp = (start + vtf.mvPos.z) * rangeScale;
fogZ = exp2(-8.0 * temp * temp);
break;
default:
fogZ = 0.0;
break;
}
return float4(lerp(colorIn, color, saturate(fogZ)).rgb, colorIn.a);
}
float4 main(in VertToFrag vtf) : SV_Target0
{
return MainPostFunc(vtf, vtf.color * texFlake.Sample(samp, vtf.uvFlake) * texEnv.Sample(sampClamp, vtf.uvEnv));
}
#vertex metal
struct VertData
{
float4 posIn[4];
float4 colorIn;
float4 uvsIn[4];
};
struct EnvFxUniform
{
float4x4 mv;
float4x4 proj;
float4x4 envMtx;
float4 moduColor;
};
struct VertToFrag
{
float4 position [[ position ]];
float4 mvPos;
float4 color;
float2 uvFlake;
float2 uvEnv;
};
vertex VertToFrag vmain(constant VertData* va [[ buffer(1) ]],
uint vertId [[ vertex_id ]], uint instId [[ instance_id ]],
constant EnvFxUniform& particle [[ buffer(2) ]])
{
VertToFrag vtf;
constant VertData& v = va[instId];
vtf.color = v.colorIn * particle.moduColor;
vtf.uvFlake = v.uvsIn[vertId].xy;
vtf.uvEnv = (envMtx * v.posIn[vertId]).xy;
vtf.mvPos = particle.mv * v.posIn[vertId];
vtf.position = particle.proj * vtf.mvPos;
return vtf;
}
#fragment metal
struct VertToFrag
{
float4 position [[ position ]];
float4 mvPos;
float4 color;
float2 uvFlake;
float2 uvEnv;
};
struct FogUniform
{
int mode;
float4 color;
float rangeScale;
float start;
};
float4 MainPostFunc(thread VertToFrag& vtf, constant FogUniform& fu, float4 colorIn)
{
float fogZ, temp;
switch (lu.mode)
{
case 2:
fogZ = (-vtf.mvPos.z - fu.start) * fu.rangeScale;
break;
case 4:
fogZ = 1.0 - exp2(-8.0 * (-vtf.mvPos.z - fu.start) * fu.rangeScale);
break;
case 5:
temp = (-vtf.mvPos.z - fu.start) * fu.rangeScale;
fogZ = 1.0 - exp2(-8.0 * temp * temp);
break;
case 6:
fogZ = exp2(-8.0 * (fu.start + vtf.mvPos.z) * fu.rangeScale);
break;
case 7:
temp = (fu.start + vtf.mvPos.z) * fu.rangeScale;
fogZ = exp2(-8.0 * temp * temp);
break;
default:
fogZ = 0.0;
break;
}
return float4(mix(colorIn, fu.color, saturate(fogZ)).rgb, colorIn.a);
}
fragment float4 fmain(VertToFrag vtf [[ stage_in ]],
sampler samp [[ sampler(0) ]],
sampler sampClamp [[ sampler(3) ]],
constant FogUniform& fu [[ buffer(3) ]],
texture2d<float> texFlake [[ texture(0) ]],
texture2d<float> texEnv [[ texture(1) ]])
{
return MainPostFunc(vtf, fu, vtf.color * texFlake.sample(samp, vtf.uvFlake) * texEnv.sample(sampClamp, vtf.uvEnv));
}
#shader CEnvFxUnderwaterShader : CEnvFxSnowShader
#srcfac srcalpha
#dstfac invsrcalpha

View File

@ -10,6 +10,7 @@ add_shader(CColoredQuadFilter)
add_shader(CDecalShaders)
add_shader(CElementGenShaders)
add_shader(CEnergyBarShader)
add_shader(CEnvFxShaders)
add_shader(CFogVolumeFilter)
add_shader(CFogVolumePlaneShader)
add_shader(CLineRendererShaders)

2
hecl

@ -1 +1 @@
Subproject commit 7561dd66e6ab5f5b7d4f94fc7bf732653ce104fb
Subproject commit 26541cd2b460592049b75b9612562fa6b7d01cc5

@ -1 +1 @@
Subproject commit 8d29c1449c4e661449c6b666c2fe17ce35dff023
Subproject commit 6475d4ad284a6106f55313f86d8fdc2ac13a381b