Single Laser tr3 - Tripwire (#1336)

* first try of the TR3 laserbeams - nothing to see

* update laser; thickness with ocb

* fixed collision

* SLOT-change.  NEWSlot ID #426

replaced ID_TRIPWIRE with ID_LASER_BEAM

* Rename files

* Rename functions

* Cleanup

* Simplify laser beam

* Cleanup

* Construct laser beam cylinder

* changed shader

* Set beam radius with OCB

* fixed shader for laserbeam

* fixed shader for single laserbeam; finished code

* Update TombEngine.sln

Win32 restored on lines 18 and 19

* update ObjectsIDs.h

* moved laser effects into SpriteEffects.hlsli

---------

Co-authored-by: Sezz <sezzary@outlook.com>
This commit is contained in:
Nemoel-Tomo 2024-03-25 21:50:21 +01:00 committed by GitHub
parent c8cbb73ed9
commit ffd9c21d50
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 612 additions and 165 deletions

View file

@ -924,6 +924,7 @@ FISHTANK
DOPPELGANGER_ORIGIN
CORPSE
WRAITH_TRAP
SINGLE_LASER
MESHSWAP1
MESHSWAP2
MESHSWAP3

View file

@ -49,6 +49,7 @@
#include "Objects/TR5/Emitter/tr5_rats_emitter.h"
#include "Objects/TR5/Emitter/tr5_spider_emitter.h"
#include "Objects/TR5/Trap/LaserBarrier.h"
#include "Objects/TR5/Trap/LaserBeam.h"
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
#include "Scripting/Include/Objects/ScriptInterfaceObjectsHandler.h"
#include "Scripting/Include/ScriptInterfaceGame.h"
@ -430,6 +431,7 @@ void CleanUp()
ClearDrips();
ClearRipples();
ClearLaserBarrierEffects();
ClearLaserBeamEffects();
DisableSmokeParticles();
DisableSparkParticles();
DisableDebris();

View file

@ -0,0 +1,231 @@
#include "framework.h"
#include "Objects/TR5/Trap/LaserBeam.h"
#include "Game/collision/collide_room.h"
#include "Game/collision/floordata.h"
#include "Game/control/los.h"
#include "Game/effects/effects.h"
#include "Game/effects/item_fx.h"
#include "Game/effects/spark.h"
#include "Game/items.h"
#include "Game/Lara/lara.h"
#include "Game/people.h"
#include "Math/Math.h"
#include "Renderer/Renderer.h"
#include "Specific/level.h"
using namespace TEN::Effects::Items;
using namespace TEN::Effects::Spark;
using namespace TEN::Math;
using namespace TEN::Renderer;
namespace TEN::Traps::TR5
{
constexpr auto LASER_BEAM_LIGHT_INTENSITY = 50.0f;
constexpr auto LASER_BEAM_LIGHT_AMPLITUDE = 31.0f;
extern std::unordered_map<int, LaserBeamEffect> LaserBeams = {};
void LaserBeamEffect::Initialize(const ItemInfo& item)
{
constexpr auto RADIUS_STEP = BLOCK(0.002f);
Color = item.Model.Color;
Color.w = 1.0f;
Radius = (item.TriggerFlags == 0) ? RADIUS_STEP : (abs(item.TriggerFlags) * RADIUS_STEP);
IsLethal = (item.TriggerFlags > 0);
IsHeavyActivator = (item.TriggerFlags <= 0);
Update(item);
}
static void SpawnLaserSpark(const GameVector& pos, short angle, int count, const Vector4& colorStart)
{
for (int i = 0; i < count; i++)
{
float ang = TO_RAD(angle);
auto vel = Vector3(
sin(ang + Random::GenerateFloat(-PI_DIV_2, PI_DIV_2)),
Random::GenerateFloat(-1, 1),
cos(ang + Random::GenerateFloat(-PI_DIV_2, PI_DIV_2)));
vel += Vector3(Random::GenerateFloat(-64, 64), Random::GenerateFloat(-64, 64), Random::GenerateFloat(-64, 64));
vel.Normalize(vel);
auto& spark = GetFreeSparkParticle();
spark = {};
spark.age = 0;
spark.life = Random::GenerateFloat(10, 20);
spark.friction = 0.98f;
spark.gravity = 1.2f;
spark.width = 7.0f;
spark.height = 34.0f;
spark.room = pos.RoomNumber;
spark.pos = pos.ToVector3();
spark.velocity = vel * Random::GenerateFloat(17, 24);
spark.sourceColor = colorStart;
spark.destinationColor = Vector4::Zero;
spark.active = true;
}
}
static void SpawnLaserBeamLight(const Vector3& pos, int roomNumber, const Color& color, float intensity, float amplitude)
{
constexpr auto FALLOFF = 8;
float intensityNorm = intensity - Random::GenerateFloat(0.0f, amplitude);
TriggerDynamicLight(
pos.x, pos.y, pos.z,
FALLOFF,
intensityNorm * (color.x / 2),
intensityNorm * (color.y / 2),
intensityNorm * (color.z / 2));
}
void LaserBeamEffect::Update(const ItemInfo& item)
{
auto orient = EulerAngles(item.Pose.Orientation.x + ANGLE(180.0f), item.Pose.Orientation.y, item.Pose.Orientation.z);
auto dir = orient.ToDirection();
auto rotMatrix = orient.ToRotationMatrix();
auto origin = GameVector(item.Pose.Position, item.RoomNumber);
auto target = GameVector(
Geometry::TranslatePoint(origin.ToVector3(), dir, MAX_VISIBILITY_DISTANCE),
GetCollision(origin.ToVector3i(), origin.RoomNumber, dir, MAX_VISIBILITY_DISTANCE).RoomNumber);
// Hit wall; spawn sparks and light.
if (!LOS(&origin, &target))
{
if (item.TriggerFlags > 0)
{
SpawnLaserSpark(target, Random::GenerateAngle(), 3, Color);
SpawnLaserSpark(target, Random::GenerateAngle(), 3, Color);
}
SpawnLaserBeamLight(target.ToVector3(), target.RoomNumber, item.Model.Color, LASER_BEAM_LIGHT_INTENSITY, LASER_BEAM_LIGHT_AMPLITUDE);
}
float length = Vector3::Distance(origin.ToVector3(), target.ToVector3());
// Calculate cylinder vertices.
float angle = 0.0f;
for (int i = 0; i < LaserBeamEffect::SUBDIVISION_COUNT; i++)
{
float sinAngle = sin(angle);
float cosAngle = cos(angle);
auto relVertex = Vector3(Radius * sinAngle, Radius * cosAngle, 0.0f);
auto vertex = item.Pose.Position.ToVector3() + Vector3::Transform(relVertex, rotMatrix);
Vertices[i] = vertex;
Vertices[SUBDIVISION_COUNT + i] = Geometry::TranslatePoint(vertex, dir, length);
angle += PI_MUL_2 / SUBDIVISION_COUNT;
}
// Calculate bounding box.
float boxApothem = (Radius - ((Radius * SQRT_2) - Radius) + Radius) / 2;
auto center = (origin.ToVector3() + target.ToVector3()) / 2;
auto extents = Vector3(boxApothem, boxApothem, length / 2);
BoundingBox = BoundingOrientedBox(center, extents, orient.ToQuaternion());
}
void InitializeLaserBeam(short itemNumber)
{
const auto& item = g_Level.Items[itemNumber];
auto beam = LaserBeamEffect{};
beam.Initialize(item);
LaserBeams.insert({ itemNumber, beam });
}
void ControlLaserBeam(short itemNumber)
{
if (!LaserBeams.count(itemNumber))
return;
auto& item = g_Level.Items[itemNumber];
auto& beam = LaserBeams.at(itemNumber);
if (!TriggerActive(&item))
{
beam.IsActive = false;
beam.Color.w = 0.0f;
item.Model.Color.w = 0.0f;
return;
}
// Brightness fade-in and distortion.
if (item.Model.Color.w < 1.0f)
item.Model.Color.w += 0.02f;
if (beam.Color.w < 1.0f)
beam.Color.w += 0.02f;
// TODO: Weird.
if (item.Model.Color.w > 8.0f)
{
beam.Color.w = 0.8f;
item.Model.Color.w = 0.8f;
}
beam.IsActive = true;
beam.Update(item);
if (item.Model.Color.w >= 0.8f)
SpawnLaserBeamLight(item.Pose.Position.ToVector3(), item.RoomNumber, item.Model.Color, LASER_BEAM_LIGHT_INTENSITY, LASER_BEAM_LIGHT_AMPLITUDE);
SoundEffect(SFX_TR5_DOOR_BEAM, &item.Pose);
}
void CollideLaserBeam(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll)
{
constexpr auto LASER_BEAM_LIGHT_INTENSITY_MODIFY = 255.0f;
constexpr auto LASER_BEAM_LIGHT_AMPLITUDE_MODIFY = 100.0f;
if (!LaserBeams.count(itemNumber))
return;
auto& item = g_Level.Items[itemNumber];
auto& beam = LaserBeams.at(itemNumber);
if (!beam.IsActive)
return;
auto origin = GameVector(item.Pose.Position, item.RoomNumber);
auto basePos = origin.ToVector3();
auto rotMatrix = EulerAngles(item.Pose.Orientation.x + ANGLE(180.0f), item.Pose.Orientation.y, item.Pose.Orientation.z);
auto target = GameVector(Geometry::TranslatePoint(origin.ToVector3(), rotMatrix, MAX_VISIBILITY_DISTANCE), 0);
auto pointColl = GetCollision(target.ToVector3i(),item.RoomNumber);
if (pointColl.RoomNumber != target.RoomNumber)
target.RoomNumber = pointColl.RoomNumber;
bool los2 = LOS(&origin, &target);
auto hitPos = Vector3i::Zero;
if (ObjectOnLOS2(&origin, &target, &hitPos, nullptr, ID_LARA) == LaraItem->Index && !los2)
{
if (beam.IsLethal &&
playerItem->HitPoints > 0 && playerItem->Effect.Type != EffectType::Smoke)
{
ItemRedLaserBurn(playerItem, 2.0f * FPS);
DoDamage(playerItem, MAXINT);
}
else if (beam.IsHeavyActivator)
{
TestTriggers(&item, true, item.Flags & IFLAG_ACTIVATION_MASK);
}
beam.Color.w = Random::GenerateFloat(0.6f, 1.0f);
SpawnLaserBeamLight(item.Pose.Position.ToVector3(), item.RoomNumber, item.Model.Color, LASER_BEAM_LIGHT_INTENSITY_MODIFY, LASER_BEAM_LIGHT_AMPLITUDE_MODIFY);
}
}
void ClearLaserBeamEffects()
{
LaserBeams.clear();
}
}

View file

@ -0,0 +1,35 @@
#pragma once
#include "Math/Math.h"
using namespace TEN::Math;
struct CollisionInfo;
struct ItemInfo;
namespace TEN::Traps::TR5
{
struct LaserBeamEffect
{
static constexpr auto SUBDIVISION_COUNT = 8;
Vector4 Color = Vector4::Zero;
BoundingOrientedBox BoundingBox = {};
std::array<Vector3, SUBDIVISION_COUNT * 2> Vertices = {};
float Radius = 0.0f;
bool IsActive = false;
bool IsLethal = false;
bool IsHeavyActivator = false;
void Initialize(const ItemInfo& item);
void Update(const ItemInfo& item);
};
extern std::unordered_map<int, LaserBeamEffect> LaserBeams;
void InitializeLaserBeam(short itemNumber);
void ControlLaserBeam(short itemNumber);
void CollideLaserBeam(short itemNumber, ItemInfo* playerItem, CollisionInfo* coll);
void ClearLaserBeamEffects();
}

View file

@ -14,7 +14,7 @@
#include "Specific/level.h"
// Creatures
#include "Objects/TR5/Entity/AutoGun.h" // OK
#include "Objects/TR5/Entity/AutoGun.h" // OK
#include "Objects/TR5/Entity/HeavyGuard.h" // OK
#include "Objects/TR5/Entity/tr5_brownbeast.h" // OK
#include "Objects/TR5/Entity/tr5_chef.h" // OK
@ -58,6 +58,7 @@
#include "Objects/Effects/EmberEmitter.h"
#include "Objects/Effects/tr5_electricity.h"
#include "Objects/TR5/Trap/LaserBarrier.h"
#include "Objects/TR5/Trap/LaserBeam.h"
#include "Objects/TR5/Trap/ZipLine.h"
#include "Objects/TR5/Object/tr5_rollingball.h"
#include "Objects/TR5/Trap/tr5_ventilator.h"
@ -947,6 +948,16 @@ static void StartTrap(ObjectInfo *obj)
obj->drawRoutine = nullptr;
obj->usingDrawAnimatingItem = false;
}
obj = &Objects[ID_LASER_BEAM];
if (obj->loaded)
{
obj->Initialize = InitializeLaserBeam;
obj->control = ControlLaserBeam;
obj->collision = CollideLaserBeam;
obj->drawRoutine = nullptr;
obj->usingDrawAnimatingItem = false;
}
}
static void StartSwitch(ObjectInfo *obj)

View file

@ -343,7 +343,7 @@ enum GAME_OBJECT_ID : short
ID_EXPANDING_PLATFORM,
ID_SQUISHY_BLOCK1,
ID_SQUISHY_BLOCK2,
ID_TRIPWIRE,
ID_LASER_BEAM,
ID_MINE_DETECTOR,
ID_MAP,
ID_SECRET_MAP,

View file

@ -412,6 +412,7 @@ namespace TEN::Renderer
void InitializeSky();
void DrawAllStrings();
void PrepareLaserBarriers(RenderView& view);
void PrepareSingleLaserBeam(RenderView& view);
void DrawHorizonAndSky(RenderView& renderView, ID3D11DepthStencilView* depthTarget);
void DrawRooms(RenderView& view, RendererPass rendererPass);
void DrawItems(RenderView& view, RendererPass rendererPass);

View file

@ -1556,6 +1556,7 @@ namespace TEN::Renderer
PrepareRopes(view);
PrepareStreamers(view);
PrepareLaserBarriers(view);
PrepareSingleLaserBeam(view);
// Sprites grouped in buckets for instancing. Non-commutative sprites are collected for a later stage.
SortAndPrepareSprites(view);

View file

@ -27,6 +27,7 @@
#include "Game/Setup.h"
#include "Math/Math.h"
#include "Objects/TR5/Trap/LaserBarrier.h"
#include "Objects/TR5/Trap/LaserBeam.h"
#include "Objects/Utils/object_helper.h"
#include "Renderer/Structures/RendererSprite2D.h"
#include "Renderer/Structures/RendererSprite.h"
@ -62,10 +63,7 @@ namespace TEN::Renderer
void Renderer::PrepareLaserBarriers(RenderView& view)
{
if (LaserBarriers.empty())
return;
for (const auto& [entityID, barrier] : LaserBarriers)
for (const auto& [itemNumber, barrier] : LaserBarriers)
{
for (const auto& beam : barrier.Beams)
{
@ -79,11 +77,59 @@ namespace TEN::Renderer
}
}
void Renderer::PrepareSingleLaserBeam(RenderView& view)
{
for (const auto& [itemNumber, beam] : LaserBeams)
{
// Prepare cylinder tube.
for (int i = 0; i < LaserBeamEffect::SUBDIVISION_COUNT; i++)
{
bool isLastSubdivision = (i == (LaserBeamEffect::SUBDIVISION_COUNT - 1));
AddColoredQuad(
beam.Vertices[i],
beam.Vertices[isLastSubdivision ? 0 : (i + 1)],
beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + (isLastSubdivision ? 0 : (i + 1))],
beam.Vertices[LaserBeamEffect::SUBDIVISION_COUNT + i],
beam.Color, beam.Color,
beam.Color, beam.Color,
BlendMode::Additive, view, SpriteRenderType::LaserBeam);
}
// Prepare cylinder caps.
for (int i = 0; i < 2; i++)
{
int baseIndex = LaserBeamEffect::SUBDIVISION_COUNT * i;
AddColoredQuad(
beam.Vertices[baseIndex + 0], beam.Vertices[baseIndex + 1],
beam.Vertices[baseIndex + 2], beam.Vertices[baseIndex + 3],
beam.Color, beam.Color,
beam.Color, beam.Color,
BlendMode::Additive, view, SpriteRenderType::LaserBeam);
AddColoredQuad(
beam.Vertices[baseIndex + 0], beam.Vertices[baseIndex + 3],
beam.Vertices[baseIndex + 4], beam.Vertices[baseIndex + 7],
beam.Color, beam.Color,
beam.Color, beam.Color,
BlendMode::Additive, view, SpriteRenderType::LaserBeam);
AddColoredQuad(
beam.Vertices[baseIndex + 4], beam.Vertices[baseIndex + 5],
beam.Vertices[baseIndex + 6], beam.Vertices[baseIndex + 7],
beam.Color, beam.Color,
beam.Color, beam.Color,
BlendMode::Additive, view, SpriteRenderType::LaserBeam);
}
}
}
void Renderer::PrepareStreamers(RenderView& view)
{
constexpr auto BLEND_MODE_DEFAULT = BlendMode::Additive;
constexpr auto DEFAULT_BLEND_MODE = BlendMode::Additive;
for (const auto& [entityNumber, module] : StreamerEffect.Modules)
for (const auto& [itemNumber, module] : StreamerEffect.Modules)
{
for (const auto& [tag, pool] : module.Pools)
{
@ -96,9 +142,9 @@ namespace TEN::Renderer
if (segment.Life <= 0.0f)
continue;
// Determine blend mode.
auto blendMode = BLEND_MODE_DEFAULT;
auto blendMode = DEFAULT_BLEND_MODE;
if (segment.Flags & (int)StreamerFlags::BlendModeAdditive)
blendMode = BlendMode::AlphaBlend;

View file

@ -232,7 +232,8 @@ enum class RendererPass
enum class SpriteRenderType
{
Default,
LaserBarrier
LaserBarrier,
LaserBeam
};
enum class RendererObjectType

View file

@ -346,7 +346,7 @@ The following constants are inside ObjID.
EXPANDING_PLATFORM
SQUISHY_BLOCK1
SQUISHY_BLOCK2
TRIPWIRE
LASER_BEAM
MINE_DETECTOR
MAP
SECRET_MAP
@ -1521,7 +1521,7 @@ static const std::unordered_map<std::string, GAME_OBJECT_ID> kObjIDs {
{ "EXPANDING_PLATFORM", ID_EXPANDING_PLATFORM },
{ "SQUISHY_BLOCK1", ID_SQUISHY_BLOCK1 },
{ "SQUISHY_BLOCK2", ID_SQUISHY_BLOCK2 },
{ "TRIPWIRE", ID_TRIPWIRE },
{ "LASER_BEAM", ID_LASER_BEAM },
{ "MINE_DETECTOR", ID_MINE_DETECTOR },
{ "MAP", ID_MAP },
{ "SECRET_MAP", ID_SECRET_MAP },

View file

@ -24,182 +24,89 @@
cbuffer BlendingBuffer : register(b12)
{
uint BlendMode;
int AlphaTest;
float AlphaThreshold;
uint BlendMode;
int AlphaTest;
float AlphaThreshold;
};
void DoAlphaTest(float4 inputColor)
{
if (AlphaTest == ALPHATEST_GREATER_THAN && inputColor.w < AlphaThreshold)
{
discard;
}
else if (AlphaTest == ALPHATEST_LESS_THAN && inputColor.w > AlphaThreshold)
{
discard;
}
else
{
return;
}
if (AlphaTest == ALPHATEST_GREATER_THAN && inputColor.w < AlphaThreshold)
{
discard;
}
else if (AlphaTest == ALPHATEST_LESS_THAN && inputColor.w > AlphaThreshold)
{
discard;
}
else
{
return;
}
}
float4 DoDistanceFogForPixel(float4 sourceColor, float4 fogColor, float value)
{
switch (BlendMode)
{
case BLENDMODE_ADDITIVE:
case BLENDMODE_SCREEN:
case BLENDMODE_LIGHTEN:
fogColor.xyz *= Luma(sourceColor.xyz);
break;
switch (BlendMode)
{
case BLENDMODE_ADDITIVE:
case BLENDMODE_SCREEN:
case BLENDMODE_LIGHTEN:
fogColor.xyz *= Luma(sourceColor.xyz);
break;
case BLENDMODE_SUBTRACTIVE:
case BLENDMODE_EXCLUDE:
fogColor.xyz *= 1.0f - Luma(sourceColor.xyz);
break;
case BLENDMODE_SUBTRACTIVE:
case BLENDMODE_EXCLUDE:
fogColor.xyz *= 1.0f - Luma(sourceColor.xyz);
break;
case BLENDMODE_ALPHABLEND:
fogColor.w = sourceColor.w;
break;
case BLENDMODE_ALPHABLEND:
fogColor.w = sourceColor.w;
break;
default:
break;
}
default:
break;
}
if (fogColor.w > sourceColor.w)
fogColor.w = sourceColor.w;
if (fogColor.w > sourceColor.w)
fogColor.w = sourceColor.w;
float4 result = lerp(sourceColor, fogColor, value);
return result;
float4 result = lerp(sourceColor, fogColor, value);
return result;
}
float4 DoFogBulbsForPixel(float4 sourceColor, float4 fogColor)
{
switch (BlendMode)
{
case BLENDMODE_ADDITIVE:
case BLENDMODE_SCREEN:
case BLENDMODE_LIGHTEN:
fogColor.xyz *= Luma(sourceColor);
break;
switch (BlendMode)
{
case BLENDMODE_ADDITIVE:
case BLENDMODE_SCREEN:
case BLENDMODE_LIGHTEN:
fogColor.xyz *= Luma(sourceColor);
break;
case BLENDMODE_SUBTRACTIVE:
case BLENDMODE_EXCLUDE:
fogColor.xyz *= 1.0f - Luma(sourceColor.xyz);
break;
case BLENDMODE_SUBTRACTIVE:
case BLENDMODE_EXCLUDE:
fogColor.xyz *= 1.0f - Luma(sourceColor.xyz);
break;
case BLENDMODE_ALPHABLEND:
fogColor.w = sourceColor.w;
break;
case BLENDMODE_ALPHABLEND:
fogColor.w = sourceColor.w;
break;
default:
break;
default:
break;
}
}
if (fogColor.w > sourceColor.w)
fogColor.w = sourceColor.w;
if (fogColor.w > sourceColor.w)
fogColor.w = sourceColor.w;
float4 result = sourceColor;
float4 result = sourceColor;
result.xyz += saturate(fogColor.xyz);
result.xyz += saturate(fogColor.xyz);
return result;
}
float4 DoLaserBarrierEffect(float3 input, float4 output, float2 uv, float faceFactor, float timeUniform)
{
float2 noiseTexture = input.xy / uv;
noiseTexture *= uv.x / uv.y;
float noiseValue = FractalNoise(noiseTexture * 8.0f - timeUniform);
float4 color = output;
float gradL = smoothstep(0.0, 1.0, uv.x);
float gradR = smoothstep(1.0, 0.0, uv.x);
float gradT = smoothstep(0.0, 0.25, uv.y);
float gradB = 1.0 - smoothstep(0.75, 1.0, uv.y);
float distortion = timeUniform / 1024;
float3 noisix = SimplexNoise
(
SimplexNoise(float3(input.r * distortion, input.g, input.b))
);
float3 shadowx = SimplexNoise
(
cos(SimplexNoise(sin(timeUniform + input.rgb * 400)))
);
noisix.x = noisix.x > 0.9 ? 0.7 : noisix.x;
noisix.y = noisix.y > 0.9 ? 0.7 : noisix.y;
noisix.z = noisix.z > 0.9 ? 0.7 : noisix.z;
color.rgb += noisix + 0.5f;
color.rgb -= noisix + 0.2f;
float frequency = 0.1;
float amplitude = 0.8;
float persistence = 0.5;
float noiseValue2 = 0;
float noiseValue3 = 0;
float2 uv84 = (uv * 2.4);
uv84.y = (uv84.y - 1.3);
uv84.x = (uv84.x / 1.3);
float2 uv85 = (uv / 2.4);
noiseValue2 = AnimatedNebula(uv84, timeUniform * 0.1f);
frequency = 2.5;
amplitude = 0.2;
persistence = 4.7;
float2 uv83 = uv * 8;
uv83.y = (uv.y + (timeUniform * 0.02));
noiseValue3 = NebularNoise(uv83, frequency, amplitude, persistence);
noiseValue2 += AnimatedNebula(uv/2, timeUniform * 0.05f);
color.rgb *= noiseValue2 + 0.6f;
color.rgb += noiseValue3;
color.a *= noiseValue + 0.01f;
color.rgb -= shadowx + 0.1f;
color.a *= noiseValue2 + 0.9f;
color.a *= noiseValue3 + 2.0f;
float fade0 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradT)));
float fade1 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradB)));
float fade2 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradB)));
float fade3 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradT)));
float fadeL = 1.40f * faceFactor * faceFactor * (1.0 - gradL);
float fadeB = 2.75f * faceFactor * faceFactor * (1.0 - gradB);
float fadeR = 1.40f * faceFactor * faceFactor * (1.0 - gradR);
float fadeT = 2.75f * faceFactor * faceFactor * (1.0 - gradT);
float fade = max(
max(max(fade0, fade1), max(fade2, fade3)),
max(max(fadeL, fadeR), max(fadeB, fadeT)));
float scale = 1.0 - fade;
color *= scale;
float decayFactor = 1.0f;
if (uv.y > 0.5f && uv.y < 1.0f)
{
decayFactor = uv.y / 2;
}
if (uv.y < 0.5f && uv.y > 0.0f)
{
decayFactor = (1.0f - uv.y) / 2;
}
color *= decayFactor;
color.rgb = smoothstep(ZERO, EIGHT_FIVE, color.rgb);
return color;
return result;
}
#endif // BLENDINGSHADER

View file

@ -0,0 +1,200 @@
#ifndef SPRITEEFFECTSSHADER
#define SPRITEEFFECTSSHADER
#include "./Math.hlsli"
#define ZERO float3(0.0f, 0.0f, 0.0f)
#define EIGHT_FIVE float3( 0.85f, 0.85f, 0.85f)
#define BLENDING 0.707f
float4 DoLaserBarrierEffect(float3 input, float4 output, float2 uv, float faceFactor, float timeUniform)
{
float2 noiseTexture = input.xy / uv;
noiseTexture *= uv.x / uv.y;
float noiseValue = FractalNoise(noiseTexture * 8.0f - timeUniform);
float4 color = output;
float gradL = smoothstep(0.0, 1.0, uv.x);
float gradR = smoothstep(1.0, 0.0, uv.x);
float gradT = smoothstep(0.0, 0.25, uv.y);
float gradB = 1.0 - smoothstep(0.75, 1.0, uv.y);
float distortion = timeUniform / 1024;
float3 noisix = SimplexNoise
(
SimplexNoise(float3(input.r * distortion, input.g, input.b))
);
float3 shadowx = SimplexNoise
(
cos(SimplexNoise(sin(timeUniform + input.rgb * 400)))
);
noisix.x = noisix.x > 0.9 ? 0.7 : noisix.x;
noisix.y = noisix.y > 0.9 ? 0.7 : noisix.y;
noisix.z = noisix.z > 0.9 ? 0.7 : noisix.z;
color.rgb += noisix + 0.5f;
color.rgb -= noisix + 0.2f;
float frequency = 0.1;
float amplitude = 0.8;
float persistence = 0.5;
float noiseValue2 = 0;
float noiseValue3 = 0;
float2 uv84 = (uv * 2.4);
uv84.y = (uv84.y - 1.3);
uv84.x = (uv84.x / 1.3);
float2 uv85 = (uv / 2.4);
noiseValue2 = AnimatedNebula(uv84, timeUniform * 0.1f);
frequency = 2.5;
amplitude = 0.2;
persistence = 4.7;
float2 uv83 = uv * 8;
uv83.y = (uv.y + (timeUniform * 0.02));
noiseValue3 = NebularNoise(uv83, frequency, amplitude, persistence);
noiseValue2 += AnimatedNebula(uv / 2, timeUniform * 0.05f);
color.rgb *= noiseValue2 + 0.6f;
color.rgb += noiseValue3;
color.a *= noiseValue + 0.01f;
color.rgb -= shadowx + 0.1f;
color.a *= noiseValue2 + 0.9f;
color.a *= noiseValue3 + 2.0f;
float fade0 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradT)));
float fade1 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradB)));
float fade2 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradB)));
float fade3 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradT)));
float fadeL = 1.40f * faceFactor * faceFactor * (1.0 - gradL);
float fadeB = 2.75f * faceFactor * faceFactor * (1.0 - gradB);
float fadeR = 1.40f * faceFactor * faceFactor * (1.0 - gradR);
float fadeT = 2.75f * faceFactor * faceFactor * (1.0 - gradT);
float fade = max(
max(max(fade0, fade1), max(fade2, fade3)),
max(max(fadeL, fadeR), max(fadeB, fadeT)));
float scale = 1.0 - fade;
color *= scale;
float decayFactor = 1.0f;
if (uv.y > 0.5f && uv.y < 1.0f)
{
decayFactor = uv.y / 2;
}
if (uv.y < 0.5f && uv.y > 0.0f)
{
decayFactor = (1.0f - uv.y) / 2;
}
color *= decayFactor;
color.rgb = smoothstep(ZERO, EIGHT_FIVE, color.rgb);
return color;
}
float4 DoLaserBeamEffect(float3 input, float4 output, float2 uv, float faceFactor, float timeUniform)
{
float2 noiseTexture = input.xy / uv;
noiseTexture *= uv.x / uv.y;
float noiseValue = FractalNoise(noiseTexture * 0.1f - timeUniform);
float4 color = output;
float gradL = smoothstep(0.0, 0.0, uv.x);
float gradR = smoothstep(0.0, 0.0, uv.x);
float gradT = smoothstep(0.0, 0.25, uv.y);
float gradB = 1.0 - smoothstep(0.75, 1.0, uv.y);
// Stretching the UV coordinates
float stretchFactor = 0.005f;
uv.x *= stretchFactor;
float distortion = timeUniform / 1024;
float3 noisix = SimplexNoise
(
SimplexNoise(float3(input.r * distortion, input.g, input.b))
);
float3 shadowx = SimplexNoise
(
cos(SimplexNoise(sin(timeUniform + input.rgb * 400)))
);
noisix.x = noisix.x > 0.9 ? 0.7 : noisix.x;
noisix.y = noisix.y > 0.9 ? 0.7 : noisix.y;
noisix.z = noisix.z > 0.9 ? 0.7 : noisix.z;
color.rgb += noisix + 0.5f;
color.rgb -= noisix + 0.2f;
float frequency = 0.1;
float amplitude = 0.8;
float persistence = 0.5;
float noiseValue2 = 0;
float noiseValue3 = 0;
float2 uv84 = (uv * 1.4);
uv84.y = (uv84.y - 1.3);
uv84.x = (uv84.x / 1.3);
float2 uv85 = (uv / 1.4);
noiseValue2 = AnimatedNebula(uv84, timeUniform * 0.1f);
frequency = 2.5;
amplitude = 0.2;
persistence = 4.7;
float2 uv83 = uv * 6;
uv83.y = (uv.y + (timeUniform * 0.02));
noiseValue3 = NebularNoise(uv83, frequency, amplitude, persistence);
noiseValue2 += AnimatedNebula(uv / 2, timeUniform * 0.05f);
color.rgb *= noiseValue2 + 0.6f;
color.rgb += noiseValue3;
color.a *= noiseValue + 0.01f;
color.rgb -= shadowx + 0.1f;
color.a *= noiseValue2 + 0.9f;
color.a *= noiseValue3 + 2.0f;
float fade0 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradT)));
float fade1 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradL, gradB)));
float fade2 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradB)));
float fade3 = faceFactor * max(0.0, 1.0 - dot(float2(BLENDING, BLENDING), float2(gradR, gradT)));
float fadeL = 0; //fade out hight
float fadeB = 0.3f * faceFactor * faceFactor * (0.3 - gradB); //fade out width
float fadeR = 0; //fade out hight
float fadeT = 0.3f * faceFactor * faceFactor * (0.3 - gradT); //fade out width
float fade = max(
max(max(fade0, fade1), max(fade2, fade3)),
max(max(fadeL, fadeR), max(fadeB, fadeT)));
float scale = 1.0 - fade;
color *= scale;
float decayFactor = 1.0f;
if (uv.y > 0.5f && uv.y < 1.0f)
{
decayFactor = uv.y / 2;
}
if (uv.y < 0.5f && uv.y > 0.0f)
{
decayFactor = (1.0f - uv.y) / 2;
}
color *= decayFactor;
color.rgb *= 0.17; // Reduce brightness. Don't change
color.rgb = smoothstep(ZERO, EIGHT_FIVE, color.rgb);
return color;
}
#endif // SPRITEEFFECTSSHADER

View file

@ -3,6 +3,7 @@
#include "./VertexInput.hlsli"
#include "./Math.hlsli"
#include "./ShaderLight.hlsli"
#include "./SpriteEffects.hlsli"
// NOTE: This shader is used for all 3D and alpha blended sprites, because we send aleady transformed vertices to the GPU
// instead of instances
@ -77,9 +78,14 @@ float4 PS(PixelShaderInput input) : SV_TARGET
output = DoLaserBarrierEffect(input.Position, output, input.UV, FADE_FACTOR, Frame);
}
if (RenderType == 2)
{
output = DoLaserBeamEffect(input.Position, output, input.UV, FADE_FACTOR, Frame);
}
output.xyz -= float3(input.FogBulbs.w, input.FogBulbs.w, input.FogBulbs.w);
output.xyz = saturate(output.xyz);
output = DoDistanceFogForPixel(output, float4(0.0f, 0.0f, 0.0f, 0.0f), input.DistanceFog);
return output;

View file

@ -668,6 +668,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)"</Command>
<ClInclude Include="Objects\TR5\Switch\tr5_crowdove_switch.h" />
<ClInclude Include="Objects\TR5\Switch\tr5_raisingcog.h" />
<ClInclude Include="Objects\TR5\Trap\LaserBarrier.h" />
<ClInclude Include="Objects\TR5\Trap\LaserBeam.h" />
<ClInclude Include="Objects\TR5\Trap\tr5_explosion.h" />
<ClInclude Include="Objects\TR5\Trap\tr5_fallingceiling.h" />
<ClInclude Include="Objects\TR5\Trap\tr5_romehammer.h" />
@ -1162,6 +1163,7 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)"</Command>
<ClCompile Include="Objects\TR5\Switch\tr5_raisingcog.cpp" />
<ClCompile Include="Objects\TR5\tr5_objects.cpp" />
<ClCompile Include="Objects\TR5\Trap\LaserBarrier.cpp" />
<ClCompile Include="Objects\TR5\Trap\LaserBeam.cpp" />
<ClCompile Include="Objects\TR5\Trap\tr5_explosion.cpp" />
<ClCompile Include="Objects\TR5\Trap\tr5_fallingceiling.cpp" />
<ClCompile Include="Objects\TR5\Trap\tr5_romehammer.cpp" />
@ -1273,6 +1275,9 @@ xcopy /Y "$(SolutionDir)Libs\zlib\x64\*.dll" "$(TargetDir)"</Command>
<DeploymentContent>true</DeploymentContent>
</None>
<None Include="Shaders\Shadows.hlsli" />
<None Include="Shaders\SpriteEffects.hlsli">
<DeploymentContent>true</DeploymentContent>
</None>
<None Include="Shaders\VertexEffects.hlsli" />
<None Include="Shaders\VertexInput.hlsli">
<DeploymentContent>true</DeploymentContent>