2023.4
This commit is contained in:
parent
b8941ef04e
commit
8eb4422cd3
|
@ -486,7 +486,7 @@ void TextureD3D11::ClearCshGenerateMips()
|
|||
if (!_vCshGenerateMips.empty())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
auto shader = renderer.GetShaderGenerateMips();
|
||||
auto shader = (_desc._flags & TextureDesc::Flags::cubeMap) ? renderer.GetShaderGenerateCubeMapMips() : renderer.GetShaderGenerateMips();
|
||||
for (auto& csh : _vCshGenerateMips)
|
||||
shader->FreeDescriptorSet(csh);
|
||||
_vCshGenerateMips.clear();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define SDL_VIDEO_DRIVER_WINRT 1
|
||||
#define VERUS_INCLUDE_D3D11
|
||||
#define VERUS_INCLUDE_PIX
|
||||
#define XR_USE_GRAPHICS_API_D3D11
|
||||
#include <verus.h>
|
||||
|
||||
|
|
|
@ -315,6 +315,27 @@ void CommandBufferD3D12::TraceRays(int width, int height, int depth)
|
|||
//GetD3DGraphicsCommandList()->DispatchRays(&desc);
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::ProfilerBeginEvent(UINT32 color, CSZ text)
|
||||
{
|
||||
#if defined(VERUS_INCLUDE_PIX) && defined(VERUS_PROFILER_CALLS)
|
||||
PIXBeginEvent(GetD3DGraphicsCommandList(), VERUS_COLOR_TO_D3D(color), text);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::ProfilerEndEvent()
|
||||
{
|
||||
#if defined(VERUS_INCLUDE_PIX) && defined(VERUS_PROFILER_CALLS)
|
||||
PIXEndEvent(GetD3DGraphicsCommandList());
|
||||
#endif
|
||||
}
|
||||
|
||||
void CommandBufferD3D12::ProfilerSetMarker(UINT32 color, CSZ text)
|
||||
{
|
||||
#if defined(VERUS_INCLUDE_PIX) && defined(VERUS_PROFILER_CALLS)
|
||||
PIXSetMarker(GetD3DGraphicsCommandList(), VERUS_COLOR_TO_D3D(color), text);
|
||||
#endif
|
||||
}
|
||||
|
||||
ID3D12GraphicsCommandList3* CommandBufferD3D12::GetD3DGraphicsCommandList() const
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
|
|
@ -53,6 +53,10 @@ namespace verus
|
|||
virtual void DispatchMesh(int groupCountX, int groupCountY, int groupCountZ) override;
|
||||
virtual void TraceRays(int width, int height, int depth) override;
|
||||
|
||||
virtual void ProfilerBeginEvent(UINT32 color, CSZ text) override;
|
||||
virtual void ProfilerEndEvent() override;
|
||||
virtual void ProfilerSetMarker(UINT32 color, CSZ text) override;
|
||||
|
||||
//
|
||||
// D3D12
|
||||
//
|
||||
|
|
|
@ -620,7 +620,7 @@ void TextureD3D12::ClearCshGenerateMips()
|
|||
if (!_vCshGenerateMips.empty())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
auto shader = renderer.GetShaderGenerateMips();
|
||||
auto shader = (_desc._flags & TextureDesc::Flags::cubeMap) ? renderer.GetShaderGenerateCubeMapMips() : renderer.GetShaderGenerateMips();
|
||||
for (auto& csh : _vCshGenerateMips)
|
||||
shader->FreeDescriptorSet(csh);
|
||||
_vCshGenerateMips.clear();
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#define SDL_VIDEO_DRIVER_WINRT 1
|
||||
#define VERUS_INCLUDE_D3D12
|
||||
#define VERUS_INCLUDE_PIX
|
||||
#define XR_USE_GRAPHICS_API_D3D12
|
||||
#include <verus.h>
|
||||
|
||||
|
|
|
@ -235,6 +235,7 @@ Vector<CSZ> RendererVulkan::GetRequiredExtensions()
|
|||
|
||||
void RendererVulkan::CreateInstance()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VkResult res = VK_SUCCESS;
|
||||
|
||||
#if defined(_DEBUG) || defined(VERUS_RELEASE_DEBUG)
|
||||
|
@ -244,20 +245,16 @@ void RendererVulkan::CreateInstance()
|
|||
|
||||
const auto vExtensions = GetRequiredExtensions();
|
||||
|
||||
const int major = (VERUS_SDK_VERSION >> 24) & 0xFF;
|
||||
const int minor = (VERUS_SDK_VERSION >> 16) & 0xFF;
|
||||
const int patch = (VERUS_SDK_VERSION) & 0xFFFF;
|
||||
|
||||
VkValidationFeatureEnableEXT enabledValidationFeatures[] = { VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT };
|
||||
VkValidationFeaturesEXT vkvf = { VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT };
|
||||
vkvf.enabledValidationFeatureCount = VERUS_COUNT_OF(enabledValidationFeatures);
|
||||
vkvf.pEnabledValidationFeatures = enabledValidationFeatures;
|
||||
|
||||
VkApplicationInfo vkai = { VK_STRUCTURE_TYPE_APPLICATION_INFO };
|
||||
vkai.pApplicationName = "Game";
|
||||
vkai.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
vkai.pEngineName = "Verus";
|
||||
vkai.engineVersion = VK_MAKE_VERSION(major, minor, patch);
|
||||
vkai.pApplicationName = settings._info._appName;
|
||||
vkai.applicationVersion = settings._info._appVersion;
|
||||
vkai.pEngineName = settings._info._engineName;
|
||||
vkai.engineVersion = settings._info._engineVersion;
|
||||
vkai.apiVersion = s_apiVersion;
|
||||
|
||||
VkInstanceCreateInfo vkici = { VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO };
|
||||
|
|
|
@ -536,7 +536,7 @@ Continue TextureVulkan::Scheduled_Update()
|
|||
if (!_vCshGenerateMips.empty())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
auto shader = renderer.GetShaderGenerateMips();
|
||||
auto shader = (_desc._flags & TextureDesc::Flags::cubeMap) ? renderer.GetShaderGenerateCubeMapMips() : renderer.GetShaderGenerateMips();
|
||||
for (auto& csh : _vCshGenerateMips)
|
||||
shader->FreeDescriptorSet(csh);
|
||||
_vCshGenerateMips.clear();
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>C:\Compressonator_4.3.206\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.5\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.22.0-bin\include;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\include;C:\Home\Middleware\SDL2-2.0.22\include;C:\VulkanSDK\1.3.239.0\Include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Compressonator_4.3.206\lib\VS2019\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.5\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.22.0-bin\libs\Win64;C:\Home\Middleware\OpenXR-SDK-release-1.0.25\lib;C:\Home\Middleware\SDL2-2.0.22\lib\x64;C:\VulkanSDK\1.3.239.0\Lib;$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>C:\Compressonator_4.3.206\include;C:\Home\Projects\Verus\verus\Verus\src;C:\Home\Middleware\AMD Tootle 2.3\include;C:\Home\Middleware\bullet3-2.89\src;C:\Home\Middleware\bullet3-2.89\Extras;C:\Home\Middleware\libogg-1.3.5\include;C:\Home\Middleware\libvorbis-1.3.7\include;C:\Home\Middleware\openal-soft-1.22.0-bin\include;C:\Home\Middleware\OpenXR-SDK-release-1.0.27\include;C:\Home\Middleware\SDL2-2.0.22\include;C:\Home\Middleware\WinPixEventRuntime\include;C:\VulkanSDK\1.3.239.0\Include;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>C:\Compressonator_4.3.206\lib\VS2019\x64;C:\Home\Middleware\bullet3-2.89\bin;C:\Home\Middleware\AMD Tootle 2.3\lib;C:\Home\Middleware\libogg-1.3.5\lib;C:\Home\Middleware\libvorbis-1.3.7\lib2;C:\Home\Middleware\openal-soft-1.22.0-bin\libs\Win64;C:\Home\Middleware\OpenXR-SDK-release-1.0.27\lib;C:\Home\Middleware\SDL2-2.0.22\lib\x64;C:\Home\Middleware\WinPixEventRuntime\lib;C:\VulkanSDK\1.3.239.0\Lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemGroup />
|
||||
|
|
|
@ -304,6 +304,7 @@
|
|||
<ClInclude Include="src\World\WorldManager.h" />
|
||||
<ClInclude Include="src\World\MaterialManager.h" />
|
||||
<ClInclude Include="src\World\Mesh.h" />
|
||||
<ClInclude Include="src\World\WorldNodes\BlockChainNode.h" />
|
||||
<ClInclude Include="src\World\WorldNodes\BlockNode.h" />
|
||||
<ClInclude Include="src\World\WorldNodes\ControlPointNode.h" />
|
||||
<ClInclude Include="src\World\WorldNodes\EmitterNode.h" />
|
||||
|
@ -636,6 +637,7 @@
|
|||
<ClCompile Include="src\World\WorldManager.cpp" />
|
||||
<ClCompile Include="src\World\MaterialManager.cpp" />
|
||||
<ClCompile Include="src\World\Mesh.cpp" />
|
||||
<ClCompile Include="src\World\WorldNodes\BlockChainNode.cpp" />
|
||||
<ClCompile Include="src\World\WorldNodes\BlockNode.cpp" />
|
||||
<ClCompile Include="src\World\WorldNodes\ControlPointNode.cpp" />
|
||||
<ClCompile Include="src\World\WorldNodes\EmitterNode.cpp" />
|
||||
|
|
|
@ -810,6 +810,9 @@
|
|||
<ClInclude Include="src\World\WorldNodes\PathNode.h">
|
||||
<Filter>src\World\WorldNodes</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\World\WorldNodes\BlockChainNode.h">
|
||||
<Filter>src\World\WorldNodes</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\CGI\BaseGeometry.cpp">
|
||||
|
@ -1397,6 +1400,9 @@
|
|||
<ClCompile Include="src\World\WorldNodes\PathNode.cpp">
|
||||
<Filter>src\World\WorldNodes</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\World\WorldNodes\BlockChainNode.cpp">
|
||||
<Filter>src\World\WorldNodes</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\Shaders\Lib.hlsl">
|
||||
|
|
|
@ -32,7 +32,7 @@ void Collection::Async_WhenLoaded(CSZ url, RcBlob blob)
|
|||
md._motion.ComputePlaybackSpeed(md._duration);
|
||||
}
|
||||
|
||||
void Collection::AddMotion(CSZ name, bool loop, float duration)
|
||||
void Collection::AddMotion(CSZ name, bool looping, float duration, bool fast)
|
||||
{
|
||||
CSZ shortName = name;
|
||||
if (_useShortNames)
|
||||
|
@ -42,7 +42,8 @@ void Collection::AddMotion(CSZ name, bool loop, float duration)
|
|||
}
|
||||
RMotionData md = *TStoreMotions::Insert(shortName);
|
||||
md._duration = duration;
|
||||
md._loop = loop;
|
||||
md._looping = looping;
|
||||
md._fast = fast;
|
||||
IO::Async::I().Load(name, this);
|
||||
}
|
||||
|
||||
|
@ -107,8 +108,8 @@ void Animation::Update(int layerCount, PLayer pLayers)
|
|||
md._motion.ProcessTriggers(_time, this, GetTriggerStatesArray());
|
||||
if (_time >= duration)
|
||||
{
|
||||
_playing = md._loop; // Continue?
|
||||
_time = md._loop ? fmod(_time, duration) : duration;
|
||||
_playing = md._looping; // Continue?
|
||||
_time = md._looping ? fmod(_time, duration) : duration;
|
||||
md._motion.ResetTriggers(GetTriggerStatesArray()); // New loop, reset triggers.
|
||||
if (_pDelegate)
|
||||
_pDelegate->Animation_OnEnd(_C(_currentMotion)); // This can call TransitionTo and change everything.
|
||||
|
@ -178,11 +179,17 @@ void Animation::Pause()
|
|||
|
||||
void Animation::TransitionTo(CSZ name, Interval duration, int randTime, PMotion pFromMotion)
|
||||
{
|
||||
bool prevMotionFast = false;
|
||||
PMotion pMotion = pFromMotion;
|
||||
if (!_currentMotion.empty() || pFromMotion) // Deal with previous motion?
|
||||
{
|
||||
PMotionData pMotionData = nullptr;
|
||||
if (!pFromMotion)
|
||||
pMotion = &_pCollection->Find(_C(_currentMotion))->_motion;
|
||||
{
|
||||
pMotionData = _pCollection->Find(_C(_currentMotion));
|
||||
pMotion = &pMotionData->_motion;
|
||||
prevMotionFast = pMotionData->_fast;
|
||||
}
|
||||
if (_transition) // Already in transition?
|
||||
pMotion->BindBlendMotion(&_transitionMotion, Math::ApplyEasing(_easing, _transitionTime / _transitionDuration));
|
||||
pMotion->BakeMotionAt(_time, _transitionMotion); // Capture current pose.
|
||||
|
@ -209,8 +216,17 @@ void Animation::TransitionTo(CSZ name, Interval duration, int randTime, PMotion
|
|||
pMotion->ResetTriggers(GetTriggerStatesArray());
|
||||
if (name)
|
||||
{
|
||||
pMotion = &_pCollection->Find(name)->_motion;
|
||||
PMotionData pMotionData = _pCollection->Find(name);
|
||||
pMotion = &pMotionData->_motion;
|
||||
pMotion->ResetTriggers(GetTriggerStatesArray());
|
||||
if (prevMotionFast)
|
||||
_easing = pMotionData->_fast ? Easing::quadInOut : Easing::cubicOut;
|
||||
else
|
||||
_easing = pMotionData->_fast ? Easing::cubicIn : Easing::quadInOut;
|
||||
}
|
||||
else
|
||||
{
|
||||
_easing = prevMotionFast ? Easing::cubicOut : Easing::quadInOut;
|
||||
}
|
||||
|
||||
// Reset time:
|
||||
|
|
|
@ -17,7 +17,8 @@ namespace verus
|
|||
{
|
||||
Motion _motion;
|
||||
float _duration = 0;
|
||||
bool _loop = true;
|
||||
bool _looping = true;
|
||||
bool _fast = false; // For auto easing.
|
||||
};
|
||||
VERUS_TYPEDEFS(MotionData);
|
||||
|
||||
|
@ -33,7 +34,7 @@ namespace verus
|
|||
|
||||
virtual void Async_WhenLoaded(CSZ url, RcBlob blob) override;
|
||||
|
||||
void AddMotion(CSZ name, bool loop = true, float duration = 0);
|
||||
void AddMotion(CSZ name, bool looping = true, float duration = 0, bool fast = false);
|
||||
void DeleteAll();
|
||||
PMotionData Find(CSZ name);
|
||||
int GetMaxBones();
|
||||
|
@ -68,7 +69,7 @@ namespace verus
|
|||
String _currentMotion;
|
||||
String _prevMotion;
|
||||
Vector<int> _vTriggerStates;
|
||||
Easing _easing = Easing::quadInOut;
|
||||
Easing _easing = Easing::none;
|
||||
float _time = 0;
|
||||
float _transitionDuration = 0;
|
||||
float _transitionTime = 0;
|
||||
|
@ -99,8 +100,6 @@ namespace verus
|
|||
Interval duration = 0.5f, int randTime = -1, PMotion pFromMotion = nullptr);
|
||||
bool IsInTransition() const { return _transition; }
|
||||
|
||||
void SetEasing(Easing easing) { _easing = easing; }
|
||||
|
||||
virtual void Motion_OnTrigger(CSZ name, int state) override;
|
||||
|
||||
PMotion GetMotion();
|
||||
|
|
|
@ -162,6 +162,8 @@ void Settings::ParseCommandLineArgs(int argc, char* argv[])
|
|||
_commandLine._borderlessWindowed = true;
|
||||
if (IsArg(i, "--restarted"))
|
||||
_commandLine._restarted = true;
|
||||
if (IsArg(i, "--xr-height") && i + 1 < argc)
|
||||
_commandLine._xrHeight = static_cast<float>(atof(argv[i + 1]));
|
||||
}
|
||||
|
||||
SetFilename("Settings.json");
|
||||
|
@ -233,6 +235,8 @@ void Settings::Load()
|
|||
_sceneShadowQuality = static_cast<Quality>(GetI("sceneShadowQuality", +_sceneShadowQuality));
|
||||
_sceneWaterQuality = static_cast<WaterQuality>(GetI("sceneWaterQuality", +_sceneWaterQuality));
|
||||
_uiLang = GetS("uiLang", _C(_uiLang));
|
||||
_xrFOV = GetF("xrFOV", _xrFOV);
|
||||
_xrHeight = GetF("xrHeight", _xrHeight);
|
||||
}
|
||||
|
||||
void Settings::HandleHighDpi()
|
||||
|
@ -276,10 +280,22 @@ void Settings::HandleCommandLineArgs()
|
|||
_displayMode = DisplayMode::borderlessWindowed;
|
||||
MatchScreen();
|
||||
}
|
||||
|
||||
if (_commandLine._xrHeight != -FLT_MAX)
|
||||
_xrHeight = _commandLine._xrHeight;
|
||||
}
|
||||
|
||||
void Settings::Validate()
|
||||
{
|
||||
if (!_info._appName)
|
||||
_info._appName = "Unnamed";
|
||||
if (!_info._appVersion)
|
||||
_info._appVersion = VERUS_MAKE_VERSION(0, 1, 0);
|
||||
if (!_info._engineName)
|
||||
_info._engineName = VERUS_ENGINE_NAME;
|
||||
if (!_info._engineVersion)
|
||||
_info._engineVersion = VERUS_SDK_VERSION;
|
||||
|
||||
_displayFOV = Math::Clamp<float>(_displayFOV, 60, 90);
|
||||
_displayOffscreenScale = Math::Clamp(_displayOffscreenScale, 0.25f, 4.f);
|
||||
_displaySizeWidth = Math::Clamp(_displaySizeWidth, 480, 0x2000);
|
||||
|
@ -291,6 +307,8 @@ void Settings::Validate()
|
|||
_sceneGrassDensity = Math::Clamp(_sceneGrassDensity, 100, 1000);
|
||||
_sceneShadowQuality = Math::Clamp(_sceneShadowQuality, Quality::low, Quality::ultra);
|
||||
_sceneWaterQuality = Math::Clamp(_sceneWaterQuality, WaterQuality::solidColor, WaterQuality::trueWavesRefraction);
|
||||
_xrFOV = Math::Clamp<float>(_xrFOV, 45, 135);
|
||||
_xrHeight = Math::Clamp<float>(_xrHeight, -3, 3);
|
||||
|
||||
if (_uiLang != "RU" && _uiLang != "EN")
|
||||
_uiLang = "EN";
|
||||
|
@ -329,6 +347,8 @@ void Settings::Save()
|
|||
Set("sceneShadowQuality", +_sceneShadowQuality);
|
||||
Set("sceneWaterQuality", +_sceneWaterQuality);
|
||||
Set("uiLang", _C(_uiLang));
|
||||
Set("xrFOV", _xrFOV);
|
||||
Set("xrHeight", _xrHeight);
|
||||
|
||||
Json::Save();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,16 @@ namespace verus
|
|||
borderlessWindowed
|
||||
};
|
||||
|
||||
class Info
|
||||
{
|
||||
public:
|
||||
CSZ _appName = nullptr;
|
||||
UINT32 _appVersion = 0;
|
||||
CSZ _engineName = nullptr;
|
||||
UINT32 _engineVersion = 0;
|
||||
};
|
||||
VERUS_TYPEDEFS(Info);
|
||||
|
||||
class QualitySettings
|
||||
{
|
||||
public:
|
||||
|
@ -115,12 +125,13 @@ namespace verus
|
|||
public:
|
||||
struct CommandLine
|
||||
{
|
||||
int _gapi = -1;
|
||||
int _openXR = -1;
|
||||
bool _exclusiveFullscreen = false;
|
||||
bool _windowed = false;
|
||||
bool _borderlessWindowed = false;
|
||||
bool _restarted = false;
|
||||
int _gapi = -1;
|
||||
int _openXR = -1;
|
||||
float _xrHeight = -FLT_MAX;
|
||||
bool _exclusiveFullscreen = false;
|
||||
bool _windowed = false;
|
||||
bool _borderlessWindowed = false;
|
||||
bool _restarted = false;
|
||||
};
|
||||
|
||||
enum Platform : int
|
||||
|
@ -140,9 +151,12 @@ namespace verus
|
|||
bool _openXR = false;
|
||||
bool _physicsSupportDebugDraw = false;
|
||||
String _uiLang = "EN";
|
||||
float _xrFOV = 110;
|
||||
float _xrHeight = 0;
|
||||
CommandLine _commandLine;
|
||||
Limits _limits;
|
||||
String _imguiFont;
|
||||
Info _info;
|
||||
float _highDpiScale = 1;
|
||||
Platform _platform = Platform::classic;
|
||||
|
||||
|
|
|
@ -77,6 +77,12 @@ namespace verus
|
|||
virtual void TraceRays(int width, int height, int depth) {} // WIP.
|
||||
// </Draw>
|
||||
|
||||
// <Profiler>
|
||||
virtual void ProfilerBeginEvent(UINT32 color, CSZ text) {}
|
||||
virtual void ProfilerEndEvent() {}
|
||||
virtual void ProfilerSetMarker(UINT32 color, CSZ text) {}
|
||||
// </Profiler>
|
||||
|
||||
RcVector4 GetViewportSize() const { return _viewportSize; }
|
||||
RcVector4 GetViewScaleBias() const { return _viewScaleBias; }
|
||||
};
|
||||
|
|
|
@ -92,9 +92,13 @@ bool BaseExtReality::CheckRequiredExtensions() const
|
|||
|
||||
void BaseExtReality::CreateInstance()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
XrResult res = XR_SUCCESS;
|
||||
XrInstanceCreateInfo xrici = { XR_TYPE_INSTANCE_CREATE_INFO };
|
||||
strcpy_s(xrici.applicationInfo.applicationName, "TestApp");
|
||||
strcpy_s(xrici.applicationInfo.applicationName, settings._info._appName);
|
||||
xrici.applicationInfo.applicationVersion = settings._info._appVersion;
|
||||
strcpy_s(xrici.applicationInfo.engineName, settings._info._engineName);
|
||||
xrici.applicationInfo.engineVersion = settings._info._engineVersion;
|
||||
xrici.applicationInfo.apiVersion = XR_CURRENT_API_VERSION;
|
||||
xrici.enabledExtensionCount = Utils::Cast32(_vRequiredExtensions.size());
|
||||
xrici.enabledExtensionNames = _vRequiredExtensions.data();
|
||||
|
|
|
@ -564,7 +564,11 @@ void DeferredShading::BeginGeometryPass()
|
|||
_activeGeometryPass = true;
|
||||
_frame = renderer.GetFrameCount();
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh,
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(0, 128, 128, 255), "DeferredShading/GeometryPass...");
|
||||
|
||||
cb->BeginRenderPass(_rph, _fbh,
|
||||
{
|
||||
_tex[TEX_GBUFFER_0]->GetClearValue(),
|
||||
_tex[TEX_GBUFFER_1]->GetClearValue(),
|
||||
|
@ -583,6 +587,9 @@ void DeferredShading::EndGeometryPass()
|
|||
VERUS_RT_ASSERT(renderer.GetFrameCount() == _frame);
|
||||
VERUS_RT_ASSERT(_activeGeometryPass && !_activeLightingPass && !_activeForwardRendering);
|
||||
_activeGeometryPass = false;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
bool DeferredShading::BeginLightingPass(bool ambient, bool terrainOcclusion)
|
||||
|
@ -594,6 +601,8 @@ bool DeferredShading::BeginLightingPass(bool ambient, bool terrainOcclusion)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 255, 96, 255), "...DeferredShading/LightingPass");
|
||||
|
||||
cb->NextSubpass();
|
||||
|
||||
if (ambient)
|
||||
|
@ -683,8 +692,12 @@ void DeferredShading::EndLightingPass()
|
|||
VERUS_RT_ASSERT(!_activeGeometryPass && _activeLightingPass && !_activeForwardRendering);
|
||||
_activeLightingPass = false;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
_shader[SHADER_LIGHT]->EndBindDescriptors();
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
cb->EndRenderPass();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void DeferredShading::BeginComposeAndForwardRendering(bool underwaterMask)
|
||||
|
@ -699,6 +712,8 @@ void DeferredShading::BeginComposeAndForwardRendering(bool underwaterMask)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 255, 255, 255), "DeferredShading/ComposeAndForwardRendering");
|
||||
|
||||
// Compose buffers, that is perform "final color = albedo * diffuse + specular" computation. Result is still HDR:
|
||||
cb->BeginRenderPass(_rphCompose, _fbhCompose,
|
||||
{
|
||||
|
@ -745,7 +760,11 @@ void DeferredShading::EndComposeAndForwardRendering()
|
|||
VERUS_RT_ASSERT(!_activeGeometryPass && !_activeLightingPass && _activeForwardRendering);
|
||||
_activeForwardRendering = false;
|
||||
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->EndRenderPass();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void DeferredShading::DrawReflection()
|
||||
|
@ -755,20 +774,25 @@ void DeferredShading::DrawReflection()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->BeginRenderPass(_rphReflection, _fbhReflection, { _tex[TEX_COMPOSED_A]->GetClearValue() });
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 128, 96, 255), "DeferredShading/DrawReflection");
|
||||
{
|
||||
|
||||
s_ubReflectionVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubReflectionVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubReflectionVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
cb->BeginRenderPass(_rphReflection, _fbhReflection, { _tex[TEX_COMPOSED_A]->GetClearValue() });
|
||||
|
||||
cb->BindPipeline(ssr.IsCubeMapDebugMode() ? _pipe[PIPE_REFLECTION_DEBUG] : _pipe[PIPE_REFLECTION]);
|
||||
_shader[SHADER_REFLECTION]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_REFLECTION], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_REFLECTION], 1, _cshReflection);
|
||||
_shader[SHADER_REFLECTION]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
s_ubReflectionVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubReflectionVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubReflectionVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
|
||||
cb->EndRenderPass();
|
||||
cb->BindPipeline(ssr.IsCubeMapDebugMode() ? _pipe[PIPE_REFLECTION_DEBUG] : _pipe[PIPE_REFLECTION]);
|
||||
_shader[SHADER_REFLECTION]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_REFLECTION], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_REFLECTION], 1, _cshReflection);
|
||||
_shader[SHADER_REFLECTION]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
|
||||
cb->EndRenderPass();
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void DeferredShading::ToneMapping()
|
||||
|
@ -777,18 +801,22 @@ void DeferredShading::ToneMapping()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
s_ubComposeFS._exposure_underwaterMask.x = renderer.GetExposure();
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 160, 255, 255), "DeferredShading/ToneMapping");
|
||||
{
|
||||
s_ubComposeVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubComposeVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
s_ubComposeFS._exposure_underwaterMask.x = renderer.GetExposure();
|
||||
|
||||
// Convert HDR image to SDR. First multiply by exposure, then apply tone mapping curve:
|
||||
cb->BindPipeline(_pipe[PIPE_TONE_MAPPING]);
|
||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshToneMapping);
|
||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
// Convert HDR image to SDR. First multiply by exposure, then apply tone mapping curve:
|
||||
cb->BindPipeline(_pipe[PIPE_TONE_MAPPING]);
|
||||
_shader[SHADER_COMPOSE]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_COMPOSE], 1, _cshToneMapping);
|
||||
_shader[SHADER_COMPOSE]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
bool DeferredShading::IsLightUrl(CSZ url)
|
||||
|
@ -839,7 +867,7 @@ void DeferredShading::OnNewLightType(CommandBufferPtr cb, LightType type, bool w
|
|||
s_ubShadowFS._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrixDS(2).UniformBufferFormat();
|
||||
s_ubShadowFS._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrixDS(3).UniformBufferFormat();
|
||||
s_ubShadowFS._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixP().UniformBufferFormat();
|
||||
s_ubShadowFS._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubShadowFS._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubShadowFS._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubShadowFS._shadowConfig));
|
||||
cb->BindDescriptors(_shader[SHADER_LIGHT], 3);
|
||||
}
|
||||
|
|
|
@ -296,7 +296,12 @@ void Renderer::Update()
|
|||
|
||||
void Renderer::Draw()
|
||||
{
|
||||
if (_pRendererDelegate)
|
||||
if (!_pRendererDelegate)
|
||||
return;
|
||||
|
||||
auto cb = GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(165, 13, 35, 255), "Renderer/Draw");
|
||||
{
|
||||
_currentViewType = ViewType::none;
|
||||
_currentViewIndex = 0;
|
||||
|
@ -305,45 +310,50 @@ void Renderer::Draw()
|
|||
_currentViewX = 0;
|
||||
_currentViewY = 0;
|
||||
_pRendererDelegate->Renderer_OnDraw();
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
{
|
||||
ViewDesc viewDesc;
|
||||
viewDesc._type = ViewType::screen;
|
||||
_currentViewType = viewDesc._type;
|
||||
_currentViewIndex = 0;
|
||||
_currentViewWidth = _screenSwapChainWidth;
|
||||
_currentViewHeight = _screenSwapChainHeight;
|
||||
_currentViewX = 0;
|
||||
_currentViewY = 0;
|
||||
_pRendererDelegate->Renderer_OnDrawView(viewDesc);
|
||||
}
|
||||
|
||||
auto pExtReality = _pBaseRenderer->GetExtReality();
|
||||
if (pExtReality->IsInitialized())
|
||||
{
|
||||
const int viewCount = pExtReality->LocateViews();
|
||||
VERUS_FOR(i, viewCount)
|
||||
{
|
||||
ViewDesc viewDesc;
|
||||
pExtReality->BeginView(i, viewDesc);
|
||||
_currentViewType = viewDesc._type;
|
||||
_currentViewIndex = viewDesc._index;
|
||||
_currentViewWidth = viewDesc._vpWidth;
|
||||
_currentViewHeight = viewDesc._vpHeight;
|
||||
_currentViewX = viewDesc._vpX;
|
||||
_currentViewY = viewDesc._vpY;
|
||||
_pRendererDelegate->Renderer_OnDrawView(viewDesc);
|
||||
pExtReality->EndView(i);
|
||||
}
|
||||
}
|
||||
|
||||
_currentViewType = ViewType::none;
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(128, 187, 1, 255), "Renderer/DrawView");
|
||||
{
|
||||
ViewDesc viewDesc;
|
||||
viewDesc._type = ViewType::screen;
|
||||
_currentViewType = viewDesc._type;
|
||||
_currentViewIndex = 0;
|
||||
_currentViewWidth = 0;
|
||||
_currentViewHeight = 0;
|
||||
_currentViewWidth = _screenSwapChainWidth;
|
||||
_currentViewHeight = _screenSwapChainHeight;
|
||||
_currentViewX = 0;
|
||||
_currentViewY = 0;
|
||||
_pRendererDelegate->Renderer_OnDrawView(viewDesc);
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
auto pExtReality = _pBaseRenderer->GetExtReality();
|
||||
if (pExtReality->IsInitialized())
|
||||
{
|
||||
const int viewCount = pExtReality->LocateViews();
|
||||
VERUS_FOR(i, viewCount)
|
||||
{
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(116, 43, 144, 255), "Renderer/DrawView(XR)");
|
||||
ViewDesc viewDesc;
|
||||
pExtReality->BeginView(i, viewDesc);
|
||||
_currentViewType = viewDesc._type;
|
||||
_currentViewIndex = viewDesc._index;
|
||||
_currentViewWidth = viewDesc._vpWidth;
|
||||
_currentViewHeight = viewDesc._vpHeight;
|
||||
_currentViewX = viewDesc._vpX;
|
||||
_currentViewY = viewDesc._vpY;
|
||||
_pRendererDelegate->Renderer_OnDrawView(viewDesc);
|
||||
pExtReality->EndView(i);
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
}
|
||||
|
||||
_currentViewType = ViewType::none;
|
||||
_currentViewIndex = 0;
|
||||
_currentViewWidth = 0;
|
||||
_currentViewHeight = 0;
|
||||
_currentViewX = 0;
|
||||
_currentViewY = 0;
|
||||
}
|
||||
|
||||
void Renderer::BeginFrame()
|
||||
|
@ -353,10 +363,18 @@ void Renderer::BeginFrame()
|
|||
pExtReality->BeginFrame();
|
||||
|
||||
_pBaseRenderer->BeginFrame();
|
||||
|
||||
auto cb = GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_WHITE, "Renderer/Frame");
|
||||
}
|
||||
|
||||
void Renderer::AcquireSwapChainImage()
|
||||
{
|
||||
auto cb = GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_SET_MARKER(cb, VERUS_COLOR_WHITE, "Renderer/AcquireSwapChainImage");
|
||||
|
||||
switch (_currentViewType)
|
||||
{
|
||||
case ViewType::screen:
|
||||
|
@ -376,6 +394,10 @@ void Renderer::AcquireSwapChainImage()
|
|||
|
||||
void Renderer::EndFrame()
|
||||
{
|
||||
auto cb = GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
_pBaseRenderer->EndFrame();
|
||||
|
||||
auto pExtReality = _pBaseRenderer->GetExtReality();
|
||||
|
@ -537,7 +559,11 @@ void Renderer::DrawOffscreenColor(PBaseCommandBuffer pCB, bool endRenderPass)
|
|||
case ViewType::screen:
|
||||
{
|
||||
if (!pExtReality->IsInitialized())
|
||||
{
|
||||
VERUS_PROFILER_BEGIN_EVENT(pCB, VERUS_COLOR_BLACK, "Renderer/DrawOffscreenColor/GenerateMips");
|
||||
_tex[TEX_OFFSCREEN_COLOR]->GenerateMips();
|
||||
VERUS_PROFILER_END_EVENT(pCB);
|
||||
}
|
||||
|
||||
pCB->BeginRenderPass(_rphScreenSwapChain, _fbhScreenSwapChain[_pBaseRenderer->GetSwapChainBufferIndex()], { Vector4(0) },
|
||||
ViewportScissorFlags::setScissorForFramebuffer);
|
||||
|
@ -554,7 +580,11 @@ void Renderer::DrawOffscreenColor(PBaseCommandBuffer pCB, bool endRenderPass)
|
|||
{
|
||||
VERUS_RT_ASSERT(pExtReality->IsInitialized());
|
||||
if (!_currentViewIndex)
|
||||
{
|
||||
VERUS_PROFILER_BEGIN_EVENT(pCB, VERUS_COLOR_BLACK, "Renderer/DrawOffscreenColor/GenerateMips");
|
||||
_tex[TEX_OFFSCREEN_COLOR]->GenerateMips();
|
||||
VERUS_PROFILER_END_EVENT(pCB);
|
||||
}
|
||||
|
||||
pCB->BeginRenderPass(pExtReality->GetRenderPassHandle(), pExtReality->GetFramebufferHandle(), { Vector4(0) },
|
||||
ViewportScissorFlags::setScissorForFramebuffer);
|
||||
|
|
|
@ -78,10 +78,13 @@ void Bloom::InitByAtmosphere(CGI::TexturePtr texShadow)
|
|||
|
||||
void Bloom::Done()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rphLightShafts);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
if (CGI::Renderer::IsLoaded())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rphLightShafts);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
}
|
||||
VERUS_DONE(Bloom);
|
||||
}
|
||||
|
||||
|
@ -148,6 +151,8 @@ void Bloom::Generate()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 96, 255, 255), "Bloom/Generate");
|
||||
|
||||
cb->BeginRenderPass(_rph, _fbh, { _tex[TEX_PING]->GetClearValue() },
|
||||
CGI::ViewportScissorFlags::setAllForCurrentViewScaled | CGI::ViewportScissorFlags::applyHalfScale);
|
||||
|
||||
|
@ -189,7 +194,7 @@ void Bloom::Generate()
|
|||
s_ubBloomLightShaftsFS._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrix(2).UniformBufferFormat();
|
||||
s_ubBloomLightShaftsFS._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrix(3).UniformBufferFormat();
|
||||
s_ubBloomLightShaftsFS._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixVP().UniformBufferFormat();
|
||||
s_ubBloomLightShaftsFS._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubBloomLightShaftsFS._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubBloomLightShaftsFS._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubBloomLightShaftsFS._shadowConfig));
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_LIGHT_SHAFTS]);
|
||||
|
@ -206,6 +211,8 @@ void Bloom::Generate()
|
|||
if (_blurLightShafts)
|
||||
Blur::I().GenerateForBloom(true);
|
||||
}
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
CGI::TexturePtr Bloom::GetTexture() const
|
||||
|
|
|
@ -170,26 +170,28 @@ void Blur::Init()
|
|||
|
||||
void Blur::Done()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
if (CGI::Renderer::IsLoaded())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
|
||||
renderer->DeleteFramebuffer(_fbhMotionBlur);
|
||||
renderer->DeleteRenderPass(_rphMotionBlur);
|
||||
renderer->DeleteFramebuffer(_fbhMotionBlur);
|
||||
renderer->DeleteRenderPass(_rphMotionBlur);
|
||||
|
||||
renderer->DeleteFramebuffer(_fbhAntiAliasing);
|
||||
renderer->DeleteRenderPass(_rphAntiAliasing);
|
||||
renderer->DeleteFramebuffer(_fbhAntiAliasing);
|
||||
renderer->DeleteRenderPass(_rphAntiAliasing);
|
||||
|
||||
_bloomHandles.DeleteFramebuffers();
|
||||
_bloomHandles.DeleteRenderPasses();
|
||||
_bloomHandles.DeleteFramebuffers();
|
||||
_bloomHandles.DeleteRenderPasses();
|
||||
|
||||
_dofHandles.DeleteFramebuffers();
|
||||
_dofHandles.DeleteRenderPasses();
|
||||
_dofHandles.DeleteFramebuffers();
|
||||
_dofHandles.DeleteRenderPasses();
|
||||
|
||||
_rdsHandles.DeleteFramebuffers();
|
||||
_rdsHandles.DeleteRenderPasses();
|
||||
|
||||
renderer->DeleteFramebuffer(_fbhSsao);
|
||||
renderer->DeleteRenderPass(_rphSsao);
|
||||
_rdsHandles.DeleteFramebuffers();
|
||||
_rdsHandles.DeleteRenderPasses();
|
||||
|
||||
renderer->DeleteFramebuffer(_fbhSsao);
|
||||
renderer->DeleteRenderPass(_rphSsao);
|
||||
}
|
||||
VERUS_DONE(Blur);
|
||||
}
|
||||
|
||||
|
@ -287,6 +289,8 @@ void Blur::GenerateForSsao()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForSsao");
|
||||
|
||||
_shader->BeginBindDescriptors();
|
||||
{
|
||||
cb->BeginRenderPass(_rphSsao, _fbhSsao, { renderer.GetDS().GetGBuffer(2)->GetClearValue() });
|
||||
|
@ -304,6 +308,8 @@ void Blur::GenerateForSsao()
|
|||
cb->EndRenderPass();
|
||||
}
|
||||
_shader->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::GenerateForResolveDitheringAndSharpen()
|
||||
|
@ -312,6 +318,8 @@ void Blur::GenerateForResolveDitheringAndSharpen()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForResolveDitheringAndSharpen");
|
||||
|
||||
_shader->BeginBindDescriptors();
|
||||
{
|
||||
cb->BeginRenderPass(_rdsHandles._rphU, _rdsHandles._fbhU, { renderer.GetDS().GetComposedTextureB()->GetClearValue() });
|
||||
|
@ -340,6 +348,8 @@ void Blur::GenerateForResolveDitheringAndSharpen()
|
|||
cb->EndRenderPass();
|
||||
}
|
||||
_shader->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::GenerateForDepthOfField()
|
||||
|
@ -351,7 +361,6 @@ void Blur::GenerateForDepthOfField()
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
const float radius = 0.02f;
|
||||
const Matrix3 matR = Matrix3::rotationZ(Math::ToRadians(45));
|
||||
const Vector3 dirs[] =
|
||||
{
|
||||
|
@ -384,6 +393,8 @@ void Blur::GenerateForDepthOfField()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForDepthOfField");
|
||||
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||
_shader->BeginBindDescriptors();
|
||||
{
|
||||
|
@ -393,11 +404,10 @@ void Blur::GenerateForDepthOfField()
|
|||
s_ubBlurVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubBlurVS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
s_ubBlurFS._tcViewScaleBias = cb->GetViewScaleBias().GLM();
|
||||
UpdateUniformBuffer(radius, 0, renderer.GetCurrentViewWidth(), samplesPerPixel, maxSamples);
|
||||
UpdateUniformBuffer(_dofRadius, 0, renderer.GetCurrentViewWidth(), samplesPerPixel, maxSamples);
|
||||
s_ubExtraBlurFS._zNearFarEx = wm.GetPassCamera()->GetZNearFarEx().GLM();
|
||||
s_ubExtraBlurFS._textureSize = cb->GetViewportSize().GLM();
|
||||
s_ubExtraBlurFS._focusDist_blurStrength.x = _dofFocusDist;
|
||||
s_ubExtraBlurFS._focusDist_blurStrength.y = _dofBlurStrength;
|
||||
s_ubExtraBlurFS._focusDist.x = _dofFocusDist;
|
||||
s_ubExtraBlurFS._blurDir = float4(
|
||||
dirs[0].getX(), dirs[0].getY() * renderer.GetCurrentViewAspectRatio(),
|
||||
dirs[1].getX(), dirs[1].getY() * renderer.GetCurrentViewAspectRatio());
|
||||
|
@ -413,7 +423,7 @@ void Blur::GenerateForDepthOfField()
|
|||
{
|
||||
cb->BeginRenderPass(_dofHandles._rphV, _dofHandles._fbhV, { renderer.GetDS().GetComposedTextureA()->GetClearValue() });
|
||||
|
||||
UpdateUniformBuffer(radius * 0.5f, 0, renderer.GetCurrentViewHeight(), samplesPerPixel, maxSamples);
|
||||
UpdateUniformBuffer(_dofRadius * 0.5f, 0, renderer.GetCurrentViewHeight(), samplesPerPixel, maxSamples);
|
||||
s_ubExtraBlurFS._blurDir = float4(dirs[2].getX(), dirs[2].getY() * renderer.GetCurrentViewAspectRatio(), 0, 0);
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_DOF_V]);
|
||||
|
@ -426,6 +436,8 @@ void Blur::GenerateForDepthOfField()
|
|||
}
|
||||
_shader->EndBindDescriptors();
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::GenerateForBloom(bool forLightShafts)
|
||||
|
@ -467,6 +479,8 @@ void Blur::GenerateForBloom(bool forLightShafts)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForBloom");
|
||||
|
||||
_shader->BeginBindDescriptors();
|
||||
{
|
||||
cb->BeginRenderPass(_bloomHandles._rphU, _bloomHandles._fbhU, { bloom.GetPongTexture()->GetClearValue() },
|
||||
|
@ -499,6 +513,8 @@ void Blur::GenerateForBloom(bool forLightShafts)
|
|||
cb->EndRenderPass();
|
||||
}
|
||||
_shader->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::GenerateForAntiAliasing()
|
||||
|
@ -509,6 +525,8 @@ void Blur::GenerateForAntiAliasing()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForAntiAliasing");
|
||||
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||
cb->BeginRenderPass(_rphAntiAliasing, _fbhAntiAliasing, { renderer.GetDS().GetComposedTextureB()->GetClearValue() });
|
||||
|
||||
|
@ -529,6 +547,8 @@ void Blur::GenerateForAntiAliasing()
|
|||
|
||||
cb->EndRenderPass();
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::GenerateForMotionBlur()
|
||||
|
@ -539,6 +559,8 @@ void Blur::GenerateForMotionBlur()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 0, 64, 255), "Blur/GenerateForMotionBlur");
|
||||
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||
cb->BeginRenderPass(_rphMotionBlur, _fbhMotionBlur, { renderer.GetDS().GetComposedTextureA()->GetClearValue() });
|
||||
|
||||
|
@ -560,6 +582,8 @@ void Blur::GenerateForMotionBlur()
|
|||
|
||||
cb->EndRenderPass();
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Blur::UpdateUniformBuffer(float radius, int sampleCount, int texSize, float samplesPerPixel, int maxSamples)
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace verus
|
|||
CGI::CSHandle _cshMotionBlurExtra;
|
||||
|
||||
float _dofFocusDist = 10;
|
||||
float _dofBlurStrength = 0.2f;
|
||||
float _dofRadius = 0.005f;
|
||||
float _bloomRadius = 0.02f;
|
||||
float _bloomLightShaftsRadius = 0.002f;
|
||||
bool _enableDepthOfField = false;
|
||||
|
@ -106,8 +106,8 @@ namespace verus
|
|||
void EnableDepthOfField(bool b) { _enableDepthOfField = b; }
|
||||
float GetDofFocusDistance() const { return _dofFocusDist; }
|
||||
void SetDofFocusDistance(float dist) { _dofFocusDist = dist; }
|
||||
float GetDofBlurStrength() const { return _dofBlurStrength; }
|
||||
void SetDofBlurStrength(float strength) { _dofBlurStrength = strength; }
|
||||
float GetDofRadius() const { return _dofRadius; }
|
||||
void SetDofRadius(float radius) { _dofRadius = radius; }
|
||||
};
|
||||
VERUS_TYPEDEFS(Blur);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,8 @@ void Cinema::Draw()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(200, 180, 150, 255), "Cinema/Draw");
|
||||
|
||||
s_ubCinemaVS._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubCinemaVS._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubCinemaVS._matP = Math::ToUVMatrix(0, renderer.GetDS().GetGBuffer(0)->GetSize(), &_texFilmGrain->GetSize(), _uOffset, _vOffset).UniformBufferFormat();
|
||||
|
@ -97,4 +99,6 @@ void Cinema::Draw()
|
|||
cb->BindDescriptors(_shader, 1, _csh);
|
||||
_shader->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
|
|
@ -649,7 +649,7 @@ bool Particles::TimeCorrectedVerletIntegration(RParticle particle, RPoint3 point
|
|||
else
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
if (wm.RayTestEx(particle._prevPosition, particle._position, nullptr, &point, &normal, nullptr, Physics::Bullet::I().GetMainMask()))
|
||||
if (wm.RayTestEx(particle._prevPosition, particle._position, nullptr, &point, &normal, nullptr, Physics::Bullet::I().GetStaticMask()))
|
||||
{
|
||||
hit = true;
|
||||
particle._inContact = normal.getY() > 0.7071f;
|
||||
|
|
|
@ -70,9 +70,12 @@ void Ssao::InitCmd()
|
|||
|
||||
void Ssao::Done()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
if (CGI::Renderer::IsLoaded())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
}
|
||||
VERUS_DONE(Ssao);
|
||||
}
|
||||
|
||||
|
@ -125,6 +128,8 @@ void Ssao::Generate()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 64, 255, 255), "Ssao/Generate");
|
||||
|
||||
cb->BeginRenderPass(_rph, _fbh, { renderer.GetDS().GetGBuffer(3)->GetClearValue() });
|
||||
|
||||
World::RCamera passCamera = *wm.GetPassCamera();
|
||||
|
@ -153,6 +158,8 @@ void Ssao::Generate()
|
|||
|
||||
if (_blur)
|
||||
Blur::I().GenerateForSsao();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Ssao::UpdateRandNormalsTexture()
|
||||
|
|
|
@ -59,9 +59,12 @@ void Ssr::Init()
|
|||
|
||||
void Ssr::Done()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
if (CGI::Renderer::IsLoaded())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
renderer->DeleteFramebuffer(_fbh);
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
}
|
||||
VERUS_DONE(Ssr);
|
||||
}
|
||||
|
||||
|
@ -134,6 +137,8 @@ void Ssr::Generate()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 32, 255, 255), "Ssr/Generate");
|
||||
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilAttachment, CGI::ImageLayout::depthStencilReadOnly, 0);
|
||||
cb->BeginRenderPass(_rph, _fbh, { renderer.GetDS().GetLightAccSpecularTexture()->GetClearValue() });
|
||||
|
||||
|
@ -164,4 +169,6 @@ void Ssr::Generate()
|
|||
|
||||
cb->EndRenderPass();
|
||||
cb->PipelineImageMemoryBarrier(renderer.GetTexDepthStencil(), CGI::ImageLayout::depthStencilReadOnly, CGI::ImageLayout::depthStencilAttachment, 0);
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
|
|
@ -259,10 +259,9 @@ void BaseCharacter::ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye,
|
|||
|
||||
const RcVector3 offsetW = GetYawMatrix() * offset;
|
||||
const Point3 pos = _smoothPosition;
|
||||
const float startAt = _cc.GetRadius() + _cc.GetHeight() * 0.5f; // Inside capsule.
|
||||
const Point3 origin = pos + Vector3(0, startAt, 0);
|
||||
const Point3 origin = pos + Vector3(0, GetThirdPersonCameraBaseHeight(), 0);
|
||||
at = pos + offsetW;
|
||||
if (wm.RayTestEx(origin, at, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask()))
|
||||
if (wm.RayTestEx(origin, at, nullptr, &point, &norm, &r, Physics::Bullet::I().GetStaticMask()))
|
||||
at = point + norm * r;
|
||||
eye = at - GetFrontDirection() * _cameraRadius.GetValue() + offsetW * 0.05f;
|
||||
}
|
||||
|
@ -288,7 +287,7 @@ float BaseCharacter::ComputeThirdPersonCamera(World::RCamera camera, Anim::RcOrb
|
|||
eye = at + Vector3(toEye);
|
||||
|
||||
float ret = 0;
|
||||
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask())) // Hitting the wall?
|
||||
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetStaticMask())) // Hitting the wall?
|
||||
{
|
||||
eye = point + norm * r;
|
||||
const float maxCameraRadius = VMath::dist(at, eye) + r;
|
||||
|
@ -324,7 +323,7 @@ void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVec
|
|||
Point3 eye, at;
|
||||
ComputeThirdPersonCameraArgs(offset, eye, at);
|
||||
|
||||
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetMainMask())) // Hitting the wall?
|
||||
if (wm.RayTestEx(at, eye, nullptr, &point, &norm, &r, Physics::Bullet::I().GetStaticMask())) // Hitting the wall?
|
||||
{
|
||||
eye = point + norm * r;
|
||||
}
|
||||
|
@ -340,6 +339,11 @@ void BaseCharacter::ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVec
|
|||
aimDir = VMath::normalizeApprox(at - eye);
|
||||
}
|
||||
|
||||
float BaseCharacter::GetThirdPersonCameraBaseHeight() const
|
||||
{
|
||||
return _cc.GetRadius() + _cc.GetHeight() * 0.5f; // Inside capsule.
|
||||
}
|
||||
|
||||
void BaseCharacter::SetMaxCameraRadius(float r)
|
||||
{
|
||||
_maxCameraRadius = r;
|
||||
|
|
|
@ -79,6 +79,7 @@ namespace verus
|
|||
virtual void ComputeThirdPersonCameraArgs(RcVector3 offset, RPoint3 eye, RPoint3 at);
|
||||
float ComputeThirdPersonCamera(World::RCamera camera, Anim::RcOrbit orbit, RcVector3 offset = Vector3(0));
|
||||
void ComputeThirdPersonAim(RPoint3 aimPos, RVector3 aimDir, RcVector3 offset = Vector3(0));
|
||||
float GetThirdPersonCameraBaseHeight() const;
|
||||
void SetMaxCameraRadius(float r);
|
||||
float GetCameraRadius() const { return _cameraRadius.GetValue(); }
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ BaseGame::~BaseGame()
|
|||
RestartApp();
|
||||
}
|
||||
|
||||
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc windowDesc)
|
||||
void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::RcInfo appInfo, App::Window::RcDesc windowDesc)
|
||||
{
|
||||
const int ret = SDL_Init(SDL_INIT_EVERYTHING);
|
||||
if (ret)
|
||||
|
@ -74,6 +74,7 @@ void BaseGame::Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc windowDes
|
|||
|
||||
App::Settings::Make();
|
||||
VERUS_QREF_SETTINGS;
|
||||
settings._info = appInfo;
|
||||
settings.ParseCommandLineArgs(argc, argv);
|
||||
settings.Load();
|
||||
settings.HandleHighDpi();
|
||||
|
@ -155,38 +156,47 @@ void BaseGame::Loop(bool relativeMouseMode)
|
|||
|
||||
// <RawInput>
|
||||
bool keyboardShortcut = false;
|
||||
if (_p->_rawInputEvents && !ImGui::GetIO().WantCaptureMouse)
|
||||
if (_p->_rawInputEvents)
|
||||
{
|
||||
switch (event.type)
|
||||
if (!ImGui::GetIO().WantCaptureMouse)
|
||||
{
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
keyboardShortcut = BaseGame_SDL_OnKeyboardShortcut(event.key.keysym.sym, event.key.keysym.mod);
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
BaseGame_SDL_OnMouseMotion(event.motion.xrel, event.motion.yrel);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (2 == event.button.clicks)
|
||||
BaseGame_SDL_OnMouseDoubleClick(event.button.button);
|
||||
else
|
||||
BaseGame_SDL_OnMouseButtonDown(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
BaseGame_SDL_OnMouseButtonUp(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
BaseGame_SDL_OnMouseWheel(event.wheel.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEMOTION:
|
||||
if (!ImGui::GetIO().WantCaptureKeyboard)
|
||||
{
|
||||
BaseGame_SDL_OnMouseMotion(event.motion.xrel, event.motion.yrel);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
{
|
||||
if (2 == event.button.clicks)
|
||||
BaseGame_SDL_OnMouseDoubleClick(event.button.button);
|
||||
else
|
||||
BaseGame_SDL_OnMouseButtonDown(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
BaseGame_SDL_OnMouseButtonUp(event.button.button);
|
||||
}
|
||||
break;
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
BaseGame_SDL_OnMouseWheel(event.wheel.y);
|
||||
}
|
||||
break;
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
keyboardShortcut = BaseGame_SDL_OnKeyboardShortcut(event.key.keysym.sym, event.key.keysym.mod);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// </RawInput>
|
||||
|
@ -266,59 +276,77 @@ void BaseGame::Loop(bool relativeMouseMode)
|
|||
|
||||
renderer.BeginFrame();
|
||||
|
||||
async.Update();
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
timer.Update();
|
||||
|
||||
BaseGame_EnterRequestedState();
|
||||
|
||||
if (_p->_defaultCameraMovement) // Handle input:
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(0, 113, 197, 255), "BaseGame/Update");
|
||||
{
|
||||
const float speed = im.IsKeyPressed(SDL_SCANCODE_SPACE) ? 20.f : 2.f;
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_W))
|
||||
_p->_cameraSpirit.MoveFront(speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_S))
|
||||
_p->_cameraSpirit.MoveFront(-speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_A))
|
||||
_p->_cameraSpirit.MoveSide(-speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_D))
|
||||
_p->_cameraSpirit.MoveSide(speed);
|
||||
}
|
||||
im.HandleInput();
|
||||
if (_restartApp)
|
||||
continue;
|
||||
VERUS_PROFILER_SET_MARKER(cb, VERUS_COLOR_WHITE, "BaseGame/Update/Async");
|
||||
async.Update();
|
||||
|
||||
if (Physics::Bullet::IsValidSingleton())
|
||||
Physics::Bullet::I().Simulate();
|
||||
VERUS_PROFILER_SET_MARKER(cb, VERUS_COLOR_WHITE, "BaseGame/Update/Timer");
|
||||
timer.Update();
|
||||
|
||||
if (_p->_defaultCameraMovement)
|
||||
{
|
||||
_p->_cameraSpirit.HandleActions();
|
||||
_p->_cameraSpirit.Update();
|
||||
_p->_camera.MoveEyeTo(_p->_cameraSpirit.GetPosition());
|
||||
_p->_camera.MoveAtTo(_p->_cameraSpirit.GetPosition() + _p->_cameraSpirit.GetFrontDirection());
|
||||
if (World::Water::IsValidSingleton())
|
||||
BaseGame_EnterRequestedState();
|
||||
|
||||
if (_p->_defaultCameraMovement) // Handle input:
|
||||
{
|
||||
VERUS_QREF_WATER;
|
||||
if (water.IsInitialized())
|
||||
_p->_camera.ExcludeWaterLine();
|
||||
const float speed = im.IsKeyPressed(SDL_SCANCODE_SPACE) ? 20.f : 2.f;
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_W))
|
||||
_p->_cameraSpirit.MoveFront(speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_S))
|
||||
_p->_cameraSpirit.MoveFront(-speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_A))
|
||||
_p->_cameraSpirit.MoveSide(-speed);
|
||||
if (im.IsKeyPressed(SDL_SCANCODE_D))
|
||||
_p->_cameraSpirit.MoveSide(speed);
|
||||
}
|
||||
_p->_camera.Update();
|
||||
if (World::WorldManager::IsValidSingleton())
|
||||
World::WorldManager::I().SetAllCameras(&_p->_camera);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (World::WorldManager::IsValidSingleton())
|
||||
World::WorldManager::I().SetAllCameras(nullptr);
|
||||
}
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(38, 125, 11, 255), "BaseGame/Update/Input");
|
||||
im.HandleInput();
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
if (_restartApp)
|
||||
continue;
|
||||
|
||||
BaseGame_Update(); // Between physics and audio update.
|
||||
if (_restartApp)
|
||||
continue;
|
||||
if (Physics::Bullet::IsValidSingleton())
|
||||
{
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(246, 154, 0, 255), "BaseGame/Update/Physics");
|
||||
Physics::Bullet::I().Simulate();
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
if (Audio::AudioSystem::IsValidSingleton())
|
||||
Audio::AudioSystem::I().Update();
|
||||
if (_p->_defaultCameraMovement)
|
||||
{
|
||||
_p->_cameraSpirit.HandleActions();
|
||||
_p->_cameraSpirit.Update();
|
||||
_p->_camera.MoveEyeTo(_p->_cameraSpirit.GetPosition());
|
||||
_p->_camera.MoveAtTo(_p->_cameraSpirit.GetPosition() + _p->_cameraSpirit.GetFrontDirection());
|
||||
if (World::Water::IsValidSingleton())
|
||||
{
|
||||
VERUS_QREF_WATER;
|
||||
if (water.IsInitialized())
|
||||
_p->_camera.ExcludeWaterLine();
|
||||
}
|
||||
_p->_camera.Update();
|
||||
if (World::WorldManager::IsValidSingleton())
|
||||
World::WorldManager::I().SetAllCameras(&_p->_camera);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (World::WorldManager::IsValidSingleton())
|
||||
World::WorldManager::I().SetAllCameras(nullptr);
|
||||
}
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(0, 167, 116, 255), "BaseGame/Update/Game");
|
||||
BaseGame_Update(); // Between physics and audio update.
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
if (_restartApp)
|
||||
continue;
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(128, 0, 0, 255), "BaseGame/Update/Audio");
|
||||
if (Audio::AudioSystem::IsValidSingleton())
|
||||
Audio::AudioSystem::I().Update();
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
// Draw current frame:
|
||||
renderer.Draw();
|
||||
|
|
|
@ -18,7 +18,9 @@ namespace verus
|
|||
BaseGame();
|
||||
~BaseGame();
|
||||
|
||||
void Initialize(VERUS_MAIN_DEFAULT_ARGS, App::Window::RcDesc windowDesc = App::Window::Desc());
|
||||
void Initialize(VERUS_MAIN_DEFAULT_ARGS,
|
||||
App::RcInfo appInfo = App::Info(),
|
||||
App::Window::RcDesc windowDesc = App::Window::Desc());
|
||||
void Loop(bool relativeMouseMode = true);
|
||||
void Exit();
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ void Spirit::ComputeDerivedVars(float smoothSpeed)
|
|||
_dv._frontDir2D = _dv._matYaw * Vector3(0, 0, 1);
|
||||
_dv._sideDir = VMath::normalizeApprox(VMath::cross(_dv._frontDir, Vector3(0, 1, 0)));
|
||||
_dv._sideDir2D = VMath::normalizeApprox(VMath::cross(_dv._frontDir2D, Vector3(0, 1, 0)));
|
||||
if (VMath::distSqr(_position, _dv._jerkyPosition) > 5 * 5.f)
|
||||
if (VMath::distSqr(_position, _dv._jerkyPosition) > _jerkyPositionDelta * _jerkyPositionDelta)
|
||||
_dv._jerkyPosition = _position;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ namespace verus
|
|||
float _accel = 0;
|
||||
float _decel = 0;
|
||||
float _turnLeanStrength = 0;
|
||||
float _jerkyPositionDelta = 10;
|
||||
|
||||
public:
|
||||
Spirit();
|
||||
|
|
|
@ -11,6 +11,12 @@ namespace verus
|
|||
int _pong = 1;
|
||||
|
||||
public:
|
||||
void Reserve(int capacity)
|
||||
{
|
||||
_v[0].reserve(capacity);
|
||||
_v[1].reserve(capacity);
|
||||
}
|
||||
|
||||
void PushBack(const T& x)
|
||||
{
|
||||
_v[_ping].push_back(x);
|
||||
|
@ -19,6 +25,7 @@ namespace verus
|
|||
template<typename TFnInsert, typename TFnDelete>
|
||||
void HandleDifference(const TFnInsert& fnInsert, const TFnDelete& fnDelete)
|
||||
{
|
||||
// Sort and remove duplicates:
|
||||
std::sort(_v[_ping].begin(), _v[_ping].end(), [](const T& a, const T& b)
|
||||
{
|
||||
return a.GetID() < b.GetID();
|
||||
|
@ -31,34 +38,43 @@ namespace verus
|
|||
typename Vector<T>::iterator itPong = _v[_pong].begin(), itPongEnd = _v[_pong].end();
|
||||
while (itPing != itPingEnd)
|
||||
{
|
||||
if (itPong == itPongEnd) // No more items in pong?
|
||||
if (itPong == itPongEnd) // Ran out of pong elements?
|
||||
{
|
||||
while (itPing != itPingEnd) // All remaining.
|
||||
while (itPing != itPingEnd) // Ping leftovers.
|
||||
fnInsert(*itPing++);
|
||||
break;
|
||||
}
|
||||
|
||||
if (itPing->GetID() < itPong->GetID()) // New item in ping, insert it:
|
||||
if (itPing->GetID() < itPong->GetID()) // Found new element in ping?
|
||||
{
|
||||
fnInsert(*itPing++);
|
||||
}
|
||||
else if (itPong->GetID() < itPing->GetID()) // Old item in pong, delete it.
|
||||
else if (itPong->GetID() < itPing->GetID()) // Found outdated element in pong?
|
||||
{
|
||||
fnDelete(*itPong++);
|
||||
}
|
||||
else // Same:
|
||||
{
|
||||
*itPing = *itPong; // No need to insert or delete, just copy payload.
|
||||
*itPing = *itPong; // Copy existing payload from pong to ping.
|
||||
itPing++;
|
||||
itPong++;
|
||||
}
|
||||
}
|
||||
while (itPong != itPongEnd) // Handle leftovers.
|
||||
// Ran out of ping elements?
|
||||
while (itPong != itPongEnd) // Pong leftovers.
|
||||
fnDelete(*itPong++);
|
||||
|
||||
// Swap:
|
||||
_pong = _ping;
|
||||
_ping = (_ping + 1) & 0x1;
|
||||
_v[_ping].clear();
|
||||
}
|
||||
|
||||
template<typename TFn>
|
||||
void ForEach(const TFn& fn)
|
||||
{
|
||||
for (auto& x : _v[_pong])
|
||||
fn(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define _C(x) ((x).c_str())
|
||||
|
||||
#define VERUS_MAKE_VERSION(major, minor, patch) (((major)<<24)|((minor)<<12)|(patch))
|
||||
#define VERUS_VERSION_MAJOR(version) ((version >> 24) & 0xFF)
|
||||
#define VERUS_VERSION_MINOR(version) ((version >> 12) & 0xFFF)
|
||||
#define VERUS_VERSION_PATCH(version) ((version) & 0xFFF)
|
||||
|
||||
#define VERUS_P_FOR(i, to) Parallel::For(0, to, [&](int i)
|
||||
#define VERUS_U_FOR(i, to) for(UINT32 i = 0; i < to; ++i)
|
||||
|
@ -93,3 +96,14 @@
|
|||
#define VERUS_COLOR_BLEND_TINTED_GLASS "s*(sc)+d*(1-sc)"
|
||||
#define VERUS_COLOR_BLEND_MIN "min(s, d)"
|
||||
#define VERUS_COLOR_BLEND_MAX "max(s, d)"
|
||||
|
||||
#ifdef VERUS_PROFILER_CALLS
|
||||
# pragma message("VERUS_PROFILER_CALLS is defined")
|
||||
# define VERUS_PROFILER_BEGIN_EVENT(cb, color, text) cb->ProfilerBeginEvent(color, text)
|
||||
# define VERUS_PROFILER_END_EVENT(cb) cb->ProfilerEndEvent()
|
||||
# define VERUS_PROFILER_SET_MARKER(cb, color, text) cb->ProfilerSetMarker(color, text)
|
||||
#else
|
||||
# define VERUS_PROFILER_BEGIN_EVENT(cb, color, text)
|
||||
# define VERUS_PROFILER_END_EVENT(cb)
|
||||
# define VERUS_PROFILER_SET_MARKER(cb, color, text)
|
||||
#endif
|
||||
|
|
|
@ -9,24 +9,31 @@ namespace verus
|
|||
Vector<T> _v;
|
||||
int _next = 0;
|
||||
|
||||
void IncrementNext()
|
||||
{
|
||||
_next = (_next + 1) % _v.size();
|
||||
}
|
||||
|
||||
public:
|
||||
void Resize(int size)
|
||||
{
|
||||
_v.resize(size);
|
||||
_next = Math::Min(_next, static_cast<int>(_v.size()));
|
||||
_next = Math::Min(_next, static_cast<int>(_v.size()) - 1);
|
||||
}
|
||||
|
||||
int Reserve()
|
||||
{
|
||||
_next = Math::Min(_next, static_cast<int>(_v.size()));
|
||||
_next = Math::Min(_next, static_cast<int>(_v.size()) - 1);
|
||||
VERUS_FOR(i, _v.size())
|
||||
{
|
||||
if (!_v[_next].IsReserved())
|
||||
{
|
||||
_v[_next].Reserve();
|
||||
return _next++;
|
||||
const int ret = _next;
|
||||
IncrementNext();
|
||||
return ret;
|
||||
}
|
||||
_next = (_next + 1) % _v.size();
|
||||
IncrementNext();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -32,3 +32,8 @@ Range::Iterator Range::end() const
|
|||
{
|
||||
return _end;
|
||||
}
|
||||
|
||||
bool Range::Includes(int value) const
|
||||
{
|
||||
return value >= _begin && value < _end;
|
||||
}
|
||||
|
|
|
@ -31,5 +31,7 @@ namespace verus
|
|||
|
||||
Iterator begin() const;
|
||||
Iterator end() const;
|
||||
|
||||
bool Includes(int value) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -305,7 +305,7 @@ void Transform3::InstFormat(VMath::Vector4* p) const
|
|||
memcpy(p, &m, 3 * sizeof(Vector4));
|
||||
}
|
||||
|
||||
float4 Transform3::ToSpriteMat() const
|
||||
float4 Transform3::ToSpriteRollMatrix() const
|
||||
{
|
||||
const Vector3 up = getUpper3x3() * Vector3(0, 1);
|
||||
const glm::vec2 upNorm(glm::normalize(up.GLM2()));
|
||||
|
|
|
@ -86,7 +86,7 @@ namespace verus
|
|||
mataff UniformBufferFormat() const;
|
||||
static mataff UniformBufferFormatIdentity();
|
||||
void InstFormat(VMath::Vector4* p) const;
|
||||
float4 ToSpriteMat() const;
|
||||
float4 ToSpriteRollMatrix() const;
|
||||
|
||||
const float* ToPointer() const { return reinterpret_cast<const float*>(this); }
|
||||
|
||||
|
|
|
@ -206,6 +206,7 @@ Continue Octree::TraverseVisible(RcFrustum frustum, PResult pResult, int current
|
|||
if (_vNodes.empty())
|
||||
return Continue::no;
|
||||
|
||||
// <Init>
|
||||
if (!currentNode)
|
||||
{
|
||||
_defaultResult = Result();
|
||||
|
@ -215,53 +216,91 @@ Continue Octree::TraverseVisible(RcFrustum frustum, PResult pResult, int current
|
|||
pResult->_passedTestCount = 0;
|
||||
pResult->_pLastFoundToken = nullptr;
|
||||
pResult->_depth = World::WorldManager::IsDrawingDepth(World::DrawDepth::automatic);
|
||||
_skipTestNode = -1;
|
||||
}
|
||||
// </Init>
|
||||
|
||||
pResult->_testCount++;
|
||||
const float onePixel = Math::ComputeOnePixelDistance(
|
||||
_vNodes[currentNode].GetSphere().GetRadius());
|
||||
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
||||
frustum.GetZNearPosition(), _vNodes[currentNode].GetSphere().GetCenter()) < onePixel * onePixel;
|
||||
|
||||
if (notTooSmall &&
|
||||
Relation::outside != frustum.ContainsSphere(_vNodes[currentNode].GetSphere()) &&
|
||||
Relation::outside != frustum.ContainsAabb(_vNodes[currentNode].GetBounds()))
|
||||
// <TestNode>
|
||||
if (-1 == _skipTestNode)
|
||||
{
|
||||
pResult->_testCount++;
|
||||
|
||||
const float onePixel = Math::ComputeOnePixelDistance(
|
||||
_vNodes[currentNode].GetSphere().GetRadius());
|
||||
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
||||
frustum.GetZNearPosition(), _vNodes[currentNode].GetSphere().GetCenter()) < onePixel * onePixel;
|
||||
|
||||
Relation relation = Relation::outside;
|
||||
if (notTooSmall)
|
||||
{
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
{
|
||||
RcElement element = node.GetElementAt(i);
|
||||
|
||||
pResult->_testCount++;
|
||||
const float onePixel = Math::ComputeOnePixelDistance(
|
||||
element._sphere.GetRadius());
|
||||
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
||||
frustum.GetZNearPosition(), element._sphere.GetCenter()) < onePixel * onePixel;
|
||||
|
||||
if (notTooSmall &&
|
||||
Relation::outside != frustum.ContainsSphere(element._sphere) &&
|
||||
Relation::outside != frustum.ContainsAabb(element._bounds))
|
||||
{
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Octree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
}
|
||||
relation = frustum.ContainsSphere(_vNodes[currentNode].GetSphere());
|
||||
if (Relation::outside != relation)
|
||||
relation = frustum.ContainsAabb(_vNodes[currentNode].GetBounds());
|
||||
}
|
||||
|
||||
if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
||||
switch (relation)
|
||||
{
|
||||
VERUS_FOR(i, 8)
|
||||
{
|
||||
const int childIndex = Node::GetChildIndex(currentNode, i);
|
||||
if (Continue::no == TraverseVisible(frustum, pResult, childIndex, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
case Relation::outside: return Continue::yes; // Early return.
|
||||
case Relation::inside: _skipTestNode = currentNode;
|
||||
}
|
||||
}
|
||||
// </TestNode>
|
||||
|
||||
// <ProcessNodeElements>
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
{
|
||||
RcElement element = node.GetElementAt(i);
|
||||
|
||||
// <TestElement>
|
||||
pResult->_testCount++;
|
||||
|
||||
const float onePixel = Math::ComputeOnePixelDistance(
|
||||
element._sphere.GetRadius());
|
||||
const bool notTooSmall = pResult->_depth || VMath::distSqr(
|
||||
frustum.GetZNearPosition(), element._sphere.GetCenter()) < onePixel * onePixel;
|
||||
|
||||
Relation relation = Relation::outside;
|
||||
if (notTooSmall)
|
||||
{
|
||||
if (-1 == _skipTestNode)
|
||||
{
|
||||
relation = frustum.ContainsSphere(element._sphere);
|
||||
if (Relation::outside != relation)
|
||||
relation = frustum.ContainsAabb(element._bounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
relation = Relation::inside;
|
||||
}
|
||||
}
|
||||
// </TestElement>
|
||||
|
||||
if (Relation::outside != relation)
|
||||
{
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Octree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </ProcessNodeElements>
|
||||
|
||||
// <TraverseChildren>
|
||||
if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
||||
{
|
||||
VERUS_FOR(i, 8)
|
||||
{
|
||||
const int childIndex = Node::GetChildIndex(currentNode, i);
|
||||
if (Continue::no == TraverseVisible(frustum, pResult, childIndex, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </TraverseChildren>
|
||||
|
||||
if (_skipTestNode == currentNode)
|
||||
_skipTestNode = -1;
|
||||
|
||||
return Continue::yes;
|
||||
}
|
||||
|
||||
|
@ -270,6 +309,7 @@ Continue Octree::TraverseVisible(RcPoint3 point, PResult pResult, int currentNod
|
|||
if (_vNodes.empty())
|
||||
return Continue::no;
|
||||
|
||||
// <Init>
|
||||
if (!currentNode)
|
||||
{
|
||||
_defaultResult = Result();
|
||||
|
@ -279,27 +319,29 @@ Continue Octree::TraverseVisible(RcPoint3 point, PResult pResult, int currentNod
|
|||
pResult->_passedTestCount = 0;
|
||||
pResult->_pLastFoundToken = nullptr;
|
||||
}
|
||||
// </Init>
|
||||
|
||||
pResult->_testCount++;
|
||||
if (_vNodes[currentNode].GetBounds().IsInside(point))
|
||||
{
|
||||
// <ProcessNodeElements>
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
{
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
RcElement element = node.GetElementAt(i);
|
||||
pResult->_testCount++;
|
||||
if (element._bounds.IsInside(point))
|
||||
{
|
||||
RcElement element = node.GetElementAt(i);
|
||||
pResult->_testCount++;
|
||||
if (element._bounds.IsInside(point))
|
||||
{
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Octree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Octree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </ProcessNodeElements>
|
||||
|
||||
// <TraverseChildren>
|
||||
if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
||||
{
|
||||
BYTE remapped[8];
|
||||
|
@ -311,6 +353,7 @@ Continue Octree::TraverseVisible(RcPoint3 point, PResult pResult, int currentNod
|
|||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </TraverseChildren>
|
||||
}
|
||||
return Continue::yes;
|
||||
}
|
||||
|
|
|
@ -73,6 +73,7 @@ namespace verus
|
|||
Vector<Node> _vNodes;
|
||||
POctreeDelegate _pDelegate = nullptr;
|
||||
Result _defaultResult;
|
||||
int _skipTestNode = -1;
|
||||
|
||||
public:
|
||||
Octree();
|
||||
|
|
|
@ -196,6 +196,7 @@ Continue Quadtree::TraverseVisible(RcPoint3 point, PResult pResult, int currentN
|
|||
if (_vNodes.empty())
|
||||
return Continue::no;
|
||||
|
||||
// <Init>
|
||||
if (!currentNode)
|
||||
{
|
||||
_defaultResult = Result();
|
||||
|
@ -205,27 +206,29 @@ Continue Quadtree::TraverseVisible(RcPoint3 point, PResult pResult, int currentN
|
|||
pResult->_passedTestCount = 0;
|
||||
pResult->_pLastFoundToken = nullptr;
|
||||
}
|
||||
// </Init>
|
||||
|
||||
pResult->_testCount++;
|
||||
if (_vNodes[currentNode].GetBounds().IsInside2D(point))
|
||||
{
|
||||
// <ProcessNodeElements>
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
{
|
||||
RcNode node = _vNodes[currentNode];
|
||||
const int count = node.GetElementCount();
|
||||
VERUS_FOR(i, count)
|
||||
RcElement element = node.GetElementAt(i);
|
||||
pResult->_testCount++;
|
||||
if (element._bounds.IsInside2D(point))
|
||||
{
|
||||
RcElement element = node.GetElementAt(i);
|
||||
pResult->_testCount++;
|
||||
if (element._bounds.IsInside2D(point))
|
||||
{
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Quadtree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
pResult->_passedTestCount++;
|
||||
pResult->_pLastFoundToken = element._pToken;
|
||||
if (Continue::no == _pDelegate->Quadtree_ProcessNode(element._pToken, pUser))
|
||||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </ProcessNodeElements>
|
||||
|
||||
// <TraverseChildren>
|
||||
if (Node::HasChildren(currentNode, Utils::Cast32(_vNodes.size())))
|
||||
{
|
||||
BYTE remapped[4];
|
||||
|
@ -237,6 +240,7 @@ Continue Quadtree::TraverseVisible(RcPoint3 point, PResult pResult, int currentN
|
|||
return Continue::no;
|
||||
}
|
||||
}
|
||||
// </TraverseChildren>
|
||||
}
|
||||
return Continue::yes;
|
||||
}
|
||||
|
|
|
@ -155,13 +155,14 @@ void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
|
|||
{
|
||||
VERUS_QREF_WM;
|
||||
|
||||
// <Init>
|
||||
if (!currentNode)
|
||||
{
|
||||
_testCount = 0;
|
||||
_passedTestCount = 0;
|
||||
_skipTestNode = -1;
|
||||
}
|
||||
|
||||
_testCount++;
|
||||
// </Init>
|
||||
|
||||
bool testFrustum = true;
|
||||
if (_distCoarseMode && depth + 2 >= _maxDepth)
|
||||
|
@ -177,9 +178,18 @@ void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
|
|||
testFrustum = false;
|
||||
}
|
||||
|
||||
RFrustum frustum = wm.GetPassCamera()->GetFrustum();
|
||||
if (testFrustum && Relation::outside == frustum.ContainsAabb(_vNodes[currentNode].GetBounds()))
|
||||
return;
|
||||
// <TestNode>
|
||||
if (testFrustum && -1 == _skipTestNode)
|
||||
{
|
||||
_testCount++;
|
||||
RFrustum frustum = wm.GetPassCamera()->GetFrustum();
|
||||
switch (frustum.ContainsAabb(_vNodes[currentNode].GetBounds()))
|
||||
{
|
||||
case Relation::outside: return; // Early return.
|
||||
case Relation::inside: _skipTestNode = currentNode;
|
||||
}
|
||||
}
|
||||
// </TestNode>
|
||||
|
||||
// Yes, it is visible:
|
||||
if (Node::HasChildren(currentNode, _nodeCount)) // Node has children -> update them:
|
||||
|
@ -197,4 +207,7 @@ void QuadtreeIntegral::TraverseVisible(int currentNode, int depth)
|
|||
_vNodes[currentNode].GetOffsetIJ(),
|
||||
_vNodes[currentNode].GetSphere().GetCenter());
|
||||
}
|
||||
|
||||
if (_skipTestNode == currentNode)
|
||||
_skipTestNode = -1;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ namespace verus
|
|||
int _nodeCount = 0;
|
||||
int _testCount = 0;
|
||||
int _passedTestCount = 0;
|
||||
int _skipTestNode = -1;
|
||||
int _mapSide = 0;
|
||||
int _limit = 0;
|
||||
int _maxDepth = 0;
|
||||
|
|
|
@ -18,9 +18,12 @@ void Bullet::Init()
|
|||
VERUS_INIT();
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
|
||||
const btVector3 worldAabbMin(-2048, -1024, -2048);
|
||||
const btVector3 worldAabbMax(+2048, +1024, +2048);
|
||||
|
||||
_pCollisionConfiguration = new(_pCollisionConfiguration.GetData()) btDefaultCollisionConfiguration();
|
||||
_pDispatcher = new(_pDispatcher.GetData()) btCollisionDispatcher(_pCollisionConfiguration.Get());
|
||||
_pBroadphaseInterface = new(_pBroadphaseInterface.GetData()) btDbvtBroadphase();
|
||||
_pBroadphaseInterface = new(_pBroadphaseInterface.GetData()) btAxisSweep3(worldAabbMin, worldAabbMax);
|
||||
_pConstraintSolver = new(_pConstraintSolver.GetData()) btSequentialImpulseConstraintSolver();
|
||||
|
||||
_pBroadphaseInterface->getOverlappingPairCache()->setInternalGhostPairCallback(&_ghostPairCallback);
|
||||
|
@ -252,6 +255,7 @@ CSZ Bullet::GroupToString(int index)
|
|||
"Gizmo",
|
||||
"Particle",
|
||||
"Terrain",
|
||||
"Forest",
|
||||
"Transport",
|
||||
"Wall"
|
||||
};
|
||||
|
|
|
@ -72,14 +72,14 @@ namespace verus
|
|||
|
||||
LocalPtr<btDefaultCollisionConfiguration> _pCollisionConfiguration;
|
||||
LocalPtr<btCollisionDispatcher> _pDispatcher;
|
||||
LocalPtr<btDbvtBroadphase> _pBroadphaseInterface;
|
||||
LocalPtr<btAxisSweep3> _pBroadphaseInterface;
|
||||
LocalPtr<btSequentialImpulseConstraintSolver> _pConstraintSolver;
|
||||
LocalPtr<btDiscreteDynamicsWorld> _pDiscreteDynamicsWorld;
|
||||
LocalPtr<btStaticPlaneShape> _pStaticPlaneShape;
|
||||
LocalRigidBody _pStaticPlaneRigidBody;
|
||||
btGhostPairCallback _ghostPairCallback;
|
||||
BulletDebugDraw _debugDraw;
|
||||
Group _mainMask = Group::immovable | Group::terrain;
|
||||
Group _staticMask = Group::immovable | Group::terrain | Group::forest;
|
||||
bool _pauseSimulation = false;
|
||||
|
||||
public:
|
||||
|
@ -89,6 +89,10 @@ namespace verus
|
|||
void Init();
|
||||
void Done();
|
||||
|
||||
btDefaultCollisionConfiguration* GetCollisionConfiguration() { return _pCollisionConfiguration.Get(); }
|
||||
btCollisionDispatcher* GetDispatcher() { return _pDispatcher.Get(); }
|
||||
btAxisSweep3* GetBroadphaseInterface() { return _pBroadphaseInterface.Get(); }
|
||||
btSequentialImpulseConstraintSolver* GetConstraintSolver() { return _pConstraintSolver.Get(); }
|
||||
btDiscreteDynamicsWorld* GetWorld() { return _pDiscreteDynamicsWorld.Get(); }
|
||||
|
||||
btRigidBody* AddNewRigidBody(
|
||||
|
@ -124,8 +128,9 @@ namespace verus
|
|||
|
||||
static CSZ GroupToString(int index);
|
||||
|
||||
Group GetMainMask() const { return _mainMask; }
|
||||
void SetMainMask(Group mask) { _mainMask = mask; }
|
||||
Group GetStaticMask() const { return _staticMask; }
|
||||
Group GetNonStaticMask() const { return ~_staticMask; }
|
||||
void SetStaticMask(Group mask) { _staticMask = mask; }
|
||||
};
|
||||
VERUS_TYPEDEFS(Bullet);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ void CharacterController::Init(RcPoint3 pos, RcDesc desc)
|
|||
_pKCC = new(_pKCC.GetData()) KinematicCharacterController(_pGhostObject.Get(), _pCapsule.Get(), stepHeight);
|
||||
_pKCC->setGravity(-bullet.GetWorld()->getGravity().getY());
|
||||
_pKCC->setMaxSlope(btRadians(48));
|
||||
bullet.GetWorld()->addCollisionObject(_pGhostObject.Get(), +Group::character, -1);
|
||||
bullet.GetWorld()->addCollisionObject(_pGhostObject.Get(), +Group::character, +Group::all);
|
||||
bullet.GetWorld()->addAction(_pKCC.Get());
|
||||
UpdateScaling();
|
||||
}
|
||||
|
|
|
@ -21,8 +21,9 @@ namespace verus
|
|||
gizmo = (1 << 10), // Editor::PGizmoTool
|
||||
particle = (1 << 11),
|
||||
terrain = (1 << 12),
|
||||
transport = (1 << 13),
|
||||
wall = (1 << 14),
|
||||
forest = (1 << 13),
|
||||
transport = (1 << 14),
|
||||
wall = (1 << 15),
|
||||
all = UINT32_MAX
|
||||
};
|
||||
}
|
||||
|
|
|
@ -56,11 +56,11 @@ void Vehicle::Init(RcDesc desc)
|
|||
const float k = forcePerWheel / desc._suspensionRestLength; // Hooke's law (F = k * x).
|
||||
|
||||
_vehicleTuning.m_suspensionStiffness = k / desc._mass; // Per 1 kg.
|
||||
_vehicleTuning.m_suspensionCompression = _vehicleTuning.m_suspensionStiffness * 0.15f;
|
||||
_vehicleTuning.m_suspensionDamping = _vehicleTuning.m_suspensionStiffness * 0.2f;
|
||||
_vehicleTuning.m_suspensionCompression = _vehicleTuning.m_suspensionStiffness * 0.09f; // Compression damping (absorb bumps).
|
||||
_vehicleTuning.m_suspensionDamping = _vehicleTuning.m_suspensionStiffness * 0.11f; // Relaxation damping (track the downslope of the bump).
|
||||
_vehicleTuning.m_maxSuspensionTravelCm = 100 * 2 * desc._suspensionRestLength;
|
||||
_vehicleTuning.m_frictionSlip = 1.5f;
|
||||
_vehicleTuning.m_maxSuspensionForce = forcePerWheel * 3;
|
||||
_vehicleTuning.m_frictionSlip = 2;
|
||||
_vehicleTuning.m_maxSuspensionForce = forcePerWheel * 10;
|
||||
|
||||
averageWheelPos -= centerOfMassOffset;
|
||||
averageWheelPos.setY(0);
|
||||
|
@ -88,8 +88,8 @@ void Vehicle::Init(RcDesc desc)
|
|||
|
||||
_pChassis = bullet.AddNewRigidBody(_pChassis, desc._mass, desc._tr.Bullet(), _pCompoundShape.Get(),
|
||||
+Group::transport, +Group::all, &trCoM);
|
||||
_pChassis->setFriction(Bullet::GetFriction(Material::metal));
|
||||
_pChassis->setRestitution(Bullet::GetRestitution(Material::metal) * 0.25f); // Energy-absorbing deformation.
|
||||
_pChassis->setFriction(0);
|
||||
_pChassis->setRestitution(0);
|
||||
_pChassis->setUserPointer(this);
|
||||
_pChassis->setActivationState(DISABLE_DEACTIVATION);
|
||||
_pVehicleRaycaster = new(_pVehicleRaycaster.GetData()) btDefaultVehicleRaycaster(bullet.GetWorld());
|
||||
|
|
|
@ -100,7 +100,7 @@ FSO mainFS(VSO si)
|
|||
g_ubBloomLightShaftsFS._matShadowCSM2,
|
||||
g_ubBloomLightShaftsFS._matShadowCSM3,
|
||||
g_ubBloomLightShaftsFS._matScreenCSM,
|
||||
g_ubBloomLightShaftsFS._csmSplitRanges,
|
||||
g_ubBloomLightShaftsFS._csmSliceBounds,
|
||||
g_ubBloomLightShaftsFS._shadowConfig,
|
||||
false);
|
||||
acc += shadowMask * step(pickingRayLen, distToEye);
|
||||
|
|
|
@ -25,6 +25,6 @@ VERUS_UBUFFER UB_BloomLightShaftsFS
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
|
|
@ -305,7 +305,7 @@ FSO mainSharpenFS(VSO si)
|
|||
|
||||
float DepthToCircleOfConfusion(float depth, float focusDist)
|
||||
{
|
||||
return abs((depth - focusDist * 2.0) / depth + 1.0);
|
||||
return abs((depth - focusDist) / depth);
|
||||
}
|
||||
|
||||
#ifdef _VS
|
||||
|
@ -327,16 +327,15 @@ FSO mainDofFS(VSO si)
|
|||
{
|
||||
FSO so;
|
||||
|
||||
const float focusDist = g_ubExtraBlurFS._focusDist_blurStrength.x;
|
||||
const float blurStrength = g_ubExtraBlurFS._focusDist_blurStrength.y;
|
||||
const float focusDist = g_ubExtraBlurFS._focusDist.x;
|
||||
|
||||
const float originDepthSam = g_texDepth.SampleLevel(g_samDepth, si.tc0.zw, 0.0).r;
|
||||
const float originDepth = ToLinearDepth(originDepthSam, g_ubExtraBlurFS._zNearFarEx);
|
||||
const float scale = DepthToCircleOfConfusion(originDepth, focusDist) * blurStrength;
|
||||
const float scale = DepthToCircleOfConfusion(originDepth, focusDist);
|
||||
|
||||
const int sampleCount = clamp(g_ubBlurFS._sampleCount * scale, 3, 31);
|
||||
const float radius = g_ubBlurFS._radius_invRadius_stride.x * scale;
|
||||
const float invRadius = 1.0 / radius;
|
||||
const float invRadius = 1.0 / (radius + _SINGULARITY_FIX);
|
||||
const float2 blurDir = g_ubExtraBlurFS._blurDir.xy;
|
||||
const float2 blurDir2 = g_ubExtraBlurFS._blurDir.zw * radius;
|
||||
|
||||
|
@ -355,9 +354,9 @@ FSO mainDofFS(VSO si)
|
|||
const float kernelDepthSam = g_texDepth.SampleLevel(g_samDepth, tcView, 0.0).r;
|
||||
const float kernelDepth = ToLinearDepth(kernelDepthSam, g_ubExtraBlurFS._zNearFarEx);
|
||||
const float kernelDeeper = kernelDepth - originDepth;
|
||||
const float kernelScale = DepthToCircleOfConfusion(kernelDepth, focusDist) * blurStrength;
|
||||
const float kernelScale = DepthToCircleOfConfusion(kernelDepth, focusDist);
|
||||
// Blurry area should not sample sharp area unless it is closer to the camera.
|
||||
float weight = min(scale, min(2.0, max(kernelScale, kernelDeeper)));
|
||||
float weight = _SINGULARITY_FIX + min(scale, max(kernelScale, kernelDeeper));
|
||||
|
||||
#ifdef DEF_U // 1st pass - make a rhombus:
|
||||
weight *= 1.0 - 0.5 * origin;
|
||||
|
@ -502,7 +501,7 @@ FSO mainMotionFS(VSO si)
|
|||
#else
|
||||
const float3 rand = Rand(si.pos.xy);
|
||||
const float2 ndcPos = ToNdcPos(si.tc0.xy);
|
||||
const float offsetScale = 0.6 + 0.1 * rand.x; // Blur 60% - 70% of frame time.
|
||||
const float offsetScale = 0.6 + 0.1 * rand.x; // Blur 60% - 70% of frame time (shutter time).
|
||||
|
||||
#if _SHADER_QUALITY <= _Q_LOW
|
||||
const int sampleCount = 6;
|
||||
|
@ -543,7 +542,7 @@ FSO mainMotionFS(VSO si)
|
|||
const float kernelDepth = ToLinearDepth(kernelDepthSam, g_ubExtraBlurFS._zNearFarEx);
|
||||
const float kernelDeeper = kernelDepth - originDepth;
|
||||
const float allowed = saturate(1.0 + kernelDeeper * equalize) * gBuffer1Sam.a; // Closer points require extra care.
|
||||
const float weight = 1.0 + saturate(kernelDeeper); // To fix the seam between foreground and background.
|
||||
const float weight = 1.0 + 2.0 * saturate(kernelDeeper); // To fix the seam between foreground and background.
|
||||
|
||||
const float3 kernelColorSam = g_tex.SampleLevel(g_sam, kernelCoords, 0.0).rgb;
|
||||
acc += lerp(0.0, float4(kernelColorSam * weight, weight), allowed);
|
||||
|
|
|
@ -21,5 +21,5 @@ VERUS_UBUFFER UB_ExtraBlurFS
|
|||
float4 _zNearFarEx;
|
||||
float4 _textureSize;
|
||||
float4 _blurDir;
|
||||
float4 _focusDist_blurStrength;
|
||||
float4 _focusDist;
|
||||
};
|
||||
|
|
|
@ -35,16 +35,16 @@ struct VSI
|
|||
|
||||
struct VSO
|
||||
{
|
||||
float4 pos : SV_Position;
|
||||
float4 clipSpacePos : TEXCOORD0;
|
||||
float4 pos : SV_Position;
|
||||
float4 clipSpacePos : TEXCOORD0;
|
||||
#if defined(DEF_DIR) || defined(DEF_SPOT) // Direction and cone shape for spot.
|
||||
float4 lightDirWV_invConeDelta : TEXCOORD1;
|
||||
float4 lightDirWV_invConeDelta : TEXCOORD1;
|
||||
#endif
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT) // Omni and spot have position and radius.
|
||||
float3 lightPosWV : TEXCOORD2;
|
||||
float3 radius_radiusSq_invRadiusSq : TEXCOORD3;
|
||||
float4 lightPosWV_lampRadius : TEXCOORD2;
|
||||
float4 radius_radiusSq_invRadiusSq_invLampRadius : TEXCOORD3;
|
||||
#endif
|
||||
float4 color_coneOut : TEXCOORD4;
|
||||
float4 color_coneOut : TEXCOORD4;
|
||||
};
|
||||
|
||||
#ifdef _VS
|
||||
|
@ -100,10 +100,14 @@ VSO mainVS(VSI si)
|
|||
#endif
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||
{
|
||||
so.lightPosWV = mul(float4(0, 0, 0, 1), matWV).xyz;
|
||||
so.radius_radiusSq_invRadiusSq.y = dot(scaledFrontDir, scaledFrontDir);
|
||||
so.radius_radiusSq_invRadiusSq.x = sqrt(so.radius_radiusSq_invRadiusSq.y);
|
||||
so.radius_radiusSq_invRadiusSq.z = 1.0 / so.radius_radiusSq_invRadiusSq.y;
|
||||
so.lightPosWV_lampRadius.xyz = mul(float4(0, 0, 0, 1), matWV).xyz;
|
||||
so.radius_radiusSq_invRadiusSq_invLampRadius.y = dot(scaledFrontDir, scaledFrontDir);
|
||||
so.radius_radiusSq_invRadiusSq_invLampRadius.x = sqrt(so.radius_radiusSq_invRadiusSq_invLampRadius.y);
|
||||
so.radius_radiusSq_invRadiusSq_invLampRadius.z = 1.0 / so.radius_radiusSq_invRadiusSq_invLampRadius.y;
|
||||
|
||||
const float lampRadius = ComputeLampRadius(so.radius_radiusSq_invRadiusSq_invLampRadius.x, color);
|
||||
so.lightPosWV_lampRadius.w = lampRadius;
|
||||
so.radius_radiusSq_invRadiusSq_invLampRadius.w = 1.0 / lampRadius;
|
||||
}
|
||||
#endif
|
||||
// </MoreLightParams>
|
||||
|
@ -113,6 +117,7 @@ VSO mainVS(VSI si)
|
|||
#endif
|
||||
|
||||
#ifdef _FS
|
||||
[earlydepthstencil]
|
||||
DS_ACC_FSO mainFS(VSO si)
|
||||
{
|
||||
DS_ACC_FSO so;
|
||||
|
@ -135,12 +140,14 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
const float coneOut = si.color_coneOut.a;
|
||||
#endif
|
||||
|
||||
// Omni and spot have position and radius:
|
||||
// Omni and spot have position, radius and size:
|
||||
#if defined(DEF_OMNI) || defined(DEF_SPOT)
|
||||
const float3 lightPosWV = si.lightPosWV;
|
||||
const float radius = si.radius_radiusSq_invRadiusSq.x;
|
||||
const float radiusSq = si.radius_radiusSq_invRadiusSq.y;
|
||||
const float invRadiusSq = si.radius_radiusSq_invRadiusSq.z;
|
||||
const float3 lightPosWV = si.lightPosWV_lampRadius.xyz;
|
||||
const float radius = si.radius_radiusSq_invRadiusSq_invLampRadius.x;
|
||||
const float radiusSq = si.radius_radiusSq_invRadiusSq_invLampRadius.y;
|
||||
const float invRadiusSq = si.radius_radiusSq_invRadiusSq_invLampRadius.z;
|
||||
const float lampRadius = si.lightPosWV_lampRadius.w;
|
||||
const float invLampRadius = si.radius_radiusSq_invRadiusSq_invLampRadius.w;
|
||||
#endif
|
||||
|
||||
// Depth:
|
||||
|
@ -179,17 +186,20 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
const float lightFalloff = 1.0; // No falloff.
|
||||
#else
|
||||
const float3 toLightWV = lightPosWV - posWV;
|
||||
const float3 dirToLightWV = normalize(toLightWV);
|
||||
const float distToLightSq = dot(toLightWV, toLightWV);
|
||||
const float distToLight = length(toLightWV);
|
||||
const float distToLightSq = distToLight * distToLight;
|
||||
const float3 dirToLightWV = toLightWV / distToLight;
|
||||
const float lightFalloff = ComputePointLightIntensity(distToLightSq, radiusSq, invRadiusSq);
|
||||
#endif
|
||||
#ifdef DEF_SPOT // Extra step for spot light:
|
||||
const float coneIntensity = ComputeSpotLightConeIntensity(dirToLightWV, lightDirWV, coneOut, invConeDelta);
|
||||
const float coneIntensity = ComputeSpotLightConeIntensity(dirToLightWV, lightDirWV, coneOut, invConeDelta) *
|
||||
saturate(distToLight * invLampRadius * 10.0 - 10.0);
|
||||
#else
|
||||
const float coneIntensity = 1.0; // No cone.
|
||||
#endif
|
||||
const float lightFalloffWithCone = lightFalloff * coneIntensity;
|
||||
const float3 dirToEyeWV = normalize(-posWV);
|
||||
const float distToEye = length(posWV);
|
||||
const float3 dirToEyeWV = -posWV / distToEye;
|
||||
const float3 lightColor = si.color_coneOut.rgb;
|
||||
// </LightData>
|
||||
|
||||
|
@ -212,14 +222,20 @@ DS_ACC_FSO mainFS(VSO si)
|
|||
g_ubShadowFS._matShadowCSM2,
|
||||
g_ubShadowFS._matShadowCSM3,
|
||||
g_ubShadowFS._matScreenCSM,
|
||||
g_ubShadowFS._csmSplitRanges,
|
||||
g_ubShadowFS._csmSliceBounds,
|
||||
shadowConfig);
|
||||
#endif
|
||||
}
|
||||
// </Shadow>
|
||||
|
||||
const float lightMinRoughness = 0.015;
|
||||
const float lightRoughness = lightMinRoughness + roughness * (1.0 / (1.0 - lightMinRoughness));
|
||||
#ifdef DEF_DIR
|
||||
const float lightMinRoughness = 0.015; // The sun.
|
||||
#else
|
||||
const float distToReflected = distToLight + distToEye;
|
||||
const float lampRadiusFactor = lampRadius / (1.0 + distToReflected * distToReflected);
|
||||
const float lightMinRoughness = clamp(lampRadiusFactor * 64.0, 0.01, 0.6);
|
||||
#endif
|
||||
const float lightRoughness = lightMinRoughness + (1.0 - lightMinRoughness) * roughness;
|
||||
|
||||
float3 punctualDiff, punctualSpec;
|
||||
VerusLit(normalWV, dirToLightWV, dirToEyeWV, tangentWV,
|
||||
|
|
|
@ -28,7 +28,7 @@ VERUS_UBUFFER UB_ShadowFS
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
||||
|
|
|
@ -42,8 +42,8 @@ VSO mainVS(VSI si)
|
|||
const float3 toEye = g_ubForestVS._eyePos.xyz - si.pos.xyz;
|
||||
const float distToHead = distance(g_ubForestVS._headPos.xyz, si.pos.xyz);
|
||||
|
||||
const float nearAlpha = ComputeFade(distToHead, 60.0, 90.0);
|
||||
const float farAlpha = 1.0 - ComputeFade(distToHead, 900.0, 1000.0);
|
||||
const float nearAlpha = QuadOutEasing(ComputeFade(distToHead, 50.0, 100.0));
|
||||
const float farAlpha = 1.0 - ComputeFade(distToHead, 750.0, 1000.0);
|
||||
|
||||
so.pos = mul(si.pos, g_ubForestVS._matWVP);
|
||||
so.tc0 = 0.0;
|
||||
|
@ -77,8 +77,8 @@ void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
|
|||
{
|
||||
const float2 posOffset = _POINT_SPRITE_POS_OFFSETS[i] * so.psize;
|
||||
const float2 offset = float2(
|
||||
dot(posOffset, g_ubForestVS._spriteMat.xy),
|
||||
dot(posOffset, g_ubForestVS._spriteMat.zw));
|
||||
dot(posOffset, g_ubForestVS._matRoll.xy),
|
||||
dot(posOffset, g_ubForestVS._matRoll.zw));
|
||||
so.pos.xy = center + offset;
|
||||
so.tc0 = _POINT_SPRITE_TEX_COORDS[i];
|
||||
stream.Append(so);
|
||||
|
@ -105,7 +105,7 @@ float ComputeMask(float2 tc, float alpha)
|
|||
{
|
||||
const float2 tcCenter = tc - 0.5;
|
||||
const float grad = 1.0 - saturate(dot(tcCenter, tcCenter) * 4.0);
|
||||
return saturate(grad + (alpha * 2.0 - 1.0));
|
||||
return saturate(grad + (alpha * 2.0 - 1.0)); // 0 to grad to 1.
|
||||
}
|
||||
|
||||
#ifdef _FS
|
||||
|
@ -159,7 +159,7 @@ DS_FSO mainFS(VSO si)
|
|||
so.target1.a = 1.0;
|
||||
so.target3.a = max(so.target3.a, AlphaToResolveDitheringMask(alpha));
|
||||
|
||||
const float fudgeFactor = 1.5;
|
||||
const float fudgeFactor = 1.2;
|
||||
clip(saturate(alpha * fudgeFactor) * mask - (dither + (1.0 / 8.0)));
|
||||
|
||||
return so;
|
||||
|
|
|
@ -7,7 +7,7 @@ VERUS_UBUFFER UB_ForestVS
|
|||
float4 _viewportSize;
|
||||
float4 _eyePos;
|
||||
float4 _headPos;
|
||||
float4 _spriteMat;
|
||||
float4 _matRoll;
|
||||
};
|
||||
|
||||
VERUS_UBUFFER UB_ForestFS
|
||||
|
|
|
@ -184,8 +184,8 @@ void mainGS(point VSO si[1], inout TriangleStream<VSO> stream)
|
|||
{
|
||||
const float2 posOffset = _POINT_SPRITE_POS_OFFSETS[i] * so.psize;
|
||||
const float2 offset = float2(
|
||||
dot(posOffset, g_ubGrassVS._spriteMat.xy),
|
||||
dot(posOffset, g_ubGrassVS._spriteMat.zw));
|
||||
dot(posOffset, g_ubGrassVS._matRoll.xy),
|
||||
dot(posOffset, g_ubGrassVS._matRoll.zw));
|
||||
so.pos.xy = center + offset;
|
||||
so.tc0 = _POINT_SPRITE_TEX_COORDS[i];
|
||||
stream.Append(so);
|
||||
|
|
|
@ -10,7 +10,7 @@ VERUS_UBUFFER UB_GrassVS
|
|||
float4 _headPos;
|
||||
float4 _viewportSize;
|
||||
float4 _warp_turb;
|
||||
float4 _spriteMat;
|
||||
float4 _matRoll;
|
||||
};
|
||||
|
||||
VERUS_UBUFFER UB_GrassFS
|
||||
|
|
|
@ -88,7 +88,6 @@ VSO mainVS(VSI si)
|
|||
const float4 userColor = g_ubPerObject._userColor;
|
||||
#endif
|
||||
|
||||
float addLamBias = 0.0;
|
||||
#if defined(DEF_SKINNED) || defined(DEF_ROBOTIC)
|
||||
const float4 warpMask = float4(
|
||||
1,
|
||||
|
@ -124,9 +123,6 @@ VSO mainVS(VSI si)
|
|||
lerp(matW33[1], matNewW33[1], userColor.a),
|
||||
lerp(matW33[2], matNewW33[2], userColor.a),
|
||||
matW[3]);
|
||||
|
||||
const float weight = 1.0 - saturate(dot(offsetXYZ, offsetXYZ));
|
||||
addLamBias = (-(weight * weight * weight)) * saturate(userColor.a);
|
||||
}
|
||||
const float3 pos = inPos;
|
||||
#else
|
||||
|
@ -196,7 +192,7 @@ VSO mainVS(VSI si)
|
|||
so.color0 = userColor;
|
||||
#ifdef DEF_PLANT
|
||||
so.color0.rgb = RandomColor(userColor.xz, 0.25, 0.15);
|
||||
so.color0.a = 1.0 - ComputeFade(max(-so.pos.z, so.pos.w), 70.0, 100.0);
|
||||
so.color0.a = QuadOutEasing(1.0 - ComputeFade(max(-so.pos.z, so.pos.w), 50.0, 100.0));
|
||||
#endif
|
||||
#if !defined(DEF_DEPTH) && !defined(DEF_SOLID_COLOR)
|
||||
so.matTBN0 = float4(tanWV, posW.x);
|
||||
|
@ -415,7 +411,7 @@ DS_FSO mainFS(VSO si)
|
|||
// <Strass>
|
||||
{
|
||||
const float strass = g_texStrass.Sample(g_samStrass, tc0 * mm_strassScale).r;
|
||||
roughness *= 1.0 - clamp(strass * mm_roughDiffuse * 4.0, 0.0, 0.99);
|
||||
roughness *= 1.0 - strass * mm_roughDiffuse;
|
||||
}
|
||||
// </Strass>
|
||||
|
||||
|
|
|
@ -173,6 +173,7 @@ VSO mainDS(_IN_DS)
|
|||
#endif
|
||||
|
||||
#ifdef _FS
|
||||
[earlydepthstencil]
|
||||
DS_FSO mainFS(VSO si)
|
||||
{
|
||||
DS_FSO so;
|
||||
|
@ -184,16 +185,36 @@ DS_FSO mainFS(VSO si)
|
|||
// Fix interpolation errors by rounding:
|
||||
si.layerForChannel = round(si.layerForChannel);
|
||||
const float2 tcLayer = si.tcLayer_tcMap.xy;
|
||||
const float2 tcLayer2 = si.tcLayer_tcMap.xy * 0.25;
|
||||
const float2 tcMap = si.tcLayer_tcMap.zw;
|
||||
|
||||
const float4 blendSam = g_texBlend.Sample(g_samBlend, si.tcBlend.xy);
|
||||
const float4 weights = float4(blendSam.rgb, 1.0 - dot(blendSam.rgb, 1.0));
|
||||
float4 weights;
|
||||
{
|
||||
const float4 blendSam = g_texBlend.Sample(g_samBlend, si.tcBlend.xy);
|
||||
weights = float4(blendSam.rgb, 1.0 - dot(blendSam.rgb, 1.0));
|
||||
|
||||
#if _SHADER_QUALITY >= _Q_HIGH
|
||||
const float2 tc = tcLayer * 0.125;
|
||||
const float4 blendNoise = float4(
|
||||
g_texDetail.Sample(g_samDetail, tc + si.layerForChannel.rr * (1.0 / 16.0)).r,
|
||||
g_texDetail.Sample(g_samDetail, tc + si.layerForChannel.gg * (1.0 / 16.0)).r,
|
||||
g_texDetail.Sample(g_samDetail, tc + si.layerForChannel.bb * (1.0 / 16.0)).r,
|
||||
g_texDetail.Sample(g_samDetail, tc + si.layerForChannel.aa * (1.0 / 16.0)).r);
|
||||
const float4 noiseMask = saturate(weights * (1.0 - weights) * 3.0);
|
||||
weights = lerp(weights, saturate((blendNoise - 0.5) * 6.0 + 0.5), noiseMask);
|
||||
weights /= dot(weights, 1.0);
|
||||
#endif
|
||||
}
|
||||
|
||||
const float4 texEnabled = ceil(weights);
|
||||
const float3 tcLayerR = float3(tcLayer * texEnabled.r, si.layerForChannel.r);
|
||||
const float3 tcLayerG = float3(tcLayer * texEnabled.g, si.layerForChannel.g);
|
||||
const float3 tcLayerB = float3(tcLayer * texEnabled.b, si.layerForChannel.b);
|
||||
const float3 tcLayerA = float3(tcLayer * texEnabled.a, si.layerForChannel.a);
|
||||
const float3 tcLayerR2 = float3(tcLayer2 * texEnabled.r, si.layerForChannel.r);
|
||||
const float3 tcLayerG2 = float3(tcLayer2 * texEnabled.g, si.layerForChannel.g);
|
||||
const float3 tcLayerB2 = float3(tcLayer2 * texEnabled.b, si.layerForChannel.b);
|
||||
const float3 tcLayerA2 = float3(tcLayer2 * texEnabled.a, si.layerForChannel.a);
|
||||
|
||||
// <Basis>
|
||||
float3 basisTan, basisBin, basisNrm;
|
||||
|
@ -217,11 +238,20 @@ DS_FSO mainFS(VSO si)
|
|||
float detailStrength;
|
||||
float roughStrength;
|
||||
{
|
||||
const float ratio = 0.4;
|
||||
float3 accAlbedo = 0.0;
|
||||
accAlbedo += g_texLayers.Sample(g_samLayers, tcLayerR).rgb * weights.r;
|
||||
accAlbedo += g_texLayers.Sample(g_samLayers, tcLayerG).rgb * weights.g;
|
||||
accAlbedo += g_texLayers.Sample(g_samLayers, tcLayerB).rgb * weights.b;
|
||||
accAlbedo += g_texLayers.Sample(g_samLayers, tcLayerA).rgb * weights.a;
|
||||
accAlbedo += lerp(
|
||||
g_texLayers.Sample(g_samLayers, tcLayerR).rgb,
|
||||
g_texLayers.Sample(g_samLayers, tcLayerR2).rgb, ratio) * weights.r;
|
||||
accAlbedo += lerp(
|
||||
g_texLayers.Sample(g_samLayers, tcLayerG).rgb,
|
||||
g_texLayers.Sample(g_samLayers, tcLayerG2).rgb, ratio) * weights.g;
|
||||
accAlbedo += lerp(
|
||||
g_texLayers.Sample(g_samLayers, tcLayerB).rgb,
|
||||
g_texLayers.Sample(g_samLayers, tcLayerB2).rgb, ratio) * weights.b;
|
||||
accAlbedo += lerp(
|
||||
g_texLayers.Sample(g_samLayers, tcLayerA).rgb,
|
||||
g_texLayers.Sample(g_samLayers, tcLayerA2).rgb, ratio) * weights.a;
|
||||
albedo = accAlbedo;
|
||||
|
||||
static float vDetailStrength[_MAX_TERRAIN_LAYERS] = (float[_MAX_TERRAIN_LAYERS])g_ubTerrainFS._vDetailStrength;
|
||||
|
@ -269,11 +299,20 @@ DS_FSO mainFS(VSO si)
|
|||
float3 normalWV;
|
||||
float3 tangentWV;
|
||||
{
|
||||
const float ratio = 0.4;
|
||||
float4 accNormal = 0.0;
|
||||
accNormal += g_texLayersN.Sample(g_samLayersN, tcLayerR) * weights.r;
|
||||
accNormal += g_texLayersN.Sample(g_samLayersN, tcLayerG) * weights.g;
|
||||
accNormal += g_texLayersN.Sample(g_samLayersN, tcLayerB) * weights.b;
|
||||
accNormal += g_texLayersN.Sample(g_samLayersN, tcLayerA) * weights.a;
|
||||
accNormal += lerp(
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerR),
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerR2), ratio) * weights.r;
|
||||
accNormal += lerp(
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerG),
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerG2), ratio) * weights.g;
|
||||
accNormal += lerp(
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerB),
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerB2), ratio) * weights.b;
|
||||
accNormal += lerp(
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerA),
|
||||
g_texLayersN.Sample(g_samLayersN, tcLayerA2), ratio) * weights.a;
|
||||
|
||||
accNormal.rg = saturate(accNormal.rg * lerp(0.5, detailNSam.rg, detailStrength) * 2.0);
|
||||
|
||||
|
@ -319,7 +358,7 @@ DS_FSO mainFS(VSO si)
|
|||
// <Strass>
|
||||
{
|
||||
const float strass = g_texStrass.Sample(g_samStrass, tcLayer * g_strassScale).r;
|
||||
roughness *= 1.0 - clamp(strass * roughStrength * 4.0, 0.0, 0.99);
|
||||
roughness *= 1.0 - strass * roughStrength;
|
||||
}
|
||||
// </Strass>
|
||||
|
||||
|
@ -341,6 +380,20 @@ DS_FSO mainFS(VSO si)
|
|||
DS_SetTangent(so, tangentWV);
|
||||
DS_SetAnisoSpec(so, anisoSpec);
|
||||
DS_SetRoughDiffuse(so, roughStrength);
|
||||
|
||||
#if 0
|
||||
DS_SetAlbedo(so, 1.0);
|
||||
|
||||
DS_SetNormal(so, matFromTBN[2]);
|
||||
DS_SetEmission(so, 0.0);
|
||||
|
||||
DS_SetOcclusion(so, 1.0);
|
||||
DS_SetRoughness(so, 0.0);
|
||||
DS_SetMetallic(so, 1.0);
|
||||
DS_SetWrapDiffuse(so, 0.0);
|
||||
|
||||
DS_SetRoughDiffuse(so, 0.0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -208,6 +208,12 @@ float SinAcos(float x) // sin(acos(x))
|
|||
{
|
||||
return sqrt(saturate(1.0 - x * x));
|
||||
}
|
||||
|
||||
float QuadOutEasing(float x)
|
||||
{
|
||||
const float a = 1.0 - x;
|
||||
return 1.0 - a * a;
|
||||
}
|
||||
// </Math>
|
||||
|
||||
// <PhysicallyBasedRendering>
|
||||
|
|
|
@ -75,7 +75,7 @@ float3 ToneMappingACES(float3 x)
|
|||
float3 VerusToneMapping(float3 hdr, float filmicLook = 1.0)
|
||||
{
|
||||
const float maxValue = max(max(hdr.r, hdr.g), hdr.b);
|
||||
const float desatMask = saturate(maxValue * 0.1);
|
||||
const float desatMask = saturate(maxValue * 0.05);
|
||||
hdr = lerp(hdr, maxValue, desatMask * desatMask); // Color crosstalk.
|
||||
const float3 ldr = lerp(1.0 - exp(-hdr), ToneMappingACES(hdr), filmicLook);
|
||||
return saturate(ldr);
|
||||
|
|
|
@ -201,7 +201,7 @@ float ShadowMapCSM(
|
|||
matrix mat2,
|
||||
matrix mat3,
|
||||
matrix matScreen,
|
||||
float4 csmSplitRanges,
|
||||
float4 csmSliceBounds,
|
||||
float4 config)
|
||||
{
|
||||
#if _SHADOW_QUALITY >= _Q_HIGH
|
||||
|
@ -213,22 +213,22 @@ float ShadowMapCSM(
|
|||
|
||||
if (IsClippedCSM(clipSpacePos))
|
||||
{
|
||||
if (depth >= csmSplitRanges.x)
|
||||
if (depth >= csmSliceBounds.x)
|
||||
{
|
||||
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5;
|
||||
const float fade = saturate((depth - fadeStart) / (csmSplitRanges.w - fadeStart));
|
||||
const float fadeStart = (csmSliceBounds.x + csmSliceBounds.w) * 0.5;
|
||||
const float fade = saturate((depth - fadeStart) / (csmSliceBounds.w - fadeStart));
|
||||
|
||||
contrast = contrastScale * contrastScale * contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
|
||||
ret = max(PCF(texCmp, samCmp, tex, sam, tc, config), fade);
|
||||
}
|
||||
else if (depth >= csmSplitRanges.y)
|
||||
else if (depth >= csmSliceBounds.y)
|
||||
{
|
||||
contrast = contrastScale * contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat1).xyz;
|
||||
ret = PCF(texCmp, samCmp, tex, sam, tc, config);
|
||||
}
|
||||
else if (depth >= csmSplitRanges.z)
|
||||
else if (depth >= csmSliceBounds.z)
|
||||
{
|
||||
contrast = contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat2).xyz;
|
||||
|
@ -263,7 +263,7 @@ float SimpleShadowMapCSM(
|
|||
matrix mat2,
|
||||
matrix mat3,
|
||||
matrix matScreen,
|
||||
float4 csmSplitRanges,
|
||||
float4 csmSliceBounds,
|
||||
float4 config,
|
||||
bool clipping = true)
|
||||
{
|
||||
|
@ -276,22 +276,22 @@ float SimpleShadowMapCSM(
|
|||
|
||||
if (!clipping || IsClippedCSM(clipSpacePos))
|
||||
{
|
||||
if (depth >= csmSplitRanges.x)
|
||||
if (depth >= csmSliceBounds.x)
|
||||
{
|
||||
const float fadeStart = (csmSplitRanges.x + csmSplitRanges.w) * 0.5;
|
||||
const float fade = saturate((depth - fadeStart) / (csmSplitRanges.w - fadeStart));
|
||||
const float fadeStart = (csmSliceBounds.x + csmSliceBounds.w) * 0.5;
|
||||
const float fade = saturate((depth - fadeStart) / (csmSliceBounds.w - fadeStart));
|
||||
|
||||
contrast = contrastScale * contrastScale * contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat0).xyz;
|
||||
ret = max(SimplePCF(texCmp, samCmp, tc), fade);
|
||||
}
|
||||
else if (depth >= csmSplitRanges.y)
|
||||
else if (depth >= csmSliceBounds.y)
|
||||
{
|
||||
contrast = contrastScale * contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat1).xyz;
|
||||
ret = SimplePCF(texCmp, samCmp, tc);
|
||||
}
|
||||
else if (depth >= csmSplitRanges.z)
|
||||
else if (depth >= csmSliceBounds.z)
|
||||
{
|
||||
contrast = contrastScale;
|
||||
const float3 tc = mul(float4(biasedPos, 1.0), mat2).xyz;
|
||||
|
|
|
@ -163,3 +163,8 @@ float ComputeSpotLightConeIntensity(float3 dirToLight, float3 lightDir, float co
|
|||
const float dp = dot(-dirToLight, lightDir);
|
||||
return saturate((dp - coneOut) * invConeDelta);
|
||||
}
|
||||
|
||||
float ComputeLampRadius(float radius, float3 color)
|
||||
{
|
||||
return radius * 10.0 / dot(color, 1.0 / 3.0);
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ float ComputeNormalZ(float2 v)
|
|||
return sqrt(saturate(1.0 - dot(v.xy, v.xy)));
|
||||
}
|
||||
|
||||
float3 NormalMapFromBC5(float4 normalSam, float contrast = -1.0)
|
||||
float3 NormalMapFromBC5(float4 normalSam, float contrast = -2.0)
|
||||
{
|
||||
float3 normal = (normalSam.rgb - 0.5) * contrast;
|
||||
normal.z = ComputeNormalZ(normal.xy);
|
||||
|
|
|
@ -57,8 +57,8 @@ VSO mainVS(VSI si)
|
|||
const float3 toEye = eyePos - si.pos.xyz;
|
||||
const float distToMainCamera = distance(mainCameraEyePos, si.pos.xyz);
|
||||
|
||||
const float nearAlpha = ComputeFade(distToMainCamera, 6.0, 9.0);
|
||||
const float farAlpha = 1.0 - ComputeFade(distToMainCamera, 900.0, 1000.0);
|
||||
const float nearAlpha = ComputeFade(distToMainCamera, 5.0, 10.0);
|
||||
const float farAlpha = 1.0 - ComputeFade(distToMainCamera, 750.0, 1000.0);
|
||||
|
||||
so.pos = mul(si.pos, g_ubSimpleForestVS._matWVP);
|
||||
so.tc0 = 0.0;
|
||||
|
@ -119,7 +119,7 @@ float ComputeMask(float2 tc, float alpha)
|
|||
{
|
||||
const float2 tcCenter = tc - 0.5;
|
||||
const float grad = 1.0 - saturate(dot(tcCenter, tcCenter) * 4.0);
|
||||
return saturate(grad + (alpha * 2.0 - 1.0));
|
||||
return saturate(grad + (alpha * 2.0 - 1.0)); // 0 to grad to 1.
|
||||
}
|
||||
|
||||
#ifdef _FS
|
||||
|
@ -171,7 +171,7 @@ FSO mainFS(VSO si)
|
|||
g_ubSimpleForestFS._matShadowCSM2,
|
||||
g_ubSimpleForestFS._matShadowCSM3,
|
||||
g_ubSimpleForestFS._matScreenCSM,
|
||||
g_ubSimpleForestFS._csmSplitRanges,
|
||||
g_ubSimpleForestFS._csmSliceBounds,
|
||||
g_ubSimpleForestFS._shadowConfig);
|
||||
}
|
||||
// </Shadow>
|
||||
|
|
|
@ -24,6 +24,6 @@ VERUS_UBUFFER UB_SimpleForestFS
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
|
|
@ -245,7 +245,7 @@ FSO mainFS(VSO si)
|
|||
g_ubSimplePerFrame._matShadowCSM2,
|
||||
g_ubSimplePerFrame._matShadowCSM3,
|
||||
g_ubSimplePerFrame._matScreenCSM,
|
||||
g_ubSimplePerFrame._csmSplitRanges,
|
||||
g_ubSimplePerFrame._csmSliceBounds,
|
||||
g_ubSimplePerFrame._shadowConfig);
|
||||
}
|
||||
// </Shadow>
|
||||
|
|
|
@ -14,7 +14,7 @@ VERUS_UBUFFER UB_SimplePerFrame
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ FSO mainFS(VSO si)
|
|||
g_ubSimpleTerrainFS._matShadowCSM2,
|
||||
g_ubSimpleTerrainFS._matShadowCSM3,
|
||||
g_ubSimpleTerrainFS._matScreenCSM,
|
||||
g_ubSimpleTerrainFS._csmSplitRanges,
|
||||
g_ubSimpleTerrainFS._csmSliceBounds,
|
||||
g_ubSimpleTerrainFS._shadowConfig);
|
||||
}
|
||||
// </Shadow>
|
||||
|
|
|
@ -21,6 +21,6 @@ VERUS_UBUFFER UB_SimpleTerrainFS
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
|
|
@ -304,7 +304,7 @@ FSO mainFS(VSO si)
|
|||
g_ubWaterFS._matShadowCSM2,
|
||||
g_ubWaterFS._matShadowCSM3,
|
||||
g_ubWaterFS._matScreenCSM,
|
||||
g_ubWaterFS._csmSplitRanges,
|
||||
g_ubWaterFS._csmSliceBounds,
|
||||
shadowConfig);
|
||||
}
|
||||
// </Shadow>
|
||||
|
|
|
@ -26,6 +26,6 @@ VERUS_UBUFFER UB_WaterFS
|
|||
matrix _matShadowCSM2;
|
||||
matrix _matShadowCSM3;
|
||||
matrix _matScreenCSM;
|
||||
float4 _csmSplitRanges;
|
||||
float4 _csmSliceBounds;
|
||||
float4 _shadowConfig;
|
||||
};
|
||||
|
|
|
@ -472,15 +472,15 @@ float Atmosphere::GetWindSpeed() const
|
|||
return _wind._speed;
|
||||
}
|
||||
|
||||
void Atmosphere::BeginShadow(int split)
|
||||
void Atmosphere::BeginShadow(int slice)
|
||||
{
|
||||
const Vector3 up = _sun._matTilt * Vector3(0, 0, 1);
|
||||
_shadowMapBaker.Begin(_sun._dirTo, split, up);
|
||||
_shadowMapBaker.Begin(_sun._dirTo, slice, up);
|
||||
}
|
||||
|
||||
void Atmosphere::EndShadow(int split)
|
||||
void Atmosphere::EndShadow(int slice)
|
||||
{
|
||||
_shadowMapBaker.End(split);
|
||||
_shadowMapBaker.End(slice);
|
||||
}
|
||||
|
||||
void Atmosphere::CreateCelestialBodyMesh()
|
||||
|
|
|
@ -167,8 +167,8 @@ namespace verus
|
|||
RCubeMapBaker GetCubeMapBaker() { return _cubeMapBaker; }
|
||||
|
||||
// ShadowMap:
|
||||
void BeginShadow(int split);
|
||||
void EndShadow(int split);
|
||||
void BeginShadow(int slice);
|
||||
void EndShadow(int slice);
|
||||
RCascadedShadowMapBaker GetShadowMapBaker() { return _shadowMapBaker; }
|
||||
|
||||
void CreateCelestialBodyMesh();
|
||||
|
|
|
@ -22,11 +22,92 @@ BaseMesh::~BaseMesh()
|
|||
|
||||
void BaseMesh::Init(CSZ url)
|
||||
{
|
||||
VERUS_INIT();
|
||||
_url = url;
|
||||
if (Str::StartsWith(url, "[_GEN]:"))
|
||||
return;
|
||||
VERUS_INIT();
|
||||
IO::Async::I().Load(url, this);
|
||||
}
|
||||
|
||||
void BaseMesh::Init(RcSourceBuffers sourceBuffers)
|
||||
{
|
||||
VERUS_INIT();
|
||||
VERUS_RT_ASSERT(!_vertCount);
|
||||
|
||||
_vertCount = Utils::Cast32(sourceBuffers._vPos.size());
|
||||
_indexCount = Utils::Cast32(sourceBuffers._vIndices.size());
|
||||
_faceCount = _indexCount ? _indexCount / 3 : _vertCount / 3;
|
||||
|
||||
if (_indexCount)
|
||||
_vIndices.assign(sourceBuffers._vIndices.begin(), sourceBuffers._vIndices.end());
|
||||
|
||||
_vBinding0.resize(_vertCount);
|
||||
if (!sourceBuffers._vPos.empty())
|
||||
{
|
||||
Math::Bounds bounds;
|
||||
VERUS_FOR(i, _vertCount)
|
||||
bounds.Include(sourceBuffers._vPos[i]);
|
||||
const glm::vec3 extents = bounds.GetExtents().GLM();
|
||||
glm::vec3 scale, bias;
|
||||
ComputeDeq(scale, bias, extents, bounds.GetMin().GLM());
|
||||
memcpy(_posDeq + 0, glm::value_ptr(scale), sizeof(float) * 3);
|
||||
memcpy(_posDeq + 3, glm::value_ptr(bias), sizeof(float) * 3);
|
||||
VERUS_FOR(i, _vertCount)
|
||||
{
|
||||
glm::vec3 v(sourceBuffers._vPos[i]);
|
||||
QuantizeV(v, extents, bounds.GetMin().GLM());
|
||||
_vBinding0[i]._pos[0] = short(v.x);
|
||||
_vBinding0[i]._pos[1] = short(v.y);
|
||||
_vBinding0[i]._pos[2] = short(v.z);
|
||||
}
|
||||
}
|
||||
if (!sourceBuffers._vTc0.empty())
|
||||
{
|
||||
Math::Bounds bounds;
|
||||
VERUS_FOR(i, _vertCount)
|
||||
bounds.Include(sourceBuffers._vTc0[i]);
|
||||
const glm::vec3 extents = bounds.GetExtents().GLM();
|
||||
glm::vec3 scale, bias;
|
||||
ComputeDeq(scale, bias, extents, bounds.GetMin().GLM());
|
||||
memcpy(_tc0Deq + 0, glm::value_ptr(scale), sizeof(float) * 2);
|
||||
memcpy(_tc0Deq + 2, glm::value_ptr(bias), sizeof(float) * 2);
|
||||
VERUS_FOR(i, _vertCount)
|
||||
{
|
||||
glm::vec3 v(sourceBuffers._vTc0[i], 0);
|
||||
QuantizeV(v, extents, bounds.GetMin().GLM());
|
||||
_vBinding0[i]._tc0[0] = short(v.x);
|
||||
_vBinding0[i]._tc0[1] = short(v.y);
|
||||
}
|
||||
}
|
||||
if (!sourceBuffers._vNrm.empty())
|
||||
{
|
||||
VERUS_FOR(i, _vertCount)
|
||||
Convert::SnormToSint8(glm::value_ptr(sourceBuffers._vNrm[i]), _vBinding0[i]._nrm, 3);
|
||||
}
|
||||
|
||||
if (sourceBuffers._recalculateTangentSpace)
|
||||
{
|
||||
_vBinding2.resize(_vertCount);
|
||||
Vector<glm::vec3> vTan, vBin;
|
||||
Math::TangentSpaceTools::RecalculateTangentSpace(
|
||||
sourceBuffers._vIndices,
|
||||
sourceBuffers._vPos,
|
||||
sourceBuffers._vNrm,
|
||||
sourceBuffers._vTc0,
|
||||
vTan, vBin);
|
||||
VERUS_FOR(i, _vertCount)
|
||||
{
|
||||
Convert::SnormToSint16(glm::value_ptr(vTan[i]), _vBinding2[i]._tan, 3);
|
||||
Convert::SnormToSint16(glm::value_ptr(vBin[i]), _vBinding2[i]._bin, 3);
|
||||
}
|
||||
}
|
||||
|
||||
if (_initShape)
|
||||
InitShape(Transform3::identity());
|
||||
|
||||
CreateDeviceBuffers();
|
||||
}
|
||||
|
||||
void BaseMesh::Done()
|
||||
{
|
||||
IO::Async::Cancel(this);
|
||||
|
@ -466,15 +547,15 @@ void BaseMesh::RecalculateTangentSpace()
|
|||
|
||||
Math::TangentSpaceTools::RecalculateNormals(_vIndices, vV, vN, 1);
|
||||
VERUS_FOR(i, _vertCount)
|
||||
Convert::SnormToSint8(&vN[i].x, _vBinding0[i]._nrm, 3);
|
||||
Convert::SnormToSint8(glm::value_ptr(vN[i]), _vBinding0[i]._nrm, 3);
|
||||
|
||||
if (!_vBinding2.empty())
|
||||
{
|
||||
Math::TangentSpaceTools::RecalculateTangentSpace(_vIndices, vV, vN, vTex, vTan, vBin);
|
||||
VERUS_FOR(i, _vertCount)
|
||||
{
|
||||
Convert::SnormToSint16(&vTan[i].x, _vBinding2[i]._tan, 3);
|
||||
Convert::SnormToSint16(&vBin[i].x, _vBinding2[i]._bin, 3);
|
||||
Convert::SnormToSint16(glm::value_ptr(vTan[i]), _vBinding2[i]._tan, 3);
|
||||
Convert::SnormToSint16(glm::value_ptr(vBin[i]), _vBinding2[i]._bin, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -493,11 +574,11 @@ btBvhTriangleMeshShape* BaseMesh::InitShape(RcTransform3 tr, CSZ url)
|
|||
|
||||
DoneShape();
|
||||
|
||||
String finalUrl = url ? url : _url;
|
||||
String finalURL = url ? url : _url;
|
||||
String cacheFilename;
|
||||
if (!finalUrl.empty())
|
||||
if (!finalURL.empty() && !Str::StartsWith(_C(finalURL), "[_GEN]:"))
|
||||
{
|
||||
String filename = Str::ToPakFriendlyUrl(_C(finalUrl));
|
||||
String filename = Str::ToPakFriendlyUrl(_C(finalURL));
|
||||
if (url)
|
||||
filename += ".INST";
|
||||
filename = "[Models]:PhyCache/" + filename + ".bullet";
|
||||
|
|
|
@ -60,10 +60,21 @@ namespace verus
|
|||
bool _initShape = false;
|
||||
|
||||
public:
|
||||
struct SourceBuffers
|
||||
{
|
||||
Vector<UINT16> _vIndices;
|
||||
Vector<glm::vec3> _vPos;
|
||||
Vector<glm::vec2> _vTc0;
|
||||
Vector<glm::vec3> _vNrm;
|
||||
bool _recalculateTangentSpace = true;
|
||||
};
|
||||
VERUS_TYPEDEFS(SourceBuffers);
|
||||
|
||||
BaseMesh();
|
||||
virtual ~BaseMesh();
|
||||
|
||||
void Init(CSZ url);
|
||||
void Init(RcSourceBuffers sourceBuffers);
|
||||
void Done();
|
||||
|
||||
Str GetURL() const { return _C(_url); }
|
||||
|
|
|
@ -74,6 +74,18 @@ void CubeMapBaker::BeginEnvMap(CGI::CubeMapFace cubeMapFace, RcPoint3 center)
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
switch (cubeMapFace)
|
||||
{
|
||||
case CGI::CubeMapFace::posX: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 240, 240, 255), "CubeMapBaker/posX"); break;
|
||||
case CGI::CubeMapFace::negX: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(255, 224, 224, 255), "CubeMapBaker/negX"); break;
|
||||
case CGI::CubeMapFace::posY: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(240, 255, 240, 255), "CubeMapBaker/posY"); break;
|
||||
case CGI::CubeMapFace::negY: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(224, 255, 224, 255), "CubeMapBaker/negY"); break;
|
||||
case CGI::CubeMapFace::posZ: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(240, 240, 255, 255), "CubeMapBaker/posZ"); break;
|
||||
case CGI::CubeMapFace::negZ: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(224, 224, 255, 255), "CubeMapBaker/negZ"); break;
|
||||
}
|
||||
|
||||
_center = center;
|
||||
|
||||
Vector3 facePos = Vector3(0);
|
||||
|
@ -99,7 +111,7 @@ void CubeMapBaker::BeginEnvMap(CGI::CubeMapFace cubeMapFace, RcPoint3 center)
|
|||
|
||||
_pPrevPassCamera = wm.SetPassCamera(&_passCamera);
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh[+cubeMapFace],
|
||||
cb->BeginRenderPass(_rph, _fbh[+cubeMapFace],
|
||||
{
|
||||
_tex[TEX_COLOR]->GetClearValue(),
|
||||
_tex[TEX_DEPTH]->GetClearValue()
|
||||
|
@ -112,7 +124,11 @@ void CubeMapBaker::EndEnvMap()
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->EndRenderPass();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
wm.SetPassCamera(_pPrevPassCamera);
|
||||
}
|
||||
|
|
|
@ -577,6 +577,10 @@ void EditorTerrain::ApplyBrushSplat(const float xz[2], int layer, int radius, fl
|
|||
falloff = Convert::Sint8ToSnorm(GetNormalAt(ij)[1]);
|
||||
falloff = pow(falloff, 10.f);
|
||||
break;
|
||||
case TerrainSplatMode::inversedNormal:
|
||||
falloff = Convert::Sint8ToSnorm(GetNormalAt(ij)[1]);
|
||||
falloff = 1 - pow(falloff, 10.f);
|
||||
break;
|
||||
}
|
||||
SplatTileAtEx(ij, layer, strength * maskValue * falloff);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace verus
|
|||
solid,
|
||||
grad,
|
||||
normal,
|
||||
inversedNormal,
|
||||
rand
|
||||
};
|
||||
|
||||
|
|
|
@ -80,13 +80,14 @@ void Forest::Init(PTerrain pTerrain, CSZ url)
|
|||
};
|
||||
_scatter.Init(s_scatterSide, SCATTER_TYPE_COUNT, id, 19201);
|
||||
_scatter.SetDelegate(this);
|
||||
_scatter.SetMaxDist(_maxDist * 1.25f);
|
||||
_scatter.SetMaxDist(_maxDistForModels * 1.25f);
|
||||
|
||||
_vPlants.reserve(16);
|
||||
_vLayerData.reserve(16);
|
||||
_vDrawPlants.resize(_capacity);
|
||||
|
||||
_vCollisionPool.Resize(1000);
|
||||
_vCollisionPlants.Reserve(400);
|
||||
_vCollisionPool.Resize(400);
|
||||
|
||||
if (url)
|
||||
{
|
||||
|
@ -127,6 +128,7 @@ void Forest::Init(PTerrain pTerrain, CSZ url)
|
|||
typeNode.attribute("minScale").as_float(0.5f),
|
||||
typeNode.attribute("maxScale").as_float(1.5f),
|
||||
typeNode.attribute("windBending").as_float(1),
|
||||
typeNode.attribute("hullSplitU").as_float(-1),
|
||||
typeNode.attribute("allowedNormal").as_int(116));
|
||||
}
|
||||
|
||||
|
@ -143,11 +145,15 @@ void Forest::Done()
|
|||
bullet.GetWorld()->removeRigidBody(block.GetRigidBody());
|
||||
block.GetDefaultMotionState()->~btDefaultMotionState();
|
||||
block.GetRigidBody()->~btRigidBody();
|
||||
block.GetScaledBvhTriangleMeshShape()->~btScaledBvhTriangleMeshShape();
|
||||
block.GetUniformScalingShapeForBranches()->~btUniformScalingShape();
|
||||
block.GetUniformScalingShapeForTrunk()->~btUniformScalingShape();
|
||||
block.GetCompoundShape()->~btCompoundShape();
|
||||
block.Free();
|
||||
});
|
||||
for (auto& plant : _vPlants)
|
||||
{
|
||||
plant._pConvexHullShapeForBranches.Delete();
|
||||
plant._pConvexHullShapeForTrunk.Delete();
|
||||
s_shader[SHADER_SIMPLE]->FreeDescriptorSet(plant._cshSimple);
|
||||
s_shader[SHADER_MAIN]->FreeDescriptorSet(plant._csh);
|
||||
}
|
||||
|
@ -178,7 +184,6 @@ void Forest::Update()
|
|||
Mesh::Desc meshDesc;
|
||||
meshDesc._url = _C(plant._url);
|
||||
meshDesc._instanceCapacity = _capacity;
|
||||
meshDesc._initShape = true;
|
||||
plant._mesh.Init(meshDesc);
|
||||
|
||||
Material::Desc matDesc;
|
||||
|
@ -203,6 +208,22 @@ void Forest::Update()
|
|||
_maxSizeAll = plant._maxSize;
|
||||
_pTerrain->FattenQuadtreeNodesBy(_maxSizeAll);
|
||||
}
|
||||
|
||||
// Time to create convex hulls:
|
||||
plant._pConvexHullShapeForTrunk = new(plant._pConvexHullShapeForTrunk.GetData()) btConvexHullShape();
|
||||
plant._pConvexHullShapeForBranches = new(plant._pConvexHullShapeForBranches.GetData()) btConvexHullShape();
|
||||
plant._mesh.ForEachVertex([&plant](int index, RcPoint3 pos, RcVector3 nrm, RcPoint3 tc)
|
||||
{
|
||||
if (tc.getX() >= plant._hullSplitU)
|
||||
plant._pConvexHullShapeForBranches->addPoint(pos.Bullet(), false);
|
||||
else
|
||||
plant._pConvexHullShapeForTrunk->addPoint(pos.Bullet(), false);
|
||||
return Continue::yes;
|
||||
});
|
||||
plant._pConvexHullShapeForTrunk->recalcLocalAabb();
|
||||
plant._pConvexHullShapeForBranches->recalcLocalAabb();
|
||||
plant._pConvexHullShapeForTrunk->optimizeConvexHull();
|
||||
plant._pConvexHullShapeForBranches->optimizeConvexHull();
|
||||
}
|
||||
|
||||
if (!plant._tex[0] && plant._mesh.IsLoaded() && plant._material->IsLoaded())
|
||||
|
@ -333,36 +354,31 @@ void Forest::Layout(bool reflection)
|
|||
{
|
||||
if (!IsInitialized())
|
||||
return;
|
||||
|
||||
_visibleCount = 0;
|
||||
|
||||
VERUS_QREF_ATMO;
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
_visibleCount = 0;
|
||||
for (auto& plant : _vPlants)
|
||||
{
|
||||
for (auto& bc : plant._vBakedChunks)
|
||||
bc._visible = false;
|
||||
|
||||
{
|
||||
const float zFarWas = wm.GetHeadCamera()->GetZFar();
|
||||
|
||||
if (!reflection)
|
||||
{
|
||||
wm.GetHeadCamera()->SetFrustumFar(_maxDist);
|
||||
Math::RQuadtreeIntegral qt = _pTerrain->GetQuadtree();
|
||||
qt.SetDelegate(&_scatter);
|
||||
qt.TraverseVisible();
|
||||
qt.SetDelegate(_pTerrain);
|
||||
}
|
||||
|
||||
wm.GetHeadCamera()->SetFrustumFar(1000);
|
||||
_octree.TraverseVisible(wm.GetHeadCamera()->GetFrustum());
|
||||
|
||||
wm.GetHeadCamera()->SetFrustumFar(zFarWas);
|
||||
|
||||
if (reflection)
|
||||
return;
|
||||
}
|
||||
|
||||
_octree.TraverseVisible(wm.GetPassCamera()->GetFrustum());
|
||||
if (!reflection)
|
||||
{
|
||||
Math::RQuadtreeIntegral quadtree = _pTerrain->GetQuadtree();
|
||||
quadtree.SetDelegate(&_scatter);
|
||||
quadtree.TraverseVisible();
|
||||
quadtree.SetDelegate(_pTerrain);
|
||||
|
||||
SortVisible();
|
||||
}
|
||||
}
|
||||
|
||||
void Forest::SortVisible()
|
||||
{
|
||||
const float tessDistSq = _tessDist * _tessDist;
|
||||
std::sort(_vDrawPlants.begin(), _vDrawPlants.begin() + _visibleCount, [tessDistSq](RDrawPlant plantA, RDrawPlant plantB)
|
||||
{
|
||||
|
@ -406,6 +422,8 @@ void Forest::DrawModels(bool allowTess)
|
|||
auto cb = renderer.GetCommandBuffer();
|
||||
auto shader = Mesh::GetShader();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 255, 160, 255), "Forest/DrawModels");
|
||||
|
||||
auto DrawMesh = [cb](PMesh pMesh)
|
||||
{
|
||||
if (pMesh && !pMesh->IsInstanceBufferEmpty(true))
|
||||
|
@ -480,6 +498,8 @@ void Forest::DrawModels(bool allowTess)
|
|||
}
|
||||
}
|
||||
shader->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Forest::DrawSprites()
|
||||
|
@ -494,12 +514,14 @@ void Forest::DrawSprites()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 255, 160, 255), "Forest/DrawSprites");
|
||||
|
||||
s_ubForestVS._matP = wm.GetPassCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubForestVS._matWVP = wm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubForestVS._viewportSize = cb->GetViewportSize().GLM();
|
||||
s_ubForestVS._eyePos = float4(wm.GetPassCamera()->GetEyePosition().GLM(), 0);
|
||||
s_ubForestVS._headPos = float4(wm.GetHeadCamera()->GetEyePosition().GLM(), 0);
|
||||
s_ubForestVS._spriteMat = wm.GetPassCamera()->GetMatrixV().ToSpriteMat();
|
||||
s_ubForestVS._matRoll = wm.GetPassCamera()->GetMatrixV().ToSpriteRollMatrix();
|
||||
|
||||
cb->BindPipeline(_pipe[drawingDepth ? PIPE_DEPTH : PIPE_MAIN]);
|
||||
cb->BindVertexBuffers(_geo);
|
||||
|
@ -517,6 +539,8 @@ void Forest::DrawSprites()
|
|||
}
|
||||
}
|
||||
s_shader[SHADER_MAIN]->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Forest::DrawSimple(DrawSimpleMode mode, CGI::CubeMapFace cubeMapFace)
|
||||
|
@ -568,6 +592,8 @@ void Forest::DrawSimple(DrawSimpleMode mode, CGI::CubeMapFace cubeMapFace)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(32, 255, 160, 255), "Forest/DrawSimple");
|
||||
|
||||
s_ubSimpleForestVS._matP = wm.GetPassCamera()->GetMatrixP().UniformBufferFormat();
|
||||
s_ubSimpleForestVS._matWVP = wm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubSimpleForestVS._viewportSize = cb->GetViewportSize().GLM();
|
||||
|
@ -585,7 +611,7 @@ void Forest::DrawSimple(DrawSimpleMode mode, CGI::CubeMapFace cubeMapFace)
|
|||
s_ubSimpleForestFS._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrix(2).UniformBufferFormat();
|
||||
s_ubSimpleForestFS._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrix(3).UniformBufferFormat();
|
||||
s_ubSimpleForestFS._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixVP().UniformBufferFormat();
|
||||
s_ubSimpleForestFS._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubSimpleForestFS._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubSimpleForestFS._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubSimpleForestFS._shadowConfig));
|
||||
|
||||
switch (mode)
|
||||
|
@ -608,6 +634,8 @@ void Forest::DrawSimple(DrawSimpleMode mode, CGI::CubeMapFace cubeMapFace)
|
|||
}
|
||||
}
|
||||
s_shader[SHADER_SIMPLE]->EndBindDescriptors();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Forest::UpdateCollision(const Vector<Vector4>& vZones)
|
||||
|
@ -624,8 +652,8 @@ void Forest::UpdateCollision(const Vector<Vector4>& vZones)
|
|||
};
|
||||
const int r = static_cast<int>(zone.getW() + 0.5f);
|
||||
const int r2 = r * r;
|
||||
const int iRange[2] = { Math::Clamp(centerIJ[0] - r, 0, mapSide), Math::Clamp(centerIJ[0] + r, 0, mapSide) };
|
||||
const int jRange[2] = { Math::Clamp(centerIJ[1] - r, 0, mapSide), Math::Clamp(centerIJ[1] + r, 0, mapSide) };
|
||||
const int iRange[2] = { Math::Clamp(centerIJ[0] - r, 0, mapSide), Math::Clamp(centerIJ[0] + r + 1, 0, mapSide) };
|
||||
const int jRange[2] = { Math::Clamp(centerIJ[1] - r, 0, mapSide), Math::Clamp(centerIJ[1] + r + 1, 0, mapSide) };
|
||||
for (int i = iRange[0]; i < iRange[1]; ++i)
|
||||
{
|
||||
const int offsetI = centerIJ[0] - i;
|
||||
|
@ -697,22 +725,36 @@ void Forest::UpdateCollision(const Vector<Vector4>& vZones)
|
|||
const float t = (plant._alignToNormal - 0.1f) / 0.8f;
|
||||
const Matrix3 matBasis = Matrix3::Lerp(Matrix3::identity(), _pTerrain->GetBasisAt(ij), t);
|
||||
const Transform3 matW = Transform3(matBasis * Matrix3::rotationY(instance._angle), Vector3(pos));
|
||||
btScaledBvhTriangleMeshShape* pShape = new(block.GetScaledBvhTriangleMeshShape())
|
||||
btScaledBvhTriangleMeshShape(plant._mesh.GetShape(), btVector3(scale, scale, scale));
|
||||
btRigidBody* pRigidBody = bullet.AddNewRigidBody(0, matW.Bullet(), pShape, +Physics::Group::immovable, +Physics::Group::all, nullptr,
|
||||
btCompoundShape* pCompoundShape = new(block.GetCompoundShape()) btCompoundShape();
|
||||
btUniformScalingShape* pUniformScalingShapeForTrunk = new(block.GetUniformScalingShapeForTrunk())
|
||||
btUniformScalingShape(plant._pConvexHullShapeForTrunk.Get(), scale);
|
||||
btUniformScalingShape* pUniformScalingShapeForBranches = new(block.GetUniformScalingShapeForBranches())
|
||||
btUniformScalingShape(plant._pConvexHullShapeForBranches.Get(), scale);
|
||||
// DebugDraw will not show UniformScalingShape, add ConvexHullShape instead.
|
||||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
if (plant._pConvexHullShapeForTrunk->getNumPoints())
|
||||
pCompoundShape->addChildShape(tr, pUniformScalingShapeForTrunk);
|
||||
if (plant._pConvexHullShapeForBranches->getNumPoints())
|
||||
pCompoundShape->addChildShape(tr, pUniformScalingShapeForBranches);
|
||||
btRigidBody* pRigidBody = bullet.AddNewRigidBody(0, matW.Bullet(), pCompoundShape, +Physics::Group::forest, +bullet.GetNonStaticMask(), nullptr,
|
||||
block.GetDefaultMotionState(),
|
||||
block.GetRigidBody());
|
||||
pRigidBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::stone));
|
||||
pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::stone));
|
||||
pRigidBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::wood));
|
||||
pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::wood));
|
||||
},
|
||||
[this](RCollisionPlant cp)
|
||||
{
|
||||
if (cp._poolBlockIndex < 0)
|
||||
return;
|
||||
VERUS_QREF_BULLET;
|
||||
RCollisionPoolBlock block = _vCollisionPool.GetBlockAt(cp._poolBlockIndex);
|
||||
bullet.GetWorld()->removeRigidBody(block.GetRigidBody());
|
||||
block.GetDefaultMotionState()->~btDefaultMotionState();
|
||||
block.GetRigidBody()->~btRigidBody();
|
||||
block.GetScaledBvhTriangleMeshShape()->~btScaledBvhTriangleMeshShape();
|
||||
block.GetUniformScalingShapeForBranches()->~btUniformScalingShape();
|
||||
block.GetUniformScalingShapeForTrunk()->~btUniformScalingShape();
|
||||
block.GetCompoundShape()->~btCompoundShape();
|
||||
block.Free();
|
||||
});
|
||||
}
|
||||
|
@ -776,6 +818,7 @@ void Forest::SetLayer(int layer, RcLayerDesc desc)
|
|||
plant._alignToNormal = plantDesc._alignToNormal;
|
||||
plant._maxScale = plantDesc._maxScale;
|
||||
plant._windBending = plantDesc._windBending;
|
||||
plant._hullSplitU = plantDesc._hullSplitU;
|
||||
plant._allowedNormal = plantDesc._allowedNormal;
|
||||
const float ds = plantDesc._maxScale - plantDesc._minScale;
|
||||
const int count = 64;
|
||||
|
@ -783,10 +826,6 @@ void Forest::SetLayer(int layer, RcLayerDesc desc)
|
|||
VERUS_FOR(i, count)
|
||||
plant._vScales[i] = plantDesc._minScale + ds * (i * i * i) / (count * count * count);
|
||||
std::shuffle(plant._vScales.begin(), plant._vScales.end(), random.GetGenerator());
|
||||
|
||||
//plant._vShapePool.resize(2000 * sizeof(btScaledBvhTriangleMeshShape));
|
||||
//plant._vMotionStatePool.resize(2000 * sizeof(btDefaultMotionState));
|
||||
//plant._vRigidBodyPool.resize(2000 * sizeof(btRigidBody));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1185,7 +1224,7 @@ void Forest::Scatter_AddInstance(const int ij[2], int type, float x, float z, fl
|
|||
Point3 pos(x, h, z);
|
||||
RcPoint3 headPos = wm.GetHeadCamera()->GetEyePosition();
|
||||
const float distSq = VMath::distSqr(headPos, pos);
|
||||
const float maxDistSq = _maxDist * _maxDist;
|
||||
const float maxDistSq = _maxDistForModels * _maxDistForModels;
|
||||
if (distSq >= maxDistSq)
|
||||
return;
|
||||
|
||||
|
@ -1231,7 +1270,7 @@ Continue Forest::Octree_ProcessNode(void* pToken, void* pUser)
|
|||
{
|
||||
VERUS_QREF_WM;
|
||||
PBakedChunk pBakedChunk = static_cast<PBakedChunk>(pToken);
|
||||
pBakedChunk->_visible = wm.GetPassCamera()->GetFrustum().ContainsAabb(pBakedChunk->_bounds) != Relation::outside;
|
||||
pBakedChunk->_visible = true;
|
||||
return Continue::yes;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,24 +74,32 @@ namespace verus
|
|||
class alignas(VERUS_MEMORY_ALIGNMENT) CollisionPoolBlock
|
||||
{
|
||||
public:
|
||||
BYTE _data[sizeof(btScaledBvhTriangleMeshShape) + sizeof(btDefaultMotionState) + sizeof(btRigidBody)];
|
||||
bool _reserved = 0;
|
||||
BYTE _data[sizeof(btCompoundShape) + 2 * sizeof(btUniformScalingShape) + sizeof(btDefaultMotionState) + sizeof(btRigidBody)];
|
||||
bool _reserved = false;
|
||||
|
||||
bool IsReserved() const { return _reserved; }
|
||||
void Reserve() { _reserved = true; }
|
||||
void Free() { _reserved = false; }
|
||||
|
||||
btScaledBvhTriangleMeshShape* GetScaledBvhTriangleMeshShape()
|
||||
btCompoundShape* GetCompoundShape()
|
||||
{
|
||||
return reinterpret_cast<btScaledBvhTriangleMeshShape*>(&_data[0]);
|
||||
return reinterpret_cast<btCompoundShape*>(&_data[0]);
|
||||
}
|
||||
btUniformScalingShape* GetUniformScalingShapeForTrunk()
|
||||
{
|
||||
return reinterpret_cast<btUniformScalingShape*>(&_data[sizeof(btCompoundShape)]);
|
||||
}
|
||||
btUniformScalingShape* GetUniformScalingShapeForBranches()
|
||||
{
|
||||
return reinterpret_cast<btUniformScalingShape*>(&_data[sizeof(btCompoundShape) + sizeof(btUniformScalingShape)]);
|
||||
}
|
||||
btDefaultMotionState* GetDefaultMotionState()
|
||||
{
|
||||
return reinterpret_cast<btDefaultMotionState*>(&_data[sizeof(btScaledBvhTriangleMeshShape)]);
|
||||
return reinterpret_cast<btDefaultMotionState*>(&_data[sizeof(btCompoundShape) + 2 * sizeof(btUniformScalingShape)]);
|
||||
}
|
||||
btRigidBody* GetRigidBody()
|
||||
{
|
||||
return reinterpret_cast<btRigidBody*>(&_data[sizeof(btScaledBvhTriangleMeshShape) + sizeof(btDefaultMotionState)]);
|
||||
return reinterpret_cast<btRigidBody*>(&_data[sizeof(btCompoundShape) + 2 * sizeof(btUniformScalingShape) + sizeof(btDefaultMotionState)]);
|
||||
}
|
||||
};
|
||||
VERUS_TYPEDEFS(CollisionPoolBlock);
|
||||
|
@ -114,12 +122,15 @@ namespace verus
|
|||
CGI::TexturePwns<TEX_COUNT> _tex;
|
||||
CGI::CSHandle _csh;
|
||||
CGI::CSHandle _cshSimple;
|
||||
LocalPtr<btConvexHullShape> _pConvexHullShapeForTrunk;
|
||||
LocalPtr<btConvexHullShape> _pConvexHullShapeForBranches;
|
||||
Vector<BakedChunk> _vBakedChunks;
|
||||
Vector<float> _vScales;
|
||||
float _alignToNormal = 1;
|
||||
float _maxScale = 0;
|
||||
float _maxSize = 0;
|
||||
float _windBending = 1;
|
||||
float _hullSplitU = -1;
|
||||
char _allowedNormal = 116;
|
||||
|
||||
float GetSize() const;
|
||||
|
@ -171,7 +182,8 @@ namespace verus
|
|||
DifferenceVector<CollisionPlant> _vCollisionPlants;
|
||||
Pool<CollisionPoolBlock> _vCollisionPool;
|
||||
const float _margin = 1.1f;
|
||||
float _maxDist = 100;
|
||||
float _maxDistForModels = 100;
|
||||
float _maxDistForChunks = 1000;
|
||||
float _tessDist = 50;
|
||||
float _maxSizeAll = 0;
|
||||
float _phaseY = 0;
|
||||
|
@ -190,15 +202,24 @@ namespace verus
|
|||
float _minScale = 0.8f;
|
||||
float _maxScale = 1.25f;
|
||||
float _windBending = 1;
|
||||
float _hullSplitU = -1;
|
||||
char _allowedNormal = 116;
|
||||
|
||||
void Set(CSZ url, float alignToNormal = 1, float minScale = 0.8f, float maxScale = 1.25f, float windBending = 1, char allowedNormal = 116)
|
||||
void Set(
|
||||
CSZ url,
|
||||
float alignToNormal = 1,
|
||||
float minScale = 0.8f,
|
||||
float maxScale = 1.25f,
|
||||
float windBending = 1,
|
||||
float hullSplitU = -1,
|
||||
char allowedNormal = 116)
|
||||
{
|
||||
_url = url;
|
||||
_alignToNormal = alignToNormal;
|
||||
_minScale = minScale;
|
||||
_maxScale = maxScale;
|
||||
_windBending = windBending;
|
||||
_hullSplitU = hullSplitU;
|
||||
_allowedNormal = allowedNormal;
|
||||
}
|
||||
};
|
||||
|
@ -225,6 +246,7 @@ namespace verus
|
|||
void ResetInstanceCount();
|
||||
void Update();
|
||||
void Layout(bool reflection = false);
|
||||
void SortVisible();
|
||||
void Draw(bool allowTess = true);
|
||||
VERUS_P(void DrawModels(bool allowTess));
|
||||
VERUS_P(void DrawSprites());
|
||||
|
|
|
@ -207,21 +207,19 @@ void Grass::Layout()
|
|||
{
|
||||
VERUS_QREF_WM;
|
||||
|
||||
// <Traverse>
|
||||
_visiblePatchCount = 0;
|
||||
|
||||
const float zFar = wm.GetPassCamera()->GetZFar();
|
||||
wm.GetPassCamera()->SetZFar(128);
|
||||
wm.GetPassCamera()->UpdateZNearFar();
|
||||
|
||||
// Reuse terrain's quadtree:
|
||||
Math::RQuadtreeIntegral quadtree = _pTerrain->GetQuadtree();
|
||||
_visiblePatchCount = 0;
|
||||
quadtree.SetDelegate(this);
|
||||
quadtree.TraverseVisible();
|
||||
quadtree.SetDelegate(_pTerrain);
|
||||
|
||||
wm.GetPassCamera()->SetZFar(zFar);
|
||||
wm.GetPassCamera()->UpdateZNearFar();
|
||||
// </Traverse>
|
||||
}
|
||||
|
||||
void Grass::Draw()
|
||||
|
@ -251,7 +249,7 @@ void Grass::Draw()
|
|||
s_ubGrassVS._headPos = float4(wm.GetHeadCamera()->GetEyePosition().GLM(), 0);
|
||||
s_ubGrassVS._viewportSize = cb->GetViewportSize().GLM();
|
||||
s_ubGrassVS._warp_turb = Vector4(_warpSpring.GetOffset(), _turbulence).GLM();
|
||||
s_ubGrassVS._spriteMat = wm.GetPassCamera()->GetMatrixV().ToSpriteMat();
|
||||
s_ubGrassVS._matRoll = wm.GetPassCamera()->GetMatrixV().ToSpriteRollMatrix();
|
||||
|
||||
cb->BindVertexBuffers(_geo);
|
||||
cb->BindIndexBuffer(_geo);
|
||||
|
|
|
@ -167,7 +167,7 @@ void LightMapBaker::Init(RcDesc desc)
|
|||
{
|
||||
tex->GetClearValue(),
|
||||
_tex[TEX_DEPTH]->GetClearValue()
|
||||
});
|
||||
}, CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
tex->GenerateMips();
|
||||
}
|
||||
|
@ -179,19 +179,22 @@ void LightMapBaker::Init(RcDesc desc)
|
|||
|
||||
void LightMapBaker::Done()
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
if (renderer.GetShaderQuad())
|
||||
if (CGI::Renderer::IsLoaded())
|
||||
{
|
||||
VERUS_QREF_RENDERER;
|
||||
if (renderer.GetShaderQuad())
|
||||
{
|
||||
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_cshQuad[ringBufferIndex]);
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_cshHemicubeMask);
|
||||
}
|
||||
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_cshQuad[ringBufferIndex]);
|
||||
renderer.GetShaderQuad()->FreeDescriptorSet(_cshHemicubeMask);
|
||||
{
|
||||
VERUS_FOR(batchIndex, s_batchSize)
|
||||
renderer->DeleteFramebuffer(_fbh[ringBufferIndex][batchIndex]);
|
||||
}
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
}
|
||||
VERUS_FOR(ringBufferIndex, CGI::BaseRenderer::s_ringBufferSize)
|
||||
{
|
||||
VERUS_FOR(batchIndex, s_batchSize)
|
||||
renderer->DeleteFramebuffer(_fbh[ringBufferIndex][batchIndex]);
|
||||
}
|
||||
renderer->DeleteRenderPass(_rph);
|
||||
VERUS_DONE(LightMapBaker);
|
||||
}
|
||||
|
||||
|
@ -358,7 +361,7 @@ void LightMapBaker::DrawEmpty()
|
|||
{
|
||||
tex->GetClearValue(),
|
||||
_tex[TEX_DEPTH]->GetClearValue()
|
||||
});
|
||||
}, CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
|
||||
DrawHemicubeMask();
|
||||
|
||||
|
@ -404,7 +407,7 @@ void LightMapBaker::DrawLumel(RcPoint3 pos, RcVector3 nrm, int batchIndex)
|
|||
{
|
||||
tex->GetClearValue(),
|
||||
_tex[TEX_DEPTH]->GetClearValue()
|
||||
});
|
||||
}, CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
if (_pDelegate)
|
||||
{
|
||||
const glm::vec2 randVec = glm::circularRand(1.f);
|
||||
|
@ -420,7 +423,7 @@ void LightMapBaker::DrawLumel(RcPoint3 pos, RcVector3 nrm, int batchIndex)
|
|||
{
|
||||
const CGI::CubeMapFace cubeMapFace = static_cast<CGI::CubeMapFace>(i);
|
||||
|
||||
Camera cam;
|
||||
MainCamera cam;
|
||||
cam.MoveEyeTo(drawLumelDesc._eyePos);
|
||||
switch (cubeMapFace)
|
||||
{
|
||||
|
@ -450,12 +453,14 @@ void LightMapBaker::DrawLumel(RcPoint3 pos, RcVector3 nrm, int batchIndex)
|
|||
cam.SetZNear(0.00001f);
|
||||
cam.SetZFar(_desc._distance);
|
||||
cam.Update();
|
||||
PCamera pPrevCamera = wm.SetPassCamera(&cam);
|
||||
auto pPrevPassCamera = wm.SetPassCamera(&cam);
|
||||
auto pPrevHeadCamera = wm.SetHeadCamera(&cam);
|
||||
|
||||
drawLumelDesc._frontDir = cam.GetFrontDirection();
|
||||
_pDelegate->LightMapBaker_Draw(cubeMapFace, drawLumelDesc);
|
||||
|
||||
wm.SetPassCamera(pPrevCamera);
|
||||
wm.SetPassCamera(pPrevPassCamera);
|
||||
wm.SetHeadCamera(pPrevHeadCamera);
|
||||
}
|
||||
_pDelegate->LightMapBaker_Draw(CGI::CubeMapFace::negZ, drawLumelDesc);
|
||||
|
||||
|
|
|
@ -80,11 +80,21 @@ void Mesh::Init(RcDesc desc)
|
|||
}
|
||||
|
||||
_instanceCapacity = desc._instanceCapacity;
|
||||
_instanceBufferFormat = desc._instanceBufferFormat;
|
||||
_initShape = desc._initShape;
|
||||
|
||||
BaseMesh::Init(desc._url);
|
||||
}
|
||||
|
||||
void Mesh::Init(RcSourceBuffers sourceBuffers, RcDesc desc)
|
||||
{
|
||||
_instanceCapacity = desc._instanceCapacity;
|
||||
_instanceBufferFormat = desc._instanceBufferFormat;
|
||||
_initShape = desc._initShape;
|
||||
|
||||
BaseMesh::Init(sourceBuffers);
|
||||
}
|
||||
|
||||
void Mesh::Done()
|
||||
{
|
||||
VERUS_DONE(Mesh);
|
||||
|
@ -505,7 +515,7 @@ void Mesh::UpdateUniformBufferSimplePerFrame(DrawSimpleMode mode)
|
|||
s_ubSimplePerFrame._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrix(2).UniformBufferFormat();
|
||||
s_ubSimplePerFrame._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrix(3).UniformBufferFormat();
|
||||
s_ubSimplePerFrame._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixVP().UniformBufferFormat();
|
||||
s_ubSimplePerFrame._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubSimplePerFrame._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubSimplePerFrame._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubSimplePerFrame._shadowConfig));
|
||||
}
|
||||
|
||||
|
@ -520,26 +530,29 @@ void Mesh::CreateDeviceBuffers()
|
|||
|
||||
CGI::GeometryDesc geoDesc;
|
||||
geoDesc._name = _C(_url);
|
||||
const CGI::VertexInputAttrDesc viaDesc[] =
|
||||
Vector<CGI::VertexInputAttrDesc> vViaDesc;
|
||||
{
|
||||
{0, offsetof(VertexInputBinding0, _pos), CGI::ViaType::shorts, 4, CGI::ViaUsage::position, 0},
|
||||
{0, offsetof(VertexInputBinding0, _tc0), CGI::ViaType::shorts, 2, CGI::ViaUsage::texCoord, 0},
|
||||
{0, offsetof(VertexInputBinding0, _nrm), CGI::ViaType::ubytes, 4, CGI::ViaUsage::normal, 0},
|
||||
{1, offsetof(VertexInputBinding1, _bw), CGI::ViaType::shorts, 4, CGI::ViaUsage::blendWeights, 0},
|
||||
{1, offsetof(VertexInputBinding1, _bi), CGI::ViaType::shorts, 4, CGI::ViaUsage::blendIndices, 0},
|
||||
{2, offsetof(VertexInputBinding2, _tan), CGI::ViaType::shorts, 4, CGI::ViaUsage::tangent, 0},
|
||||
{2, offsetof(VertexInputBinding2, _bin), CGI::ViaType::shorts, 4, CGI::ViaUsage::binormal, 0},
|
||||
{3, offsetof(VertexInputBinding3, _tc1), CGI::ViaType::shorts, 2, CGI::ViaUsage::texCoord, 1},
|
||||
{3, offsetof(VertexInputBinding3, _clr), CGI::ViaType::ubytes, 4, CGI::ViaUsage::color, 0},
|
||||
|
||||
{-4, offsetof(PerInstanceData, _matPart0), CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 0},
|
||||
{-4, offsetof(PerInstanceData, _matPart1), CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 1},
|
||||
{-4, offsetof(PerInstanceData, _matPart2), CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 2},
|
||||
{-4, offsetof(PerInstanceData, _instData), CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 3},
|
||||
CGI::VertexInputAttrDesc::End()
|
||||
};
|
||||
geoDesc._pVertexInputAttrDesc = viaDesc;
|
||||
const int strides[] = { sizeof(VertexInputBinding0), sizeof(VertexInputBinding1), sizeof(VertexInputBinding2), sizeof(VertexInputBinding3), sizeof(PerInstanceData), 0 };
|
||||
vViaDesc.reserve(16);
|
||||
vViaDesc.push_back({ 0, offsetof(VertexInputBinding0, _pos), CGI::ViaType::shorts, 4, CGI::ViaUsage::position, 0 });
|
||||
vViaDesc.push_back({ 0, offsetof(VertexInputBinding0, _tc0), CGI::ViaType::shorts, 2, CGI::ViaUsage::texCoord, 0 });
|
||||
vViaDesc.push_back({ 0, offsetof(VertexInputBinding0, _nrm), CGI::ViaType::ubytes, 4, CGI::ViaUsage::normal, 0 });
|
||||
vViaDesc.push_back({ 1, offsetof(VertexInputBinding1, _bw), CGI::ViaType::shorts, 4, CGI::ViaUsage::blendWeights, 0 });
|
||||
vViaDesc.push_back({ 1, offsetof(VertexInputBinding1, _bi), CGI::ViaType::shorts, 4, CGI::ViaUsage::blendIndices, 0 });
|
||||
vViaDesc.push_back({ 2, offsetof(VertexInputBinding2, _tan), CGI::ViaType::shorts, 4, CGI::ViaUsage::tangent, 0 });
|
||||
vViaDesc.push_back({ 2, offsetof(VertexInputBinding2, _bin), CGI::ViaType::shorts, 4, CGI::ViaUsage::binormal, 0 });
|
||||
vViaDesc.push_back({ 3, offsetof(VertexInputBinding3, _tc1), CGI::ViaType::shorts, 2, CGI::ViaUsage::texCoord, 1 });
|
||||
vViaDesc.push_back({ 3, offsetof(VertexInputBinding3, _clr), CGI::ViaType::ubytes, 4, CGI::ViaUsage::color, 0 });
|
||||
vViaDesc.push_back({ 3, offsetof(VertexInputBinding3, _clr), CGI::ViaType::ubytes, 4, CGI::ViaUsage::color, 0 });
|
||||
vViaDesc.push_back({ -4, 0, CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 0 });
|
||||
vViaDesc.push_back({ -4, 16, CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 1 });
|
||||
vViaDesc.push_back({ -4, 32, CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 2 });
|
||||
vViaDesc.push_back({ -4, 48, CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 3 });
|
||||
if (InstanceBufferFormat::mataff_2float4 == _instanceBufferFormat)
|
||||
vViaDesc.push_back({ -4, 64, CGI::ViaType::floats, 4, CGI::ViaUsage::instData, 4 });
|
||||
vViaDesc.push_back(CGI::VertexInputAttrDesc::End());
|
||||
}
|
||||
geoDesc._pVertexInputAttrDesc = vViaDesc.data();
|
||||
const int strides[] = { sizeof(VertexInputBinding0), sizeof(VertexInputBinding1), sizeof(VertexInputBinding2), sizeof(VertexInputBinding3), GetInstanceSize(), 0 };
|
||||
geoDesc._pStrides = strides;
|
||||
geoDesc._32BitIndices = _vIndices.empty();
|
||||
_geo.Init(geoDesc);
|
||||
|
@ -588,9 +601,9 @@ void Mesh::CreateDeviceBuffers()
|
|||
// Instance buffer:
|
||||
if (_instanceCapacity > 0)
|
||||
{
|
||||
_vInstanceBuffer.resize(_instanceCapacity);
|
||||
_vInstanceBuffer.resize(_instanceCapacity * GetInstanceSize());
|
||||
_bindingsMask |= (1 << 4);
|
||||
_geo->CreateVertexBuffer(Utils::Cast32(_vInstanceBuffer.size()), 4);
|
||||
_geo->CreateVertexBuffer(_instanceCapacity, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -605,15 +618,30 @@ void Mesh::ResetInstanceCount()
|
|||
_firstInstance = 0;
|
||||
}
|
||||
|
||||
void Mesh::PushInstance(RcTransform3 matW, RcVector4 instData)
|
||||
void Mesh::PushInstance(RcTransform3 matW, RcVector4 instData, PcVector4 pInstData1)
|
||||
{
|
||||
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||
if (!_vertCount)
|
||||
return;
|
||||
if (IsInstanceBufferFull())
|
||||
return;
|
||||
matW.InstFormat(&_vInstanceBuffer[_instanceCount]._matPart0);
|
||||
_vInstanceBuffer[_instanceCount]._instData = instData;
|
||||
const int offset = _instanceCount * GetInstanceSize();
|
||||
switch (_instanceBufferFormat)
|
||||
{
|
||||
case InstanceBufferFormat::mataff_float4:
|
||||
{
|
||||
matW.InstFormat(reinterpret_cast<PVector4>(&_vInstanceBuffer[offset]));
|
||||
*reinterpret_cast<PVector4>(&_vInstanceBuffer[offset] + 48) = instData;
|
||||
}
|
||||
break;
|
||||
case InstanceBufferFormat::mataff_2float4:
|
||||
{
|
||||
matW.InstFormat(reinterpret_cast<PVector4>(&_vInstanceBuffer[offset]));
|
||||
*reinterpret_cast<PVector4>(&_vInstanceBuffer[offset] + 48) = instData;
|
||||
*reinterpret_cast<PVector4>(&_vInstanceBuffer[offset] + 64) = *pInstData1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
_instanceCount++;
|
||||
}
|
||||
|
||||
|
@ -633,8 +661,19 @@ bool Mesh::IsInstanceBufferEmpty(bool fromFirstInstance)
|
|||
return GetInstanceCount(fromFirstInstance) <= 0;
|
||||
}
|
||||
|
||||
int Mesh::GetInstanceSize() const
|
||||
{
|
||||
switch (_instanceBufferFormat)
|
||||
{
|
||||
case InstanceBufferFormat::mataff_float4: return 64;
|
||||
case InstanceBufferFormat::mataff_2float4: return 80;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Mesh::UpdateInstanceBuffer()
|
||||
{
|
||||
VERUS_RT_ASSERT(!_vInstanceBuffer.empty());
|
||||
_geo->UpdateVertexBuffer(&_vInstanceBuffer[_firstInstance], 4, nullptr, GetInstanceCount(true), _firstInstance);
|
||||
const int offset = _firstInstance * GetInstanceSize();
|
||||
_geo->UpdateVertexBuffer(&_vInstanceBuffer[offset], 4, nullptr, GetInstanceCount(true), _firstInstance);
|
||||
}
|
||||
|
|
|
@ -69,12 +69,10 @@ namespace verus
|
|||
PIPE_COUNT
|
||||
};
|
||||
|
||||
struct PerInstanceData
|
||||
enum class InstanceBufferFormat : int
|
||||
{
|
||||
Vector4 _matPart0 = Vector4(0);
|
||||
Vector4 _matPart1 = Vector4(0);
|
||||
Vector4 _matPart2 = Vector4(0);
|
||||
Vector4 _instData = Vector4(0);
|
||||
mataff_float4,
|
||||
mataff_2float4
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -91,20 +89,22 @@ namespace verus
|
|||
static UB_SimpleSkeletonVS s_ubSimpleSkeletonVS;
|
||||
static UB_SimplePerObject s_ubSimplePerObject;
|
||||
|
||||
CGI::GeometryPwn _geo;
|
||||
Vector<PerInstanceData> _vInstanceBuffer;
|
||||
int _instanceCapacity = 0;
|
||||
int _instanceCount = 0;
|
||||
int _firstInstance = 0;
|
||||
UINT32 _bindingsMask = 0;
|
||||
CGI::GeometryPwn _geo;
|
||||
Vector<BYTE> _vInstanceBuffer;
|
||||
int _instanceCapacity = 0;
|
||||
int _instanceCount = 0;
|
||||
int _firstInstance = 0;
|
||||
InstanceBufferFormat _instanceBufferFormat = InstanceBufferFormat::mataff_float4;
|
||||
UINT32 _bindingsMask = 0;
|
||||
|
||||
public:
|
||||
struct Desc
|
||||
{
|
||||
CSZ _url = nullptr;
|
||||
CSZ _warpURL = nullptr;
|
||||
int _instanceCapacity = 0;
|
||||
bool _initShape = false;
|
||||
CSZ _url = nullptr;
|
||||
CSZ _warpURL = nullptr;
|
||||
int _instanceCapacity = 0;
|
||||
InstanceBufferFormat _instanceBufferFormat = InstanceBufferFormat::mataff_float4;
|
||||
bool _initShape = false;
|
||||
|
||||
Desc(CSZ url = nullptr) : _url(url) {}
|
||||
};
|
||||
|
@ -131,6 +131,7 @@ namespace verus
|
|||
static void DoneStatic();
|
||||
|
||||
void Init(RcDesc desc = Desc());
|
||||
void Init(RcSourceBuffers sourceBuffers, RcDesc desc = Desc());
|
||||
void Done();
|
||||
|
||||
void Draw(RcDrawDesc drawDesc, CGI::CommandBufferPtr cb);
|
||||
|
@ -160,9 +161,10 @@ namespace verus
|
|||
// Instancing:
|
||||
void ResetInstanceCount();
|
||||
void MarkFirstInstance() { _firstInstance = _instanceCount; }
|
||||
void PushInstance(RcTransform3 matW, RcVector4 instData);
|
||||
void PushInstance(RcTransform3 matW, RcVector4 instData, PcVector4 pInstData1 = nullptr);
|
||||
bool IsInstanceBufferFull();
|
||||
bool IsInstanceBufferEmpty(bool fromFirstInstance = false);
|
||||
int GetInstanceSize() const;
|
||||
|
||||
void UpdateInstanceBuffer();
|
||||
int GetInstanceCount(bool fromFirstInstance = false) const { return fromFirstInstance ? _instanceCount - _firstInstance : _instanceCount; }
|
||||
|
|
|
@ -57,6 +57,10 @@ void ShadowMapBaker::Begin(RcVector3 dirToSun, RcVector3 up)
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 96, 96, 255), "ShadowMapBaker");
|
||||
|
||||
Point3 eye, at;
|
||||
const float texSizeInMeters = 100;
|
||||
const float depth = texSizeInMeters * 10;
|
||||
|
@ -75,7 +79,6 @@ void ShadowMapBaker::Begin(RcVector3 dirToSun, RcVector3 up)
|
|||
at = (matFromLightSpace * snappedPos).getXYZ();
|
||||
}
|
||||
|
||||
// Setup light space camera and use it (used for terrain draw, etc.):
|
||||
eye = at + dirToSun * (depth * (2 / 3.f));
|
||||
const float zNear = 1;
|
||||
const float zFar = zNear + depth;
|
||||
|
@ -92,7 +95,7 @@ void ShadowMapBaker::Begin(RcVector3 dirToSun, RcVector3 up)
|
|||
|
||||
_config._unormDepthScale = depth;
|
||||
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh, { _tex->GetClearValue() },
|
||||
cb->BeginRenderPass(_rph, _fbh, { _tex->GetClearValue() },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
|
||||
VERUS_RT_ASSERT(!_baking);
|
||||
|
@ -104,7 +107,11 @@ void ShadowMapBaker::End()
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
cb->EndRenderPass();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
const Matrix4 m = Math::ToUVMatrix();
|
||||
_matShadow = m * _passCamera.GetMatrixVP();
|
||||
|
@ -161,8 +168,12 @@ void CascadedShadowMapBaker::Init(int side)
|
|||
VERUS_QREF_RENDERER;
|
||||
|
||||
_side = side;
|
||||
_headCameraPreferredRange = 300;
|
||||
if (settings._sceneShadowQuality >= App::Settings::Quality::ultra)
|
||||
{
|
||||
_side *= 2;
|
||||
_headCameraPreferredRange = 1000;
|
||||
}
|
||||
|
||||
_rph = renderer->CreateShadowRenderPass(CGI::Format::unormD24uintS8);
|
||||
|
||||
|
@ -205,7 +216,7 @@ void CascadedShadowMapBaker::UpdateMatrixForCurrentView()
|
|||
_matShadowCSM_DS[i] = _matShadowCSM[i] * wm.GetViewCamera()->GetMatrixInvV();
|
||||
}
|
||||
|
||||
void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
||||
void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int slice, RcVector3 up)
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneShadowQuality < App::Settings::Quality::high)
|
||||
|
@ -214,14 +225,29 @@ void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
|||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
_currentSplit = split;
|
||||
_currentSlice = slice;
|
||||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
switch (_currentSlice)
|
||||
{
|
||||
case 0: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(48, 48, 48, 255), "CascadedShadowMapBaker/0"); break;
|
||||
case 1: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(64, 64, 64, 255), "CascadedShadowMapBaker/1"); break;
|
||||
case 2: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(80, 80, 80, 255), "CascadedShadowMapBaker/2"); break;
|
||||
case 3: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 96, 96, 255), "CascadedShadowMapBaker/3"); break;
|
||||
default: VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 96, 96, 255), "CascadedShadowMapBaker"); break;
|
||||
}
|
||||
|
||||
RcCamera headCamera = *wm.GetHeadCamera();
|
||||
_passCamera = headCamera;
|
||||
|
||||
Point3 eye, at;
|
||||
float texWidthInMeters, texHeightInMeters, texSizeInMeters;
|
||||
float zNear, zFar;
|
||||
|
||||
const Matrix4 matToLightSpace = Matrix4::lookAt(Point3(0), Point3(-dirToSun), up);
|
||||
const float headCameraRange = Math::Min<float>(_headCameraPreferredRange, headCamera.GetZFar() - headCamera.GetZNear());
|
||||
|
||||
auto ComputeTextureSize = [&texWidthInMeters, &texHeightInMeters, &texSizeInMeters](Math::RcBounds bounds)
|
||||
{
|
||||
// Stabilize size:
|
||||
|
@ -231,50 +257,26 @@ void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
|||
texSizeInMeters = Math::Max(texWidthInMeters, texHeightInMeters);
|
||||
};
|
||||
|
||||
const Matrix4 matToLightSpace = Matrix4::lookAt(Point3(0), Point3(-dirToSun), up);
|
||||
const float headCameraMaxRange = (settings._sceneShadowQuality >= App::Settings::Quality::ultra) ? 1000.f : 300.f;
|
||||
const float headCameraRange = Math::Min<float>(headCameraMaxRange, headCamera.GetZFar() - headCamera.GetZNear()); // Clip terrain, etc.
|
||||
_passCamera = headCamera;
|
||||
|
||||
auto PrepareCameraArguments = [this, &eye, &at, &zNear, &zFar, &dirToSun, &matToLightSpace](RcPoint3 centerPosLS)
|
||||
auto PrepareCameraArguments = [this, &eye, &at, &zNear, &zFar, &dirToSun, &matToLightSpace](RcPoint3 centerPosLS, float atOffset)
|
||||
{
|
||||
at = (VMath::orthoInverse(matToLightSpace) * centerPosLS).getXYZ();
|
||||
eye = at + dirToSun * (_depth * (2 / 3.f));
|
||||
at = (VMath::orthoInverse(matToLightSpace) * centerPosLS).getXYZ() + dirToSun * atOffset;
|
||||
eye = at + dirToSun * _depth;
|
||||
zNear = 1;
|
||||
zFar = zNear + _depth;
|
||||
};
|
||||
|
||||
if (0 == _currentSplit)
|
||||
if (0 == _currentSlice)
|
||||
{
|
||||
_matScreenVP = _passCamera.GetMatrixVP();
|
||||
_matScreenP = _passCamera.GetMatrixP();
|
||||
|
||||
_depth = Math::Min(headCameraRange * 10, 10000.f); // 10 times larger than side.
|
||||
|
||||
_passCamera.SetZFar(_passCamera.GetZNear() + headCameraRange);
|
||||
_passCamera.Update(); // Prepare frustum for measurements.
|
||||
|
||||
Point3 focusedCenterPos; // With stable Z.
|
||||
const Math::Bounds frustumBoundsLS = _passCamera.GetFrustum().GetBounds(matToLightSpace, &focusedCenterPos);
|
||||
ComputeTextureSize(frustumBoundsLS);
|
||||
|
||||
// Setup CSM light space camera for full range (used for terrain layout, etc.):
|
||||
PrepareCameraArguments(focusedCenterPos);
|
||||
_passCameraCSM.MoveEyeTo(eye);
|
||||
_passCameraCSM.MoveAtTo(at);
|
||||
_passCameraCSM.SetUpDirection(up);
|
||||
_passCameraCSM.SetYFov(0);
|
||||
_passCameraCSM.SetZNear(zNear);
|
||||
_passCameraCSM.SetZFar(zFar);
|
||||
_passCameraCSM.SetXMag(texSizeInMeters);
|
||||
_passCameraCSM.SetYMag(texSizeInMeters);
|
||||
_passCameraCSM.Update();
|
||||
_depth = Math::Min(headCameraRange * 2, 2000.f);
|
||||
}
|
||||
|
||||
if (settings._sceneShadowQuality >= App::Settings::Quality::ultra) // Adjusted for 7x7 PCF.
|
||||
{
|
||||
// Compute split ranges (weights are 2, 4.5, 12, 39):
|
||||
_splitRanges = Vector4(
|
||||
// Compute slice bounds (weights are 2, 4.5, 12, 39):
|
||||
_sliceBounds = Vector4(
|
||||
headCamera.GetZNear() + headCameraRange * (18.5f / 57.5f),
|
||||
headCamera.GetZNear() + headCameraRange * (6.5f / 57.5f),
|
||||
headCamera.GetZNear() + headCameraRange * (2 / 57.5f),
|
||||
|
@ -282,40 +284,41 @@ void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
|||
}
|
||||
else // Adjusted for 5x5 PCF.
|
||||
{
|
||||
// Compute split ranges (weights are 2, 3, 6, 15):
|
||||
_splitRanges = Vector4(
|
||||
// Compute slice bounds (weights are 2, 3, 6, 15):
|
||||
_sliceBounds = Vector4(
|
||||
headCamera.GetZNear() + headCameraRange * (10 / 26.f),
|
||||
headCamera.GetZNear() + headCameraRange * (5 / 26.f),
|
||||
headCamera.GetZNear() + headCameraRange * (2 / 26.f),
|
||||
headCamera.GetZNear());
|
||||
}
|
||||
|
||||
// Default scene camera with the current split range:
|
||||
switch (_currentSplit)
|
||||
// Default world camera with current slice bounds:
|
||||
switch (_currentSlice)
|
||||
{
|
||||
case 0:
|
||||
_passCamera.SetZNear(_splitRanges.getX());
|
||||
_passCamera.SetZNear(_sliceBounds.getX());
|
||||
_passCamera.SetZFar(headCamera.GetZNear() + headCameraRange);
|
||||
break;
|
||||
case 1:
|
||||
_passCamera.SetZNear(_splitRanges.getY());
|
||||
_passCamera.SetZFar(_splitRanges.getX());
|
||||
_passCamera.SetZNear(_sliceBounds.getY());
|
||||
_passCamera.SetZFar(_sliceBounds.getX());
|
||||
break;
|
||||
case 2:
|
||||
_passCamera.SetZNear(_splitRanges.getZ());
|
||||
_passCamera.SetZFar(_splitRanges.getY());
|
||||
_passCamera.SetZNear(_sliceBounds.getZ());
|
||||
_passCamera.SetZFar(_sliceBounds.getY());
|
||||
break;
|
||||
case 3:
|
||||
_passCamera.SetZNear(_splitRanges.getW());
|
||||
_passCamera.SetZFar(_splitRanges.getZ());
|
||||
_passCamera.SetZNear(_sliceBounds.getW());
|
||||
_passCamera.SetZFar(_sliceBounds.getZ());
|
||||
break;
|
||||
}
|
||||
_splitRanges.setW(headCamera.GetZNear() + headCameraRange);
|
||||
_sliceBounds.setW(headCamera.GetZNear() + headCameraRange);
|
||||
_passCamera.Update(); // Prepare frustum for measurements.
|
||||
|
||||
Point3 focusedCenterPos; // With stable Z.
|
||||
const Math::Bounds frustumBoundsLS = _passCamera.GetFrustum().GetBounds(matToLightSpace, &focusedCenterPos);
|
||||
ComputeTextureSize(frustumBoundsLS);
|
||||
const float atOffset = frustumBoundsLS.GetMin().getZ() - focusedCenterPos.getZ();
|
||||
|
||||
if (_snapToTexels)
|
||||
{
|
||||
|
@ -328,8 +331,7 @@ void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
|||
focusedCenterPos.setY(focusedCenterPos.getY() - fmod(snappedPos.getY() + texelSizeInMeters * 0.5f, texelSizeInMeters));
|
||||
}
|
||||
|
||||
// Setup light space camera and use it (used for terrain draw, etc.):
|
||||
PrepareCameraArguments(focusedCenterPos);
|
||||
PrepareCameraArguments(focusedCenterPos, atOffset);
|
||||
_passCamera.MoveEyeTo(eye);
|
||||
_passCamera.MoveAtTo(at);
|
||||
_passCamera.SetUpDirection(up);
|
||||
|
@ -343,26 +345,26 @@ void CascadedShadowMapBaker::Begin(RcVector3 dirToSun, int split, RcVector3 up)
|
|||
|
||||
_config._unormDepthScale = zFar - zNear;
|
||||
|
||||
if (0 == _currentSplit)
|
||||
if (0 == _currentSlice)
|
||||
{
|
||||
renderer.GetCommandBuffer()->BeginRenderPass(_rph, _fbh, { _tex->GetClearValue() },
|
||||
cb->BeginRenderPass(_rph, _fbh, { _tex->GetClearValue() },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
}
|
||||
|
||||
const float s = static_cast<float>(_side / 2);
|
||||
switch (_currentSplit)
|
||||
switch (_currentSlice)
|
||||
{
|
||||
case 0: renderer.GetCommandBuffer()->SetViewport({ Vector4(0, 0, s, s) }); break;
|
||||
case 1: renderer.GetCommandBuffer()->SetViewport({ Vector4(s, 0, s, s) }); break;
|
||||
case 2: renderer.GetCommandBuffer()->SetViewport({ Vector4(0, s, s, s) }); break;
|
||||
case 3: renderer.GetCommandBuffer()->SetViewport({ Vector4(s, s, s, s) }); break;
|
||||
case 0: cb->SetViewport({ Vector4(0, 0, s, s) }); break;
|
||||
case 1: cb->SetViewport({ Vector4(s, 0, s, s) }); break;
|
||||
case 2: cb->SetViewport({ Vector4(0, s, s, s) }); break;
|
||||
case 3: cb->SetViewport({ Vector4(s, s, s, s) }); break;
|
||||
}
|
||||
|
||||
VERUS_RT_ASSERT(!_baking);
|
||||
_baking = true;
|
||||
}
|
||||
|
||||
void CascadedShadowMapBaker::End(int split)
|
||||
void CascadedShadowMapBaker::End(int slice)
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneShadowQuality < App::Settings::Quality::high)
|
||||
|
@ -370,44 +372,40 @@ void CascadedShadowMapBaker::End(int split)
|
|||
|
||||
VERUS_QREF_RENDERER;
|
||||
VERUS_QREF_WM;
|
||||
VERUS_RT_ASSERT(_currentSplit == split);
|
||||
VERUS_RT_ASSERT(_currentSlice == slice);
|
||||
|
||||
if (3 == _currentSplit)
|
||||
renderer.GetCommandBuffer()->EndRenderPass();
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
if (3 == _currentSlice)
|
||||
cb->EndRenderPass();
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
|
||||
const Matrix4 m = Math::ToUVMatrix();
|
||||
_matShadowCSM[_currentSplit] = _matOffset[_currentSplit] * m * _passCamera.GetMatrixVP();
|
||||
_matShadowCSM[_currentSlice] = _matOffset[_currentSlice] * m * _passCamera.GetMatrixVP();
|
||||
|
||||
_pPrevPassCamera = wm.SetPassCamera(_pPrevPassCamera);
|
||||
VERUS_RT_ASSERT(&_passCamera == _pPrevPassCamera); // Check camera's integrity.
|
||||
_pPrevPassCamera = nullptr;
|
||||
|
||||
_currentSplit = -1;
|
||||
_currentSlice = -1;
|
||||
|
||||
VERUS_RT_ASSERT(_baking);
|
||||
_baking = false;
|
||||
}
|
||||
|
||||
RcMatrix4 CascadedShadowMapBaker::GetShadowMatrix(int split) const
|
||||
RcMatrix4 CascadedShadowMapBaker::GetShadowMatrix(int slice) const
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneShadowQuality < App::Settings::Quality::high)
|
||||
return ShadowMapBaker::GetShadowMatrix();
|
||||
return _matShadowCSM[split];
|
||||
return _matShadowCSM[slice];
|
||||
}
|
||||
|
||||
RcMatrix4 CascadedShadowMapBaker::GetShadowMatrixDS(int split) const
|
||||
RcMatrix4 CascadedShadowMapBaker::GetShadowMatrixDS(int slice) const
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneShadowQuality < App::Settings::Quality::high)
|
||||
return ShadowMapBaker::GetShadowMatrixDS();
|
||||
return _matShadowCSM_DS[split];
|
||||
}
|
||||
|
||||
PCamera CascadedShadowMapBaker::GetPassCameraCSM()
|
||||
{
|
||||
VERUS_QREF_CONST_SETTINGS;
|
||||
if (settings._sceneShadowQuality < App::Settings::Quality::high)
|
||||
return nullptr;
|
||||
return &_passCameraCSM;
|
||||
return _matShadowCSM_DS[slice];
|
||||
}
|
||||
|
|
|
@ -63,10 +63,10 @@ namespace verus
|
|||
Matrix4 _matOffset[4];
|
||||
Matrix4 _matScreenVP = Matrix4::identity();
|
||||
Matrix4 _matScreenP = Matrix4::identity();
|
||||
Vector4 _splitRanges = Vector4(0);
|
||||
Camera _passCameraCSM;
|
||||
int _currentSplit = -1;
|
||||
Vector4 _sliceBounds = Vector4(0);
|
||||
int _currentSlice = -1;
|
||||
float _depth = 0;
|
||||
float _headCameraPreferredRange = 0;
|
||||
|
||||
public:
|
||||
CascadedShadowMapBaker();
|
||||
|
@ -77,19 +77,17 @@ namespace verus
|
|||
|
||||
void UpdateMatrixForCurrentView();
|
||||
|
||||
void Begin(RcVector3 dirToSun, int split, RcVector3 up = Vector3(0, 1, 0));
|
||||
void End(int split);
|
||||
void Begin(RcVector3 dirToSun, int slice, RcVector3 up = Vector3(0, 1, 0));
|
||||
void End(int slice);
|
||||
|
||||
RcMatrix4 GetShadowMatrix(int split = 0) const;
|
||||
RcMatrix4 GetShadowMatrixDS(int split = 0) const;
|
||||
RcMatrix4 GetShadowMatrix(int slice = 0) const;
|
||||
RcMatrix4 GetShadowMatrixDS(int slice = 0) const;
|
||||
|
||||
RcMatrix4 GetScreenMatrixVP() const { return _matScreenVP; }
|
||||
RcMatrix4 GetScreenMatrixP() const { return _matScreenP; }
|
||||
|
||||
int GetCurrentSplit() const { return _currentSplit; }
|
||||
RcVector4 GetSplitRanges() const { return _splitRanges; }
|
||||
|
||||
PCamera GetPassCameraCSM();
|
||||
int GetCurrentSlice() const { return _currentSlice; }
|
||||
RcVector4 GetSliceBounds() const { return _sliceBounds; }
|
||||
};
|
||||
VERUS_TYPEDEFS(CascadedShadowMapBaker);
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ void TerrainPhysics::Init(Physics::PUserPtr p, int w, int h, const void* pData,
|
|||
btTransform tr;
|
||||
tr.setIdentity();
|
||||
tr.setOrigin(btVector3(-0.5f, 0, -0.5f));
|
||||
_pRigidBody = bullet.AddNewRigidBody(_pRigidBody, 0, tr, _pShape.Get(), +Physics::Group::terrain);
|
||||
_pRigidBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::wood));
|
||||
_pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::wood));
|
||||
_pRigidBody = bullet.AddNewRigidBody(_pRigidBody, 0, tr, _pShape.Get(), +Physics::Group::terrain, +bullet.GetNonStaticMask());
|
||||
_pRigidBody->setFriction(Physics::Bullet::GetFriction(Physics::Material::stone));
|
||||
_pRigidBody->setRestitution(Physics::Bullet::GetRestitution(Physics::Material::stone));
|
||||
_pRigidBody->setUserPointer(p);
|
||||
|
||||
EnableDebugDraw(false);
|
||||
|
@ -740,26 +740,30 @@ void Terrain::Layout()
|
|||
VERUS_QREF_CONST_SETTINGS;
|
||||
VERUS_QREF_WM;
|
||||
|
||||
// <Traverse>
|
||||
PCamera pPrevPassCamera = nullptr;
|
||||
// For CSM we need to create geometry beyond the view frustum (1st slice):
|
||||
if (settings._sceneShadowQuality >= App::Settings::Quality::high && atmo.GetShadowMapBaker().IsBaking())
|
||||
{
|
||||
PCamera pPassCameraCSM = atmo.GetShadowMapBaker().GetPassCameraCSM();
|
||||
if (pPassCameraCSM)
|
||||
pPrevPassCamera = wm.SetPassCamera(pPassCameraCSM);
|
||||
}
|
||||
|
||||
_visiblePatchCount = 0;
|
||||
_visibleSortedPatchCount = 0;
|
||||
_visibleRandomPatchCount = 0;
|
||||
_quadtree.TraverseVisible();
|
||||
SortVisiblePatches();
|
||||
|
||||
// Back to original camera:
|
||||
if (pPrevPassCamera)
|
||||
wm.SetPassCamera(pPrevPassCamera);
|
||||
// </Traverse>
|
||||
_quadtree.TraverseVisible();
|
||||
|
||||
SortVisible();
|
||||
}
|
||||
|
||||
void Terrain::SortVisible()
|
||||
{
|
||||
_visiblePatchCount = _visibleSortedPatchCount + _visibleRandomPatchCount;
|
||||
std::sort(_vSortedPatchIndices.begin(), _vSortedPatchIndices.begin() + _visibleSortedPatchCount, [this](int a, int b)
|
||||
{
|
||||
RcTerrainPatch patchA = GetPatch(a);
|
||||
RcTerrainPatch patchB = GetPatch(b);
|
||||
|
||||
if (patchA._quadtreeLOD != patchB._quadtreeLOD)
|
||||
return patchA._quadtreeLOD < patchB._quadtreeLOD;
|
||||
|
||||
return patchA._distToHeadSq < patchB._distToHeadSq;
|
||||
});
|
||||
if (_visibleRandomPatchCount)
|
||||
memcpy(&_vSortedPatchIndices[_visibleSortedPatchCount], _vRandomPatchIndices.data(), _visibleRandomPatchCount * sizeof(UINT16));
|
||||
}
|
||||
|
||||
void Terrain::Draw(RcDrawDesc dd)
|
||||
|
@ -777,6 +781,8 @@ void Terrain::Draw(RcDrawDesc dd)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(160, 255, 96, 255), "Terrain/Draw");
|
||||
|
||||
s_ubTerrainVS._matW = matW.UniformBufferFormat();
|
||||
s_ubTerrainVS._matWV = Transform3(wm.GetPassCamera()->GetMatrixV() * matW).UniformBufferFormat();
|
||||
s_ubTerrainVS._matV = wm.GetPassCamera()->GetMatrixV().UniformBufferFormat();
|
||||
|
@ -873,6 +879,8 @@ void Terrain::Draw(RcDrawDesc dd)
|
|||
|
||||
_geo->UpdateVertexBuffer(&_vInstanceBuffer[_instanceCount], 1, cb.Get(), _visiblePatchCount, _instanceCount);
|
||||
_instanceCount += _visiblePatchCount;
|
||||
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Terrain::DrawSimple(DrawSimpleMode mode)
|
||||
|
@ -890,6 +898,8 @@ void Terrain::DrawSimple(DrawSimpleMode mode)
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(160, 255, 64, 255), "Terrain/DrawSimple");
|
||||
|
||||
s_ubSimpleTerrainVS._matW = matW.UniformBufferFormat();
|
||||
s_ubSimpleTerrainVS._matVP = wm.GetPassCamera()->GetMatrixVP().UniformBufferFormat();
|
||||
s_ubSimpleTerrainVS._headPos = float4(wm.GetHeadCamera()->GetEyePosition().GLM(), 0);
|
||||
|
@ -905,7 +915,7 @@ void Terrain::DrawSimple(DrawSimpleMode mode)
|
|||
s_ubSimpleTerrainFS._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrix(2).UniformBufferFormat();
|
||||
s_ubSimpleTerrainFS._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrix(3).UniformBufferFormat();
|
||||
s_ubSimpleTerrainFS._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixVP().UniformBufferFormat();
|
||||
s_ubSimpleTerrainFS._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubSimpleTerrainFS._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubSimpleTerrainFS._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubSimpleTerrainFS._shadowConfig));
|
||||
|
||||
cb->BindVertexBuffers(_geo);
|
||||
|
@ -973,23 +983,8 @@ void Terrain::DrawSimple(DrawSimpleMode mode)
|
|||
|
||||
_geo->UpdateVertexBuffer(&_vInstanceBuffer[_instanceCount], 1, cb.Get(), _visiblePatchCount, _instanceCount);
|
||||
_instanceCount += _visiblePatchCount;
|
||||
}
|
||||
|
||||
void Terrain::SortVisiblePatches()
|
||||
{
|
||||
_visiblePatchCount = _visibleSortedPatchCount + _visibleRandomPatchCount;
|
||||
std::sort(_vSortedPatchIndices.begin(), _vSortedPatchIndices.begin() + _visibleSortedPatchCount, [this](int a, int b)
|
||||
{
|
||||
RcTerrainPatch patchA = GetPatch(a);
|
||||
RcTerrainPatch patchB = GetPatch(b);
|
||||
|
||||
if (patchA._quadtreeLOD != patchB._quadtreeLOD)
|
||||
return patchA._quadtreeLOD < patchB._quadtreeLOD;
|
||||
|
||||
return patchA._distToHeadSq < patchB._distToHeadSq;
|
||||
});
|
||||
if (_visibleRandomPatchCount)
|
||||
memcpy(&_vSortedPatchIndices[_visibleSortedPatchCount], _vRandomPatchIndices.data(), _visibleRandomPatchCount * sizeof(UINT16));
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
int Terrain::UserPtr_GetType()
|
||||
|
|
|
@ -219,11 +219,10 @@ namespace verus
|
|||
|
||||
void ResetInstanceCount();
|
||||
void Layout();
|
||||
void SortVisible();
|
||||
void Draw(RcDrawDesc dd = DrawDesc());
|
||||
void DrawSimple(DrawSimpleMode mode);
|
||||
|
||||
void SortVisiblePatches();
|
||||
|
||||
virtual int UserPtr_GetType() override;
|
||||
|
||||
int GetMapSide() const { return _mapSide; }
|
||||
|
|
|
@ -265,7 +265,7 @@ void Water::Draw()
|
|||
s_ubWaterFS._matShadowCSM2 = atmo.GetShadowMapBaker().GetShadowMatrix(2).UniformBufferFormat();
|
||||
s_ubWaterFS._matShadowCSM3 = atmo.GetShadowMapBaker().GetShadowMatrix(3).UniformBufferFormat();
|
||||
s_ubWaterFS._matScreenCSM = atmo.GetShadowMapBaker().GetScreenMatrixVP().UniformBufferFormat();
|
||||
s_ubWaterFS._csmSplitRanges = atmo.GetShadowMapBaker().GetSplitRanges().GLM();
|
||||
s_ubWaterFS._csmSliceBounds = atmo.GetShadowMapBaker().GetSliceBounds().GLM();
|
||||
memcpy(&s_ubWaterFS._shadowConfig, &atmo.GetShadowMapBaker().GetConfig(), sizeof(s_ubWaterFS._shadowConfig));
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_MAIN]);
|
||||
|
@ -341,7 +341,9 @@ void Water::EndPlanarReflection(CGI::PBaseCommandBuffer pCB)
|
|||
wm.SetPassCamera(_pPrevPassCamera);
|
||||
wm.SetHeadCamera(_pPrevHeadCamera);
|
||||
|
||||
VERUS_PROFILER_BEGIN_EVENT(pCB, VERUS_COLOR_BLACK, "Water/PlanarReflection/GenerateMips");
|
||||
_tex[TEX_REFLECTION]->GenerateMips();
|
||||
VERUS_PROFILER_END_EVENT(pCB);
|
||||
}
|
||||
|
||||
void Water::GenerateTextures()
|
||||
|
@ -367,24 +369,30 @@ void Water::GenerateHeightmapTexture()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenHeightmapFS._phase.x = _phase;
|
||||
memcpy(&s_ubGenHeightmapFS._amplitudes, _amplitudes, sizeof(_amplitudes));
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(96, 96, 160, 255), "Water/GenerateHeightmapTexture");
|
||||
{
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenHeightmapFS._phase.x = _phase;
|
||||
memcpy(&s_ubGenHeightmapFS._amplitudes, _amplitudes, sizeof(_amplitudes));
|
||||
|
||||
cb->BeginRenderPass(_rphGenHeightmap, _fbhGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP]->GetClearValue(), },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
cb->BeginRenderPass(_rphGenHeightmap, _fbhGenHeightmap, { _tex[TEX_GEN_HEIGHTMAP]->GetClearValue(), },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_HEIGHTMAP]);
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 1, _cshGenHeightmap);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_HEIGHTMAP]);
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 1, _cshGenHeightmap);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
|
||||
cb->EndRenderPass();
|
||||
cb->EndRenderPass();
|
||||
|
||||
_tex[TEX_GEN_HEIGHTMAP]->GenerateMips(cb.Get());
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_BLACK, "Water/GenerateHeightmapTexture/GenerateMips");
|
||||
_tex[TEX_GEN_HEIGHTMAP]->GenerateMips(cb.Get());
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
void Water::GenerateNormalsTexture()
|
||||
|
@ -393,24 +401,30 @@ void Water::GenerateNormalsTexture()
|
|||
|
||||
auto cb = renderer.GetCommandBuffer();
|
||||
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenNormalsFS._textureSize = _tex[TEX_GEN_HEIGHTMAP]->GetSize().GLM();
|
||||
s_ubGenNormalsFS._waterScale.x = 1 / _patchSide;
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_RGBA(128, 128, 255, 255), "Water/GenerateNormalsTexture");
|
||||
{
|
||||
s_ubGen._matW = Math::QuadMatrix().UniformBufferFormat();
|
||||
s_ubGen._matV = Math::ToUVMatrix().UniformBufferFormat();
|
||||
s_ubGenNormalsFS._textureSize = _tex[TEX_GEN_HEIGHTMAP]->GetSize().GLM();
|
||||
s_ubGenNormalsFS._waterScale.x = 1 / _patchSide;
|
||||
|
||||
cb->BeginRenderPass(_rphGenNormals, _fbhGenNormals, { _tex[TEX_GEN_NORMALS]->GetClearValue(), },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
cb->BeginRenderPass(_rphGenNormals, _fbhGenNormals, { _tex[TEX_GEN_NORMALS]->GetClearValue(), },
|
||||
CGI::ViewportScissorFlags::setAllForFramebuffer);
|
||||
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_NORMALS]);
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 2, _cshGenNormals);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
cb->BindPipeline(_pipe[PIPE_GEN_NORMALS]);
|
||||
_shader[SHADER_GEN]->BeginBindDescriptors();
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 0);
|
||||
cb->BindDescriptors(_shader[SHADER_GEN], 2, _cshGenNormals);
|
||||
_shader[SHADER_GEN]->EndBindDescriptors();
|
||||
renderer.DrawQuad(cb.Get());
|
||||
|
||||
cb->EndRenderPass();
|
||||
cb->EndRenderPass();
|
||||
|
||||
_tex[TEX_GEN_NORMALS]->GenerateMips(cb.Get());
|
||||
VERUS_PROFILER_BEGIN_EVENT(cb, VERUS_COLOR_BLACK, "Water/GenerateNormalsTexture/GenerateMips");
|
||||
_tex[TEX_GEN_NORMALS]->GenerateMips(cb.Get());
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
VERUS_PROFILER_END_EVENT(cb);
|
||||
}
|
||||
|
||||
CGI::TexturePtr Water::GetCausticsTexture() const
|
||||
|
|
|
@ -61,8 +61,8 @@ void WorldManager::Update()
|
|||
{
|
||||
VERUS_UPDATE_ONCE_CHECK;
|
||||
|
||||
for (auto pNode : _vNodes)
|
||||
pNode->Update();
|
||||
VERUS_FOR(i, _vNodes.size()) // Must check size every loop iteration.
|
||||
_vNodes[i]->Update(); // Can add/remove child nodes.
|
||||
}
|
||||
|
||||
void WorldManager::UpdateParts()
|
||||
|
@ -88,21 +88,16 @@ void WorldManager::Layout()
|
|||
_visibleCount = 0;
|
||||
VERUS_ZERO_MEM(_visibleCountPerType);
|
||||
|
||||
// <Traverse>
|
||||
PCamera pPrevPassCamera = nullptr;
|
||||
// For CSM we need to create geometry beyond the view frustum (1st slice):
|
||||
if (settings._sceneShadowQuality >= App::Settings::Quality::high && atmo.GetShadowMapBaker().IsBaking())
|
||||
{
|
||||
PCamera pPassCameraCSM = atmo.GetShadowMapBaker().GetPassCameraCSM();
|
||||
if (pPassCameraCSM)
|
||||
pPrevPassCamera = SetPassCamera(pPassCameraCSM);
|
||||
}
|
||||
_octree.TraverseVisible(_pPassCamera->GetFrustum());
|
||||
// Back to original camera:
|
||||
if (pPrevPassCamera)
|
||||
SetPassCamera(pPrevPassCamera);
|
||||
// </Traverse>
|
||||
|
||||
SortVisible();
|
||||
|
||||
for (auto& x : TStoreTerrainNodes::_list)
|
||||
x.Layout();
|
||||
}
|
||||
|
||||
void WorldManager::SortVisible()
|
||||
{
|
||||
VERUS_RT_ASSERT(!_visibleCountPerType[+NodeType::unknown]);
|
||||
std::sort(_vVisibleNodes.begin(), _vVisibleNodes.begin() + _visibleCount, [](PBaseNode pA, PBaseNode pB)
|
||||
{
|
||||
|
@ -157,9 +152,6 @@ void WorldManager::Layout()
|
|||
// Draw same node types front-to-back:
|
||||
return pA->GetDistToHeadSq() < pB->GetDistToHeadSq();
|
||||
});
|
||||
|
||||
for (auto& x : TStoreTerrainNodes::_list)
|
||||
x.Layout();
|
||||
}
|
||||
|
||||
void WorldManager::Draw()
|
||||
|
@ -448,6 +440,8 @@ Continue WorldManager::Octree_ProcessNode(void* pToken, void* pUser)
|
|||
PBaseNode pNode = static_cast<PBaseNode>(pToken);
|
||||
if (pNode->IsDisabled())
|
||||
return Continue::yes;
|
||||
if (IsDrawingDepth(DrawDepth::automatic) && !pNode->IsShadowCaster())
|
||||
return Continue::yes;
|
||||
_vVisibleNodes[_visibleCount++] = pNode;
|
||||
_visibleCountPerType[+pNode->GetType()]++;
|
||||
return Continue::yes;
|
||||
|
@ -792,6 +786,7 @@ void WorldManager::DeleteNode(NodeType type, CSZ name, bool hierarchy)
|
|||
case NodeType::model: deleted = TStoreModelNodes::Delete(_C(static_cast<RModelNode>(node).GetURL())); break;
|
||||
case NodeType::particles: deleted = TStoreParticlesNodes::Delete(_C(static_cast<RParticlesNode>(node).GetURL())); break;
|
||||
case NodeType::block: TStoreBlockNodes::Delete(static_cast<PBlockNode>(&node)); break;
|
||||
case NodeType::blockChain: TStoreBlockChainNodes::Delete(static_cast<PBlockChainNode>(&node)); break;
|
||||
case NodeType::controlPoint: TStoreControlPointNodes::Delete(static_cast<PControlPointNode>(&node)); break;
|
||||
case NodeType::emitter: TStoreEmitterNodes::Delete(static_cast<PEmitterNode>(&node)); break;
|
||||
case NodeType::instance: TStoreInstanceNodes::Delete(static_cast<PInstanceNode>(&node)); break;
|
||||
|
@ -841,17 +836,18 @@ PBaseNode WorldManager::DuplicateNode(PBaseNode pTargetNode, HierarchyDuplicatio
|
|||
BroadcastOnNodeDuplicated(pTargetNode, false, pNewNode, hierarchyDuplication);
|
||||
switch (pTargetNode->GetType())
|
||||
{
|
||||
case NodeType::base: {BaseNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::block: {BlockNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::controlPoint: {ControlPointNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::emitter: {EmitterNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::instance: {InstanceNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::light: {LightNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::path: {PathNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::physics: {PhysicsNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::prefab: {PrefabNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::shaker: {ShakerNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::sound: {SoundNodePtr node; node.Duplicate(*pTargetNode); pNewNode = node.Get(); break; }
|
||||
case NodeType::base: {BaseNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::block: {BlockNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::blockChain: {BlockChainNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::controlPoint: {ControlPointNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::emitter: {EmitterNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::instance: {InstanceNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::light: {LightNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::path: {PathNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::physics: {PhysicsNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::prefab: {PrefabNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::shaker: {ShakerNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
case NodeType::sound: {SoundNodePtr node; node.Duplicate(*pTargetNode, hierarchyDuplication); pNewNode = node.Get(); break; }
|
||||
}
|
||||
BroadcastOnNodeDuplicated(pTargetNode, true, pNewNode, hierarchyDuplication);
|
||||
|
||||
|
@ -935,14 +931,11 @@ int WorldManager::GetSelectedCount()
|
|||
|
||||
void WorldManager::SelectAllChildNodes(PBaseNode pTargetNode)
|
||||
{
|
||||
const int nodeIndex = GetIndexOf(pTargetNode);
|
||||
const int nodeDepth = pTargetNode->GetDepth();
|
||||
|
||||
const int nodeCount = GetNodeCount();
|
||||
for (int i = nodeIndex + 1; i < nodeCount; ++i)
|
||||
for (int i = GetIndexOf(pTargetNode) + 1; i < nodeCount; ++i)
|
||||
{
|
||||
PBaseNode pNode = _vNodes[i];
|
||||
if (pNode->GetDepth() <= nodeDepth)
|
||||
if (pNode->GetDepth() <= pTargetNode->GetDepth())
|
||||
break;
|
||||
pNode->Select();
|
||||
}
|
||||
|
@ -959,6 +952,165 @@ void WorldManager::ResetRigidBodyTransforms()
|
|||
});
|
||||
}
|
||||
|
||||
void WorldManager::GenerateBlockChainNodes(PBlockChainNode pBlockChainNode)
|
||||
{
|
||||
if (!pBlockChainNode->GetSourceModelCount())
|
||||
return;
|
||||
VERUS_RT_ASSERT(NodeType::path == pBlockChainNode->GetParent()->GetType());
|
||||
|
||||
char buffer[IO::Stream::s_bufferSize] = {};
|
||||
|
||||
PPathNode pPathNode = static_cast<PPathNode>(pBlockChainNode->GetParent());
|
||||
PControlPointNode pHeadNode = nullptr;
|
||||
|
||||
float fullLength = 0;
|
||||
ForEachControlPointOf(pPathNode, false, [&fullLength, &pHeadNode](World::PControlPointNode pControlPointNode)
|
||||
{
|
||||
if (!pHeadNode && pControlPointNode->IsHeadControlPoint())
|
||||
pHeadNode = pControlPointNode;
|
||||
fullLength += pControlPointNode->GetSegmentLength();
|
||||
return Continue::yes;
|
||||
});
|
||||
|
||||
pBlockChainNode->ParseArguments();
|
||||
|
||||
float length = 0;
|
||||
int slot = 0;
|
||||
while (true)
|
||||
{
|
||||
const float slotLength = pBlockChainNode->GetLengthForSlot(slot++);
|
||||
if (slotLength < VERUS_FLOAT_THRESHOLD)
|
||||
break;
|
||||
length += slotLength;
|
||||
if (length >= fullLength)
|
||||
break;
|
||||
}
|
||||
|
||||
// Delete previously generated nodes:
|
||||
CGI::Renderer::I()->WaitIdle();
|
||||
bool nodeDeleted = false;
|
||||
do
|
||||
{
|
||||
nodeDeleted = false;
|
||||
for (auto pNode : _vNodes)
|
||||
{
|
||||
if (pNode->GetParent() == pBlockChainNode && (pNode->GetType() == NodeType::model || pNode->GetType() == NodeType::block))
|
||||
{
|
||||
DeleteNode(pNode);
|
||||
nodeDeleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (nodeDeleted);
|
||||
|
||||
_recursionDepth = 1; // Disable sorting.
|
||||
|
||||
const int slotCount = slot;
|
||||
slot = 0;
|
||||
const float scale = fullLength / length;
|
||||
const float bankedTurn = pPathNode->GetDictionary().FindFloat("_BankedTurn");
|
||||
float distOffset = 0;
|
||||
while (slot < slotCount)
|
||||
{
|
||||
const float slotLength = pBlockChainNode->GetLengthForSlot(slot) * scale;
|
||||
const float pivotOffset = distOffset + slotLength * 0.5f;
|
||||
|
||||
Point3 pivotPos;
|
||||
pHeadNode->ComputePositionAt(pivotOffset, pivotPos);
|
||||
|
||||
ModelNodePtr modelNode = pBlockChainNode->GetModelNodeForSlot(slot);
|
||||
if (modelNode)
|
||||
{
|
||||
RMesh mesh = modelNode->GetMesh();
|
||||
|
||||
BaseMesh::SourceBuffers sourceBuffers;
|
||||
sourceBuffers._vIndices.resize(mesh.GetIndexCount());
|
||||
sourceBuffers._vPos.resize(mesh.GetVertCount());
|
||||
sourceBuffers._vTc0.resize(mesh.GetVertCount());
|
||||
sourceBuffers._vNrm.resize(mesh.GetVertCount());
|
||||
memcpy(sourceBuffers._vIndices.data(), mesh.GetIndices(), sourceBuffers._vIndices.size() * sizeof(UINT16));
|
||||
mesh.ForEachVertex([&sourceBuffers, pHeadNode, fullLength, scale, pivotOffset, &pivotPos, bankedTurn](int index, RcPoint3 pos, RcVector3 nrm, RcPoint3 tc)
|
||||
{
|
||||
const float offsetFromPivot = pos.getZ() * scale;
|
||||
|
||||
Point3 posOnPath;
|
||||
Vector3 pathDir;
|
||||
pHeadNode->ComputePositionAt(pivotOffset + offsetFromPivot, posOnPath, &pathDir, true);
|
||||
|
||||
const Vector3 zAxis = pathDir;
|
||||
Vector3 yAxis(0, 1, 0);
|
||||
Vector3 xAxis = VMath::cross(yAxis, zAxis);
|
||||
yAxis = VMath::cross(zAxis, xAxis);
|
||||
|
||||
if (bankedTurn > 0)
|
||||
{
|
||||
Point3 posOnPath2;
|
||||
pHeadNode->ComputePositionAt(pivotOffset + offsetFromPivot + 5, posOnPath2, nullptr, true);
|
||||
const Vector3 delta = VMath::normalize(posOnPath2 - posOnPath) - pathDir;
|
||||
yAxis = VMath::normalize(yAxis + delta * bankedTurn);
|
||||
xAxis = VMath::cross(yAxis, zAxis);
|
||||
yAxis = VMath::cross(zAxis, xAxis);
|
||||
}
|
||||
|
||||
const Matrix3 mat(xAxis, yAxis, zAxis);
|
||||
const Point3 newPos = (posOnPath - pivotPos) + xAxis * pos.getX() + yAxis * pos.getY();
|
||||
const Vector3 newNrm = mat * nrm;
|
||||
|
||||
sourceBuffers._vPos[index] = newPos.GLM();
|
||||
sourceBuffers._vTc0[index] = tc.GLM2();
|
||||
sourceBuffers._vNrm[index] = newNrm.GLM();
|
||||
return Continue::yes;
|
||||
});
|
||||
|
||||
BlockChainNode::PcSourceModel pSourceModel = pBlockChainNode->GetSourceModelForSlot(slot);
|
||||
|
||||
String url("[_GEN]:");
|
||||
url += _C(pBlockChainNode->GetName());
|
||||
url += "/";
|
||||
url += std::to_string(slot);
|
||||
|
||||
ModelNode::Desc modelNodeDesc;
|
||||
modelNodeDesc._url = _C(url);
|
||||
modelNodeDesc._materialURL = _C(modelNode->GetMaterial()->_name);
|
||||
ModelNodePtr genModelNode;
|
||||
genModelNode.Init(modelNodeDesc);
|
||||
genModelNode->SetGeneratedFlag();
|
||||
genModelNode->SetParent(pBlockChainNode);
|
||||
Mesh::Desc meshDesc;
|
||||
meshDesc._instanceCapacity = 1000;
|
||||
meshDesc._initShape = true;
|
||||
genModelNode->GetMesh().Init(sourceBuffers, meshDesc);
|
||||
|
||||
BlockNode::Desc blockNodeDesc;
|
||||
blockNodeDesc._modelURL = _C(url);
|
||||
BlockNodePtr genBlockNode;
|
||||
genBlockNode.Init(blockNodeDesc);
|
||||
genBlockNode->SetGeneratedFlag();
|
||||
genBlockNode->SetParent(pBlockChainNode);
|
||||
genBlockNode->MoveTo(pivotPos + Vector3(pBlockChainNode->GetPosition(true)));
|
||||
if (pSourceModel && pSourceModel->_noShadowCaster)
|
||||
genBlockNode->SetShadowCasterFlag(false);
|
||||
|
||||
if (pSourceModel && !pSourceModel->_noPhysicsNode)
|
||||
{
|
||||
PhysicsNodePtr genPhysicsNode;
|
||||
genPhysicsNode.Init(_C(genBlockNode->GetName()));
|
||||
genPhysicsNode->SetGeneratedFlag();
|
||||
genPhysicsNode->SetParent(genBlockNode.Get(), true);
|
||||
}
|
||||
|
||||
sprintf_s(buffer, "%d", slot);
|
||||
genBlockNode->GetDictionary().Insert("_BlockChainSlot", buffer);
|
||||
}
|
||||
|
||||
slot++;
|
||||
distOffset += slotLength;
|
||||
}
|
||||
|
||||
_recursionDepth = 0; // Enable sorting.
|
||||
SortNodes();
|
||||
}
|
||||
|
||||
bool WorldManager::Connect2ControlPoints(PControlPointNode pNodeA, PControlPointNode pNodeB)
|
||||
{
|
||||
if (!pNodeA || !pNodeB)
|
||||
|
@ -1000,6 +1152,7 @@ void WorldManager::UpdatePrefabInstances(PPrefabNode pPrefabNode, bool sortNodes
|
|||
});
|
||||
|
||||
// Delete all nodes which are children of these instances:
|
||||
CGI::Renderer::I()->WaitIdle();
|
||||
bool nodeDeleted = false;
|
||||
do
|
||||
{
|
||||
|
@ -1080,6 +1233,7 @@ void WorldManager::ReplaceSimilarWithInstances(PPrefabNode pPrefabNode)
|
|||
}
|
||||
const bool multiMode = (childCount >= 2);
|
||||
|
||||
CGI::Renderer::I()->WaitIdle();
|
||||
bool nodeDeleted = false;
|
||||
do
|
||||
{
|
||||
|
@ -1204,6 +1358,13 @@ PBlockNode WorldManager::InsertBlockNode()
|
|||
return p;
|
||||
}
|
||||
|
||||
PBlockChainNode WorldManager::InsertBlockChainNode()
|
||||
{
|
||||
auto p = TStoreBlockChainNodes::Insert();
|
||||
_vNodes.push_back(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
PControlPointNode WorldManager::InsertControlPointNode()
|
||||
{
|
||||
auto p = TStoreControlPointNodes::Insert();
|
||||
|
@ -1385,6 +1546,7 @@ void WorldManager::Deserialize(IO::RStream stream)
|
|||
case NodeType::model: InsertModelNode(_C(url))->Deserialize(stream); break;
|
||||
case NodeType::particles: InsertParticlesNode(_C(url))->Deserialize(stream); break;
|
||||
case NodeType::block: InsertBlockNode()->Deserialize(stream); break;
|
||||
case NodeType::blockChain: InsertBlockChainNode()->Deserialize(stream); break;
|
||||
case NodeType::controlPoint: InsertControlPointNode()->Deserialize(stream); break;
|
||||
case NodeType::emitter: InsertEmitterNode()->Deserialize(stream); break;
|
||||
case NodeType::instance: InsertInstanceNode()->Deserialize(stream); break;
|
||||
|
@ -1403,7 +1565,6 @@ void WorldManager::Deserialize(IO::RStream stream)
|
|||
|
||||
for (auto pNode : _vNodes)
|
||||
pNode->OnAllNodesDeserialized();
|
||||
|
||||
for (auto& prefabNode : TStorePrefabNodes::_list)
|
||||
UpdatePrefabInstances(&prefabNode, false);
|
||||
SortNodes();
|
||||
|
@ -1486,6 +1647,7 @@ UINT32 WorldManager::NodeTypeToHash(NodeType type)
|
|||
case NodeType::model: return 'EDOM';
|
||||
case NodeType::particles: return 'TRAP';
|
||||
case NodeType::block: return 'COLB';
|
||||
case NodeType::blockChain: return 'HCLB';
|
||||
case NodeType::controlPoint: return 'TNOC';
|
||||
case NodeType::emitter: return 'TIME';
|
||||
case NodeType::instance: return 'TSNI';
|
||||
|
@ -1509,6 +1671,7 @@ NodeType WorldManager::HashToNodeType(UINT32 hash)
|
|||
case 'EDOM': return NodeType::model;
|
||||
case 'TRAP': return NodeType::particles;
|
||||
case 'COLB': return NodeType::block;
|
||||
case 'HCLB': return NodeType::blockChain;
|
||||
case 'TNOC': return NodeType::controlPoint;
|
||||
case 'TIME': return NodeType::emitter;
|
||||
case 'TSNI': return NodeType::instance;
|
||||
|
@ -1546,9 +1709,9 @@ UINT32 WorldManager::NodeTypeToColor(NodeType type, int alpha)
|
|||
VERUS_COLOR_RGBA(255, 128, 255, alpha), // 11, prefab
|
||||
VERUS_COLOR_RGBA(255, 255, 128, alpha), // 12, terrain
|
||||
|
||||
VERUS_COLOR_RGBA(255, 128, 000, alpha), // 13, sound
|
||||
VERUS_COLOR_RGBA(000, 255, 128, alpha), // 14, shaker
|
||||
VERUS_COLOR_RGBA(128, 000, 255, alpha), // 15
|
||||
VERUS_COLOR_RGBA(255, 171, 85, alpha), // 13, sound
|
||||
VERUS_COLOR_RGBA(85, 255, 171, alpha), // 14, shaker
|
||||
VERUS_COLOR_RGBA(171, 85, 255, alpha), // 15, blockChain
|
||||
};
|
||||
|
||||
switch (type)
|
||||
|
@ -1557,6 +1720,7 @@ UINT32 WorldManager::NodeTypeToColor(NodeType type, int alpha)
|
|||
case NodeType::model: return colors[8];
|
||||
case NodeType::particles: return colors[7];
|
||||
case NodeType::block: return colors[2];
|
||||
case NodeType::blockChain: return colors[15];
|
||||
case NodeType::controlPoint: return colors[4];
|
||||
case NodeType::emitter: return colors[1];
|
||||
case NodeType::instance: return colors[5];
|
||||
|
|
|
@ -14,6 +14,7 @@ namespace verus
|
|||
typedef StoreUnique<String, ParticlesNode> TStoreParticlesNodes;
|
||||
typedef Store<BaseNode> TStoreBaseNodes;
|
||||
typedef Store<BlockNode> TStoreBlockNodes;
|
||||
typedef Store<BlockChainNode> TStoreBlockChainNodes;
|
||||
typedef Store<ControlPointNode> TStoreControlPointNodes;
|
||||
typedef Store<EmitterNode> TStoreEmitterNodes;
|
||||
typedef Store<InstanceNode> TStoreInstanceNodes;
|
||||
|
@ -26,10 +27,11 @@ namespace verus
|
|||
typedef Store<TerrainNode> TStoreTerrainNodes;
|
||||
class WorldManager : public Singleton<WorldManager>, public Object, public Math::OctreeDelegate,
|
||||
private TStoreModelNodes, private TStoreParticlesNodes,
|
||||
private TStoreBaseNodes, private TStoreBlockNodes, private TStoreControlPointNodes,
|
||||
private TStoreEmitterNodes, private TStoreInstanceNodes, private TStoreLightNodes,
|
||||
private TStorePathNodes, private TStorePhysicsNodes, private TStorePrefabNodes,
|
||||
private TStoreShakerNodes, private TStoreSoundNodes, private TStoreTerrainNodes
|
||||
private TStoreBaseNodes, private TStoreBlockNodes, private TStoreBlockChainNodes,
|
||||
private TStoreControlPointNodes, private TStoreEmitterNodes, private TStoreInstanceNodes,
|
||||
private TStoreLightNodes, private TStorePathNodes, private TStorePhysicsNodes,
|
||||
private TStorePrefabNodes, private TStoreShakerNodes, private TStoreSoundNodes,
|
||||
private TStoreTerrainNodes
|
||||
{
|
||||
Math::Octree _octree;
|
||||
LocalPtr<btBoxShape> _pPickingShape;
|
||||
|
@ -79,6 +81,7 @@ namespace verus
|
|||
void Update();
|
||||
void UpdateParts();
|
||||
void Layout();
|
||||
void SortVisible();
|
||||
void Draw();
|
||||
void DrawSimple(DrawSimpleMode mode);
|
||||
void DrawTerrainNodes(Terrain::RcDrawDesc dd);
|
||||
|
@ -209,6 +212,20 @@ namespace verus
|
|||
}
|
||||
}
|
||||
|
||||
if (NodeType::unknown == query._type || NodeType::blockChain == query._type)
|
||||
{
|
||||
VERUS_FOREACH_X(TStoreBlockChainNodes::TList, TStoreBlockChainNodes::_list, it)
|
||||
{
|
||||
auto& blockChain = *it++;
|
||||
if (
|
||||
MatchName(blockChain) &&
|
||||
MatchSelected(blockChain) &&
|
||||
MatchParent(blockChain))
|
||||
if (Continue::no == fn(blockChain))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (NodeType::unknown == query._type || NodeType::controlPoint == query._type)
|
||||
{
|
||||
VERUS_FOREACH_X(TStoreControlPointNodes::TList, TStoreControlPointNodes::_list, it)
|
||||
|
@ -354,20 +371,20 @@ namespace verus
|
|||
template<typename T>
|
||||
void ForEachControlPointOf(PPathNode pPathNode, bool onlyHeads, const T& fn)
|
||||
{
|
||||
const int nodeIndex = GetIndexOf(pPathNode);
|
||||
const int nodeDepth = pPathNode->GetDepth();
|
||||
|
||||
const int nodeCount = GetNodeCount();
|
||||
for (int i = nodeIndex + 1; i < nodeCount; ++i)
|
||||
for (int i = GetIndexOf(pPathNode) + 1; i < nodeCount; ++i)
|
||||
{
|
||||
PBaseNode pNode = _vNodes[i];
|
||||
if (pNode->GetDepth() <= nodeDepth)
|
||||
if (pNode->GetDepth() <= pPathNode->GetDepth())
|
||||
break;
|
||||
PControlPointNode pControlPointNode = static_cast<PControlPointNode>(pNode);
|
||||
if (!onlyHeads || pControlPointNode->IsHeadControlPoint())
|
||||
if (NodeType::controlPoint == pNode->GetType())
|
||||
{
|
||||
if (Continue::no == fn(pControlPointNode))
|
||||
return;
|
||||
PControlPointNode pControlPointNode = static_cast<PControlPointNode>(pNode);
|
||||
if (!onlyHeads || pControlPointNode->IsHeadControlPoint())
|
||||
{
|
||||
if (Continue::no == fn(pControlPointNode))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,8 +422,8 @@ namespace verus
|
|||
|
||||
void ResetRigidBodyTransforms();
|
||||
|
||||
void GenerateBlockChainNodes(PBlockChainNode pBlockChainNode);
|
||||
static bool Connect2ControlPoints(PControlPointNode pNodeA, PControlPointNode pNodeB);
|
||||
|
||||
void UpdatePrefabInstances(PPrefabNode pPrefabNode, bool sortNodes = true);
|
||||
void ReplaceSimilarWithInstances(PPrefabNode pPrefabNode);
|
||||
// </NodeOperations>
|
||||
|
@ -421,6 +438,8 @@ namespace verus
|
|||
|
||||
PBlockNode InsertBlockNode();
|
||||
|
||||
PBlockChainNode InsertBlockChainNode();
|
||||
|
||||
PControlPointNode InsertControlPointNode();
|
||||
|
||||
PEmitterNode InsertEmitterNode();
|
||||
|
|
|
@ -31,6 +31,8 @@ void BaseNode::Init(RcDesc desc)
|
|||
OnLocalTransformUpdated();
|
||||
UpdateGlobalTransform();
|
||||
AddDefaultPickingBody(); // Can be overridden by nodes that don't need this rigid body.
|
||||
|
||||
_flags &= ~Flags::readOnlyFlags;
|
||||
}
|
||||
|
||||
void BaseNode::Done()
|
||||
|
@ -41,7 +43,7 @@ void BaseNode::Done()
|
|||
VERUS_DONE(BaseNode);
|
||||
}
|
||||
|
||||
void BaseNode::Duplicate(RBaseNode node)
|
||||
void BaseNode::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
_trLocal = node._trLocal;
|
||||
_trGlobal = node._trGlobal;
|
||||
|
@ -52,7 +54,7 @@ void BaseNode::Duplicate(RBaseNode node)
|
|||
_pParent = node._pParent;
|
||||
_name = node._name;
|
||||
_type = node._type;
|
||||
_flags = node._flags;
|
||||
_flags = node._flags | Flags::readOnlyFlags;
|
||||
_groups = node._groups;
|
||||
_depth = node._depth;
|
||||
|
||||
|
@ -109,6 +111,7 @@ void BaseNode::GetEditorCommands(Vector<EditorCommand>& v)
|
|||
v.push_back(EditorCommand(nullptr, EditorCommandCode::node_resetLocalTransform));
|
||||
v.push_back(EditorCommand(nullptr, EditorCommandCode::node_resetLocalTransformKeepGlobal));
|
||||
v.push_back(EditorCommand(nullptr, EditorCommandCode::node_pointAt));
|
||||
v.push_back(EditorCommand(nullptr, EditorCommandCode::node_moveTo));
|
||||
}
|
||||
|
||||
void BaseNode::ExecuteEditorCommand(RcEditorCommand command)
|
||||
|
@ -140,6 +143,11 @@ void BaseNode::ExecuteEditorCommand(RcEditorCommand command)
|
|||
}
|
||||
}
|
||||
|
||||
bool BaseNode::CanAutoSelectParentNode() const
|
||||
{
|
||||
return _pParent && NodeType::instance == _pParent->GetType();
|
||||
}
|
||||
|
||||
void BaseNode::Rename(CSZ name)
|
||||
{
|
||||
if (_name == name)
|
||||
|
@ -275,6 +283,19 @@ void BaseNode::Select(bool select)
|
|||
VERUS_BITMASK_UNSET(_flags, Flags::selected);
|
||||
}
|
||||
|
||||
bool BaseNode::IsShadowCaster() const
|
||||
{
|
||||
return !!(_flags & Flags::shadowCaster);
|
||||
}
|
||||
|
||||
void BaseNode::SetShadowCasterFlag(bool shadowCaster)
|
||||
{
|
||||
if (shadowCaster)
|
||||
VERUS_BITMASK_SET(_flags, Flags::shadowCaster);
|
||||
else
|
||||
VERUS_BITMASK_UNSET(_flags, Flags::shadowCaster);
|
||||
}
|
||||
|
||||
bool BaseNode::IsInGroup(int index) const
|
||||
{
|
||||
return !!((_groups >> index) & 0x1);
|
||||
|
@ -573,7 +594,7 @@ void BaseNode::Serialize(IO::RSeekableStream stream)
|
|||
_dict.Serialize(stream);
|
||||
stream << wm.GetIndexOf(_pParent, true);
|
||||
stream.WriteString(_C(_name));
|
||||
stream << (_flags & ~Flags::selected);
|
||||
stream << (_flags & Flags::serializedMask);
|
||||
stream << _groups;
|
||||
}
|
||||
|
||||
|
@ -600,6 +621,7 @@ void BaseNode::Deserialize(IO::RStream stream)
|
|||
_uiScale = uiScale;
|
||||
_pParent = wm.GetNodeByIndex(parentIndex);
|
||||
_name = name;
|
||||
_flags |= Flags::readOnlyFlags;
|
||||
|
||||
UpdateDepth();
|
||||
|
||||
|
@ -699,7 +721,7 @@ void BaseNode::SerializeXML(pugi::xml_node node)
|
|||
node.append_attribute("uiS") = _C(_uiScale.ToString(true));
|
||||
node.append_attribute("parent") = wm.GetIndexOf(_pParent, true);
|
||||
node.append_attribute("name") = _C(_name);
|
||||
node.append_attribute("flags") = (_flags & ~Flags::selected);
|
||||
node.append_attribute("flags") = (_flags & Flags::serializedMask);
|
||||
node.append_attribute("groups") = _groups;
|
||||
}
|
||||
|
||||
|
@ -749,12 +771,12 @@ void BaseNodePtr::Init(BaseNode::RcDesc desc)
|
|||
_p->Init(desc);
|
||||
}
|
||||
|
||||
void BaseNodePtr::Duplicate(RBaseNode node)
|
||||
void BaseNodePtr::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = wm.InsertBaseNode();
|
||||
_p->Duplicate(node);
|
||||
_p->Duplicate(node, hierarchyDuplication);
|
||||
}
|
||||
|
||||
void BaseNodePwn::Done()
|
||||
|
|
|
@ -22,7 +22,11 @@ namespace verus
|
|||
dynamic = (1 << 2), // Will be bound to the root of octree.
|
||||
generated = (1 << 3), // Created by some other node.
|
||||
disabled = (1 << 4), // Draw method will not be called.
|
||||
selected = (1 << 5)
|
||||
selected = (1 << 5),
|
||||
shadowCaster = (1 << 6),
|
||||
|
||||
readOnlyFlags = (1u << 31),
|
||||
serializedMask = ~(octreeBindOnce | generated | selected)
|
||||
};
|
||||
|
||||
Transform3 _trLocal = Transform3::identity();
|
||||
|
@ -56,7 +60,7 @@ namespace verus
|
|||
void Init(RcDesc desc);
|
||||
void Done();
|
||||
|
||||
virtual void Duplicate(BaseNode& node);
|
||||
virtual void Duplicate(BaseNode& node, HierarchyDuplication hierarchyDuplication);
|
||||
|
||||
virtual void Update() {}
|
||||
virtual void Layout() {}
|
||||
|
@ -68,7 +72,7 @@ namespace verus
|
|||
// <Editor>
|
||||
virtual void GetEditorCommands(Vector<EditorCommand>& v);
|
||||
virtual void ExecuteEditorCommand(RcEditorCommand command);
|
||||
virtual bool CanAutoSelectParentNode() const { return false; }
|
||||
virtual bool CanAutoSelectParentNode() const;
|
||||
// </Editor>
|
||||
|
||||
// <Identity>
|
||||
|
@ -104,6 +108,9 @@ namespace verus
|
|||
|
||||
bool IsSelected() const;
|
||||
void Select(bool select = true);
|
||||
|
||||
bool IsShadowCaster() const;
|
||||
void SetShadowCasterFlag(bool shadowCaster = true);
|
||||
// </Flags>
|
||||
|
||||
// <Groups>
|
||||
|
@ -174,7 +181,7 @@ namespace verus
|
|||
{
|
||||
public:
|
||||
void Init(BaseNode::RcDesc desc);
|
||||
void Duplicate(RBaseNode node);
|
||||
void Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication);
|
||||
};
|
||||
VERUS_TYPEDEFS(BaseNodePtr);
|
||||
|
||||
|
|
|
@ -0,0 +1,286 @@
|
|||
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
|
||||
#include "verus.h"
|
||||
|
||||
using namespace verus;
|
||||
using namespace verus::World;
|
||||
|
||||
// BlockChainNode::SourceModel:
|
||||
|
||||
bool BlockChainNode::SourceModel::IsAssignedToSlot(int slot) const
|
||||
{
|
||||
for (const auto& x : _vSlots)
|
||||
{
|
||||
if (x.Includes(slot))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// BlockChainNode:
|
||||
|
||||
BlockChainNode::BlockChainNode()
|
||||
{
|
||||
_type = NodeType::blockChain;
|
||||
}
|
||||
|
||||
BlockChainNode::~BlockChainNode()
|
||||
{
|
||||
Done();
|
||||
}
|
||||
|
||||
void BlockChainNode::Init(RcDesc desc)
|
||||
{
|
||||
_pParent = desc._pPathNode;
|
||||
UpdateDepth();
|
||||
String name;
|
||||
if (!desc._name)
|
||||
name = String("Bc") + _C(desc._pPathNode->GetName());
|
||||
BaseNode::Init(desc._name ? desc._name : _C(name));
|
||||
|
||||
_vSourceModels.reserve(8);
|
||||
}
|
||||
|
||||
void BlockChainNode::Done()
|
||||
{
|
||||
VERUS_DONE(BlockChainNode);
|
||||
}
|
||||
|
||||
void BlockChainNode::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
BaseNode::Duplicate(node, hierarchyDuplication);
|
||||
|
||||
RBlockChainNode blockChainNode = static_cast<RBlockChainNode>(node);
|
||||
|
||||
if (NodeType::block == _type)
|
||||
{
|
||||
Desc desc;
|
||||
desc._name = _C(_name);
|
||||
Init(desc);
|
||||
}
|
||||
}
|
||||
|
||||
void BlockChainNode::Update()
|
||||
{
|
||||
if (!_async_generatedNodes)
|
||||
{
|
||||
bool allLoaded = true;
|
||||
for (const auto& x : _vSourceModels)
|
||||
{
|
||||
if (x._modelNode && !x._modelNode->GetMesh().IsLoaded())
|
||||
{
|
||||
allLoaded = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (allLoaded)
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
wm.GenerateBlockChainNodes(this);
|
||||
_async_generatedNodes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockChainNode::GetEditorCommands(Vector<EditorCommand>& v)
|
||||
{
|
||||
BaseNode::GetEditorCommands(v);
|
||||
|
||||
v.push_back(EditorCommand(nullptr, EditorCommandCode::separator));
|
||||
v.push_back(EditorCommand(nullptr, EditorCommandCode::blockChain_generateNodes));
|
||||
}
|
||||
|
||||
void BlockChainNode::ExecuteEditorCommand(RcEditorCommand command)
|
||||
{
|
||||
BaseNode::ExecuteEditorCommand(command);
|
||||
|
||||
switch (command._code)
|
||||
{
|
||||
case EditorCommandCode::blockChain_generateNodes:
|
||||
{
|
||||
_async_generatedNodes = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockChainNode::CanSetParent(PBaseNode pNode) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void BlockChainNode::OnNodeDeleted(PBaseNode pNode, bool afterEvent, bool hierarchy)
|
||||
{
|
||||
BaseNode::OnNodeDeleted(pNode, afterEvent, hierarchy);
|
||||
|
||||
if (!afterEvent && pNode->GetType() == NodeType::model)
|
||||
UnbindSourceModel(static_cast<PModelNode>(pNode));
|
||||
}
|
||||
|
||||
void BlockChainNode::Serialize(IO::RSeekableStream stream)
|
||||
{
|
||||
BaseNode::Serialize(stream);
|
||||
|
||||
VERUS_QREF_WM;
|
||||
|
||||
stream << GetSourceModelCount();
|
||||
for (const auto& x : _vSourceModels)
|
||||
{
|
||||
stream << wm.GetIndexOf(x._modelNode.Get(), true);
|
||||
stream << x._length;
|
||||
stream.WriteString(_C(x._arguments));
|
||||
}
|
||||
}
|
||||
|
||||
void BlockChainNode::Deserialize(IO::RStream stream)
|
||||
{
|
||||
BaseNode::Deserialize(stream);
|
||||
|
||||
VERUS_QREF_WM;
|
||||
|
||||
int sourceModelCount;
|
||||
|
||||
stream >> sourceModelCount;
|
||||
VERUS_FOR(i, sourceModelCount)
|
||||
{
|
||||
SourceModel sourceModel;
|
||||
int modelIndex = -1;
|
||||
stream >> modelIndex;
|
||||
sourceModel._modelNode.Attach(static_cast<PModelNode>(wm.GetNodeByIndex(modelIndex)));
|
||||
stream >> sourceModel._length;
|
||||
char arguments[IO::Stream::s_bufferSize] = {};
|
||||
stream.ReadString(arguments);
|
||||
sourceModel._arguments = arguments;
|
||||
_vSourceModels.push_back(std::move(sourceModel));
|
||||
}
|
||||
|
||||
if (NodeType::blockChain == _type)
|
||||
{
|
||||
Desc desc;
|
||||
desc._name = _C(_name);
|
||||
desc._pPathNode = GetParent();
|
||||
Init(desc);
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockChainNode::BindSourceModel(PModelNode pModelNode)
|
||||
{
|
||||
for (const auto& x : _vSourceModels)
|
||||
{
|
||||
if (x._modelNode == pModelNode)
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceModel sourceModel;
|
||||
sourceModel._modelNode.Attach(pModelNode);
|
||||
sourceModel._length = pModelNode ? pModelNode->GetMesh().GetBounds().GetDimensions().getZ() : 1.f;
|
||||
_vSourceModels.push_back(std::move(sourceModel));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockChainNode::UnbindSourceModel(PModelNode pModelNode)
|
||||
{
|
||||
return _vSourceModels.end() != _vSourceModels.erase(std::remove_if(_vSourceModels.begin(), _vSourceModels.end(),
|
||||
[pModelNode](RSourceModel sourceModel)
|
||||
{
|
||||
return sourceModel._modelNode == pModelNode;
|
||||
}), _vSourceModels.end());
|
||||
}
|
||||
|
||||
int BlockChainNode::GetSourceModelCount() const
|
||||
{
|
||||
return Utils::Cast32(_vSourceModels.size());
|
||||
}
|
||||
|
||||
BlockChainNode::PcSourceModel BlockChainNode::GetSourceModelForSlot(int slot) const
|
||||
{
|
||||
if (_vSourceModels.empty())
|
||||
return nullptr;
|
||||
for (int i = 1; i < _vSourceModels.size(); ++i)
|
||||
{
|
||||
if (_vSourceModels[i].IsAssignedToSlot(slot))
|
||||
return &_vSourceModels[i];
|
||||
}
|
||||
return &_vSourceModels[0];
|
||||
}
|
||||
|
||||
ModelNodePtr BlockChainNode::GetModelNodeForSlot(int slot) const
|
||||
{
|
||||
if (_vSourceModels.empty())
|
||||
return ModelNodePtr();
|
||||
for (int i = 1; i < _vSourceModels.size(); ++i)
|
||||
{
|
||||
if (_vSourceModels[i].IsAssignedToSlot(slot))
|
||||
return _vSourceModels[i]._modelNode;
|
||||
}
|
||||
return _vSourceModels[0]._modelNode;
|
||||
}
|
||||
|
||||
float BlockChainNode::GetLengthForSlot(int slot) const
|
||||
{
|
||||
if (_vSourceModels.empty())
|
||||
return 0;
|
||||
for (int i = 1; i < _vSourceModels.size(); ++i)
|
||||
{
|
||||
if (_vSourceModels[i].IsAssignedToSlot(slot))
|
||||
return _vSourceModels[i]._length;
|
||||
}
|
||||
return _vSourceModels[0]._length;
|
||||
}
|
||||
|
||||
void BlockChainNode::ParseArguments()
|
||||
{
|
||||
for (auto& x : _vSourceModels)
|
||||
{
|
||||
x._vSlots.clear();
|
||||
x._noPhysicsNode = false;
|
||||
x._noShadowCaster = false;
|
||||
Vector<String> vArgs;
|
||||
Str::Explode(_C(x._arguments), ",", vArgs);
|
||||
for (const auto& arg : vArgs)
|
||||
{
|
||||
if (isdigit(arg[0]))
|
||||
{
|
||||
const size_t dash = arg.find('-');
|
||||
if (dash != String::npos)
|
||||
x._vSlots.push_back(Range(atoi(_C(arg)), atoi(_C(arg) + dash + 1) + 1));
|
||||
else
|
||||
x._vSlots.push_back(Range(atoi(_C(arg))));
|
||||
}
|
||||
else if (arg == "-nophy")
|
||||
{
|
||||
x._noPhysicsNode = true;
|
||||
}
|
||||
else if (arg == "-nosc")
|
||||
{
|
||||
x._noShadowCaster = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// BlockChainNodePtr:
|
||||
|
||||
void BlockChainNodePtr::Init(BlockChainNode::RcDesc desc)
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = wm.InsertBlockChainNode();
|
||||
_p->Init(desc);
|
||||
}
|
||||
|
||||
void BlockChainNodePtr::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = wm.InsertBlockChainNode();
|
||||
_p->Duplicate(node, hierarchyDuplication);
|
||||
}
|
||||
|
||||
void BlockChainNodePwn::Done()
|
||||
{
|
||||
if (_p)
|
||||
{
|
||||
WorldManager::I().DeleteNode(_p);
|
||||
_p = nullptr;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright (C) 2021-2022, Dmitry Maluev (dmaluev@gmail.com). All rights reserved.
|
||||
#pragma once
|
||||
|
||||
namespace verus
|
||||
{
|
||||
namespace World
|
||||
{
|
||||
class BlockChainNode : public BaseNode
|
||||
{
|
||||
public:
|
||||
struct SourceModel
|
||||
{
|
||||
Vector<Range> _vSlots;
|
||||
ModelNodePtr _modelNode;
|
||||
String _arguments;
|
||||
float _length = 0;
|
||||
bool _noPhysicsNode = false;
|
||||
bool _noShadowCaster = false;
|
||||
|
||||
bool IsAssignedToSlot(int slot) const;
|
||||
};
|
||||
VERUS_TYPEDEFS(SourceModel);
|
||||
|
||||
private:
|
||||
Vector<SourceModel> _vSourceModels;
|
||||
bool _async_generatedNodes = false;
|
||||
|
||||
public:
|
||||
struct Desc : BaseNode::Desc
|
||||
{
|
||||
PBaseNode _pPathNode = nullptr;
|
||||
|
||||
Desc(PBaseNode pPathNode = nullptr) : _pPathNode(pPathNode) {}
|
||||
};
|
||||
VERUS_TYPEDEFS(Desc);
|
||||
|
||||
BlockChainNode();
|
||||
virtual ~BlockChainNode();
|
||||
|
||||
void Init(RcDesc desc);
|
||||
void Done();
|
||||
|
||||
virtual void Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication) override;
|
||||
|
||||
virtual void Update() override;
|
||||
|
||||
virtual void GetEditorCommands(Vector<EditorCommand>& v) override;
|
||||
virtual void ExecuteEditorCommand(RcEditorCommand command) override;
|
||||
|
||||
virtual bool CanSetParent(PBaseNode pNode) const override;
|
||||
|
||||
virtual void OnNodeDeleted(PBaseNode pNode, bool afterEvent, bool hierarchy) override;
|
||||
|
||||
virtual void Serialize(IO::RSeekableStream stream) override;
|
||||
virtual void Deserialize(IO::RStream stream) override;
|
||||
|
||||
bool BindSourceModel(PModelNode pModelNode);
|
||||
bool UnbindSourceModel(PModelNode pModelNode);
|
||||
int GetSourceModelCount() const;
|
||||
PcSourceModel GetSourceModelForSlot(int slot) const;
|
||||
ModelNodePtr GetModelNodeForSlot(int slot) const;
|
||||
|
||||
template<typename T>
|
||||
void ForEachSourceModel(const T& fn)
|
||||
{
|
||||
for (auto& x : _vSourceModels)
|
||||
fn(x);
|
||||
}
|
||||
|
||||
float GetLengthForSlot(int slot) const;
|
||||
|
||||
void ParseArguments();
|
||||
};
|
||||
VERUS_TYPEDEFS(BlockChainNode);
|
||||
|
||||
class BlockChainNodePtr : public Ptr<BlockChainNode>
|
||||
{
|
||||
public:
|
||||
void Init(BlockChainNode::RcDesc desc);
|
||||
void Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication);
|
||||
};
|
||||
VERUS_TYPEDEFS(BlockChainNodePtr);
|
||||
|
||||
class BlockChainNodePwn : public BlockChainNodePtr
|
||||
{
|
||||
public:
|
||||
~BlockChainNodePwn() { Done(); }
|
||||
void Done();
|
||||
};
|
||||
VERUS_TYPEDEFS(BlockChainNodePwn);
|
||||
}
|
||||
}
|
|
@ -18,8 +18,13 @@ BlockNode::~BlockNode()
|
|||
|
||||
void BlockNode::Init(RcDesc desc)
|
||||
{
|
||||
SetOctreeElementFlag();
|
||||
if (!(_flags & Flags::readOnlyFlags))
|
||||
{
|
||||
SetOctreeElementFlag();
|
||||
SetShadowCasterFlag();
|
||||
}
|
||||
BaseNode::Init(desc._name ? desc._name : desc._modelURL);
|
||||
SetShadowCasterFlag();
|
||||
|
||||
ModelNode::Desc modelDesc;
|
||||
modelDesc._url = desc._modelURL;
|
||||
|
@ -38,9 +43,9 @@ void BlockNode::Done()
|
|||
VERUS_DONE(BlockNode);
|
||||
}
|
||||
|
||||
void BlockNode::Duplicate(RBaseNode node)
|
||||
void BlockNode::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
BaseNode::Duplicate(node);
|
||||
BaseNode::Duplicate(node, hierarchyDuplication);
|
||||
|
||||
RBlockNode blockNode = static_cast<RBlockNode>(node);
|
||||
|
||||
|
@ -219,12 +224,12 @@ void BlockNodePtr::Init(BlockNode::RcDesc desc)
|
|||
_p->Init(desc);
|
||||
}
|
||||
|
||||
void BlockNodePtr::Duplicate(RBaseNode node)
|
||||
void BlockNodePtr::Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication)
|
||||
{
|
||||
VERUS_QREF_WM;
|
||||
VERUS_RT_ASSERT(!_p);
|
||||
_p = wm.InsertBlockNode();
|
||||
_p->Duplicate(node);
|
||||
_p->Duplicate(node, hierarchyDuplication);
|
||||
}
|
||||
|
||||
void BlockNodePwn::Done()
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace verus
|
|||
void Init(RcDesc desc);
|
||||
void Done();
|
||||
|
||||
virtual void Duplicate(RBaseNode node) override;
|
||||
virtual void Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication) override;
|
||||
|
||||
virtual void Update() override;
|
||||
|
||||
|
@ -64,7 +64,7 @@ namespace verus
|
|||
{
|
||||
public:
|
||||
void Init(BlockNode::RcDesc desc);
|
||||
void Duplicate(RBaseNode node);
|
||||
void Duplicate(RBaseNode node, HierarchyDuplication hierarchyDuplication);
|
||||
};
|
||||
VERUS_TYPEDEFS(BlockNodePtr);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue