diff --git a/TombEngine/Game/effects/Streamer.cpp b/TombEngine/Game/effects/Streamer.cpp index 98c89aa9d..bd2ec8907 100644 --- a/TombEngine/Game/effects/Streamer.cpp +++ b/TombEngine/Game/effects/Streamer.cpp @@ -24,9 +24,12 @@ namespace TEN::Effects::Streamer { StoreInterpolationData(); - // Update opacity. - if (Color.w > 0.0f) - Color.w = EaseInOutSine(0.0f, OpacityMax, Life / LifeMax); + // Update color. + float alpha = (float)Life / (float)LifeMax; + Color.x = EaseInOutSine(ColorEnd.x, ColorStart.x, alpha); + Color.y = EaseInOutSine(ColorEnd.y, ColorStart.y, alpha); + Color.z = EaseInOutSine(ColorEnd.z, ColorStart.z, alpha); + Color.w = EaseInOutSine(ColorEnd.w, ColorStart.w, alpha); // TODO: Not working. Make it work. -- Sezz 2025.03.02 // Update orientation. @@ -36,7 +39,7 @@ namespace TEN::Effects::Streamer TransformVertices(Velocity, ExpRate); // Update life. - Life -= 1.0f; + Life--; } void Streamer::StreamerSegment::TransformVertices(float vel, float expRate) @@ -95,24 +98,25 @@ namespace TEN::Effects::Streamer return _isBroken; } - void Streamer::AddSegment(const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + void Streamer::AddSegment(const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, unsigned int segmentCount) { constexpr auto FADE_IN_COEFF = 3.0f; auto& segment = GetNewSegment(); - // Avoid "clipped" streamers by clamping max life according to max segment count. - float lifeMax = std::min(round(life * FPS), (float)SEGMENT_COUNT_MAX); + // Avoid creating "clipped" streamers by clamping max life according to max segment count. + int lifeMax = (int)std::min(round(life * FPS), (float)SEGMENT_COUNT_MAX); - float alpha = (segmentCount / lifeMax) * FADE_IN_COEFF; - float opacityMax = EaseInOutSine(0.0f, color.w, alpha); + float alpha = ((float)segmentCount / (float)lifeMax) * FADE_IN_COEFF; + float opacityMax = EaseInOutSine(colorEnd.w, colorStart.w, alpha); segment.Orientation = AxisAngle(dir, orient); - segment.Color = Vector4(color.x, color.y, color.z, opacityMax); + segment.Color = + segment.ColorStart = Vector4(colorStart.x, colorStart.y, colorStart.z, opacityMax); + segment.ColorEnd = colorEnd; segment.Life = segment.LifeMax = lifeMax; - segment.OpacityMax = opacityMax; segment.Velocity = vel; segment.ExpRate = expRate; segment.Rotation = rot; @@ -153,7 +157,7 @@ namespace TEN::Effects::Streamer return _pools; } - void StreamerGroup::AddStreamer(int tag, const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + void StreamerGroup::AddStreamer(int tag, const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, StreamerFeatherType featherType, BlendMode blendMode) { @@ -165,7 +169,7 @@ namespace TEN::Effects::Streamer // Get new streamer iteration or extend existing streamer iteration with new segment. auto& streamer = GetStreamerIteration(tag, featherType, blendMode); - streamer.AddSegment(pos, dir, orient, color, width, life, vel, expRate, rot, (unsigned int)streamer.GetSegments().size()); + streamer.AddSegment(pos, dir, orient, colorStart, colorEnd, width, life, vel, expRate, rot, (unsigned int)streamer.GetSegments().size()); } void StreamerGroup::Update() @@ -247,7 +251,7 @@ namespace TEN::Effects::Streamer return _groups; } - void StreamerEffectController::Spawn(int itemNumber, int tag, const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + void StreamerEffectController::Spawn(int itemNumber, int tag, const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, StreamerFeatherType featherType, BlendMode blendMode) { @@ -259,7 +263,7 @@ namespace TEN::Effects::Streamer // Get group and extend streamer within pool. auto& group = GetGroup(itemNumber); - group.AddStreamer(tag, pos, dir, orient, color, width, life, vel, expRate, rot, featherType, blendMode); + group.AddStreamer(tag, pos, dir, orient, colorStart, colorEnd, width, life, vel, expRate, rot, featherType, blendMode); } void StreamerEffectController::Update() diff --git a/TombEngine/Game/effects/Streamer.h b/TombEngine/Game/effects/Streamer.h index 643826867..e4b337484 100644 --- a/TombEngine/Game/effects/Streamer.h +++ b/TombEngine/Game/effects/Streamer.h @@ -28,13 +28,14 @@ namespace TEN::Effects::Streamer { static constexpr auto VERTEX_COUNT = 2; - std::array Vertices = {}; + std::array Vertices = {}; // TODO: Refactor vertices to be calculated by renderer instead of by internal effect logic. AxisAngle Orientation = AxisAngle::Identity; // TODO: Interpolate? Vector4 Color = Vector4::Zero; + Vector4 ColorStart = Vector4::Zero; + Vector4 ColorEnd = Vector4::Zero; - float Life = 0.0f; - float LifeMax = 0.0f; - float OpacityMax = 0.0f; + int Life = 0; // Time in game frames. + int LifeMax = 0; // Time in game frames. float Velocity = 0.0f; float ExpRate = 0.0f; short Rotation = 0; @@ -81,7 +82,7 @@ namespace TEN::Effects::Streamer // Utilities - void AddSegment(const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + void AddSegment(const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, unsigned int segmentCount); void Update(); @@ -111,7 +112,7 @@ namespace TEN::Effects::Streamer // Utilities - void AddStreamer(int tag, const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + void AddStreamer(int tag, const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, StreamerFeatherType featherType, BlendMode blendMode); void Update(); @@ -143,7 +144,8 @@ namespace TEN::Effects::Streamer // Utilities - void Spawn(int itemNumber, int tag, const Vector3& pos, const Vector3& dir, short orient, const Vector4& color, + // TODO: Use seconds. + void Spawn(int itemNumber, int tag, const Vector3& pos, const Vector3& dir, short orient, const Color& colorStart, const Color& colorEnd, float width, float life, float vel, float expRate, short rot, StreamerFeatherType featherType = StreamerFeatherType::None, BlendMode blendMode = BlendMode::AlphaBlend); void Update(); diff --git a/TombEngine/Objects/TR4/Entity/Wraith.cpp b/TombEngine/Objects/TR4/Entity/Wraith.cpp index 59e2bbf29..75b719344 100644 --- a/TombEngine/Objects/TR4/Entity/Wraith.cpp +++ b/TombEngine/Objects/TR4/Entity/Wraith.cpp @@ -38,11 +38,12 @@ namespace TEN::Entities::TR4 static void SpawnWraithTails(const ItemInfo& item) { - constexpr auto OFFSET = Vector3(0.0f, -10.0f, -50.0f); - constexpr auto WIDTH = 8.0f; - constexpr auto LIFE_MAX = 0.5f; - constexpr auto VEL = 4.0f; - constexpr auto EXP_RATE = 1.0f; + constexpr auto OFFSET = Vector3(0.0f, -10.0f, -50.0f); + constexpr auto COLOR_END = Color(0.0f, 0.0f, 0.0f, 0.0f); + constexpr auto WIDTH = 8.0f; + constexpr auto LIFE_MAX = 0.5f; + constexpr auto VEL = 4.0f; + constexpr auto EXP_RATE = 1.0f; enum class TailTag { @@ -51,20 +52,20 @@ namespace TEN::Entities::TR4 Third }; - auto color = Vector4::Zero; + auto colorStart = Vector4::Zero; switch (item.ObjectNumber) { default: case ID_WRAITH1: - color = Vector4(1.0f, 0.6f, 0.0f, 1.0f); + colorStart = Vector4(1.0f, 0.6f, 0.0f, 1.0f); break; case ID_WRAITH2: - color = Vector4(0.0f, 0.5f, 1.0f, 1.0f); + colorStart = Vector4(0.0f, 0.5f, 1.0f, 1.0f); break; case ID_WRAITH3: - color = Vector4(1.0f); + colorStart = Vector4(1.0f); break; } @@ -81,21 +82,21 @@ namespace TEN::Entities::TR4 // Spawn first tail. StreamerEffect.Spawn( item.Index, (int)TailTag::First, - pos, dir0, orient2D, color, + pos, dir0, orient2D, colorStart, COLOR_END, WIDTH, LIFE_MAX, VEL, EXP_RATE, 0, StreamerFeatherType::Center, BlendMode::Additive); // Spawn second tail. StreamerEffect.Spawn( item.Index, (int)TailTag::Second, - pos, dir1, orient2D, color, + pos, dir1, orient2D, colorStart, COLOR_END, WIDTH, LIFE_MAX, VEL, EXP_RATE, 0, StreamerFeatherType::Center, BlendMode::Additive); // Spawn third tail. StreamerEffect.Spawn( item.Index, (int)TailTag::Third, - pos, dir2, orient2D, color, + pos, dir2, orient2D, colorStart, COLOR_END, WIDTH, LIFE_MAX, VEL, EXP_RATE, 0, StreamerFeatherType::Center, BlendMode::Additive); } diff --git a/TombEngine/Objects/Utils/VehicleHelpers.cpp b/TombEngine/Objects/Utils/VehicleHelpers.cpp index d225862e1..85ae29007 100644 --- a/TombEngine/Objects/Utils/VehicleHelpers.cpp +++ b/TombEngine/Objects/Utils/VehicleHelpers.cpp @@ -355,7 +355,8 @@ namespace TEN::Entities::Vehicles void SpawnVehicleWake(const ItemInfo& vehicleItem, const Vector3& relOffset, int waterHeight, bool isUnderwater) { - constexpr auto COLOR = Vector4(0.75f); + constexpr auto COLOR_START = Color(0.75f, 0.75f, 0.75f, 0.75f); + constexpr auto COLOR_END = Color(0.0f, 0.0f, 0.0f, 0.0f); constexpr auto LIFE_MAX = 2.5f; constexpr auto VEL_ABS = 4.0f; constexpr auto EXP_RATE_ON_WATER = 6.0f; @@ -382,14 +383,14 @@ namespace TEN::Entities::Vehicles // Spawn left wake. StreamerEffect.Spawn( vehicleItem.Index, (int)tagLeft, - positions.first, dir, orient2D, COLOR, + positions.first, dir, orient2D, COLOR_START, COLOR_END, 0.0f, life, vel, expRate, 0, StreamerFeatherType::Right, BlendMode::Additive); // Spawn right wake. StreamerEffect.Spawn( vehicleItem.Index, (int)tagRight, - positions.second, dir, orient2D, COLOR, + positions.second, dir, orient2D, COLOR_START, COLOR_END, 0.0f, life, vel, expRate, 0, StreamerFeatherType::Left, BlendMode::Additive); }