WIP TR4 style mirrors

This commit is contained in:
MontyTRC89 2024-12-05 10:20:32 +01:00
parent 116c3d71fc
commit bb3d0b993b
15 changed files with 474 additions and 126 deletions

View file

@ -145,7 +145,7 @@
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#GetWind">GetWind()</a></td> <td class="name" ><a href="#GetWind">GetWind()</a></td>
<td class="summary">Get the current wind for the current frame.</td> <td class="summary">Get the wind vector for the current game frame.</td>
</tr> </tr>
</table> </table>
@ -508,8 +508,8 @@
<strong>GetWind()</strong> <strong>GetWind()</strong>
</dt> </dt>
<dd> <dd>
Get the current wind for the current frame. 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. This represents the 3D displacement applied by the engine on things like particles affected by wind.()
@ -518,7 +518,7 @@
<ol> <ol>
<span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span> <span class="types"><a class="type" href="../3 primitive classes/Vec3.html#">Vec3</a></span>
The wind. Wind vector.
</ol> </ol>

View file

@ -383,6 +383,14 @@ pickups, and Lara herself (see also <a href="../2 classes/Objects.LaraObject.htm
<td class="summary">Disable the item, as if an antitrigger for it had been stepped on (i.e.</td> <td class="summary">Disable the item, as if an antitrigger for it had been stepped on (i.e.</td>
</tr> </tr>
<tr> <tr>
<td class="name" ><a href="#Moveable:GetCollidable">Moveable:GetCollidable()</a></td>
<td class="summary">Get the item's collision state.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:SetCollidable">Moveable:SetCollidable(collidable)</a></td>
<td class="summary">Set the item's collision.</td>
</tr>
<tr>
<td class="name" ><a href="#Moveable:MakeInvisible">Moveable:MakeInvisible()</a></td> <td class="name" ><a href="#Moveable:MakeInvisible">Moveable:MakeInvisible()</a></td>
<td class="summary">Make the item invisible.</td> <td class="summary">Make the item invisible.</td>
</tr> </tr>
@ -1967,6 +1975,49 @@ sas:SetPosition(newPos, <span class="keyword">false</span>)</pre>
</dd>
<dt>
<a name = "Moveable:GetCollidable"></a>
<strong>Moveable:GetCollidable()</strong>
</dt>
<dd>
Get the item's collision state.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">bool</span></span>
item's collision state
</ol>
</dd>
<dt>
<a name = "Moveable:SetCollidable"></a>
<strong>Moveable:SetCollidable(collidable)</strong>
</dt>
<dd>
Set the item's collision.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">collidable</span>
<span class="types"><span class="type">bool</span></span>
true if the caller should be collidable, false if no collision should occur.
</li>
</ul>
</dd> </dd>
<dt> <dt>
<a name = "Moveable:MakeInvisible"></a> <a name = "Moveable:MakeInvisible"></a>

View file

@ -53,6 +53,7 @@ namespace TEN::Renderer
FogBulbsToDraw.clear(); FogBulbsToDraw.clear();
LensFlaresToDraw.clear(); LensFlaresToDraw.clear();
TransparentObjectsToDraw.clear(); TransparentObjectsToDraw.clear();
Mirrors.clear();
} }
RenderViewCamera::RenderViewCamera(CAMERA_INFO* cam, float roll, float fov, float n, float f, int w, int h) RenderViewCamera::RenderViewCamera(CAMERA_INFO* cam, float roll, float fov, float n, float f, int w, int h)

View file

@ -15,6 +15,7 @@
#include "Renderer/Structures/RendererSortableObject.h" #include "Renderer/Structures/RendererSortableObject.h"
#include "Renderer/Structures/RendererSpriteToDraw.h" #include "Renderer/Structures/RendererSpriteToDraw.h"
#include "Renderer/Structures/RendererLensFlare.h" #include "Renderer/Structures/RendererLensFlare.h"
#include "Renderer/Structures/RendererMirror.h"
namespace TEN::Renderer namespace TEN::Renderer
{ {
@ -54,6 +55,8 @@ namespace TEN::Renderer
std::vector<RendererSortableObject> TransparentObjectsToDraw = {}; std::vector<RendererSortableObject> TransparentObjectsToDraw = {};
std::vector<RendererLensFlare> LensFlaresToDraw = {}; std::vector<RendererLensFlare> LensFlaresToDraw = {};
std::vector<RendererMirror> Mirrors = {};
RenderView(CAMERA_INFO* cam, float roll, float fov, float nearPlane, float farPlane, int w, int h); 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); RenderView(const Vector3& pos, const Vector3& dir, const Vector3& up, int w, int h, int room, float nearPlane, float farPlane, float fov);

View file

@ -380,6 +380,7 @@ namespace TEN::Renderer
ComPtr<ID3D11PixelShader> _psPostProcessExclusion; ComPtr<ID3D11PixelShader> _psPostProcessExclusion;
ComPtr<ID3D11PixelShader> _psPostProcessFinalPass; ComPtr<ID3D11PixelShader> _psPostProcessFinalPass;
ComPtr<ID3D11PixelShader> _psPostProcessLensFlare; ComPtr<ID3D11PixelShader> _psPostProcessLensFlare;
ComPtr<ID3D11PixelShader> _psDownsampleDepthBuffer;
bool _doingFullscreenPass = false; bool _doingFullscreenPass = false;
@ -454,12 +455,12 @@ namespace TEN::Renderer
void PrepareSingleLaserBeam(RenderView& view); void PrepareSingleLaserBeam(RenderView& view);
void DrawHorizonAndSky(RenderView& renderView, ID3D11DepthStencilView* depthTarget); void DrawHorizonAndSky(RenderView& renderView, ID3D11DepthStencilView* depthTarget);
void DrawRooms(RenderView& view, RendererPass rendererPass); void DrawRooms(RenderView& view, RendererPass rendererPass);
void DrawItems(RenderView& view, RendererPass rendererPass); void DrawItems(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawAnimatingItem(RendererItem* item, RenderView& view, RendererPass rendererPass); void DrawAnimatingItem(RendererItem* item, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawWaterfalls(RendererItem* item, RenderView& view, int fps, RendererPass rendererPass); void DrawWaterfalls(RendererItem* item, RendererMirror* mirror, RenderView& view, int fps, RendererPass rendererPass);
void DrawBaddyGunflashes(RenderView& view); void DrawBaddyGunflashes(RendererMirror* mirror, RenderView& view);
void DrawStatics(RenderView& view, RendererPass rendererPass); void DrawStatics(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawLara(RenderView& view, RendererPass rendererPass); void DrawLara(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void PrepareFires(RenderView& view); void PrepareFires(RenderView& view);
void PrepareParticles(RenderView& view); void PrepareParticles(RenderView& view);
void PrepareSmokes(RenderView& view); void PrepareSmokes(RenderView& view);
@ -472,9 +473,9 @@ namespace TEN::Renderer
void DrawEffects(RenderView& view, RendererPass rendererPass); void DrawEffects(RenderView& view, RendererPass rendererPass);
void DrawEffect(RenderView& view, RendererEffect* effect, RendererPass rendererPass); void DrawEffect(RenderView& view, RendererEffect* effect, RendererPass rendererPass);
void PrepareSplashes(RenderView& view); void PrepareSplashes(RenderView& view);
void DrawSprites(RenderView& view, RendererPass rendererPass); void DrawSprites(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawDisplaySprites(RenderView& view); void DrawDisplaySprites(RenderView& view);
void DrawSortedFaces(RenderView& view); void DrawSortedFaces(RendererMirror* mirror, RenderView& view);
void DrawSingleSprite(RendererSortableObject* object, RendererObjectType lastObjectType, RenderView& view); void DrawSingleSprite(RendererSortableObject* object, RendererObjectType lastObjectType, RenderView& view);
void DrawRoomSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view); void DrawRoomSorted(RendererSortableObject* objectInfo, RendererObjectType lastObjectType, RenderView& view);
void DrawItemSorted(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 DrawOverlays(RenderView& view);
void PrepareRopes(RenderView& view); void PrepareRopes(RenderView& view);
void DrawFishSwarm(RenderView& view, RendererPass rendererPass); void DrawFishSwarm(RenderView& view, RendererPass rendererPass);
void DrawBats(RenderView& view, RendererPass rendererPass); void DrawBats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawRats(RenderView& view, RendererPass rendererPass); void DrawRats(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawScarabs(RenderView& view, RendererPass rendererPass); void DrawScarabs(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawSpiders(RenderView& view, RendererPass rendererPass); void DrawSpiders(RenderView& view, RendererPass rendererPass);
bool DrawGunFlashes(RenderView& view); bool DrawGunFlashes(RendererMirror* mirror, RenderView& view);
void DrawGunShells(RenderView& view, RendererPass rendererPass); void DrawGunShells(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawLocusts(RenderView& view, RendererPass rendererPass); void DrawLocusts(RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawStatistics(); void DrawStatistics();
void DrawExamines(); void DrawExamines();
void DrawDiary(); void DrawDiary();
@ -508,9 +509,9 @@ namespace TEN::Renderer
void PrepareSmokeParticles(RenderView& view); void PrepareSmokeParticles(RenderView& view);
void PrepareSparkParticles(RenderView& view); void PrepareSparkParticles(RenderView& view);
void PrepareExplosionParticles(RenderView& view); void PrepareExplosionParticles(RenderView& view);
void DrawLaraHolsters(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, RenderView& view, RendererPass rendererPass); void DrawLaraJoints(RendererItem* itemToDraw, RendererRoom* room, RendererMirror* mirror, RenderView& view, RendererPass rendererPass);
void DrawLaraHair(RendererItem* itemToDraw, RendererRoom* room, 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 DrawMoveableMesh(RendererItem* itemToDraw, RendererMesh* mesh, RendererRoom* room, int boneIndex, RenderView& view, RendererPass rendererPass);
void PrepareSimpleParticles(RenderView& view); void PrepareSimpleParticles(RenderView& view);
void PrepareStreamers(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, const Vector4& color0, const Vector4& color1, const Vector4& color2, const Vector4& color3,
BlendMode blendMode, RenderView& view, SpriteRenderType renderType = SpriteRenderType::Default); 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); RendererObject& GetRendererObject(GAME_OBJECT_ID id);
RendererMesh* GetMesh(int meshIndex); RendererMesh* GetMesh(int meshIndex);
Texture2D CreateDefaultNormalTexture(); Texture2D CreateDefaultNormalTexture();

View file

@ -245,14 +245,14 @@ namespace TEN::Renderer
{ {
RendererRoom& room = _rooms[item->RoomNumber]; RendererRoom& room = _rooms[item->RoomNumber];
DrawLaraHolsters(item, &room, renderView, RendererPass::ShadowMap); DrawLaraHolsters(item, &room, nullptr, renderView, RendererPass::ShadowMap);
DrawLaraJoints(item, &room, renderView, RendererPass::ShadowMap); DrawLaraJoints(item, &room, nullptr, renderView, RendererPass::ShadowMap);
DrawLaraHair(item, &room, 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& room = _rooms[LaraItem->RoomNumber];
auto* item = &_items[LaraItem->Index]; auto* item = &_items[LaraItem->Index];
@ -282,6 +282,11 @@ namespace TEN::Renderer
worldMatrix = Matrix::Lerp(prevWorldMatrix, worldMatrix, _interpolationFactor); worldMatrix = Matrix::Lerp(prevWorldMatrix, worldMatrix, _interpolationFactor);
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].World = worldMatrix; _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].World = worldMatrix;
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Ambient = room.AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[gunShellCount].Color = 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) if (!Objects[ID_RATS_EMITTER].loaded)
{ {
@ -567,7 +572,12 @@ namespace TEN::Renderer
{ {
RendererMesh* mesh = GetMesh(Objects[ID_RATS_EMITTER].meshIndex + (rand() % 8)); 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.Color = Vector4::One;
_stStatic.AmbientLight = _rooms[rat->RoomNumber].AmbientLight; _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) if (!Objects[ID_BATS_EMITTER].loaded)
return; return;
@ -775,7 +785,13 @@ namespace TEN::Renderer
auto transformMatrix = Matrix::Lerp(bat.PrevTransform, bat.Transform, _interpolationFactor); 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].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[batCount].Color = Vector4::One; _stInstancedStaticMeshBuffer.StaticMeshes[batCount].Color = Vector4::One;
_stInstancedStaticMeshBuffer.StaticMeshes[batCount].LightMode = (int)mesh.LightMode; _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) if (!Objects[ID_LITTLE_BEETLE].loaded)
return; return;
@ -888,7 +904,13 @@ namespace TEN::Renderer
auto transformMatrix = Matrix::Lerp(beetle.PrevTransform, beetle.Transform, _interpolationFactor); 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].Ambient = room.AmbientLight;
_stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Color = Vector4::One; _stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].Color = Vector4::One;
_stInstancedStaticMeshBuffer.StaticMeshes[beetleCount].LightMode = (int)mesh.LightMode; _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) if (!Objects[ID_LOCUSTS].loaded)
return; return;
@ -1039,7 +1061,12 @@ namespace TEN::Renderer
auto& mesh = *GetMesh(Objects[ID_LOCUSTS].meshIndex + (-locust.counter & 3)); 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.Color = Vector4::One;
_stStatic.AmbientLight = _rooms[locust.roomNumber].AmbientLight; _stStatic.AmbientLight = _rooms[locust.roomNumber].AmbientLight;
_cbStatic.UpdateData(_stStatic, _context.Get()); _cbStatic.UpdateData(_stStatic, _context.Get());
@ -1724,7 +1751,7 @@ namespace TEN::Renderer
cameraConstantBuffer.FogMinDistance = level.GetFogMinDistance(); cameraConstantBuffer.FogMinDistance = level.GetFogMinDistance();
cameraConstantBuffer.FogMaxDistance = level.GetFogMaxDistance(); cameraConstantBuffer.FogMaxDistance = level.GetFogMaxDistance();
} }
else else
{ {
cameraConstantBuffer.FogMaxDistance = 0; cameraConstantBuffer.FogMaxDistance = 0;
cameraConstantBuffer.FogColor = Vector4::Zero; cameraConstantBuffer.FogColor = Vector4::Zero;
@ -1743,10 +1770,10 @@ namespace TEN::Renderer
cameraConstantBuffer.FogBulbs[i].Color = view.FogBulbsToDraw[i].Color; cameraConstantBuffer.FogBulbs[i].Color = view.FogBulbsToDraw[i].Color;
cameraConstantBuffer.FogBulbs[i].SquaredCameraToFogBulbDistance = SQUARE(view.FogBulbsToDraw[i].Distance); cameraConstantBuffer.FogBulbs[i].SquaredCameraToFogBulbDistance = SQUARE(view.FogBulbsToDraw[i].Distance);
cameraConstantBuffer.FogBulbs[i].FogBulbToCameraVector = view.FogBulbsToDraw[i].FogBulbToCameraVector; cameraConstantBuffer.FogBulbs[i].FogBulbToCameraVector = view.FogBulbsToDraw[i].FogBulbToCameraVector;
} }
_cbCameraMatrices.UpdateData(cameraConstantBuffer, _context.Get()); _cbCameraMatrices.UpdateData(cameraConstantBuffer, _context.Get());
ID3D11RenderTargetView* pRenderViewPtrs[2]; ID3D11RenderTargetView* pRenderViewPtrs[2];
// Bind main render target. // Bind main render target.
@ -1754,7 +1781,7 @@ namespace TEN::Renderer
// Draw horizon and sky. // Draw horizon and sky.
DrawHorizonAndSky(view, _renderTarget.DepthStencilView.Get()); DrawHorizonAndSky(view, _renderTarget.DepthStencilView.Get());
// Build G-Buffer (normals + depth). // Build G-Buffer (normals + depth).
_context->ClearRenderTargetView(_normalsRenderTarget.RenderTargetView.Get(), Colors::Black); _context->ClearRenderTargetView(_normalsRenderTarget.RenderTargetView.Get(), Colors::Black);
_context->ClearRenderTargetView(_depthRenderTarget.RenderTargetView.Get(), Colors::White); _context->ClearRenderTargetView(_depthRenderTarget.RenderTargetView.Get(), Colors::White);
@ -1764,15 +1791,18 @@ namespace TEN::Renderer
_context->OMSetRenderTargets(2, &pRenderViewPtrs[0], _renderTarget.DepthStencilView.Get()); _context->OMSetRenderTargets(2, &pRenderViewPtrs[0], _renderTarget.DepthStencilView.Get());
DrawRooms(view, RendererPass::GBuffer); DrawRooms(view, RendererPass::GBuffer);
DrawItems(view, RendererPass::GBuffer); DrawItems(nullptr, view, RendererPass::GBuffer);
DrawStatics(view, RendererPass::GBuffer); DrawStatics(nullptr, view, RendererPass::GBuffer);
DrawSpiders(view, RendererPass::GBuffer); DrawSpiders(view, RendererPass::GBuffer);
DrawScarabs(view, RendererPass::GBuffer); DrawScarabs(nullptr, view, RendererPass::GBuffer);
DrawGunShells(view, RendererPass::GBuffer); DrawGunShells(nullptr, view, RendererPass::GBuffer);
DrawBats(view, RendererPass::GBuffer); DrawBats(nullptr, view, RendererPass::GBuffer);
DrawEffects(view, RendererPass::GBuffer); DrawEffects(view, RendererPass::GBuffer);
DrawRats(view, RendererPass::GBuffer); DrawRats(nullptr, view, RendererPass::GBuffer);
DrawLocusts(view, RendererPass::GBuffer); DrawLocusts(nullptr, view, RendererPass::GBuffer);
// Downsample G-Buffer for making faster soft particles and SSAO
DownsampleGBuffer();
// Calculate ambient occlusion. // Calculate ambient occlusion.
if (g_Configuration.EnableAmbientOcclusion) if (g_Configuration.EnableAmbientOcclusion)
@ -1785,62 +1815,128 @@ namespace TEN::Renderer
_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); _context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
_context->IASetInputLayout(_inputLayout.Get()); _context->IASetInputLayout(_inputLayout.Get());
_context->RSSetViewports(1, &view.Viewport);
ResetScissor();
SetBlendMode(BlendMode::Opaque); SetBlendMode(BlendMode::Opaque);
SetCullMode(CullMode::CounterClockwise); SetCullMode(CullMode::CounterClockwise);
SetDepthState(DepthState::Write); 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. // 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()); _context->OMSetRenderTargets(1, _renderTarget.RenderTargetView.GetAddressOf(), _renderTarget.DepthStencilView.Get());
// Draw opaque, alpha test, and fast alpha blend faces. // Draw opaque, alpha test, and fast alpha blend faces.
DrawRooms(view, RendererPass::Opaque); DrawRooms(view, RendererPass::Opaque);
DrawItems(view, RendererPass::Opaque); DrawItems(nullptr, view, RendererPass::Opaque);
DrawStatics(view, RendererPass::Opaque); DrawStatics(nullptr, view, RendererPass::Opaque);
DrawSpiders(view, RendererPass::Opaque); DrawSpiders(view, RendererPass::Opaque);
DrawScarabs(view, RendererPass::Opaque); DrawScarabs(nullptr, view, RendererPass::Opaque);
DrawGunShells(view, RendererPass::Opaque); DrawGunShells(nullptr, view, RendererPass::Opaque);
DrawBats(view, RendererPass::Opaque); DrawBats(nullptr, view, RendererPass::Opaque);
DrawEffects(view, RendererPass::Opaque); DrawEffects(view, RendererPass::Opaque);
DrawRats(view, RendererPass::Opaque); DrawRats(nullptr, view, RendererPass::Opaque);
DrawLocusts(view, RendererPass::Opaque); DrawLocusts(nullptr, view, RendererPass::Opaque);
DrawDebris(view, RendererPass::Opaque); DrawDebris(view, RendererPass::Opaque);
DrawSprites(view, RendererPass::Opaque); DrawSprites(nullptr, view, RendererPass::Opaque);
DrawFishSwarm(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. // Draw additive faces.
DrawRooms(view, RendererPass::Additive); DrawRooms(view, RendererPass::Additive);
DrawItems(view, RendererPass::Additive); DrawItems(nullptr, view, RendererPass::Additive);
DrawStatics(view, RendererPass::Additive); DrawStatics(nullptr, view, RendererPass::Additive);
DrawSpiders(view, RendererPass::Additive); DrawSpiders(view, RendererPass::Additive);
DrawScarabs(view, RendererPass::Additive); DrawScarabs(nullptr, view, RendererPass::Additive);
DrawBats(view, RendererPass::Additive); DrawBats(nullptr, view, RendererPass::Additive);
DrawEffects(view, RendererPass::Additive); DrawEffects(view, RendererPass::Additive);
DrawRats(view, RendererPass::Additive); DrawRats(nullptr, view, RendererPass::Additive);
DrawLocusts(view, RendererPass::Additive); DrawLocusts(nullptr, view, RendererPass::Additive);
DrawDebris(view, RendererPass::Additive); DrawDebris(view, RendererPass::Additive);
DrawSprites(view, RendererPass::Additive); DrawSprites(nullptr, view, RendererPass::Additive);
DrawFishSwarm(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. // Collect all non-commutative transparent faces.
// NOTE: Sorted sprites already collected at beginning of frame. // NOTE: Sorted sprites already collected at beginning of frame.
DrawRooms(view, RendererPass::CollectTransparentFaces); DrawRooms(view, RendererPass::CollectTransparentFaces);
DrawItems(view, RendererPass::CollectTransparentFaces); DrawItems(nullptr, view, RendererPass::CollectTransparentFaces);
DrawStatics(view, RendererPass::CollectTransparentFaces); DrawStatics(nullptr, view, RendererPass::CollectTransparentFaces);
DrawBats(view, RendererPass::CollectTransparentFaces); DrawBats(nullptr, view, RendererPass::CollectTransparentFaces);
DrawEffects(view, RendererPass::CollectTransparentFaces); DrawEffects(view, RendererPass::CollectTransparentFaces);
DrawRats(view, RendererPass::CollectTransparentFaces); DrawRats(nullptr, view, RendererPass::CollectTransparentFaces);
DrawLocusts(view, RendererPass::CollectTransparentFaces); DrawLocusts(nullptr, view, RendererPass::CollectTransparentFaces);
DrawFishSwarm(view, RendererPass::CollectTransparentFaces); DrawFishSwarm(view, RendererPass::CollectTransparentFaces);
// Draw sorted faces. // 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. // HACK: Gunflashes drawn after everything because they are very near the camera.
DrawGunFlashes(view); DrawGunFlashes(nullptr, view);
DrawBaddyGunflashes(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. // Draw 3D debug lines and triangles.
DrawLines3D(view); DrawLines3D(view);
@ -2160,7 +2256,7 @@ namespace TEN::Renderer
_graphicsSettingsChanged = false; _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 stride = sizeof(Vertex);
unsigned int offset = 0; unsigned int offset = 0;
@ -2189,7 +2285,7 @@ namespace TEN::Renderer
switch (itemToDraw->ObjectID) switch (itemToDraw->ObjectID)
{ {
case ID_LARA: case ID_LARA:
DrawLara(view, rendererPass); DrawLara(mirror, view, rendererPass);
break; break;
case ID_WATERFALL1: case ID_WATERFALL1:
@ -2200,11 +2296,11 @@ namespace TEN::Renderer
case ID_WATERFALL6: case ID_WATERFALL6:
case ID_WATERFALLSS1: case ID_WATERFALLSS1:
case ID_WATERFALLSS2: case ID_WATERFALLSS2:
DrawWaterfalls(itemToDraw, view, 10, rendererPass); DrawWaterfalls(itemToDraw, mirror, view, 10, rendererPass);
continue; continue;
default: default:
DrawAnimatingItem(itemToDraw, view, rendererPass); DrawAnimatingItem(itemToDraw, mirror, view, rendererPass);
break; 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 // 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. // its texture height and scroll all the textures according to that height.
@ -2259,21 +2360,30 @@ namespace TEN::Renderer
_cbAnimated.UpdateData(_stAnimated, _context.Get()); _cbAnimated.UpdateData(_stAnimated, _context.Get());
DrawAnimatingItem(item, view, rendererPass); DrawAnimatingItem(item, mirror, view, rendererPass);
// Reset animated buffer after rendering just in case // Reset animated buffer after rendering just in case
_stAnimated.Fps = _stAnimated.NumFrames = _stAnimated.Type = 0; _stAnimated.Fps = _stAnimated.NumFrames = _stAnimated.Type = 0;
_cbAnimated.UpdateData(_stAnimated, _context.Get()); _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]; ItemInfo* nativeItem = &g_Level.Items[item->ItemNumber];
RendererRoom* room = &_rooms[item->RoomNumber]; RendererRoom* room = &_rooms[item->RoomNumber];
RendererObject& moveableObj = *_moveableObjects[item->ObjectID]; RendererObject& moveableObj = *_moveableObjects[item->ObjectID];
// Bind item main properties // Bind item main properties
_stItem.World = item->InterpolatedWorld; _stItem.World = item->InterpolatedWorld;
if (mirror != nullptr)
{
_stItem.World = _stItem.World * mirror->ReflectionMatrix;
}
_stItem.Color = item->Color; _stItem.Color = item->Color;
_stItem.AmbientLight = item->AmbientLight; _stItem.AmbientLight = item->AmbientLight;
memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, sizeof(Matrix) * MAX_BONES); 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) if (_staticTextures.size() == 0 || view.SortedStaticsToDraw.size() == 0)
{ {
@ -2427,6 +2537,11 @@ namespace TEN::Renderer
RendererStatic* current = statics[s]; RendererStatic* current = statics[s];
RendererRoom* room = &_rooms[current->RoomNumber]; RendererRoom* room = &_rooms[current->RoomNumber];
if (mirror != nullptr && current->RoomNumber != mirror->RoomNumber)
{
continue;
}
_stInstancedStaticMeshBuffer.StaticMeshes[k].World = current->World; _stInstancedStaticMeshBuffer.StaticMeshes[k].World = current->World;
_stInstancedStaticMeshBuffer.StaticMeshes[k].Color = current->Color; _stInstancedStaticMeshBuffer.StaticMeshes[k].Color = current->Color;
_stInstancedStaticMeshBuffer.StaticMeshes[k].Ambient = room->AmbientLight; _stInstancedStaticMeshBuffer.StaticMeshes[k].Ambient = room->AmbientLight;
@ -2440,35 +2555,38 @@ namespace TEN::Renderer
k++; k++;
} }
_cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get());
baseStaticIndex += bucketSize; baseStaticIndex += bucketSize;
for (auto& bucket : refMesh->Buckets) if (k > 0)
{ {
if (bucket.NumVertices == 0) _cbInstancedStaticMeshBuffer.UpdateData(_stInstancedStaticMeshBuffer, _context.Get());
{
continue;
}
int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1; for (auto& bucket : refMesh->Buckets)
for (int p = 0; p < passes; p++)
{ {
if (!SetupBlendModeAndAlphaTest(bucket.BlendMode, rendererPass, p)) if (bucket.NumVertices == 0)
{ {
continue; continue;
} }
BindTexture(TextureRegister::ColorMap, int passes = rendererPass == RendererPass::Opaque && bucket.BlendMode == BlendMode::AlphaTest ? 2 : 1;
&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); 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.Width = STAR_SIZE * star.Scale;
rDrawSprite.Height = 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( _stInstancedSpriteBuffer.Sprites[i].Color = Vector4(
star.Color.x, star.Color.x,
star.Color.y, star.Color.y,
@ -2884,7 +3002,7 @@ namespace TEN::Renderer
rDrawSprite.Height = 192; rDrawSprite.Height = 192;
rDrawSprite.ConstrainAxis = meteor.Direction; rDrawSprite.ConstrainAxis = meteor.Direction;
_stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, renderView); _stInstancedSpriteBuffer.Sprites[i].World = GetWorldMatrixForSprite(&rDrawSprite, nullptr, renderView);
_stInstancedSpriteBuffer.Sprites[i].Color = Vector4( _stInstancedSpriteBuffer.Sprites[i].Color = Vector4(
meteor.Color.x, meteor.Color.x,
meteor.Color.y, meteor.Color.y,
@ -2989,7 +3107,7 @@ namespace TEN::Renderer
rDrawSprite.Width = SUN_SIZE; rDrawSprite.Width = SUN_SIZE;
rDrawSprite.Height = 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].Color = Vector4::One;
_stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = 0; _stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = 0;
@ -3177,7 +3295,7 @@ namespace TEN::Renderer
return true; return true;
} }
void Renderer::DrawSortedFaces(RenderView& view) void Renderer::DrawSortedFaces(RendererMirror* mirror, RenderView& view)
{ {
std::sort( std::sort(
view.TransparentObjectsToDraw.begin(), view.TransparentObjectsToDraw.begin(),
@ -3196,6 +3314,11 @@ namespace TEN::Renderer
_sortedPolygonsVertices.clear(); _sortedPolygonsVertices.clear();
_sortedPolygonsIndices.clear(); _sortedPolygonsIndices.clear();
if (mirror != nullptr && object->ObjectType != RendererObjectType::Sprite)
{
continue;
}
if (object->ObjectType == RendererObjectType::Room) if (object->ObjectType == RendererObjectType::Room)
{ {
while (i < view.TransparentObjectsToDraw.size() && while (i < view.TransparentObjectsToDraw.size() &&
@ -3346,23 +3469,25 @@ namespace TEN::Renderer
uv2 = spr->Sprite->UV[2]; uv2 = spr->Sprite->UV[2];
uv3 = spr->Sprite->UV[3]; uv3 = spr->Sprite->UV[3];
Matrix world = GetWorldMatrixForSprite(currentObject->Sprite, mirror, view);
Vertex v0; Vertex v0;
v0.Position = Vector3::Transform(p0t, currentObject->World); v0.Position = Vector3::Transform(p0t, world);
v0.UV = uv0; v0.UV = uv0;
v0.Color = spr->c1; v0.Color = spr->c1;
Vertex v1; Vertex v1;
v1.Position = Vector3::Transform(p1t, currentObject->World); v1.Position = Vector3::Transform(p1t, world);
v1.UV = uv1; v1.UV = uv1;
v1.Color = spr->c2; v1.Color = spr->c2;
Vertex v2; Vertex v2;
v2.Position = Vector3::Transform(p2t, currentObject->World); v2.Position = Vector3::Transform(p2t, world);
v2.UV = uv2; v2.UV = uv2;
v2.Color = spr->c3; v2.Color = spr->c3;
Vertex v3; Vertex v3;
v3.Position = Vector3::Transform(p3t, currentObject->World); v3.Position = Vector3::Transform(p3t, world);
v3.UV = uv3; v3.UV = uv3;
v3.Color = spr->c4; v3.Color = spr->c4;
@ -3609,8 +3734,8 @@ namespace TEN::Renderer
D3D11_VIEWPORT viewport; D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0; viewport.TopLeftX = 0;
viewport.TopLeftY = 0; viewport.TopLeftY = 0;
viewport.Width = _screenWidth; viewport.Width = _screenWidth/2;
viewport.Height = _screenHeight; viewport.Height = _screenHeight / 2;
viewport.MinDepth = 0.0f; viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f; viewport.MaxDepth = 1.0f;
@ -3685,4 +3810,58 @@ namespace TEN::Renderer
_gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane; _gameCamera.Camera.NearPlane = _currentGameCamera.Camera.NearPlane;
_gameCamera.Camera.FarPlane = _currentGameCamera.Camera.FarPlane; _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<TextureRegister>(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;
}
} }

View file

@ -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->VSSetShader(_vsStatics.Get(), nullptr, 0);
_context->PSSetShader(_psStatics.Get(), nullptr, 0); _context->PSSetShader(_psStatics.Get(), nullptr, 0);
@ -1106,6 +1106,11 @@ namespace TEN::Renderer
worldMatrix = tMatrix * worldMatrix; worldMatrix = tMatrix * worldMatrix;
worldMatrix = rotMatrix * worldMatrix; worldMatrix = rotMatrix * worldMatrix;
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stStatic.World = worldMatrix; _stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get()); _cbStatic.UpdateData(_stStatic, _context.Get());
@ -1120,6 +1125,11 @@ namespace TEN::Renderer
worldMatrix = tMatrix * worldMatrix; worldMatrix = tMatrix * worldMatrix;
worldMatrix = rotMatrix * worldMatrix; worldMatrix = rotMatrix * worldMatrix;
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stStatic.World = worldMatrix; _stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get()); _cbStatic.UpdateData(_stStatic, _context.Get());
@ -1134,7 +1144,7 @@ namespace TEN::Renderer
return true; return true;
} }
void Renderer::DrawBaddyGunflashes(RenderView& view) void Renderer::DrawBaddyGunflashes(RendererMirror* mirror, RenderView& view)
{ {
_context->VSSetShader(_vsStatics.Get(), nullptr, 0); _context->VSSetShader(_vsStatics.Get(), nullptr, 0);
_context->PSSetShader(_psStatics.Get(), nullptr, 0); _context->PSSetShader(_psStatics.Get(), nullptr, 0);
@ -1151,6 +1161,11 @@ namespace TEN::Renderer
{ {
auto& nativeItem = g_Level.Items[rItemPtr->ItemNumber]; auto& nativeItem = g_Level.Items[rItemPtr->ItemNumber];
if (mirror != nullptr && nativeItem.RoomNumber != mirror->RoomNumber)
{
continue;
}
if (!nativeItem.IsCreature()) if (!nativeItem.IsCreature())
continue; continue;
@ -1196,6 +1211,11 @@ namespace TEN::Renderer
if (creature.MuzzleFlash[0].ApplyZRotation) if (creature.MuzzleFlash[0].ApplyZRotation)
worldMatrix = rotMatrixZ * worldMatrix; worldMatrix = rotMatrixZ * worldMatrix;
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stStatic.World = worldMatrix; _stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get()); _cbStatic.UpdateData(_stStatic, _context.Get());
@ -1236,6 +1256,11 @@ namespace TEN::Renderer
if (creature.MuzzleFlash[1].ApplyZRotation) if (creature.MuzzleFlash[1].ApplyZRotation)
worldMatrix = rotMatrixZ * worldMatrix; worldMatrix = rotMatrixZ * worldMatrix;
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stStatic.World = worldMatrix; _stStatic.World = worldMatrix;
_cbStatic.UpdateData(_stStatic, _context.Get()); _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 spriteMatrix = Matrix::Identity;
auto scaleMatrix = Matrix::CreateScale(sprite->Width * sprite->Scale, sprite->Height * sprite->Scale, sprite->Scale); 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) switch (sprite->Type)
{ {
case SpriteType::Billboard: case SpriteType::Billboard:
{ {
auto cameraUp = Vector3(view.Camera.View._12, view.Camera.View._22, view.Camera.View._32); 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; break;
@ -1286,7 +1317,7 @@ namespace TEN::Renderer
auto rotMatrix = Matrix::CreateRotationY(sprite->Rotation); auto rotMatrix = Matrix::CreateRotationY(sprite->Rotation);
auto quadForward = Vector3(0.0f, 0.0f, 1.0f); auto quadForward = Vector3(0.0f, 0.0f, 1.0f);
spriteMatrix = scaleMatrix * Matrix::CreateConstrainedBillboard( spriteMatrix = scaleMatrix * Matrix::CreateConstrainedBillboard(
sprite->pos, spritePosition,
Camera.pos.ToVector3(), Camera.pos.ToVector3(),
sprite->ConstrainAxis, sprite->ConstrainAxis,
nullptr, nullptr,
@ -1296,7 +1327,7 @@ namespace TEN::Renderer
case SpriteType::LookAtBillboard: 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); auto rotMatrix = Matrix::CreateRotationZ(sprite->Rotation) * Matrix::CreateLookAt(Vector3::Zero, sprite->LookAtAxis, Vector3::UnitZ);
spriteMatrix = scaleMatrix * rotMatrix * tMatrix; spriteMatrix = scaleMatrix * rotMatrix * tMatrix;
} }

View file

@ -147,6 +147,19 @@ namespace TEN::Renderer
for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++) for (int i = 0; i < std::min(MAX_LENS_FLARES_DRAW, (int)tempLensFlares.size()); i++)
renderView.LensFlaresToDraw.push_back(tempLensFlares[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) bool Renderer::CheckPortal(short parentRoomNumber, RendererDoor* door, Vector4 viewPort, Vector4* clipPort, RenderView& renderView)

View file

@ -278,8 +278,13 @@ void Renderer::UpdateLaraAnimations(bool force)
rItem.DoneAnimations = true; 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. // Don't draw player if using optics.
if (Lara.Control.Look.OpticRange != 0 || SpotcamDontDrawLara) if (Lara.Control.Look.OpticRange != 0 || SpotcamDontDrawLara)
return; return;
@ -305,7 +310,12 @@ void TEN::Renderer::Renderer::DrawLara(RenderView& view, RendererPass rendererPa
RendererRoom* room = &_rooms[LaraItem->RoomNumber]; 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.Color = item->Color;
_stItem.AmbientLight = item->AmbientLight; _stItem.AmbientLight = item->AmbientLight;
memcpy(_stItem.BonesMatrices, item->InterpolatedAnimTransforms, laraObj.AnimationTransforms.size() * sizeof(Matrix)); 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); DrawMoveableMesh(item, GetMesh(nativeItem->Model.MeshIndex[k]), room, k, view, rendererPass);
} }
DrawLaraHolsters(item, room, view, rendererPass); DrawLaraHolsters(item, room, mirror, view, rendererPass);
DrawLaraJoints(item, room, view, rendererPass); DrawLaraJoints(item, room, mirror, view, rendererPass);
DrawLaraHair(item, room, 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++) 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.World = Matrix::Identity;
_stItem.BonesMatrices[0] = itemToDraw->InterpolatedAnimTransforms[LM_HEAD] * itemToDraw->InterpolatedWorld; _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++) 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)) * Quaternion::Lerp(segment.PrevOrientation, segment.Orientation, _interpolationFactor)) *
Matrix::CreateTranslation( Matrix::CreateTranslation(
Vector3::Lerp(segment.PrevPosition, segment.Position, _interpolationFactor)); Vector3::Lerp(segment.PrevPosition, segment.Position, _interpolationFactor));
if (mirror != nullptr)
{
worldMatrix = worldMatrix * mirror->ReflectionMatrix;
}
_stItem.BonesMatrices[i + 1] = worldMatrix; _stItem.BonesMatrices[i + 1] = worldMatrix;
_stItem.BoneLightModes[i] = (int)LightMode::Dynamic; _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()) if (!_moveableObjects[ID_LARA_SKIN_JOINTS].has_value())
return; 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 leftHolsterID = Lara.Control.Weapon.HolsterInfo.LeftHolster;
HolsterSlot rightHolsterID = Lara.Control.Weapon.HolsterInfo.RightHolster; HolsterSlot rightHolsterID = Lara.Control.Weapon.HolsterInfo.RightHolster;

View file

@ -243,7 +243,7 @@ namespace TEN::Renderer
object.Centre = rDrawSprite.pos; object.Centre = rDrawSprite.pos;
object.Distance = distance; object.Distance = distance;
object.Sprite = &rDrawSprite; object.Sprite = &rDrawSprite;
object.World = GetWorldMatrixForSprite(&rDrawSprite, view); //object.World = GetWorldMatrixForSprite(&rDrawSprite, view);
view.TransparentObjectsToDraw.push_back(object); view.TransparentObjectsToDraw.push_back(object);
} }
@ -256,7 +256,7 @@ namespace TEN::Renderer
_spriteBuckets.push_back(currentSpriteBucket); _spriteBuckets.push_back(currentSpriteBucket);
} }
void Renderer::DrawSprites(RenderView& view, RendererPass rendererPass) void Renderer::DrawSprites(RendererMirror* mirror, RenderView& view, RendererPass rendererPass)
{ {
if (view.SpritesToDraw.empty()) if (view.SpritesToDraw.empty())
return; return;
@ -296,7 +296,7 @@ namespace TEN::Renderer
{ {
auto& rDrawSprite = spriteBucket.SpritesToDraw[i]; 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].Color = rDrawSprite.color;
_stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[i].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = rDrawSprite.SoftParticle ? 1 : 0; _stInstancedSpriteBuffer.Sprites[i].IsSoftParticle = rDrawSprite.SoftParticle ? 1 : 0;
@ -414,7 +414,7 @@ namespace TEN::Renderer
UINT offset = 0; UINT offset = 0;
_context->IASetVertexBuffers(0, 1, _quadVertexBuffer.Buffer.GetAddressOf(), &stride, &offset); _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].Color = object->Sprite->color;
_stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1; _stInstancedSpriteBuffer.Sprites[0].IsBillboard = 1;
_stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = object->Sprite->SoftParticle ? 1 : 0; _stInstancedSpriteBuffer.Sprites[0].IsSoftParticle = object->Sprite->SoftParticle ? 1 : 0;

View file

@ -0,0 +1,16 @@
#pragma once
#include <SimpleMath.h>
namespace TEN::Renderer::Structures
{
using namespace DirectX;
using namespace DirectX::SimpleMath;
struct RendererMirror
{
short RoomNumber;
short MirroredRoomNumber;
Plane Plane;
Matrix ReflectionMatrix;
};
}

View file

@ -32,6 +32,20 @@ PixelShaderInput VS(VertexShaderInput input)
return output; 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 float4 PSCopy(PixelShaderInput input) : SV_Target
{ {
return ColorTexture.Sample(ColorSampler, input.UV); return ColorTexture.Sample(ColorSampler, input.UV);

View file

@ -1417,6 +1417,17 @@ bool LoadLevel(const std::string& path, bool partial)
UpdateProgress(100, 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); TENLog("Level loading complete.", LogLevel::Info);
loadedSuccessfully = true; loadedSuccessfully = true;

View file

@ -85,6 +85,13 @@ struct MESH
std::vector<BUCKET> buckets; std::vector<BUCKET> buckets;
}; };
struct MirrorInfo
{
short RoomNumber;
short MirroredRoomNumber;
Plane MirrorPlane;
};
// LevelData // LevelData
struct LEVEL struct LEVEL
{ {
@ -123,6 +130,7 @@ struct LEVEL
std::vector<int> LoopedEventSetIndices = {}; std::vector<int> LoopedEventSetIndices = {};
std::vector<AI_OBJECT> AIObjects = {}; std::vector<AI_OBJECT> AIObjects = {};
std::vector<SPRITE> Sprites = {}; std::vector<SPRITE> Sprites = {};
std::vector<MirrorInfo> Mirrors = {};
// Texture data // Texture data
TEXTURE SkyTexture = {}; TEXTURE SkyTexture = {};

View file

@ -821,6 +821,7 @@ if not exist "%ScriptsDir%\Strings.lua" xcopy /Y "$(SolutionDir)Scripts\Strings.
<ClInclude Include="Renderer\Graphics\Vertices\Vertex.h" /> <ClInclude Include="Renderer\Graphics\Vertices\Vertex.h" />
<ClInclude Include="Renderer\Renderer.h" /> <ClInclude Include="Renderer\Renderer.h" />
<ClInclude Include="Renderer\RendererEnums.h" /> <ClInclude Include="Renderer\RendererEnums.h" />
<ClInclude Include="Renderer\Structures\RendererMirror.h" />
<ClInclude Include="Renderer\RendererSprite2D.h" /> <ClInclude Include="Renderer\RendererSprite2D.h" />
<ClInclude Include="Renderer\RendererBucket.h" /> <ClInclude Include="Renderer\RendererBucket.h" />
<ClInclude Include="Renderer\RendererPolygon.h" /> <ClInclude Include="Renderer\RendererPolygon.h" />