mirror of
https://github.com/TombEngine/TombEngine.git
synced 2025-04-28 15:57:59 +03:00
Merge branch 'develop' into realtime_shader_reloading
This commit is contained in:
commit
529ffb50dd
10 changed files with 170 additions and 48 deletions
12
CHANGELOG.md
12
CHANGELOG.md
|
@ -3,7 +3,15 @@
|
|||
The dates are in European standard format where date is presented as **YYYY-MM-DD**.
|
||||
TombEngine releases are located in this repository (alongside with Tomb Editor): https://github.com/TombEngine/TombEditorReleases
|
||||
|
||||
## Version 1.7 - xxxx-xx-xx
|
||||
## Version 1.8 - xxxx-xx-xx
|
||||
|
||||
### Bug fixes
|
||||
|
||||
### New Features
|
||||
|
||||
### Lua API changes
|
||||
|
||||
## [Version 1.7](https://github.com/TombEngine/TombEditorReleases/releases/tag/v1.7.3) - 2024-12-25
|
||||
|
||||
### Bug fixes
|
||||
* Significantly improved renderer performance.
|
||||
|
@ -57,7 +65,6 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
|
|||
### Lua API changes
|
||||
* Added Flow.Statistics class, Flow.GetStatistics() and Flow.SetStatistics() functions.
|
||||
* Added Flow.GetFreezeMode() and Flow.SetFreezeMode() functions.
|
||||
* Added Flow.GetNextLevel() function to get script entry for incoming level, if it's about to start.
|
||||
* Added Effects.EmitSpotLight() function for directional spotlights.
|
||||
* Added optional cast shadow and name parameters for Effects.EmitLight() function.
|
||||
* Added Effects.GetWind() function to get current wind speed vector.
|
||||
|
@ -68,7 +75,6 @@ TombEngine releases are located in this repository (alongside with Tomb Editor):
|
|||
* Added extra argument for Sound.SetAmbientTrack() function to specify if new ambient track should play from the beginning.
|
||||
* Added new View.CameraType enum entries and return it by View.GetCameraType(), when flyby camera or binoculars/lasersight is active.
|
||||
* Added new primitive Time class, which allows to manipulate and format game time without precision loss.
|
||||
* Allow to use TR4-like load cameras by playing fixed camera from OnEnd() event and removing loadScreenFile field from level's gameflow entry.
|
||||
* Renamed Flow.WeaponType enumeration to Objects.WeaponType, and removed similar Objects.LaraWeaponType enumeration for consistency.
|
||||
* Renamed Objects.PlayerAmmoType to Objects.AmmoType for consistency.
|
||||
* Fixed Strings.DisplayString class not supporting some Unicode characters and empty lines in multiline strings.
|
||||
|
|
|
@ -167,10 +167,6 @@ scripts too.</p>
|
|||
<td class="summary">Returns the level that the game control is running in that moment.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" ><a href="#GetNextLevel">GetNextLevel()</a></td>
|
||||
<td class="summary">Returns the level that is about to load.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="name" ><a href="#EndLevel">EndLevel([index][, startPos])</a></td>
|
||||
<td class="summary">Finishes the current level, with optional level index and start position index provided.</td>
|
||||
</tr>
|
||||
|
@ -559,27 +555,6 @@ have an ID of 0, the second an ID of 1, and so on.
|
|||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "GetNextLevel"></a>
|
||||
<strong>GetNextLevel()</strong>
|
||||
</dt>
|
||||
<dd>
|
||||
Returns the level that is about to load. If no new level is about to load, returns current level.
|
||||
|
||||
|
||||
|
||||
|
||||
<h3>Returns:</h3>
|
||||
<ol>
|
||||
|
||||
<span class="types"><a class="type" href="../2 classes/Flow.Level.html#">Level</a></span>
|
||||
incoming new level or current level, if no new level is loading
|
||||
</ol>
|
||||
|
||||
|
||||
|
||||
|
||||
</dd>
|
||||
<dt>
|
||||
<a name = "EndLevel"></a>
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "Renderer/Structures/RendererRoomAmbientMap.h"
|
||||
#include "Renderer/Structures/RendererObject.h"
|
||||
#include "Renderer/Structures/RendererStar.h"
|
||||
#include "Structures/RendererShader.h"
|
||||
|
||||
enum GAME_OBJECT_ID : short;
|
||||
enum class SphereSpaceType;
|
||||
|
@ -332,6 +333,9 @@ namespace TEN::Renderer
|
|||
RenderTarget2D _SSAOBlurredRenderTarget;
|
||||
std::vector<Vector4> _SSAOKernel;
|
||||
|
||||
RendererShader _sSSAO;
|
||||
RendererShader _sSSAOBlur;
|
||||
|
||||
// New ambient light techinque
|
||||
|
||||
RenderTarget2D _roomAmbientMapFront;
|
||||
|
@ -358,6 +362,9 @@ namespace TEN::Renderer
|
|||
|
||||
ShaderManager _shaderManager;
|
||||
|
||||
RendererShader CompileOrLoadShader(const std::string& fileName, const std::string& funcName, ShaderType type, const D3D_SHADER_MACRO* defines = nullptr);
|
||||
void BindShader(const RendererShader& shader);
|
||||
|
||||
void ApplySMAA(RenderTarget2D* renderTarget, RenderView& view);
|
||||
void ApplyFXAA(RenderTarget2D* renderTarget, RenderView& view);
|
||||
void BindTexture(TextureRegister registerType, TextureBase* texture, SamplerStateRegister samplerType);
|
||||
|
|
|
@ -3507,7 +3507,7 @@ namespace TEN::Renderer
|
|||
SetScissor(objectInfo->Room->ClipBounds);
|
||||
|
||||
if (objectInfo->Bucket->Animated != 0)
|
||||
_shaderManager.Bind(Shader::RoomsAnimated);
|
||||
_shaderManager.Bind(Shader::RoomsAnimated
|
||||
|
||||
SetBlendMode(objectInfo->Bucket->BlendMode);
|
||||
SetAlphaTest(AlphaTestMode::None, ALPHA_TEST_THRESHOLD);
|
||||
|
|
|
@ -246,6 +246,8 @@ namespace TEN::Renderer
|
|||
|
||||
_fullscreenTriangleVertexBuffer = VertexBuffer<PostProcessVertex>(_device.Get(), 3, &vertices[0]);
|
||||
|
||||
_sPostProcess = CompileOrLoadShader("PostProcess", "", ShaderType::PixelAndVertex);
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC postProcessInputLayoutItems[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
||||
|
@ -600,4 +602,152 @@ namespace TEN::Renderer
|
|||
|
||||
UpdateWindow(WindowsHandle);
|
||||
}
|
||||
|
||||
void Renderer::BindShader(const RendererShader& shader)
|
||||
{
|
||||
if (shader.Vertex.Shader != nullptr) _context->VSSetShader(shader.Vertex.Shader.Get(), nullptr, 0);
|
||||
if (shader.Pixel.Shader != nullptr) _context->PSSetShader(shader.Pixel.Shader.Get(), nullptr, 0);
|
||||
if (shader.Compute.Shader != nullptr) _context->CSSetShader(shader.Compute.Shader.Get(), nullptr, 0);
|
||||
}
|
||||
|
||||
RendererShader Renderer::CompileOrLoadShader(const std::string& fileName, const std::string& funcName, ShaderType type, const D3D_SHADER_MACRO* defines)
|
||||
{
|
||||
RendererShader result = {};
|
||||
|
||||
// We need to increment the counter to avoid overwriting compiled shaders with the same source file name.
|
||||
static int compileCounter = 0;
|
||||
|
||||
// Define paths for native (uncompiled) shaders and compiled shaders.
|
||||
std::wstring shaderPath = GetAssetPath(L"Shaders\\");
|
||||
std::wstring compiledShaderPath = shaderPath + L"Bin\\";
|
||||
std::wstring wideFileName = TEN::Utils::ToWString(fileName);
|
||||
|
||||
// Ensure the /Bin subdirectory exists.
|
||||
std::filesystem::create_directories(compiledShaderPath);
|
||||
|
||||
// Helper function to load or compile a shader.
|
||||
auto loadOrCompileShader = [this, type, defines, shaderPath, compiledShaderPath]
|
||||
(const std::wstring& baseFileName, const std::string& shaderType, const std::string& functionName, const char* model, ComPtr<ID3D10Blob>& bytecode)
|
||||
{
|
||||
// Construct the full paths using GetAssetPath.
|
||||
auto prefix = ((compileCounter < 10) ? L"0" : L"") + std::to_wstring(compileCounter) + L"_";
|
||||
auto csoFileName = compiledShaderPath + prefix + baseFileName + L"." + std::wstring(shaderType.begin(), shaderType.end()) + L".cso";
|
||||
auto srcFileName = shaderPath + baseFileName;
|
||||
|
||||
// Try both .hlsl and .fx extensions for the source shader.
|
||||
auto srcFileNameWithExtension = srcFileName + L".hlsl";
|
||||
if (!std::filesystem::exists(srcFileNameWithExtension))
|
||||
{
|
||||
srcFileNameWithExtension = srcFileName + L".fx";
|
||||
if (!std::filesystem::exists(srcFileNameWithExtension))
|
||||
{
|
||||
TENLog("Shader source file not found: " + TEN::Utils::ToString(srcFileNameWithExtension), LogLevel::Error);
|
||||
throw std::runtime_error("Shader source file not found");
|
||||
}
|
||||
}
|
||||
|
||||
// Check modification dates of the source and compiled files.
|
||||
bool shouldRecompile = false;
|
||||
if (std::filesystem::exists(csoFileName))
|
||||
{
|
||||
auto csoTime = std::filesystem::last_write_time(csoFileName);
|
||||
auto srcTime = std::filesystem::last_write_time(srcFileNameWithExtension);
|
||||
shouldRecompile = srcTime > csoTime; // Recompile if the source is newer.
|
||||
}
|
||||
|
||||
// Load compiled shader if it exists and is up to date.
|
||||
if (!shouldRecompile)
|
||||
{
|
||||
std::ifstream csoFile(csoFileName, std::ios::binary);
|
||||
|
||||
if (csoFile.is_open())
|
||||
{
|
||||
// Load compiled shader.
|
||||
csoFile.seekg(0, std::ios::end);
|
||||
size_t fileSize = csoFile.tellg();
|
||||
csoFile.seekg(0, std::ios::beg);
|
||||
|
||||
std::vector<char> buffer(fileSize);
|
||||
csoFile.read(buffer.data(), fileSize);
|
||||
csoFile.close();
|
||||
|
||||
D3DCreateBlob(fileSize, &bytecode);
|
||||
memcpy(bytecode->GetBufferPointer(), buffer.data(), fileSize);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up compilation flags according to the build configuration.
|
||||
unsigned int flags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_ROW_MAJOR;
|
||||
|
||||
if constexpr (DebugBuild)
|
||||
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
||||
else
|
||||
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3 | D3DCOMPILE_IEEE_STRICTNESS;
|
||||
|
||||
auto trimmedFileName = std::filesystem::path(srcFileNameWithExtension).filename().string();
|
||||
TENLog("Compiling shader: " + trimmedFileName, LogLevel::Info);
|
||||
|
||||
// Compile shader.
|
||||
ComPtr<ID3D10Blob> errors;
|
||||
HRESULT res = D3DCompileFromFile(srcFileNameWithExtension.c_str(), defines, D3D_COMPILE_STANDARD_FILE_INCLUDE,
|
||||
(shaderType + functionName).c_str(), model, flags, 0, bytecode.GetAddressOf(), errors.GetAddressOf());
|
||||
|
||||
if (FAILED(res))
|
||||
{
|
||||
if (errors)
|
||||
{
|
||||
auto error = std::string(static_cast<const char*>(errors->GetBufferPointer()));
|
||||
TENLog(error, LogLevel::Error);
|
||||
throw std::runtime_error(error);
|
||||
}
|
||||
else
|
||||
{
|
||||
TENLog("Error while compiling shader: " + trimmedFileName, LogLevel::Error);
|
||||
throwIfFailed(res);
|
||||
}
|
||||
}
|
||||
|
||||
// Save compiled shader to .cso file.
|
||||
std::ofstream outCsoFile(csoFileName, std::ios::binary);
|
||||
if (outCsoFile.is_open())
|
||||
{
|
||||
outCsoFile.write(reinterpret_cast<const char*>(bytecode->GetBufferPointer()), bytecode->GetBufferSize());
|
||||
outCsoFile.close();
|
||||
}
|
||||
};
|
||||
|
||||
// Load or compile and create pixel shader.
|
||||
if (type == ShaderType::Pixel || type == ShaderType::PixelAndVertex)
|
||||
{
|
||||
loadOrCompileShader(wideFileName, "PS", funcName, "ps_5_0", result.Pixel.Blob);
|
||||
throwIfFailed(_device->CreatePixelShader(result.Pixel.Blob->GetBufferPointer(), result.Pixel.Blob->GetBufferSize(),
|
||||
nullptr, result.Pixel.Shader.GetAddressOf()
|
||||
));
|
||||
}
|
||||
|
||||
// Load or compile and create vertex shader.
|
||||
if (type == ShaderType::Vertex || type == ShaderType::PixelAndVertex)
|
||||
{
|
||||
loadOrCompileShader(wideFileName, "VS", funcName, "vs_5_0", result.Vertex.Blob);
|
||||
throwIfFailed(_device->CreateVertexShader(result.Vertex.Blob->GetBufferPointer(), result.Vertex.Blob->GetBufferSize(),
|
||||
nullptr, result.Vertex.Shader.GetAddressOf()
|
||||
));
|
||||
}
|
||||
|
||||
// Load or compile and create compute shader.
|
||||
if (type == ShaderType::Compute)
|
||||
{
|
||||
loadOrCompileShader(wideFileName, "CS", funcName, "cs_5_0", result.Compute.Blob);
|
||||
throwIfFailed(_device->CreateComputeShader(result.Compute.Blob->GetBufferPointer(), result.Compute.Blob->GetBufferSize(),
|
||||
nullptr, result.Compute.Shader.GetAddressOf()
|
||||
));
|
||||
}
|
||||
|
||||
// Increment the compile counter.
|
||||
compileCounter++;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@
|
|||
#include "Renderer/Structures/RendererShader.h"
|
||||
#include "Scripting/Include/Flow/ScriptInterfaceFlowHandler.h"
|
||||
#include "Specific/trutils.h"
|
||||
#include "Structures/RendererShader.h"
|
||||
|
||||
namespace TEN::Renderer::Utils
|
||||
{
|
||||
|
|
|
@ -224,7 +224,6 @@ static constexpr char ScriptReserved_IsTagPresent[] = "IsTagPresent";
|
|||
static constexpr char ScriptReserved_AddLevel[] = "AddLevel";
|
||||
static constexpr char ScriptReserved_GetLevel[] = "GetLevel";
|
||||
static constexpr char ScriptReserved_GetCurrentLevel[] = "GetCurrentLevel";
|
||||
static constexpr char ScriptReserved_GetNextLevel[] = "GetNextLevel";
|
||||
static constexpr char ScriptReserved_SetIntroImagePath[] = "SetIntroImagePath";
|
||||
static constexpr char ScriptReserved_SetTitleScreenImagePath[] = "SetTitleScreenImagePath";
|
||||
static constexpr char ScriptReserved_SetFarView[] = "SetFarView";
|
||||
|
|
|
@ -137,12 +137,6 @@ have an ID of 0, the second an ID of 1, and so on.
|
|||
*/
|
||||
tableFlow.set_function(ScriptReserved_GetCurrentLevel, &FlowHandler::GetCurrentLevel, this);
|
||||
|
||||
/*** Returns the level that is about to load. If no new level is about to load, returns current level.
|
||||
@function GetNextLevel
|
||||
@treturn Flow.Level incoming new level or current level, if no new level is loading
|
||||
*/
|
||||
tableFlow.set_function(ScriptReserved_GetNextLevel, &FlowHandler::GetNextLevel, this);
|
||||
|
||||
/*** Finishes the current level, with optional level index and start position index provided.
|
||||
If level index is not provided or is zero, jumps to next level. If level index is more than
|
||||
level count, jumps to title. If LARA\_START\_POS objects are present in level, player will be
|
||||
|
@ -467,15 +461,6 @@ Level* FlowHandler::GetCurrentLevel()
|
|||
return Levels[CurrentLevel];
|
||||
}
|
||||
|
||||
Level* FlowHandler::GetNextLevel()
|
||||
{
|
||||
if (NextLevel == CurrentLevel)
|
||||
return Levels[CurrentLevel];
|
||||
|
||||
// NOTE: Negative value indicates incoming savegame.
|
||||
return Levels[abs(NextLevel)];
|
||||
}
|
||||
|
||||
int FlowHandler::GetNumLevels() const
|
||||
{
|
||||
return (int)Levels.size();
|
||||
|
|
|
@ -54,7 +54,6 @@ public:
|
|||
void SetLanguageNames(sol::as_table_t<std::vector<std::string>>&& src);
|
||||
Level* GetLevel(int id);
|
||||
Level* GetCurrentLevel();
|
||||
Level* GetNextLevel();
|
||||
int GetLevelNumber(const std::string& flieName);
|
||||
int GetNumLevels() const;
|
||||
void EndLevel(std::optional<int> nextLevel, std::optional<int> startPosIndex);
|
||||
|
|
|
@ -128,9 +128,9 @@ float3 DoShadow(float3 worldPos, float3 normal, float3 lighting, float bias)
|
|||
float samples = 0;
|
||||
|
||||
// Perform basic PCF filtering with distance-based kernel size
|
||||
for (float y = -kernelSize; y <= kernelSize; y += 1.0)
|
||||
for (float y = -SHADOW_BLUR_MIN; y <= SHADOW_BLUR_MIN; y += 1.0)
|
||||
{
|
||||
for (float x = -kernelSize; x <= kernelSize; x += 1.0)
|
||||
for (float x = -SHADOW_BLUR_MIN; x <= SHADOW_BLUR_MIN; x += 1.0)
|
||||
{
|
||||
sum += ShadowMap.SampleCmpLevelZero(ShadowMapSampler, float3(lightClipSpace.xy + TexOffset(x, y), i), lightClipSpace.z);
|
||||
samples += 1.0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue