mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
459 lines
11 KiB
C++
459 lines
11 KiB
C++
#include "framework.h"
|
|
#include "Renderer/Renderer.h"
|
|
#include "Game/camera.h"
|
|
#include "Game/effects/tomb4fx.h"
|
|
#include "Math/Math.h"
|
|
#include "Renderer/Structures/RendererRectangle.h"
|
|
#include "Renderer/RenderView.h"
|
|
#include "Renderer/RendererUtils.h"
|
|
#include "Renderer/Graphics/VertexBuffer.h"
|
|
#include "Renderer/Structures/RendererHudBar.h"
|
|
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
|
#include "Specific/clock.h"
|
|
#include "Graphics/RenderTargetCube.h"
|
|
|
|
namespace TEN::Renderer
|
|
{
|
|
using namespace TEN::Renderer::Structures;
|
|
using namespace Utils;
|
|
Renderer g_Renderer;
|
|
|
|
Renderer::Renderer() :
|
|
_gameCamera({0, 0, 0}, {0, 0, 1}, {0, 1, 0}, 1, 1, 0, 1, 10, 90),
|
|
_oldGameCamera({ 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, 1, 1, 0, 1, 10, 90),
|
|
_currentGameCamera({ 0, 0, 0 }, { 0, 0, 1 }, { 0, 1, 0 }, 1, 1, 0, 1, 10, 90)
|
|
{
|
|
}
|
|
|
|
Renderer::~Renderer()
|
|
{
|
|
FreeRendererData();
|
|
}
|
|
|
|
void Renderer::FreeRendererData()
|
|
{
|
|
_items.resize(0);
|
|
_effects.resize(0);
|
|
_moveableObjects.resize(0);
|
|
_staticObjects.clear();
|
|
_sprites.resize(0);
|
|
_rooms.resize(0);
|
|
_roomTextures.resize(0);
|
|
_moveablesTextures.resize(0);
|
|
_staticTextures.resize(0);
|
|
_spritesTextures.resize(0);
|
|
_animatedTextures.resize(0);
|
|
_animatedTextureSets.resize(0);
|
|
|
|
_shadowLight = nullptr;
|
|
|
|
_dynamicLightList = 0;
|
|
for (auto& dynamicLightList : _dynamicLights)
|
|
dynamicLightList.resize(0);
|
|
|
|
for (auto& mesh : _meshes)
|
|
delete mesh;
|
|
_meshes.resize(0);
|
|
}
|
|
|
|
void Renderer::Lock()
|
|
{
|
|
_isLocked = true;
|
|
}
|
|
|
|
int Renderer::Synchronize()
|
|
{
|
|
// Sync the renderer
|
|
int nf = TimeSync();
|
|
if (nf < 2)
|
|
{
|
|
int i = 2 - nf;
|
|
nf = 2;
|
|
do
|
|
{
|
|
while (!TimeSync());
|
|
i--;
|
|
}
|
|
while (i);
|
|
}
|
|
|
|
return nf;
|
|
}
|
|
|
|
void Renderer::UpdateProgress(float value)
|
|
{
|
|
RenderLoadingScreen(value);
|
|
}
|
|
|
|
void Renderer::RenderToCubemap(const RenderTargetCube& dest, const Vector3& pos, int roomNumer)
|
|
{
|
|
for (int i = 0; i < 6; i++)
|
|
{
|
|
auto renderView = RenderView(pos, RenderTargetCube::forwardVectors[i], RenderTargetCube::upVectors[i],
|
|
dest.Resolution, dest.Resolution, Camera.pos.RoomNumber, 10, 20480,
|
|
90 * RADIAN);
|
|
//RenderSimpleScene(dest.RenderTargetView[i].Get(), dest.DepthStencilView[i].Get(), renderView);
|
|
_context->ClearState();
|
|
}
|
|
}
|
|
|
|
float Renderer::CalculateFrameRate()
|
|
{
|
|
static int last_time = clock();
|
|
static int count = 0;
|
|
static float fps = 0.0f;
|
|
|
|
count++;
|
|
if (count == 10)
|
|
{
|
|
double t;
|
|
time_t this_time;
|
|
this_time = clock();
|
|
t = (this_time - last_time) / (double)CLOCKS_PER_SEC;
|
|
last_time = this_time;
|
|
fps = float(count / t);
|
|
count = 0;
|
|
}
|
|
|
|
_fps = fps;
|
|
|
|
return fps;
|
|
}
|
|
|
|
void Renderer::BindTexture(TextureRegister registerType, TextureBase* texture, SamplerStateRegister samplerType)
|
|
{
|
|
_context->PSSetShaderResources((UINT)registerType, 1, texture->ShaderResourceView.GetAddressOf());
|
|
|
|
if (g_GameFlow->IsPointFilterEnabled() && samplerType != SamplerStateRegister::ShadowMap)
|
|
{
|
|
samplerType = SamplerStateRegister::PointWrap;
|
|
}
|
|
|
|
ID3D11SamplerState* samplerState = nullptr;
|
|
switch (samplerType)
|
|
{
|
|
case SamplerStateRegister::AnisotropicClamp:
|
|
samplerState = _renderStates->AnisotropicClamp();
|
|
break;
|
|
|
|
case SamplerStateRegister::AnisotropicWrap:
|
|
samplerState = _renderStates->AnisotropicWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::LinearClamp:
|
|
samplerState = _renderStates->LinearClamp();
|
|
break;
|
|
|
|
case SamplerStateRegister::LinearWrap:
|
|
samplerState = _renderStates->LinearWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::PointWrap:
|
|
samplerState = _renderStates->PointWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::ShadowMap:
|
|
samplerState = _shadowSampler.Get();
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
_context->PSSetSamplers((UINT)registerType, 1, &samplerState);
|
|
}
|
|
|
|
void Renderer::BindRenderTargetAsTexture(TextureRegister registerType, RenderTarget2D* target, SamplerStateRegister samplerType)
|
|
{
|
|
_context->PSSetShaderResources((UINT)registerType, 1, target->ShaderResourceView.GetAddressOf());
|
|
|
|
ID3D11SamplerState* samplerState = nullptr;
|
|
switch (samplerType)
|
|
{
|
|
case SamplerStateRegister::AnisotropicClamp:
|
|
samplerState = _renderStates->AnisotropicClamp();
|
|
break;
|
|
|
|
case SamplerStateRegister::AnisotropicWrap:
|
|
samplerState = _renderStates->AnisotropicWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::LinearClamp:
|
|
samplerState = _renderStates->LinearClamp();
|
|
break;
|
|
|
|
case SamplerStateRegister::LinearWrap:
|
|
samplerState = _renderStates->LinearWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::PointWrap:
|
|
samplerState = _renderStates->PointWrap();
|
|
break;
|
|
|
|
case SamplerStateRegister::ShadowMap:
|
|
samplerState = _shadowSampler.Get();
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
_context->PSSetSamplers((UINT)registerType, 1, &samplerState);
|
|
}
|
|
|
|
int Renderer::BindLight(RendererLight& light, ShaderLight* lights, int index)
|
|
{
|
|
memcpy(&lights[index], &light, sizeof(ShaderLight));
|
|
|
|
// Precalculate ranges so that it's not recalculated in shader for every pixel.
|
|
if (light.Type == LightType::Spot)
|
|
{
|
|
lights[index].InRange = cos(light.InRange * (PI / 180.0f));
|
|
lights[index].OutRange = cos(light.OutRange * (PI / 180.0f));
|
|
}
|
|
|
|
// If light has hash, interpolate its position with previous position.
|
|
if (light.Hash != 0)
|
|
{
|
|
lights[index].Position = Vector3::Lerp(light.PrevPosition, light.Position, GetInterpolationFactor());
|
|
lights[index].Direction = Vector3::Lerp(light.PrevDirection, light.Direction, GetInterpolationFactor());
|
|
}
|
|
|
|
// If we are in mirror renderer pass, reflect light.
|
|
ReflectVectorOptionally(lights[index].Position);
|
|
ReflectVectorOptionally(lights[index].Direction);
|
|
|
|
// Bitmask light type to filter it in the shader later.
|
|
return (1 << (31 - (int)light.Type));
|
|
}
|
|
|
|
void Renderer::BindRoomLights(std::vector<RendererLight*>& lights)
|
|
{
|
|
int lightTypeMask = 0;
|
|
|
|
for (int i = 0; i < lights.size(); i++)
|
|
lightTypeMask = lightTypeMask | BindLight(*lights[i], _stRoom.RoomLights, i);
|
|
|
|
_stRoom.NumRoomLights = (int)lights.size() | lightTypeMask;
|
|
}
|
|
|
|
void Renderer::BindStaticLights(std::vector<RendererLight*>& lights)
|
|
{
|
|
int lightTypeMask = 0;
|
|
|
|
for (int i = 0; i < lights.size(); i++)
|
|
lightTypeMask = lightTypeMask | BindLight(*lights[i], _stStatic.Lights, i);
|
|
|
|
_stStatic.NumLights = (int)lights.size() | lightTypeMask;
|
|
}
|
|
|
|
void Renderer::BindInstancedStaticLights(std::vector<RendererLight*>& lights, int instanceID)
|
|
{
|
|
int lightTypeMask = 0;
|
|
|
|
for (int i = 0; i < lights.size(); i++)
|
|
lightTypeMask = lightTypeMask | BindLight(*lights[i], _stInstancedStaticMeshBuffer.StaticMeshes[instanceID].Lights, i);
|
|
|
|
_stInstancedStaticMeshBuffer.StaticMeshes[instanceID].NumLights = (int)lights.size() | lightTypeMask;
|
|
}
|
|
|
|
void Renderer::BindMoveableLights(std::vector<RendererLight*>& lights, int roomNumber, int prevRoomNumber, float fade)
|
|
{
|
|
int lightTypeMask = 0;
|
|
|
|
int numLights = 0;
|
|
for (int i = 0; i < lights.size(); i++)
|
|
{
|
|
float fadedCoeff = 1.0f;
|
|
|
|
// Interpolate lights which don't affect neighbor rooms
|
|
if (!lights[i]->AffectNeighbourRooms && roomNumber != NO_VALUE && lights[i]->RoomNumber != NO_VALUE)
|
|
{
|
|
if (lights[i]->RoomNumber == roomNumber)
|
|
fadedCoeff = fade;
|
|
else if (lights[i]->RoomNumber == prevRoomNumber)
|
|
fadedCoeff = 1.0f - fade;
|
|
else
|
|
continue;
|
|
}
|
|
|
|
if (fadedCoeff == 0.0f)
|
|
continue;
|
|
|
|
lightTypeMask = lightTypeMask | BindLight(*lights[i], _stItem.Lights, numLights);
|
|
|
|
_stItem.Lights[numLights].Intensity *= fadedCoeff;
|
|
numLights++;
|
|
}
|
|
|
|
_stItem.NumLights = numLights | lightTypeMask;
|
|
}
|
|
|
|
void Renderer::BindConstantBufferVS(ConstantBufferRegister constantBufferType, ID3D11Buffer** buffer)
|
|
{
|
|
_context->VSSetConstantBuffers(static_cast<UINT>(constantBufferType), 1, buffer);
|
|
}
|
|
|
|
void Renderer::BindConstantBufferPS(ConstantBufferRegister constantBufferType, ID3D11Buffer** buffer)
|
|
{
|
|
_context->PSSetConstantBuffers(static_cast<UINT>(constantBufferType), 1, buffer);
|
|
}
|
|
|
|
void Renderer::SetBlendMode(BlendMode blendMode, bool force)
|
|
{
|
|
if (blendMode != _lastBlendMode || force)
|
|
{
|
|
switch (blendMode)
|
|
{
|
|
case BlendMode::AlphaBlend:
|
|
_context->OMSetBlendState(_renderStates->NonPremultiplied(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::AlphaTest:
|
|
_context->OMSetBlendState(_renderStates->Opaque(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Opaque:
|
|
_context->OMSetBlendState(_renderStates->Opaque(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Subtractive:
|
|
_context->OMSetBlendState(_subtractiveBlendState.Get(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Additive:
|
|
_context->OMSetBlendState(_renderStates->Additive(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Screen:
|
|
_context->OMSetBlendState(_screenBlendState.Get(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Lighten:
|
|
_context->OMSetBlendState(_lightenBlendState.Get(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
|
|
case BlendMode::Exclude:
|
|
_context->OMSetBlendState(_excludeBlendState.Get(), nullptr, 0xFFFFFFFF);
|
|
break;
|
|
}
|
|
|
|
_stBlending.BlendMode = static_cast<unsigned int>(blendMode);
|
|
_cbBlending.UpdateData(_stBlending, _context.Get());
|
|
|
|
_lastBlendMode = blendMode;
|
|
}
|
|
|
|
switch (blendMode)
|
|
{
|
|
case BlendMode::Opaque:
|
|
case BlendMode::AlphaTest:
|
|
SetDepthState(DepthState::Write);
|
|
break;
|
|
|
|
default:
|
|
SetDepthState(DepthState::Read);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Renderer::SetDepthState(DepthState depthState, bool force)
|
|
{
|
|
if (depthState != _lastDepthState || force)
|
|
{
|
|
switch (depthState)
|
|
{
|
|
case DepthState::Read:
|
|
_context->OMSetDepthStencilState(_renderStates->DepthRead(), 0xFFFFFFFF);
|
|
break;
|
|
|
|
case DepthState::Write:
|
|
_context->OMSetDepthStencilState(_renderStates->DepthDefault(), 0xFFFFFFFF);
|
|
break;
|
|
|
|
case DepthState::None:
|
|
_context->OMSetDepthStencilState(_renderStates->DepthNone(), 0xFFFFFFFF);
|
|
break;
|
|
|
|
}
|
|
|
|
_lastDepthState = depthState;
|
|
}
|
|
}
|
|
|
|
void Renderer::SetCullMode(CullMode cullMode, bool force)
|
|
{
|
|
if (_debugPage == RendererDebugPage::WireframeMode)
|
|
{
|
|
if (!_doingFullscreenPass)
|
|
{
|
|
_context->RSSetState(_renderStates->Wireframe());
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
force = true;
|
|
}
|
|
}
|
|
|
|
if (cullMode != _lastCullMode || force)
|
|
{
|
|
switch (cullMode)
|
|
{
|
|
case CullMode::None:
|
|
_context->RSSetState(_cullNoneRasterizerState.Get());
|
|
break;
|
|
|
|
case CullMode::CounterClockwise:
|
|
_context->RSSetState(_cullCounterClockwiseRasterizerState.Get());
|
|
break;
|
|
|
|
case CullMode::Clockwise:
|
|
_context->RSSetState(_cullClockwiseRasterizerState.Get());
|
|
break;
|
|
}
|
|
|
|
_lastCullMode = cullMode;
|
|
}
|
|
}
|
|
|
|
void Renderer::SetAlphaTest(AlphaTestMode mode, float threshold, bool force)
|
|
{
|
|
if (_stBlending.AlphaTest != (int)mode ||
|
|
_stBlending.AlphaThreshold != threshold ||
|
|
force)
|
|
{
|
|
_stBlending.AlphaTest = (int)mode;
|
|
_stBlending.AlphaThreshold = threshold;
|
|
_cbBlending.UpdateData(_stBlending, _context.Get());
|
|
BindConstantBufferPS(ConstantBufferRegister::Blending, _cbBlending.get());
|
|
}
|
|
}
|
|
|
|
void Renderer::SetScissor(RendererRectangle s)
|
|
{
|
|
D3D11_RECT rects;
|
|
rects.left = s.Left;
|
|
rects.top = s.Top;
|
|
rects.right = s.Right;
|
|
rects.bottom = s.Bottom;
|
|
|
|
_context->RSSetScissorRects(1, &rects);
|
|
}
|
|
|
|
void Renderer::ResetScissor()
|
|
{
|
|
D3D11_RECT rects[1];
|
|
rects[0].left = 0;
|
|
rects[0].right = _screenWidth;
|
|
rects[0].top = 0;
|
|
rects[0].bottom = _screenHeight;
|
|
|
|
_context->RSSetScissorRects(1, rects);
|
|
}
|
|
|
|
void Renderer::SetGraphicsSettingsChanged()
|
|
{
|
|
_graphicsSettingsChanged = true;
|
|
}
|
|
}
|