diff --git a/Documentation/doc/1 modules/Effects.html b/Documentation/doc/1 modules/Effects.html
index c7672b1db..d0e1a7f99 100644
--- a/Documentation/doc/1 modules/Effects.html
+++ b/Documentation/doc/1 modules/Effects.html
@@ -145,7 +145,7 @@
GetWind() |
- Get the current wind for the current frame. |
+ Get the wind vector for the current game frame. |
@@ -508,8 +508,8 @@
GetWind()
- Get the current wind for the current frame.
- This represents the 3D displacement applied by the engine on things like particles affected by wind.
+ Get the wind vector for the current game frame.
+ This represents the 3D displacement applied by the engine on things like particles affected by wind.()
@@ -518,7 +518,7 @@
Vec3
- The wind.
+ Wind vector.
diff --git a/Documentation/doc/2 classes/Objects.Moveable.html b/Documentation/doc/2 classes/Objects.Moveable.html
index 54b4f76af..823694a4e 100644
--- a/Documentation/doc/2 classes/Objects.Moveable.html
+++ b/Documentation/doc/2 classes/Objects.Moveable.html
@@ -383,6 +383,14 @@ pickups, and Lara herself (see also Disable the item, as if an antitrigger for it had been stepped on (i.e.
+ Moveable:GetCollidable() |
+ Get the item's collision state. |
+
+
+ Moveable:SetCollidable(collidable) |
+ Set the item's collision. |
+
+
Moveable:MakeInvisible() |
Make the item invisible. |
@@ -1967,6 +1975,49 @@ sas:SetPosition(newPos, false)
+
+
+
+ Moveable:GetCollidable()
+
+
+ Get the item's collision state.
+
+
+
+
+ Returns:
+
+
+ bool
+ item's collision state
+
+
+
+
+
+
+
+
+ Moveable:SetCollidable(collidable)
+
+
+ Set the item's collision.
+
+
+
+ Parameters:
+
+ - collidable
+ bool
+ true if the caller should be collidable, false if no collision should occur.
+
+
+
+
+
+
+
diff --git a/TombEngine/Renderer/RenderView.cpp b/TombEngine/Renderer/RenderView.cpp
index 1f02db401..10dd2c347 100644
--- a/TombEngine/Renderer/RenderView.cpp
+++ b/TombEngine/Renderer/RenderView.cpp
@@ -53,6 +53,7 @@ namespace TEN::Renderer
FogBulbsToDraw.clear();
LensFlaresToDraw.clear();
TransparentObjectsToDraw.clear();
+ Mirrors.clear();
}
RenderViewCamera::RenderViewCamera(CAMERA_INFO* cam, float roll, float fov, float n, float f, int w, int h)
diff --git a/TombEngine/Renderer/RenderView.h b/TombEngine/Renderer/RenderView.h
index b028b4788..740a9714c 100644
--- a/TombEngine/Renderer/RenderView.h
+++ b/TombEngine/Renderer/RenderView.h
@@ -15,6 +15,7 @@
#include "Renderer/Structures/RendererSortableObject.h"
#include "Renderer/Structures/RendererSpriteToDraw.h"
#include "Renderer/Structures/RendererLensFlare.h"
+#include "Renderer/Structures/RendererMirror.h"
namespace TEN::Renderer
{
@@ -54,6 +55,8 @@ namespace TEN::Renderer
std::vector TransparentObjectsToDraw = {};
std::vector LensFlaresToDraw = {};
+ std::vector Mirrors = {};
+
RenderView(CAMERA_INFO* cam, float roll, float fov, float nearPlane, float farPlane, int w, int h);
RenderView(const Vector3& pos, const Vector3& dir, const Vector3& up, int w, int h, int room, float nearPlane, float farPlane, float fov);
diff --git a/TombEngine/Renderer/Renderer.h b/TombEngine/Renderer/Renderer.h
index 2aac47518..c1d1de7ac 100644
--- a/TombEngine/Renderer/Renderer.h
+++ b/TombEngine/Renderer/Renderer.h
@@ -380,6 +380,7 @@ namespace TEN::Renderer
ComPtr _psPostProcessExclusion;
ComPtr _psPostProcessFinalPass;
ComPtr _psPostProcessLensFlare;
+ ComPtr _psDownsampleDepthBuffer;
bool _doingFullscreenPass = false;
@@ -454,12 +455,12 @@ namespace TEN::Renderer
void PrepareSingleLaserBeam(RenderView& view);
void DrawHorizonAndSky(RenderView& renderView, ID3D11DepthStencilView* depthTarget);
void DrawRooms(RenderView& view, RendererPass rendererPass);
- void DrawItems(RenderView& view, RendererPass rendererPass);
- void DrawAnimatingItem(RendererItem* item, RenderView& view, RendererPass rendererPass);
- void DrawWaterfalls(RendererItem* item, RenderView& view, int fps, RendererPass rendererPass);
- void DrawBaddyGunflashes(RenderView& view);
- void DrawStatics(RenderView& view, RendererPass rendererPass);
- void DrawLara(RenderView& view, RendererPass rendererPass);
+ void DrawItems(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawAnimatingItem(RendererItem* item, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawWaterfalls(RendererItem* item, RendererMirror* mirror, RenderView& view, int fps, RendererPass rendererPass);
+ void DrawBaddyGunflashes(RendererMirror* mirror, RenderView& view);
+ void DrawStatics(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawLara(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void PrepareFires(RenderView& view);
void PrepareParticles(RenderView& view);
void PrepareSmokes(RenderView& view);
@@ -472,9 +473,9 @@ namespace TEN::Renderer
void DrawEffects(RenderView& view, RendererPass rendererPass);
void DrawEffect(RenderView& view, RendererEffect* effect, RendererPass rendererPass);
void PrepareSplashes(RenderView& view);
- void DrawSprites(RenderView& view, RendererPass rendererPass);
+ void DrawSprites(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawDisplaySprites(RenderView& view);
- void DrawSortedFaces(RenderView& view);
+ void DrawSortedFaces(RendererMirror* mirror, RenderView& view);
void DrawSingleSprite(RendererSortableObject* object, RendererObjectType lastObjectType, RenderView& view);
void DrawRoomSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view);
void DrawItemSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view);
@@ -487,13 +488,13 @@ namespace TEN::Renderer
void DrawOverlays(RenderView& view);
void PrepareRopes(RenderView& view);
void DrawFishSwarm(RenderView& view, RendererPass rendererPass);
- void DrawBats(RenderView& view, RendererPass rendererPass);
- void DrawRats(RenderView& view, RendererPass rendererPass);
- void DrawScarabs(RenderView& view, RendererPass rendererPass);
+ void DrawBats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawRats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawScarabs(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawSpiders(RenderView& view, RendererPass rendererPass);
- bool DrawGunFlashes(RenderView& view);
- void DrawGunShells(RenderView& view, RendererPass rendererPass);
- void DrawLocusts(RenderView& view, RendererPass rendererPass);
+ bool DrawGunFlashes(RendererMirror* mirror, RenderView& view);
+ void DrawGunShells(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawLocusts(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawStatistics();
void DrawExamines();
void DrawDiary();
@@ -508,9 +509,9 @@ namespace TEN::Renderer
void PrepareSmokeParticles(RenderView& view);
void PrepareSparkParticles(RenderView& view);
void PrepareExplosionParticles(RenderView& view);
- void DrawLaraHolsters(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass);
- void DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass);
- void DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass);
+ void DrawLaraHolsters(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
+ void DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawMoveableMesh(RendererItem* itemToDraw, RendererMesh* mesh, RendererRoom* room, int boneIndex, RenderView& view, RendererPass rendererPass);
void PrepareSimpleParticles(RenderView& view);
void PrepareStreamers(RenderView& view);
@@ -561,7 +562,7 @@ namespace TEN::Renderer
const Vector4& color0, const Vector4& color1, const Vector4& color2, const Vector4& color3,
BlendMode blendMode, RenderView& view, SpriteRenderType renderType = SpriteRenderType::Default);
- Matrix GetWorldMatrixForSprite(RendererSpriteToDraw* spr, RenderView& view);
+ Matrix GetWorldMatrixForSprite(RendererSpriteToDraw* spr, RendererMirror* mirror, RenderView& view);
RendererObject& GetRendererObject(GAME_OBJECT_ID id);
RendererMesh* GetMesh(int meshIndex);
Texture2D CreateDefaultNormalTexture();
diff --git a/TombEngine/Renderer/RendererDraw.cpp b/TombEngine/Renderer/RendererDraw.cpp
index 0086e1fc2..3d04ed099 100644
--- a/TombEngine/Renderer/RendererDraw.cpp
+++ b/TombEngine/Renderer/RendererDraw.cpp
@@ -245,14 +245,14 @@ namespace TEN::Renderer
{
RendererRoom& room = _rooms[item->RoomNumber];
- DrawLaraHolsters(item, &room, renderView, RendererPass::ShadowMap);
- DrawLaraJoints(item, &room, renderView, RendererPass::ShadowMap);
- DrawLaraHair(item, &room, renderView, RendererPass::ShadowMap);
+ DrawLaraHolsters(item, &room, nullptr, renderView, RendererPass::ShadowMap);
+ DrawLaraJoints(item, &room, nullptr, renderView, RendererPass::ShadowMap);
+ DrawLaraHair(item, &room, nullptr, renderView, RendererPass::ShadowMap);
}
}
}
- void Renderer::DrawGunShells(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawGunShells(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
auto& room = _rooms[LaraItem->RoomNumber];
auto* item = &_items[LaraItem->Index];
@@ -282,6 +282,11 @@ namespace TEN::Renderer
worldMatrix = Matrix::Lerp(prevWorldMatrix, worldMatrix, _interpolationFactor);
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
+
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].World = worldMatrix;
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Color = room.AmbientLight;
@@ -476,7 +481,7 @@ namespace TEN::Renderer
}*/
}
- void Renderer::DrawRats(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawRats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (!Objects[ID_RATS_EMITTER].loaded)
{
@@ -567,7 +572,12 @@ namespace TEN::Renderer
{
RendererMesh* mesh = GetMesh(Objects[ID_RATS_EMITTER].meshIndex + (rand() % 8));
- _stStatic.World = rat->Transform;
+ Matrix world = rat->Transform;
+ if (mirror != nullptr)
+ {
+ world = world * mirror->ReflectionMatrix;
+ }
+ _stStatic.World = world;
_stStatic.Color = Vector4::One;
_stStatic.AmbientLight = _rooms[rat->RoomNumber].AmbientLight;
@@ -722,7 +732,7 @@ namespace TEN::Renderer
}
}
- void Renderer::DrawBats(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawBats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (!Objects[ID_BATS_EMITTER].loaded)
return;
@@ -775,7 +785,13 @@ namespace TEN::Renderer
auto transformMatrix = Matrix::Lerp(bat.PrevTransform, bat.Transform, _interpolationFactor);
- _stInstancedStaticMeshBuffer.StaticMeshes[batCount].World = transformMatrix;
+ Matrix world = transformMatrix;
+ if (mirror != nullptr)
+ {
+ world = world * mirror->ReflectionMatrix;
+ }
+
+ _stInstancedStaticMeshBuffer.StaticMeshes[batCount].World = world;
_stInstancedStaticMeshBuffer.StaticMeshes[batCount].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[batCount].Color = Vector4::One;
_stInstancedStaticMeshBuffer.StaticMeshes[batCount].LightMode = (int)mesh.LightMode;
@@ -834,7 +850,7 @@ namespace TEN::Renderer
}
}
- void Renderer::DrawScarabs(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawScarabs(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (!Objects[ID_LITTLE_BEETLE].loaded)
return;
@@ -888,7 +904,13 @@ namespace TEN::Renderer
auto transformMatrix = Matrix::Lerp(beetle.PrevTransform, beetle.Transform, _interpolationFactor);
- _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = transformMatrix;
+ Matrix world = transformMatrix;
+ if (mirror != nullptr)
+ {
+ world = world * mirror->ReflectionMatrix;
+ }
+
+ _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].World = world;
_stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Color = Vector4::One;
_stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].LightMode = (int)mesh.LightMode;
@@ -953,7 +975,7 @@ namespace TEN::Renderer
}
}
- void Renderer::DrawLocusts(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawLocusts(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (!Objects[ID_LOCUSTS].loaded)
return;
@@ -1039,7 +1061,12 @@ namespace TEN::Renderer
auto& mesh = *GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust.counter & 3));
- _stStatic.World = Matrix::Lerp(locust.PrevTransform, locust.Transform, _interpolationFactor);
+ Matrix world = Matrix::Lerp(locust.PrevTransform, locust.Transform, _interpolationFactor);
+ if (mirror != nullptr)
+ {
+ world = world * mirror->ReflectionMatrix;
+ }
+ _stStatic.World = world;
_stStatic.Color = Vector4::One;
_stStatic.AmbientLight = _rooms[locust.roomNumber].AmbientLight;
_cbStatic.UpdateData(_stStatic, _context.Get());
@@ -1724,7 +1751,7 @@ namespace TEN::Renderer
cameraConstantBuffer.FogMinDistance = level.GetFogMinDistance();
cameraConstantBuffer.FogMaxDistance = level.GetFogMaxDistance();
}
- else
+ else
{
cameraConstantBuffer.FogMaxDistance = 0;
cameraConstantBuffer.FogColor = Vector4::Zero;
@@ -1743,10 +1770,10 @@ namespace TEN::Renderer
cameraConstantBuffer.FogBulbs[i].Color = view.FogBulbsToDraw[i].Color;
cameraConstantBuffer.FogBulbs[i].SquaredCameraToFogBulbDistance = SQUARE(view.FogBulbsToDraw[i].Distance);
cameraConstantBuffer.FogBulbs[i].FogBulbToCameraVector = view.FogBulbsToDraw[i].FogBulbToCameraVector;
- }
+ }
_cbCameraMatrices.UpdateData(cameraConstantBuffer, _context.Get());
-
+
ID3D11RenderTargetView* pRenderViewPtrs[2];
// Bind main render target.
@@ -1754,7 +1781,7 @@ namespace TEN::Renderer
// Draw horizon and sky.
DrawHorizonAndSky(view, _renderTarget.DepthStencilView.Get());
-
+
// Build G-Buffer (normals + depth).
_context->ClearRenderTargetView(_normalsRenderTarget.RenderTargetView.Get(), Colors::Black);
_context->ClearRenderTargetView(_depthRenderTarget.RenderTargetView.Get(), Colors::White);
@@ -1764,15 +1791,18 @@ namespace TEN::Renderer
_context->OMSetRenderTargets(2, &pRenderViewPtrs[0], _renderTarget.DepthStencilView.Get());
DrawRooms(view, RendererPass::GBuffer);
- DrawItems(view, RendererPass::GBuffer);
- DrawStatics(view, RendererPass::GBuffer);
+ DrawItems(nullptr, view, RendererPass::GBuffer);
+ DrawStatics(nullptr, view, RendererPass::GBuffer);
DrawSpiders(view, RendererPass::GBuffer);
- DrawScarabs(view, RendererPass::GBuffer);
- DrawGunShells(view, RendererPass::GBuffer);
- DrawBats(view, RendererPass::GBuffer);
+ DrawScarabs(nullptr, view, RendererPass::GBuffer);
+ DrawGunShells(nullptr, view, RendererPass::GBuffer);
+ DrawBats(nullptr, view, RendererPass::GBuffer);
DrawEffects(view, RendererPass::GBuffer);
- DrawRats(view, RendererPass::GBuffer);
- DrawLocusts(view, RendererPass::GBuffer);
+ DrawRats(nullptr, view, RendererPass::GBuffer);
+ DrawLocusts(nullptr, view, RendererPass::GBuffer);
+
+ // Downsample G-Buffer for making faster soft particles and SSAO
+ DownsampleGBuffer();
// Calculate ambient occlusion.
if (g_Configuration.EnableAmbientOcclusion)
@@ -1785,62 +1815,128 @@ namespace TEN::Renderer
_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_context->IASetInputLayout(_inputLayout.Get());
+ _context->RSSetViewports(1, &view.Viewport);
+ ResetScissor();
+
SetBlendMode(BlendMode::Opaque);
SetCullMode(CullMode::CounterClockwise);
SetDepthState(DepthState::Write);
- _context->RSSetViewports(1, &view.Viewport);
- ResetScissor();
-
// Bind main render target again. Main depth buffer is already filled and avoids overdraw in following steps.
_context->OMSetRenderTargets(1, _renderTarget.RenderTargetView.GetAddressOf(), _renderTarget.DepthStencilView.Get());
-
+
// Draw opaque, alpha test, and fast alpha blend faces.
DrawRooms(view, RendererPass::Opaque);
- DrawItems(view, RendererPass::Opaque);
- DrawStatics(view, RendererPass::Opaque);
+ DrawItems(nullptr, view, RendererPass::Opaque);
+ DrawStatics(nullptr, view, RendererPass::Opaque);
DrawSpiders(view, RendererPass::Opaque);
- DrawScarabs(view, RendererPass::Opaque);
- DrawGunShells(view, RendererPass::Opaque);
- DrawBats(view, RendererPass::Opaque);
+ DrawScarabs(nullptr, view, RendererPass::Opaque);
+ DrawGunShells(nullptr, view, RendererPass::Opaque);
+ DrawBats(nullptr, view, RendererPass::Opaque);
DrawEffects(view, RendererPass::Opaque);
- DrawRats(view, RendererPass::Opaque);
- DrawLocusts(view, RendererPass::Opaque);
+ DrawRats(nullptr, view, RendererPass::Opaque);
+ DrawLocusts(nullptr, view, RendererPass::Opaque);
DrawDebris(view, RendererPass::Opaque);
- DrawSprites(view, RendererPass::Opaque);
+ DrawSprites(nullptr, view, RendererPass::Opaque);
DrawFishSwarm(view, RendererPass::Opaque);
+ // Draw mirrored opaque geometry only if Lara is inside a mirror room
+ if (view.Mirrors.size() > 0)
+ {
+ SetCullMode(CullMode::Clockwise);
+
+ for (auto& mirror : view.Mirrors)
+ {
+ DrawItems(&mirror, view, RendererPass::Opaque);
+ DrawStatics(&mirror, view, RendererPass::Opaque);
+ DrawScarabs(&mirror, view, RendererPass::Opaque);
+ DrawGunShells(&mirror, view, RendererPass::Opaque);
+ DrawBats(&mirror, view, RendererPass::Opaque);
+ DrawRats(&mirror, view, RendererPass::Opaque);
+ DrawLocusts(&mirror, view, RendererPass::Opaque);
+ DrawSprites(&mirror, view, RendererPass::Opaque);
+ }
+
+ SetCullMode(CullMode::CounterClockwise);
+ }
+
// Draw additive faces.
DrawRooms(view, RendererPass::Additive);
- DrawItems(view, RendererPass::Additive);
- DrawStatics(view, RendererPass::Additive);
+ DrawItems(nullptr, view, RendererPass::Additive);
+ DrawStatics(nullptr, view, RendererPass::Additive);
DrawSpiders(view, RendererPass::Additive);
- DrawScarabs(view, RendererPass::Additive);
- DrawBats(view, RendererPass::Additive);
+ DrawScarabs(nullptr, view, RendererPass::Additive);
+ DrawBats(nullptr, view, RendererPass::Additive);
DrawEffects(view, RendererPass::Additive);
- DrawRats(view, RendererPass::Additive);
- DrawLocusts(view, RendererPass::Additive);
+ DrawRats(nullptr, view, RendererPass::Additive);
+ DrawLocusts(nullptr, view, RendererPass::Additive);
DrawDebris(view, RendererPass::Additive);
- DrawSprites(view, RendererPass::Additive);
+ DrawSprites(nullptr, view, RendererPass::Additive);
DrawFishSwarm(view, RendererPass::Additive);
+ // Draw mirrored additive geometry only if Lara is inside a mirror room
+ if (view.Mirrors.size() > 0)
+ {
+ SetCullMode(CullMode::Clockwise);
+
+ for (auto& mirror : view.Mirrors)
+ {
+ DrawItems(&mirror, view, RendererPass::Additive);
+ DrawStatics(&mirror, view, RendererPass::Additive);
+ DrawScarabs(&mirror, view, RendererPass::Additive);
+ DrawBats(&mirror, view, RendererPass::Additive);
+ DrawRats(&mirror, view, RendererPass::Additive);
+ DrawLocusts(&mirror, view, RendererPass::Additive);
+ DrawSprites(&mirror, view, RendererPass::Additive);
+ }
+
+ SetCullMode(CullMode::CounterClockwise);
+ }
+
// Collect all non-commutative transparent faces.
// NOTE: Sorted sprites already collected at beginning of frame.
DrawRooms(view, RendererPass::CollectTransparentFaces);
- DrawItems(view, RendererPass::CollectTransparentFaces);
- DrawStatics(view, RendererPass::CollectTransparentFaces);
- DrawBats(view, RendererPass::CollectTransparentFaces);
+ DrawItems(nullptr, view, RendererPass::CollectTransparentFaces);
+ DrawStatics(nullptr, view, RendererPass::CollectTransparentFaces);
+ DrawBats(nullptr, view, RendererPass::CollectTransparentFaces);
DrawEffects(view, RendererPass::CollectTransparentFaces);
- DrawRats(view, RendererPass::CollectTransparentFaces);
- DrawLocusts(view, RendererPass::CollectTransparentFaces);
+ DrawRats(nullptr, view, RendererPass::CollectTransparentFaces);
+ DrawLocusts(nullptr, view, RendererPass::CollectTransparentFaces);
DrawFishSwarm(view, RendererPass::CollectTransparentFaces);
// Draw sorted faces.
- DrawSortedFaces(view);
+ DrawSortedFaces(nullptr, view);
+
+ // Draw mirrored sorted faces only if Lara is inside a mirror room
+ if (view.Mirrors.size() > 0)
+ {
+ SetCullMode(CullMode::None);
+
+ for (auto& mirror : view.Mirrors)
+ {
+ DrawSortedFaces(&mirror, view);
+ }
+
+ SetCullMode(CullMode::CounterClockwise);
+ }
// HACK: Gunflashes drawn after everything because they are very near the camera.
- DrawGunFlashes(view);
- DrawBaddyGunflashes(view);
+ DrawGunFlashes(nullptr, view);
+ DrawBaddyGunflashes(nullptr, view);
+
+ // Draw mirrored gunflashes only if Lara is inside a mirror room
+ if (view.Mirrors.size() > 0)
+ {
+ SetCullMode(CullMode::Clockwise);
+
+ for (auto& mirror : view.Mirrors)
+ {
+ DrawGunFlashes(&mirror, view);
+ DrawBaddyGunflashes(&mirror, view);
+ }
+
+ SetCullMode(CullMode::CounterClockwise);
+ }
// Draw 3D debug lines and triangles.
DrawLines3D(view);
@@ -2160,7 +2256,7 @@ namespace TEN::Renderer
_graphicsSettingsChanged = false;
}
- void Renderer::DrawItems(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawItems(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
unsigned int stride = sizeof(Vertex);
unsigned int offset = 0;
@@ -2189,7 +2285,7 @@ namespace TEN::Renderer
switch (itemToDraw->ObjectID)
{
case ID_LARA:
- DrawLara(view, rendererPass);
+ DrawLara(mirror, view, rendererPass);
break;
case ID_WATERFALL1:
@@ -2200,11 +2296,11 @@ namespace TEN::Renderer
case ID_WATERFALL6:
case ID_WATERFALLSS1:
case ID_WATERFALLSS2:
- DrawWaterfalls(itemToDraw, view, 10, rendererPass);
+ DrawWaterfalls(itemToDraw, mirror, view, 10, rendererPass);
continue;
default:
- DrawAnimatingItem(itemToDraw, view, rendererPass);
+ DrawAnimatingItem(itemToDraw, mirror, view, rendererPass);
break;
}
}
@@ -2223,8 +2319,13 @@ namespace TEN::Renderer
}
}
- void Renderer::DrawWaterfalls(RendererItem* item, RenderView& view, int fps, RendererPass rendererPass)
+ void Renderer::DrawWaterfalls(RendererItem* item, RendererMirror* mirror, RenderView& view, int fps, RendererPass rendererPass)
{
+ if (mirror != nullptr && item->RoomNumber != mirror->RoomNumber)
+ {
+ return;
+ }
+
// Extremely hacky function to get first rendered face of a waterfall object mesh, calculate
// its texture height and scroll all the textures according to that height.
@@ -2259,21 +2360,30 @@ namespace TEN::Renderer
_cbAnimated.UpdateData(_stAnimated, _context.Get());
- DrawAnimatingItem(item, view, rendererPass);
+ DrawAnimatingItem(item, mirror, view, rendererPass);
// Reset animated buffer after rendering just in case
_stAnimated.Fps = _stAnimated.NumFrames = _stAnimated.Type = 0;
_cbAnimated.UpdateData(_stAnimated, _context.Get());
}
- void Renderer::DrawAnimatingItem(RendererItem* item, RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawAnimatingItem(RendererItem* item, RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
+ if (mirror != nullptr && item->RoomNumber != mirror->RoomNumber)
+ {
+ return;
+ }
+
ItemInfo* nativeItem = &g_Level.Items[item->ItemNumber];
RendererRoom* room = &_rooms[item->RoomNumber];
RendererObject& moveableObj = *_moveableObjects[item->ObjectID];
// Bind item main properties
_stItem.World = item->InterpolatedWorld;
+ if (mirror != nullptr)
+ {
+ _stItem.World = _stItem.World * mirror->ReflectionMatrix;
+ }
_stItem.Color = item->Color;
_stItem.AmbientLight = item->AmbientLight;
memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, sizeof(Matrix) * MAX_BONES);
@@ -2293,7 +2403,7 @@ namespace TEN::Renderer
}
}
- void Renderer::DrawStatics(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawStatics(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (_staticTextures.size() == 0 || view.SortedStaticsToDraw.size() == 0)
{
@@ -2427,6 +2537,11 @@ namespace TEN::Renderer
RendererStatic* current = statics[s];
RendererRoom* room = &_rooms[current->RoomNumber];
+ if (mirror != nullptr && current->RoomNumber != mirror->RoomNumber)
+ {
+ continue;
+ }
+
_stInstancedStaticMeshBuffer.StaticMeshes[k].World = current->World;
_stInstancedStaticMeshBuffer.StaticMeshes[k].Color = current->Color;
_stInstancedStaticMeshBuffer.StaticMeshes[k].Ambient = room->AmbientLight;
@@ -2440,35 +2555,38 @@ namespace TEN::Renderer
k++;
}
- _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get());
-
baseStaticIndex += bucketSize;
- for (auto& bucket : refMesh->Buckets)
+ if (k > 0)
{
- if (bucket.NumVertices == 0)
- {
- continue;
- }
+ _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get());
- int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1;
-
- for (int p = 0; p < passes; p++)
+ for (auto& bucket : refMesh->Buckets)
{
- if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p))
+ if (bucket.NumVertices == 0)
{
continue;
}
- BindTexture(TextureRegister::ColorMap,
- &std::get<0>(_staticTextures[bucket.Texture]),
- SamplerStateRegister::AnisotropicClamp);
- BindTexture(TextureRegister::NormalMap,
- &std::get<1>(_staticTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp);
+ int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1;
- DrawIndexedInstancedTriangles(bucket.NumIndices, instanceCount, bucket.StartIndex, 0);
+ for (int p = 0; p < passes; p++)
+ {
+ if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p))
+ {
+ continue;
+ }
- _numInstancedStaticsDrawCalls++;
+ BindTexture(TextureRegister::ColorMap,
+ &std::get<0>(_staticTextures[bucket.Texture]),
+ SamplerStateRegister::AnisotropicClamp);
+ BindTexture(TextureRegister::NormalMap,
+ &std::get<1>(_staticTextures[bucket.Texture]), SamplerStateRegister::AnisotropicClamp);
+
+ DrawIndexedInstancedTriangles(bucket.NumIndices, instanceCount, bucket.StartIndex, 0);
+
+ _numInstancedStaticsDrawCalls++;
+ }
}
}
}
@@ -2821,7 +2939,7 @@ namespace TEN::Renderer
rDrawSprite.Width = STAR_SIZE * star.Scale;
rDrawSprite.Height = STAR_SIZE * star.Scale;
- _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView);
+ _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, nullptr, renderView);
_stInstancedSpriteBuffer.Sprites[i].Color = Vector4(
star.Color.x,
star.Color.y,
@@ -2884,7 +3002,7 @@ namespace TEN::Renderer
rDrawSprite.Height = 192;
rDrawSprite.ConstrainAxis = meteor.Direction;
- _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView);
+ _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, nullptr, renderView);
_stInstancedSpriteBuffer.Sprites[i].Color = Vector4(
meteor.Color.x,
meteor.Color.y,
@@ -2989,7 +3107,7 @@ namespace TEN::Renderer
rDrawSprite.Width = SUN_SIZE;
rDrawSprite.Height = SUN_SIZE;
- _stInstancedSpriteBuffer.Sprites[0].World = GetWorldMatrixForSprite(&rDrawSprite, renderView);
+ _stInstancedSpriteBuffer.Sprites[0].World = GetWorldMatrixForSprite(&rDrawSprite, nullptr, renderView);
_stInstancedSpriteBuffer.Sprites[0].Color = Vector4::One;
_stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = 0;
@@ -3177,7 +3295,7 @@ namespace TEN::Renderer
return true;
}
- void Renderer::DrawSortedFaces(RenderView& view)
+ void Renderer::DrawSortedFaces(RendererMirror* mirror, RenderView& view)
{
std::sort(
view.TransparentObjectsToDraw.begin(),
@@ -3196,6 +3314,11 @@ namespace TEN::Renderer
_sortedPolygonsVertices.clear();
_sortedPolygonsIndices.clear();
+ if (mirror != nullptr && object->ObjectType != RendererObjectType::Sprite)
+ {
+ continue;
+ }
+
if (object->ObjectType == RendererObjectType::Room)
{
while (i < view.TransparentObjectsToDraw.size() &&
@@ -3346,23 +3469,25 @@ namespace TEN::Renderer
uv2 = spr->Sprite->UV[2];
uv3 = spr->Sprite->UV[3];
+ Matrix world = GetWorldMatrixForSprite(currentObject->Sprite, mirror, view);
+
Vertex v0;
- v0.Position = Vector3::Transform(p0t, currentObject->World);
+ v0.Position = Vector3::Transform(p0t, world);
v0.UV = uv0;
v0.Color = spr->c1;
Vertex v1;
- v1.Position = Vector3::Transform(p1t, currentObject->World);
+ v1.Position = Vector3::Transform(p1t, world);
v1.UV = uv1;
v1.Color = spr->c2;
Vertex v2;
- v2.Position = Vector3::Transform(p2t, currentObject->World);
+ v2.Position = Vector3::Transform(p2t, world);
v2.UV = uv2;
v2.Color = spr->c3;
Vertex v3;
- v3.Position = Vector3::Transform(p3t, currentObject->World);
+ v3.Position = Vector3::Transform(p3t, world);
v3.UV = uv3;
v3.Color = spr->c4;
@@ -3609,8 +3734,8 @@ namespace TEN::Renderer
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
- viewport.Width = _screenWidth;
- viewport.Height = _screenHeight;
+ viewport.Width = _screenWidth/2;
+ viewport.Height = _screenHeight / 2;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
@@ -3685,4 +3810,58 @@ namespace TEN::Renderer
_gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane;
_gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane;
}
+
+ void Renderer::DownsampleGBuffer()
+ {
+ // Downsample depth
+ _doingFullscreenPass = true;
+
+ SetBlendMode(BlendMode::Opaque);
+ SetCullMode(CullMode::CounterClockwise);
+ SetDepthState(DepthState::Write);
+
+ // Common vertex shader to all full screen effects
+ _context->VSSetShader(_vsPostProcess.Get(), nullptr, 0);
+
+ _context->PSSetShader(_psDownsampleDepthBuffer.Get(), nullptr, 0);
+ _context->ClearRenderTargetView(_downsampledDepthRenderTarget.RenderTargetView.Get(), Colors::White);
+ _context->OMSetRenderTargets(1, _downsampledDepthRenderTarget.RenderTargetView.GetAddressOf(), nullptr);
+
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+ viewport.Width = _screenWidth / 2;
+ viewport.Height = _screenHeight / 2;
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+
+ _context->RSSetViewports(1, &viewport);
+
+ D3D11_RECT rects[1];
+ rects[0].left = 0;
+ rects[0].right = viewport.Width;
+ rects[0].top = 0;
+ rects[0].bottom = viewport.Height;
+
+ _context->RSSetScissorRects(1, rects);
+
+ _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ _context->IASetInputLayout(_fullscreenTriangleInputLayout.Get());
+
+ UINT stride = sizeof(PostProcessVertex);
+ UINT offset = 0;
+
+ _context->IASetVertexBuffers(0, 1, _fullscreenTriangleVertexBuffer.Buffer.GetAddressOf(), &stride, &offset);
+
+ BindRenderTargetAsTexture(static_cast(0), &_depthRenderTarget, SamplerStateRegister::PointWrap);
+
+ _stPostProcessBuffer.ViewportWidth = viewport.Width;
+ _stPostProcessBuffer.ViewportHeight = viewport.Height;
+ memcpy(_stPostProcessBuffer.SSAOKernel, _SSAOKernel.data(), 16 * _SSAOKernel.size());
+ _cbPostProcessBuffer.UpdateData(_stPostProcessBuffer, _context.Get());
+
+ DrawTriangles(3, 0);
+
+ _doingFullscreenPass = false;
+ }
}
diff --git a/TombEngine/Renderer/RendererDrawEffect.cpp b/TombEngine/Renderer/RendererDrawEffect.cpp
index bd031cee0..d12697193 100644
--- a/TombEngine/Renderer/RendererDrawEffect.cpp
+++ b/TombEngine/Renderer/RendererDrawEffect.cpp
@@ -1009,7 +1009,7 @@ namespace TEN::Renderer
}
}
- bool Renderer::DrawGunFlashes(RenderView& view)
+ bool Renderer::DrawGunFlashes(RendererMirror* mirror, RenderView& view)
{
_context->VSSetShader(_vsStatics.Get(), nullptr, 0);
_context->PSSetShader(_psStatics.Get(), nullptr, 0);
@@ -1106,6 +1106,11 @@ namespace TEN::Renderer
worldMatrix = tMatrix * worldMatrix;
worldMatrix = rotMatrix * worldMatrix;
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
+
_stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get());
@@ -1120,6 +1125,11 @@ namespace TEN::Renderer
worldMatrix = tMatrix * worldMatrix;
worldMatrix = rotMatrix * worldMatrix;
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
+
_stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get());
@@ -1134,7 +1144,7 @@ namespace TEN::Renderer
return true;
}
- void Renderer::DrawBaddyGunflashes(RenderView& view)
+ void Renderer::DrawBaddyGunflashes(RendererMirror* mirror, RenderView& view)
{
_context->VSSetShader(_vsStatics.Get(), nullptr, 0);
_context->PSSetShader(_psStatics.Get(), nullptr, 0);
@@ -1151,6 +1161,11 @@ namespace TEN::Renderer
{
auto& nativeItem = g_Level.Items[rItemPtr->ItemNumber];
+ if (mirror != nullptr && nativeItem.RoomNumber != mirror->RoomNumber)
+ {
+ continue;
+ }
+
if (!nativeItem.IsCreature())
continue;
@@ -1196,6 +1211,11 @@ namespace TEN::Renderer
if (creature.MuzzleFlash[0].ApplyZRotation)
worldMatrix = rotMatrixZ * worldMatrix;
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
+
_stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get());
@@ -1236,6 +1256,11 @@ namespace TEN::Renderer
if (creature.MuzzleFlash[1].ApplyZRotation)
worldMatrix = rotMatrixZ * worldMatrix;
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
+
_stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get());
@@ -1267,17 +1292,23 @@ namespace TEN::Renderer
}
}
- Matrix Renderer::GetWorldMatrixForSprite(RendererSpriteToDraw* sprite, RenderView& view)
+ Matrix Renderer::GetWorldMatrixForSprite(RendererSpriteToDraw* sprite, RendererMirror* mirror, RenderView& view)
{
auto spriteMatrix = Matrix::Identity;
auto scaleMatrix = Matrix::CreateScale(sprite->Width * sprite->Scale, sprite->Height * sprite->Scale, sprite->Scale);
+ Vector3 spritePosition = sprite->pos;
+ if (mirror != nullptr)
+ {
+ spritePosition = Vector3::Transform(spritePosition, mirror->ReflectionMatrix); // Vector3::Reflect(spritePosition, mirror->Plane.Normal());
+ }
+
switch (sprite->Type)
{
case SpriteType::Billboard:
{
auto cameraUp = Vector3(view.Camera.View._12, view.Camera.View._22, view.Camera.View._32);
- spriteMatrix = scaleMatrix * Matrix::CreateRotationZ(sprite->Rotation) * Matrix::CreateBillboard(sprite->pos, Camera.pos.ToVector3(), cameraUp);
+ spriteMatrix = scaleMatrix * Matrix::CreateRotationZ(sprite->Rotation) * Matrix::CreateBillboard(spritePosition, Camera.pos.ToVector3(), cameraUp);
}
break;
@@ -1286,7 +1317,7 @@ namespace TEN::Renderer
auto rotMatrix = Matrix::CreateRotationY(sprite->Rotation);
auto quadForward = Vector3(0.0f, 0.0f, 1.0f);
spriteMatrix = scaleMatrix * Matrix::CreateConstrainedBillboard(
- sprite->pos,
+ spritePosition,
Camera.pos.ToVector3(),
sprite->ConstrainAxis,
nullptr,
@@ -1296,7 +1327,7 @@ namespace TEN::Renderer
case SpriteType::LookAtBillboard:
{
- auto tMatrix = Matrix::CreateTranslation(sprite->pos);
+ auto tMatrix = Matrix::CreateTranslation(spritePosition);
auto rotMatrix = Matrix::CreateRotationZ(sprite->Rotation) * Matrix::CreateLookAt(Vector3::Zero, sprite->LookAtAxis, Vector3::UnitZ);
spriteMatrix = scaleMatrix * rotMatrix * tMatrix;
}
diff --git a/TombEngine/Renderer/RendererFrame.cpp b/TombEngine/Renderer/RendererFrame.cpp
index c5244ef1e..b18435dd7 100644
--- a/TombEngine/Renderer/RendererFrame.cpp
+++ b/TombEngine/Renderer/RendererFrame.cpp
@@ -147,6 +147,19 @@ namespace TEN::Renderer
for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++)
renderView.LensFlaresToDraw.push_back(tempLensFlares[i]);
+
+ for (auto& mirror : g_Level.Mirrors)
+ {
+ if (mirror.RoomNumber == LaraItem->RoomNumber)
+ {
+ RendererMirror rendererMirror;
+ rendererMirror.RoomNumber = mirror.RoomNumber;
+ rendererMirror.MirroredRoomNumber = mirror.MirroredRoomNumber;
+ rendererMirror.Plane = mirror.MirrorPlane;
+ rendererMirror.ReflectionMatrix = Matrix::CreateReflection(rendererMirror.Plane);
+ renderView.Mirrors.push_back(rendererMirror);
+ }
+ }
}
bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView)
diff --git a/TombEngine/Renderer/RendererLara.cpp b/TombEngine/Renderer/RendererLara.cpp
index b1e29ebe5..fde9bcf84 100644
--- a/TombEngine/Renderer/RendererLara.cpp
+++ b/TombEngine/Renderer/RendererLara.cpp
@@ -278,8 +278,13 @@ void Renderer::UpdateLaraAnimations(bool force)
rItem.DoneAnimations = true;
}
-void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPass)
+void TEN::Renderer::Renderer::DrawLara(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
+ if (mirror != nullptr && LaraItem->RoomNumber != mirror->RoomNumber)
+ {
+ return;
+ }
+
// Don't draw player if using optics.
if (Lara.Control.Look.OpticRange != 0 || SpotcamDontDrawLara)
return;
@@ -305,7 +310,12 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa
RendererRoom* room = &_rooms[LaraItem->RoomNumber];
- _stItem.World = item->InterpolatedWorld; // _laraWorldMatrix;
+ _stItem.World = item->InterpolatedWorld;
+ if (mirror != nullptr)
+ {
+ _stItem.World = _stItem.World * mirror->ReflectionMatrix;
+ }
+
_stItem.Color = item->Color;
_stItem.AmbientLight = item->AmbientLight;
memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, laraObj.AnimationTransforms.size() * sizeof(Matrix));
@@ -324,12 +334,12 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa
DrawMoveableMesh(item, GetMesh(nativeItem->Model.MeshIndex[k]), room, k, view, rendererPass);
}
- DrawLaraHolsters(item, room, view, rendererPass);
- DrawLaraJoints(item, room, view, rendererPass);
- DrawLaraHair(item, room, view, rendererPass);
+ DrawLaraHolsters(item, room, mirror, view, rendererPass);
+ DrawLaraJoints(item, room, mirror, view, rendererPass);
+ DrawLaraHair(item, room, mirror, view, rendererPass);
}
-void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass)
+void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
for (int i = 0; i < HairEffect.Units.size(); i++)
{
@@ -345,6 +355,10 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render
_stItem.World = Matrix::Identity;
_stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimTransforms[LM_HEAD] * itemToDraw->InterpolatedWorld;
+ if (mirror != nullptr)
+ {
+ _stItem.BonesMatrices[0] = _stItem.BonesMatrices[0] * mirror->ReflectionMatrix;
+ }
for (int i = 0; i < unit.Segments.size(); i++)
{
@@ -354,6 +368,11 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render
Quaternion::Lerp(segment.PrevOrientation, segment.Orientation, _interpolationFactor)) *
Matrix::CreateTranslation(
Vector3::Lerp(segment.PrevPosition, segment.Position, _interpolationFactor));
+
+ if (mirror != nullptr)
+ {
+ worldMatrix = worldMatrix * mirror->ReflectionMatrix;
+ }
_stItem.BonesMatrices[i + 1] = worldMatrix;
_stItem.BoneLightModes[i] = (int)LightMode::Dynamic;
@@ -369,7 +388,7 @@ void Renderer::DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, Render
}
}
-void Renderer::DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass)
+void Renderer::DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (!_moveableObjects[ID_LARA_SKIN_JOINTS].has_value())
return;
@@ -383,7 +402,7 @@ void Renderer::DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, Rend
}
}
-void Renderer::DrawLaraHolsters(RendererItem* itemToDraw, RendererRoom* room, RenderView& view, RendererPass rendererPass)
+void Renderer::DrawLaraHolsters(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
HolsterSlot leftHolsterID = Lara.Control.Weapon.HolsterInfo.LeftHolster;
HolsterSlot rightHolsterID = Lara.Control.Weapon.HolsterInfo.RightHolster;
diff --git a/TombEngine/Renderer/RendererSprites.cpp b/TombEngine/Renderer/RendererSprites.cpp
index 417155097..457b3399f 100644
--- a/TombEngine/Renderer/RendererSprites.cpp
+++ b/TombEngine/Renderer/RendererSprites.cpp
@@ -243,7 +243,7 @@ namespace TEN::Renderer
object.Centre = rDrawSprite.pos;
object.Distance = distance;
object.Sprite = &rDrawSprite;
- object.World = GetWorldMatrixForSprite(&rDrawSprite, view);
+ //object.World = GetWorldMatrixForSprite(&rDrawSprite, view);
view.TransparentObjectsToDraw.push_back(object);
}
@@ -256,7 +256,7 @@ namespace TEN::Renderer
_spriteBuckets.push_back(currentSpriteBucket);
}
- void Renderer::DrawSprites(RenderView& view, RendererPass rendererPass)
+ void Renderer::DrawSprites(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{
if (view.SpritesToDraw.empty())
return;
@@ -296,7 +296,7 @@ namespace TEN::Renderer
{
auto& rDrawSprite = spriteBucket.SpritesToDraw[i];
- _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, view);
+ _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, mirror, view);
_stInstancedSpriteBuffer.Sprites[i].Color = rDrawSprite.color;
_stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = rDrawSprite.SoftParticle ? 1 : 0;
@@ -414,7 +414,7 @@ namespace TEN::Renderer
UINT offset = 0;
_context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset);
- _stInstancedSpriteBuffer.Sprites[0].World = GetWorldMatrixForSprite(object->Sprite, view);
+ _stInstancedSpriteBuffer.Sprites[0].World = GetWorldMatrixForSprite(object->Sprite, nullptr, view);
_stInstancedSpriteBuffer.Sprites[0].Color = object->Sprite->color;
_stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = object->Sprite->SoftParticle ? 1 : 0;
diff --git a/TombEngine/Renderer/Structures/RendererMirror.h b/TombEngine/Renderer/Structures/RendererMirror.h
new file mode 100644
index 000000000..42ed41064
--- /dev/null
+++ b/TombEngine/Renderer/Structures/RendererMirror.h
@@ -0,0 +1,16 @@
+#pragma once
+#include
+
+namespace TEN::Renderer::Structures
+{
+ using namespace DirectX;
+ using namespace DirectX::SimpleMath;
+
+ struct RendererMirror
+ {
+ short RoomNumber;
+ short MirroredRoomNumber;
+ Plane Plane;
+ Matrix ReflectionMatrix;
+ };
+}
\ No newline at end of file
diff --git a/TombEngine/Shaders/PostProcess.fx b/TombEngine/Shaders/PostProcess.fx
index 3d7b7b786..53893fb38 100644
--- a/TombEngine/Shaders/PostProcess.fx
+++ b/TombEngine/Shaders/PostProcess.fx
@@ -32,6 +32,20 @@ PixelShaderInput VS(VertexShaderInput input)
return output;
}
+float4 PSDownsampleDepthBuffer(PixelShaderInput input) : SV_Target
+{
+ // Use 2x2 max technique
+ float d1 = ColorTexture.Sample(ColorSampler, input.UV, float2(0, 0)).r;
+ float d2 = ColorTexture.Sample(ColorSampler, input.UV, float2(0, 1)).r;
+ float d3 = ColorTexture.Sample(ColorSampler, input.UV, float2(1, 0)).r;
+ float d4 = ColorTexture.Sample(ColorSampler, input.UV, float2(1, 1)).r;
+
+ return float4(
+ max(max(d1, d2), max(d3, d4)),
+ 0, 0, 1
+ );
+}
+
float4 PSCopy(PixelShaderInput input) : SV_Target
{
return ColorTexture.Sample(ColorSampler, input.UV);
diff --git a/TombEngine/Specific/level.cpp b/TombEngine/Specific/level.cpp
index a88807274..484a57c02 100644
--- a/TombEngine/Specific/level.cpp
+++ b/TombEngine/Specific/level.cpp
@@ -1417,6 +1417,17 @@ bool LoadLevel(const std::string& path, bool partial)
UpdateProgress(100, partial);
+ // MIRROR: remove after TE changes
+ g_Level.Mirrors.clear();
+
+ MirrorInfo mirror;
+ mirror.RoomNumber = 7;
+ mirror.MirrorPlane = Plane(Vector3(0, 0, 30000), Vector3(0, 0, -1));
+ g_Level.Mirrors.push_back(mirror);
+
+ mirror.MirrorPlane = Plane(Vector3(0, -2048, 0), Vector3(0,-1, 0));
+ g_Level.Mirrors.push_back(mirror);
+
TENLog("Level loading complete.", LogLevel::Info);
loadedSuccessfully = true;
diff --git a/TombEngine/Specific/level.h b/TombEngine/Specific/level.h
index 7942b68d3..d71c91fde 100644
--- a/TombEngine/Specific/level.h
+++ b/TombEngine/Specific/level.h
@@ -85,6 +85,13 @@ struct MESH
std::vector buckets;
};
+struct MirrorInfo
+{
+ short RoomNumber;
+ short MirroredRoomNumber;
+ Plane MirrorPlane;
+};
+
// LevelData
struct LEVEL
{
@@ -123,6 +130,7 @@ struct LEVEL
std::vector LoopedEventSetIndices = {};
std::vector AIObjects = {};
std::vector Sprites = {};
+ std::vector Mirrors = {};
// Texture data
TEXTURE SkyTexture = {};
diff --git a/TombEngine/TombEngine.vcxproj b/TombEngine/TombEngine.vcxproj
index d96d876a9..463379d38 100644
--- a/TombEngine/TombEngine.vcxproj
+++ b/TombEngine/TombEngine.vcxproj
@@ -821,6 +821,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
+