Add antialiasing (#645)

* Add FXAA
* Use existing luma function
* Fix order of rendering not to affect GUI by AA
* Update Renderer11Draw2D.cpp
* Add MSAA as medium and high quality AA levels
* Update configuration.h
* Update Changes.txt
* Update DX11_FinalPass.fx
* Reduce FXAA blurriness
This commit is contained in:
Lwmte 2022-08-08 21:32:33 +03:00 committed by GitHub
parent 6ffa9f04b3
commit e4f6db0a3e
17 changed files with 190 additions and 29 deletions

View file

@ -1,6 +1,7 @@
Version 1.0.1
=============
- Added antialiasing support.
- Fixed rope transparency.
- Fixed incorrect polerope grabbing.
- Fixed camera behaviour with pushable blocks.

View file

@ -1109,6 +1109,46 @@ local strings = {
"",
""
},
antialiasing = {
"Antialiasing",
"",
"",
"",
"",
"",
"",
""
},
low = {
"Low",
"",
"",
"",
"",
"",
"",
""
},
medium = {
"Medium",
"",
"",
"",
"",
"",
"",
""
},
high = {
"High",
"",
"",
"",
"",
"",
"",
""
},
waiting_for_key = {
"Waiting For Key",
"",

View file

@ -803,7 +803,10 @@ void GuiController::HandleDisplaySettingsInput(bool pause)
case 4:
SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always);
CurrentSettings.conf.EnableVolumetricFog = !CurrentSettings.conf.EnableVolumetricFog;
if (CurrentSettings.conf.Antialiasing == AntialiasingMode::None)
CurrentSettings.conf.Antialiasing = AntialiasingMode::High;
else
CurrentSettings.conf.Antialiasing = AntialiasingMode(int(CurrentSettings.conf.Antialiasing) - 1);
break;
}
}
@ -838,7 +841,10 @@ void GuiController::HandleDisplaySettingsInput(bool pause)
case 4:
SoundEffect(SFX_TR4_MENU_CHOOSE, nullptr, SoundEnvironment::Always);
CurrentSettings.conf.EnableVolumetricFog = !CurrentSettings.conf.EnableVolumetricFog;
if (CurrentSettings.conf.Antialiasing == AntialiasingMode::High)
CurrentSettings.conf.Antialiasing = AntialiasingMode::None;
else
CurrentSettings.conf.Antialiasing = AntialiasingMode(int(CurrentSettings.conf.Antialiasing) + 1);
break;
}
}

View file

@ -4,4 +4,5 @@ struct alignas(16) CPostProcessBuffer
float ScreenFadeFactor;
int ViewportWidth;
int ViewportHeight;
int FXAA;
};

View file

@ -1,6 +1,7 @@
#include "framework.h"
#include "RenderTarget2D.h"
#include "Utils.h"
#include "Specific/configuration.h"
namespace TEN::Renderer
{
@ -8,13 +9,36 @@ namespace TEN::Renderer
RenderTarget2D::RenderTarget2D(ID3D11Device* device, int w, int h, DXGI_FORMAT colorFormat, DXGI_FORMAT depthFormat)
{
// Check if antialiasing quality is available, and set it if it is.
D3D11_SRV_DIMENSION srvDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
D3D11_DSV_DIMENSION dsvDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
D3D11_RTV_DIMENSION rtvDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
int sampleCount = 1;
if (g_Configuration.Antialiasing > AntialiasingMode::Low)
{
int potentialSampleCount = (g_Configuration.Antialiasing == AntialiasingMode::Medium) ? 2 : 4;
unsigned int qualityLevels = 0;
if (device->CheckMultisampleQualityLevels(colorFormat, potentialSampleCount, &qualityLevels) == S_OK &&
qualityLevels > 0)
{
sampleCount = potentialSampleCount;
dsvDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
rtvDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
srvDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
}
}
// Now set up render target.
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = w;
desc.Height = h;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = colorFormat;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Count = sampleCount;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
@ -26,7 +50,7 @@ namespace TEN::Renderer
D3D11_RENDER_TARGET_VIEW_DESC viewDesc;
viewDesc.Format = desc.Format;
viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
viewDesc.ViewDimension = rtvDimension;
viewDesc.Texture2D.MipSlice = 0;
res = device->CreateRenderTargetView(Texture.Get(), &viewDesc, &RenderTargetView);
@ -35,7 +59,7 @@ namespace TEN::Renderer
// Setup the description of the shader resource view.
D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc;
shaderDesc.Format = desc.Format;
shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderDesc.ViewDimension = srvDimension;
shaderDesc.Texture2D.MostDetailedMip = 0;
shaderDesc.Texture2D.MipLevels = 1;
@ -47,7 +71,7 @@ namespace TEN::Renderer
depthTexDesc.Height = h;
depthTexDesc.MipLevels = 1;
depthTexDesc.ArraySize = 1;
depthTexDesc.SampleDesc.Count = 1;
depthTexDesc.SampleDesc.Count = sampleCount;
depthTexDesc.SampleDesc.Quality = 0;
depthTexDesc.Format = depthFormat;
depthTexDesc.Usage = D3D11_USAGE_DEFAULT;
@ -61,7 +85,7 @@ namespace TEN::Renderer
D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc = {};
dsvDesc.Format = depthTexDesc.Format;
dsvDesc.Flags = 0;
dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
dsvDesc.ViewDimension = dsvDimension;
dsvDesc.Texture2D.MipSlice = 0;
res = device->CreateDepthStencilView(DepthStencilTexture.Get(), &dsvDesc, &DepthStencilView);

View file

@ -524,7 +524,7 @@ namespace TEN::Renderer
void DrawSimpleParticles(RenderView& view);
void DrawFootprints(RenderView& view);
void DrawLoadingBar(float percent);
void DrawFadeAndBars(ID3D11RenderTargetView* target, ID3D11DepthStencilView* depthTarget, RenderView& view);
void DrawPostprocess(ID3D11RenderTargetView* target, ID3D11DepthStencilView* depthTarget, RenderView& view);
void RenderInventoryScene(ID3D11RenderTargetView* target, ID3D11DepthStencilView* depthTarget,
ID3D11ShaderResourceView* background);

View file

@ -1550,6 +1550,8 @@ namespace TEN::Renderer
DrawTransparentFaces(view);
DrawPostprocess(target, depthTarget, view);
// Draw GUI stuff at the end
DrawLines2D();
@ -1565,7 +1567,6 @@ namespace TEN::Renderer
DrawDebugInfo(view);
DrawAllStrings();
DrawFadeAndBars(target, depthTarget, view);
ClearScene();
}

View file

@ -251,8 +251,7 @@ namespace TEN::Renderer
}
}
void Renderer11::DrawFadeAndBars(ID3D11RenderTargetView* target, ID3D11DepthStencilView* depthTarget,
RenderView& view)
void Renderer11::DrawPostprocess(ID3D11RenderTargetView* target, ID3D11DepthStencilView* depthTarget, RenderView& view)
{
SetBlendMode(BLENDMODE_OPAQUE);
SetCullMode(CULL_MODE_CCW);
@ -299,6 +298,7 @@ namespace TEN::Renderer
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
m_context->IASetInputLayout(m_inputLayout.Get());
m_stPostProcessBuffer.FXAA = g_Configuration.Antialiasing == AntialiasingMode::Low ? 1 : 0;
m_stPostProcessBuffer.ViewportWidth = m_screenWidth;
m_stPostProcessBuffer.ViewportHeight = m_screenHeight;
m_stPostProcessBuffer.ScreenFadeFactor = ScreenFadeCurrent;

View file

@ -101,6 +101,27 @@ namespace TEN::Renderer
auto* shadowMode = g_Gui.GetCurrentSettings().conf.ShadowType != ShadowMode::None ?
(g_Gui.GetCurrentSettings().conf.ShadowType == ShadowMode::Lara ? STRING_SHADOWS_PLAYER : STRING_SHADOWS_ALL) : STRING_SHADOWS_NONE;
const char* antialiasMode;
switch (g_Gui.GetCurrentSettings().conf.Antialiasing)
{
default:
case AntialiasingMode::None:
antialiasMode = STRING_ANTIALIASING_NONE;
break;
case AntialiasingMode::Low:
antialiasMode = STRING_ANTIALIASING_LOW;
break;
case AntialiasingMode::Medium:
antialiasMode = STRING_ANTIALIASING_MEDIUM;
break;
case AntialiasingMode::High:
antialiasMode = STRING_ANTIALIASING_HIGH;
break;
}
switch (menu)
{
case Menu::Options:
@ -149,9 +170,9 @@ namespace TEN::Renderer
AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().conf.EnableCaustics), PRINTSTRING_COLOR_WHITE, SF(title_option == 3));
GetNextLinePosition(&y);
// Enable volumetric fog
AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_VOLUMETRIC_FOG), PRINTSTRING_COLOR_ORANGE, SF(title_option == 4));
AddString(MenuRightSideEntry, y, Str_Enabled(g_Gui.GetCurrentSettings().conf.EnableVolumetricFog), PRINTSTRING_COLOR_WHITE, SF(title_option == 4));
// Enable antialiasing
AddString(MenuLeftSideEntry, y, g_GameFlow->GetString(STRING_ANTIALIASING), PRINTSTRING_COLOR_ORANGE, SF(title_option == 4));
AddString(MenuRightSideEntry, y, g_GameFlow->GetString(antialiasMode), PRINTSTRING_COLOR_WHITE, SF(title_option == 4));
GetNextBlockPosition(&y);
// Apply
@ -468,6 +489,7 @@ namespace TEN::Renderer
g_Gui.DrawAmmoSelector();
g_Gui.FadeAmmoSelector();
g_Gui.DrawCompass();
DrawAllStrings();
}

View file

@ -69,6 +69,14 @@ enum class ShadowMode
All
};
enum class AntialiasingMode
{
None,
Low,
Medium,
High
};
enum LIGHT_MODES
{
LIGHT_MODE_DYNAMIC,

Binary file not shown.

View file

@ -82,7 +82,7 @@ BEGIN
CONTROL "TXT_Windowed",IDC_WINDOWED,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,103,115,10
CONTROL "TXT Shadows",IDC_SHADOWS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,79,159,10
CONTROL "TXT Caustics",IDC_CAUSTICS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,94,160,10
CONTROL "TXT Volumetric Fog",IDC_VOLUMETRIC_FOG,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,109,160,10
CONTROL "TXT Antialiasing",IDC_ANTIALIASING,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,155,109,160,10
GROUPBOX "Txt_Sound",IDC_GROUP_SOUND,7,151,320,33
CONTROL "TXT_Enable",IDC_ENABLE_SOUNDS,"Button",BS_AUTOCHECKBOX | BS_LEFTTEXT | WS_TABSTOP,254,150,67,10
COMBOBOX IDC_SNDADAPTER,13,164,308,71,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP

View file

@ -68,6 +68,11 @@
#define STRING_SHADOWS_NONE "none"
#define STRING_CAUSTICS "caustics"
#define STRING_VOLUMETRIC_FOG "volumetric_fog"
#define STRING_ANTIALIASING "antialiasing"
#define STRING_ANTIALIASING_NONE "none"
#define STRING_ANTIALIASING_LOW "low"
#define STRING_ANTIALIASING_MEDIUM "medium"
#define STRING_ANTIALIASING_HIGH "high"
#define STRING_APPLY "apply"
#define STRING_BACK "back"
#define STRING_SOUND "sound"

View file

@ -1,4 +1,9 @@
#include "./VertexInput.hlsli"
#include "./Math.hlsli"
#define FXAA_SPAN_MAX 8.0
#define FXAA_REDUCE_MUL 1.0/4.0
#define FXAA_REDUCE_MIN 1.0/64.0
cbuffer PostProcessBuffer : register(b7)
{
@ -6,6 +11,7 @@ cbuffer PostProcessBuffer : register(b7)
float ScreenFadeFactor;
int ViewportWidth;
int ViewportHeight;
int FXAA;
};
struct PixelShaderInput
@ -18,6 +24,53 @@ struct PixelShaderInput
Texture2D Texture : register(t0);
SamplerState Sampler : register(s0);
float4 Antialias(PixelShaderInput input)
{
float2 add = float2(1.0f, 1.0f) / float2(ViewportWidth, ViewportHeight);
float3 rgbNW = Texture.Sample(Sampler, input.UV + float2(-add.x, -add.y));
float3 rgbNE = Texture.Sample(Sampler, input.UV + float2(add.x, -add.y));
float3 rgbSW = Texture.Sample(Sampler, input.UV + float2(-add.x, add.y));
float3 rgbSE = Texture.Sample(Sampler, input.UV + float2(add.x, add.y));
float3 rgbM = Texture.Sample(Sampler, input.UV);
float lumaNW = Luma(rgbNW);
float lumaNE = Luma(rgbNE);
float lumaSW = Luma(rgbSW);
float lumaSE = Luma(rgbSE);
float lumaM = Luma(rgbM);
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
float2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
float dirReduce = max(
(lumaNW + lumaNE + lumaSW + lumaSE) * (0.25f * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);
float rcpDirMin = 1.0f / (min(abs(dir.x), abs(dir.y)) + dirReduce);
dir = min(float2( FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * add;
float3 rgbA = (1.0f / 2.0f) *
(Texture.Sample(Sampler, input.UV + dir * (1.0f / 3.0f - 0.5f)) +
Texture.Sample(Sampler, input.UV + dir * (2.0f / 2.0f - 0.5f)));
float3 rgbB = rgbA * (1.0f / 2.0f) + (1.0f / 4.0f) *
(Texture.Sample(Sampler, input.UV + dir * (0.0f / 3.0f - 0.5f)) +
Texture.Sample(Sampler, input.UV + dir * (3.0f / 3.0f - 0.5f)));
float lumaB = Luma(rgbB);
if ((lumaB < lumaMin) || (lumaB > lumaMax))
return float4(rgbA, 1.0f);
else
return float4(rgbB, 1.0f);
}
PixelShaderInput VS(VertexShaderInput input)
{
PixelShaderInput output;
@ -31,7 +84,8 @@ PixelShaderInput VS(VertexShaderInput input)
float4 PS(PixelShaderInput input) : SV_TARGET
{
float4 output = Texture.Sample(Sampler, input.UV);
float4 output = FXAA ? Antialias(input) : Texture.Sample(Sampler, input.UV);
float3 colorMul = min(input.Color.xyz, 1.0f);
float y = input.Position.y / ViewportHeight;

View file

@ -78,7 +78,7 @@ BOOL CALLBACK DialogProc(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
SendMessageA(GetDlgItem(handle, IDC_GROUP_RENDER_OPTIONS), WM_SETTEXT, 0, (LPARAM)g_GameFlow->GetString(STRING_RENDER_OPTIONS));
SendMessageA(GetDlgItem(handle, IDC_SHADOWS), WM_SETTEXT, 0, (LPARAM)g_GameFlow->GetString(STRING_SHADOWS));
SendMessageA(GetDlgItem(handle, IDC_CAUSTICS), WM_SETTEXT, 0, (LPARAM)g_GameFlow->GetString(STRING_CAUSTICS));
SendMessageA(GetDlgItem(handle, IDC_VOLUMETRIC_FOG), WM_SETTEXT, 0, (LPARAM)g_GameFlow->GetString(STRING_VOLUMETRIC_FOG));
SendMessageA(GetDlgItem(handle, IDC_ANTIALIASING), WM_SETTEXT, 0, (LPARAM)g_GameFlow->GetString(STRING_ANTIALIASING));
LoadResolutionsInCombobox(handle);
LoadSoundDevicesInCombobox(handle);
@ -86,8 +86,8 @@ BOOL CALLBACK DialogProc(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
// Set some default values
g_Configuration.AutoTarget = true;
g_Configuration.EnableVolumetricFog = true;
SendDlgItemMessage(handle, IDC_VOLUMETRIC_FOG, BM_SETCHECK, 1, 0);
g_Configuration.Antialiasing = AntialiasingMode::Low;
SendDlgItemMessage(handle, IDC_ANTIALIASING, BM_SETCHECK, 1, 0);
g_Configuration.ShadowType = ShadowMode::Lara;
SendDlgItemMessage(handle, IDC_SHADOWS, BM_SETCHECK, 1, 0);
@ -116,7 +116,7 @@ BOOL CALLBACK DialogProc(HWND handle, UINT msg, WPARAM wParam, LPARAM lParam)
g_Configuration.Windowed = (SendDlgItemMessage(handle, IDC_WINDOWED, BM_GETCHECK, 0, 0));
g_Configuration.ShadowType = (ShadowMode)(SendDlgItemMessage(handle, IDC_SHADOWS, BM_GETCHECK, 0, 0));
g_Configuration.EnableCaustics = (SendDlgItemMessage(handle, IDC_CAUSTICS, BM_GETCHECK, 0, 0));
g_Configuration.EnableVolumetricFog = (SendDlgItemMessage(handle, IDC_VOLUMETRIC_FOG, BM_GETCHECK, 0, 0));
g_Configuration.Antialiasing = (AntialiasingMode)(SendDlgItemMessage(handle, IDC_ANTIALIASING, BM_GETCHECK, 0, 0));
g_Configuration.EnableSound = (SendDlgItemMessage(handle, IDC_ENABLE_SOUNDS, BM_GETCHECK, 0, 0));
selectedMode = (SendDlgItemMessage(handle, IDC_RESOLUTION, CB_GETCURSEL, 0, 0));
mode = g_Configuration.SupportedScreenResolutions[selectedMode];
@ -210,7 +210,7 @@ bool SaveConfiguration()
return false;
}
if (SetBoolRegKey(rootKey, REGKEY_VOLUMETRIC_FOG, g_Configuration.EnableVolumetricFog) != ERROR_SUCCESS)
if (SetDWORDRegKey(rootKey, REGKEY_ANTIALIASING, DWORD(g_Configuration.Antialiasing)) != ERROR_SUCCESS)
{
RegCloseKey(rootKey);
return false;
@ -299,7 +299,7 @@ void InitDefaultConfiguration()
g_Configuration.EnableCaustics = true;
g_Configuration.ShadowType = ShadowMode::Lara;
g_Configuration.EnableSound = true;
g_Configuration.EnableVolumetricFog = true;
g_Configuration.Antialiasing = AntialiasingMode::Low;
g_Configuration.MusicVolume = 100;
g_Configuration.SfxVolume = 100;
g_Configuration.Width = currentScreenResolution.x;
@ -345,8 +345,8 @@ bool LoadConfiguration()
return false;
}
bool volumetricFog = false;
if (GetBoolRegKey(rootKey, REGKEY_VOLUMETRIC_FOG, &volumetricFog, true) != ERROR_SUCCESS)
DWORD antialiasing = 1;
if (GetDWORDRegKey(rootKey, REGKEY_ANTIALIASING, &antialiasing, true) != ERROR_SUCCESS)
{
RegCloseKey(rootKey);
return false;
@ -452,7 +452,7 @@ bool LoadConfiguration()
g_Configuration.ShadowType = ShadowMode(shadowMode);
g_Configuration.ShadowMaxBlobs = shadowBlobs;
g_Configuration.EnableCaustics = caustics;
g_Configuration.EnableVolumetricFog = volumetricFog;
g_Configuration.Antialiasing = AntialiasingMode(antialiasing);
g_Configuration.ShadowMapSize = shadowMapSize;
g_Configuration.EnableSound = enableSound;

View file

@ -13,7 +13,7 @@
#define REGKEY_SHADOW_MAP "ShadowMap"
#define REGKEY_SHADOW_BLOBS "ShadowBlobs"
#define REGKEY_CAUSTICS "Caustics"
#define REGKEY_VOLUMETRIC_FOG "VolumetricFog"
#define REGKEY_ANTIALIASING "Antialiasing"
#define REGKEY_SOUND_DEVICE "SoundDevice"
#define REGKEY_ENABLE_SOUND "EnableSound"
@ -39,7 +39,7 @@ struct GameConfiguration
int SfxVolume;
bool EnableCaustics;
bool EnableVolumetricFog;
AntialiasingMode Antialiasing;
ShadowMode ShadowType;
int ShadowMapSize = 1024;
int ShadowMaxBlobs = 16;

View file

@ -18,8 +18,7 @@
#define IDC_BILINEAR 1032
#define IDC_CAUSTICS 1032
#define IDC_TEXRESTXT 1033
#define IDC_LOWTEXT 1034
#define IDC_VOLUMETRIC_FOG 1034
#define IDC_ANTIALIASING 1034
#define IDC_LOWBUMP 1035
#define IDC_BUMPMAP 1036
#define IDC_SNDADAPTERTXT 1037