diff --git a/Engine/Engine.vcxproj b/Engine/Engine.vcxproj index b9d767d..1df1b2a 100644 --- a/Engine/Engine.vcxproj +++ b/Engine/Engine.vcxproj @@ -281,6 +281,8 @@ + + @@ -304,6 +306,11 @@ Compute 4.0 + + Compute + 5.0 + Compute + Compute 5.0 @@ -544,16 +551,6 @@ Compute /O2 /Gpp %(AdditionalOptions) - - Compute - 5.0 - Compute - 4.0 - Compute - 5.0 - Compute - 4.0 - Compute 5.0 @@ -583,6 +580,26 @@ Compute 5.0 + + Compute + Compute + 5.0 + + + Compute + 5.0 + Compute + + + Compute + Compute + 5.0 + + + Compute + Compute + 5.0 + Compute 5.0 diff --git a/Engine/Engine.vcxproj.filters b/Engine/Engine.vcxproj.filters index 368f0a1..1781cb9 100644 --- a/Engine/Engine.vcxproj.filters +++ b/Engine/Engine.vcxproj.filters @@ -72,6 +72,12 @@ {bf606861-2003-454a-ab74-7da83189dc71} + + {9096dc46-36a8-4493-a27e-62a0f4af9708} + + + {2a4aab81-82e6-49c4-87e3-12d55f5bcc26} + @@ -436,6 +442,12 @@ Engine\Core\Shaders\Common + + Engine\Core\Shaders\RayTrace + + + Engine\Core\Shaders\RayTrace + @@ -534,9 +546,6 @@ Engine\Core\Shaders\Particles - - Engine\Core\Shaders\RayTrace - Engine\Core\Shaders\ComputeShaders @@ -576,23 +585,38 @@ Engine\Core\Shaders\ComputeShaders - - Engine\Core\Shaders\RayTrace - - - Engine\Core\Shaders\RayTrace - Engine\Core\Shaders\ComputeShaders + + Engine\Core\Shaders\ComputeShaders + - Engine\Core\Shaders\RayTrace + Engine\Core\Shaders\RayTrace\GI - Engine\Core\Shaders\RayTrace + Engine\Core\Shaders\RayTrace\GI + + + Engine\Core\Shaders\RayTrace\GI + + + Engine\Core\Shaders\RayTrace\GI + + + Engine\Core\Shaders\RayTrace\GI + + + Engine\Core\Shaders\RayTrace\Reflex + + + Engine\Core\Shaders\RayTrace\Reflex - Engine\Core\Shaders\RayTrace + Engine\Core\Shaders\RayTrace\Reflex + + + Engine\Core\Shaders\RayTrace\Reflex \ No newline at end of file diff --git a/Engine/Engine/Components/Lights.h b/Engine/Engine/Components/Lights.h index 6773c75..ada001a 100644 --- a/Engine/Engine/Components/Lights.h +++ b/Engine/Engine/Components/Lights.h @@ -122,11 +122,14 @@ namespace HotBite { D3D11_VIEWPORT shadow_vp = {}; public: + DirectionalLight(); DirectionalLight(const DirectionalLight& other) :DirectionalLight() { assert(!other.init && "Non copyable after init."); *this = other; } + + void SetDirty() { dirty = true; } void SetPosition(const float3& pos) { data.position = pos; } const float3& GetPosition() const { return data.position; } void SetFog(bool enable) { diff --git a/Engine/Engine/Core/BVH.cpp b/Engine/Engine/Core/BVH.cpp index c76c0f7..f6bfedd 100644 --- a/Engine/Engine/Core/BVH.cpp +++ b/Engine/Engine/Core/BVH.cpp @@ -171,7 +171,14 @@ namespace HotBite { int right_count = 0; int left_offset = 0; int right_offset = 0; - if (LENGHT_F3(extent) > FLT_EPSILON) + + if (nidx.index_count == 2) { + left_count = 1; + right_count = 1; + left_offset = nidx.index_offset; + right_offset = left_offset + left_count; + + } else if (LENGHT_F3(extent) > FLT_EPSILON) { // in-place partition int i = nidx.index_offset; diff --git a/Engine/Engine/Core/BVH.h b/Engine/Engine/Core/BVH.h index 79b136c..d9392c9 100644 --- a/Engine/Engine/Core/BVH.h +++ b/Engine/Engine/Core/BVH.h @@ -140,7 +140,8 @@ namespace HotBite { return size; } - HRESULT Prepare(int size, DXGI_FORMAT format) { + HRESULT Prepare(int size) { + Unprepare(); HRESULT hr = S_OK; ID3D11Device* device = Core::DXCore::Get()->device; @@ -155,53 +156,35 @@ namespace HotBite { bd.ByteWidth = data_size; bd.CPUAccessFlags = 0; bd.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; - bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; bd.StructureByteStride = sizeof(T); uint8_t* nullData = new uint8_t[data_size]; memset(nullData, 0, data_size); initialData.pSysMem = nullData; hr = device->CreateBuffer(&bd, &initialData, &buffer); + assert(SUCCEEDED(hr)); delete[] nullData; - if (FAILED(hr)) { goto end; } - - srvDesc.Format = format; + + srvDesc.Format = DXGI_FORMAT_UNKNOWN; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; srvDesc.Buffer.FirstElement = 0; srvDesc.Buffer.NumElements = size; hr = device->CreateShaderResourceView(buffer, &srvDesc, &srv); - + assert(SUCCEEDED(hr)); srv->GetResource(&resource); uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - uav_desc.Format = format; + uav_desc.Format = DXGI_FORMAT_UNKNOWN; uav_desc.Buffer.FirstElement = 0; uav_desc.Buffer.NumElements = size; hr = device->CreateUnorderedAccessView(resource, &uav_desc, &uav); + assert(SUCCEEDED(hr)); + this->size = size; - - end: return hr; } - void Clear(T val, uint32_t start = 0, uint32_t len = 0) { - return; - if (len == 0) { - len = (uint32_t)size; - } - if (len > 0 && start < (uint32_t)size) { - ID3D11DeviceContext* context = Core::DXCore::Get()->context; - D3D11_MAPPED_SUBRESOURCE resource; - context->Map(buffer, 0, D3D11_MAP_WRITE, 0, &resource); - T* data = (T*)resource.pData; - for (uint32_t i = start; i < len; ++i) { - data[i] = val; - } - context->Unmap(buffer, 0); - } - } - - HRESULT Unprepare() { ID3D11DeviceContext* context = Core::DXCore::Get()->context; HRESULT hr = S_OK; @@ -221,8 +204,8 @@ namespace HotBite { return hr; } - ID3D11ShaderResourceView* SRV() const { - return srv; + ID3D11ShaderResourceView*const* SRV() const { + return &srv; } ID3D11UnorderedAccessView*const* UAV() const { diff --git a/Engine/Engine/Core/DXCore.cpp b/Engine/Engine/Core/DXCore.cpp index afa38e5..84d5a34 100644 --- a/Engine/Engine/Core/DXCore.cpp +++ b/Engine/Engine/Core/DXCore.cpp @@ -38,6 +38,126 @@ using namespace HotBite::Engine::ECS; DXCore* DXCore::DXCoreInstance = nullptr; Direct2D* Direct2D::instance = nullptr; +#include +#include +#include + +#include + + +HRESULT _D3D11CreateDevice( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext, + ID3D12Device** ppd3d12device) { + + + HRESULT hr = D3D12CreateDevice(pAdapter, + D3D_FEATURE_LEVEL_12_0, + IID_PPV_ARGS(ppd3d12device)); + + if (FAILED(hr)) + return hr; + + D3D12_COMMAND_QUEUE_DESC desc; + desc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + desc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + desc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + desc.NodeMask = 0; + + ID3D12CommandQueue* d3d12queue; + + hr = (*ppd3d12device)->CreateCommandQueue(&desc, + IID_PPV_ARGS(&d3d12queue)); + + if (FAILED(hr)) + return hr; + + hr = D3D11On12CreateDevice((*ppd3d12device), + Flags, pFeatureLevels, FeatureLevels, + reinterpret_cast(&d3d12queue), + 1, 0, ppDevice, ppImmediateContext, pFeatureLevel); + + return hr; +} + + +HRESULT _D3D11CreateDeviceAndSwapChain( + IDXGIAdapter* pAdapter, + D3D_DRIVER_TYPE DriverType, + HMODULE Software, + UINT Flags, + const D3D_FEATURE_LEVEL* pFeatureLevels, + UINT FeatureLevels, + UINT SDKVersion, + const DXGI_SWAP_CHAIN_DESC* pSwapChainDesc, + IDXGISwapChain** ppSwapChain, + ID3D11Device** ppDevice, + D3D_FEATURE_LEVEL* pFeatureLevel, + ID3D11DeviceContext** ppImmediateContext, + ID3D12Device** ppd3d12device) { + if (ppSwapChain && !pSwapChainDesc) + return E_INVALIDARG; + + ID3D11Device* d3d11Device; + ID3D11DeviceContext* d3d11Context; + + HRESULT status = _D3D11CreateDevice(pAdapter, DriverType, + Software, Flags, pFeatureLevels, FeatureLevels, + SDKVersion, &d3d11Device, pFeatureLevel, &d3d11Context, ppd3d12device); + + if (FAILED(status)) + return status; + + if (ppSwapChain) { + IDXGIDevice* dxgiDevice = nullptr; + IDXGIAdapter* dxgiAdapter = nullptr; + IDXGIFactory* dxgiFactory = nullptr; + + HRESULT hr = d3d11Device->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + + if (FAILED(hr)) + return E_INVALIDARG; + + hr = dxgiDevice->GetParent(IID_PPV_ARGS(&dxgiAdapter)); + dxgiDevice->Release(); + + if (FAILED(hr)) + return E_INVALIDARG; + + hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory)); + dxgiAdapter->Release(); + + if (FAILED(hr)) + return E_INVALIDARG; + + DXGI_SWAP_CHAIN_DESC desc = *pSwapChainDesc; + hr = dxgiFactory->CreateSwapChain(d3d11Device, &desc, ppSwapChain); + dxgiFactory->Release(); + + if (FAILED(hr)) + return hr; + } + + if (ppDevice != nullptr) + *ppDevice = d3d11Device; + else + d3d11Device->Release(); + + if (ppImmediateContext != nullptr) + *ppImmediateContext = d3d11Context; + else + d3d11Context->Release(); + + return S_OK; +} LRESULT DXCore::WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -122,6 +242,7 @@ DXCore::~DXCore() } #endif if (device) { device->Release(); } + if (d12device) { d12device->Release(); } } HRESULT DXCore::InitWindow(HWND parent) diff --git a/Engine/Engine/Core/DXCore.h b/Engine/Engine/Core/DXCore.h index b3e3473..0c9e719 100644 --- a/Engine/Engine/Core/DXCore.h +++ b/Engine/Engine/Core/DXCore.h @@ -27,6 +27,7 @@ SOFTWARE. #include #include #include +#include #include #include "../Defines.h" @@ -38,6 +39,7 @@ SOFTWARE. #include #pragma comment(lib, "d3d11.lib") +#pragma comment(lib, "d3d12.lib") #pragma comment(lib, "d2d1.lib") #pragma comment(lib, "dwrite.lib") @@ -141,7 +143,7 @@ namespace HotBite { float GetScreenHeight() const { return screen_dimensions.y; } public: - + ID3D12Device* d12device = nullptr; ID3D11Device* device = nullptr; ID3D11DeviceContext* context = nullptr; ID3D11SamplerState* basic_sampler = nullptr; diff --git a/Engine/Engine/Core/Material.cpp b/Engine/Engine/Core/Material.cpp index 2da3333..6331634 100644 --- a/Engine/Engine/Core/Material.cpp +++ b/Engine/Engine/Core/Material.cpp @@ -204,6 +204,9 @@ namespace HotBite { if (j.value("parallax_shadows", false)) { props.flags |= PARALLAX_SHADOW_ENABLED_FLAG; } + props.alphaColor = parseColorStringF3(j.value("alpha_color", "#00000000")); + props.alphaThreshold = j.value("alpha_threshold", 0.4f); + SetTexture(diffuse, texture_names.diffuse_texname, root, j.value("diffuse_textname", "")); SetTexture(high, texture_names.high_textname, root, j.value("high_textname", "")); SetTexture(normal, texture_names.normal_textname, root, j.value("normal_textname", "")); diff --git a/Engine/Engine/Core/Material.h b/Engine/Engine/Core/Material.h index 9decd76..41579b2 100644 --- a/Engine/Engine/Core/Material.h +++ b/Engine/Engine/Core/Material.h @@ -48,7 +48,8 @@ namespace HotBite { float3 emission_color = {}; float rt_reflex = 0.2f; - float3 padding; + float alphaThreshold = 0.4f; + float2 padding; float3 alphaColor = {}; #define NORMAL_MAP_ENABLED_FLAG 1 diff --git a/Engine/Engine/Core/Shaders/Common/MultiTexture.hlsli b/Engine/Engine/Core/Shaders/Common/MultiTexture.hlsli index b617046..d1f6b1a 100644 --- a/Engine/Engine/Core/Shaders/Common/MultiTexture.hlsli +++ b/Engine/Engine/Core/Shaders/Common/MultiTexture.hlsli @@ -80,7 +80,7 @@ void getValues(out float output_values[MAX_MULTI_TEXTURE], SamplerState basicSam } } -float3 getMutliTextureValue(SamplerState basicSampler, uint type, uint count, const uint op[MAX_MULTI_TEXTURE], const float val[MAX_MULTI_TEXTURE], +float4 getMutliTextureValue(SamplerState basicSampler, uint type, uint count, const uint op[MAX_MULTI_TEXTURE], const float val[MAX_MULTI_TEXTURE], const float uv_scales[MAX_MULTI_TEXTURE], float2 uv, const Texture2D text[MAX_MULTI_TEXTURE]) { float3 color = { 0.0f, 0.0f, 0.0f }; uint i; @@ -119,7 +119,7 @@ float3 getMutliTextureValue(SamplerState basicSampler, uint type, uint count, co }break; } } - return color; + return float4(color, 1.0f); } float3 getMutliTextureValueLevel(SamplerState basicSampler, uint level, uint type, diff --git a/Engine/Engine/Core/Shaders/Common/PixelCommon.hlsli b/Engine/Engine/Core/Shaders/Common/PixelCommon.hlsli index b5c6a9b..1a55917 100644 --- a/Engine/Engine/Core/Shaders/Common/PixelCommon.hlsli +++ b/Engine/Engine/Core/Shaders/Common/PixelCommon.hlsli @@ -97,7 +97,8 @@ struct MaterialColor float3 emission_color; float rt_reflex; - float3 padding; + float alphaThreshold; + float2 padding; float3 alphaColor; #define NORMAL_MAP_ENABLED_FLAG 1 << 0 diff --git a/Engine/Engine/Core/Shaders/Common/PixelFunctions.hlsli b/Engine/Engine/Core/Shaders/Common/PixelFunctions.hlsli index c37b3ac..da5bfaf 100644 --- a/Engine/Engine/Core/Shaders/Common/PixelFunctions.hlsli +++ b/Engine/Engine/Core/Shaders/Common/PixelFunctions.hlsli @@ -232,7 +232,7 @@ float3 DirVolumetricLight(float4 position, DirLight light, int index, float time float3 lcolor = light.Color.rgb * light.intensity; float3 color = { 0.f, 0.f, 0.f }; - float step = 0.5f; + float step = 0.4f; float max_vol = 1.0f; float3 ToEye = cameraPosition.xyz - position.xyz; @@ -329,7 +329,7 @@ float3 DirVolumetricLight(float4 position, DirLight light, int index, float time float3 VolumetricLight(float3 position, PointLight light, int index) { float3 color = { 0.f, 0.f, 0.f }; float3 step_color = light.Color.rgb; - float step = 0.5f; + float step = 0.4f; float max_vol = 0.3f; step_color.rgb *= (light.density * step); float3 intersection_position; diff --git a/Engine/Engine/Core/Shaders/Common/RayDefines.hlsli b/Engine/Engine/Core/Shaders/Common/RayDefines.hlsli index 38c19bc..2692f7b 100644 --- a/Engine/Engine/Core/Shaders/Common/RayDefines.hlsli +++ b/Engine/Engine/Core/Shaders/Common/RayDefines.hlsli @@ -26,11 +26,17 @@ SOFTWARE. #define RAY_DEFINES_ #define MAX_OBJECTS 100 -#define MAX_STACK_SIZE 50 +#define MAX_STACK_SIZE 20 + +#define GI_SCREEN 0 +#define GI_WORLD 1 + +#define REFLEX_SCREEN 0 +#define REFLEX_WORLD 1 //#define PACK_RAYS_8 -#define RAY_W_SCALE 2.0f -#define RAY_W_BIAS 0.0001f +#define RAY_W_SCALE 1.0f +#define RAY_W_BIAS 0.01f #ifdef PACK_RAYS_8 #define MAX_RAYS 8 @@ -50,6 +56,14 @@ struct BVHNode float4 reg1; // aabb_max + index; }; +#define MAX_RAY_INPUTS 4 +#define MAX_RAY_INPUTS_POS MAX_RAY_INPUTS / 2 +static const float MAX_RAY_POLAR_DIR = 2.0f * PI; //Maximum polar angle 2.0 * PI + +struct InputRays { + float4 dir2[MAX_RAY_INPUTS_POS]; +}; + struct Ray { float4 orig; float3 dir; @@ -68,14 +82,16 @@ struct RayObject { struct IntersectionResult { float3 v0; + float distance; + float3 v1; + uint object; + float3 v2; - - float distance; - float2 uv; + float u; uint3 vindex; - uint object; + float v; }; struct ObjectInfo diff --git a/Engine/Engine/Core/Shaders/Common/RayFunctions.hlsli b/Engine/Engine/Core/Shaders/Common/RayFunctions.hlsli index a166111..756562a 100644 --- a/Engine/Engine/Core/Shaders/Common/RayFunctions.hlsli +++ b/Engine/Engine/Core/Shaders/Common/RayFunctions.hlsli @@ -23,6 +23,10 @@ SOFTWARE. */ #include "RayDefines.hlsli" +ByteAddressBuffer vertexBuffer : register(t4); +ByteAddressBuffer indicesBuffer: register(t5); +Texture2D DiffuseTextures[MAX_OBJECTS]; + bool is_leaf(BVHNode node) { return (asuint(node.reg0.w) == 0); @@ -53,6 +57,15 @@ uint index(BVHNode node) return asuint(node.reg1.w); } +float node_distance(BVHNode node, float3 pos) +{ + float3 aabb0 = aabb_min(node); + float3 aabb1 = aabb_max(node); + float extent = length(aabb0 - aabb1) * 0.5f; + float3 center = (aabb0 + aabb1) * 0.5f; + float dist = max(length(center - pos) - extent, 0.0f); + return dist; +} bool IntersectTri(RayObject ray, uint indexOffset, uint vertexOffset, out IntersectionResult result) { @@ -108,7 +121,8 @@ bool IntersectTri(RayObject ray, uint indexOffset, uint vertexOffset, out Inters result.vindex = vindex; result.object = 0; result.distance = t; - result.uv = float2(u, v); + result.u = u; + result.v = v; return true; } @@ -278,7 +292,19 @@ float3 GetDiffuseColor(uint object, float2 uv) } } -Ray GetReflectedRayFromSource(RaySource source) +Ray GetRayInfoFromSourceWithNoDir(RaySource source) +{ + Ray ray; + ray.orig = float4(source.orig, 1.0f); + ray.dir = float3(0.0f, 1.0f, 0.0f); + ray.density = source.density; + ray.bounces = 0; + ray.ratio = 1.0f; + ray.t = FLT_MAX; + return ray; +} + +Ray GetReflectedRayFromSource(RaySource source, float3 cameraPosition) { Ray ray; ray.orig = float4(source.orig, 1.0f); @@ -294,7 +320,7 @@ Ray GetReflectedRayFromSource(RaySource source) return ray; } -Ray GetRefractedRayFromSource(RaySource source) +Ray GetRefractedRayFromSource(RaySource source, float3 cameraPosition) { Ray ray; ray.orig = float4(source.orig, 1.0f); diff --git a/Engine/Engine/Core/Shaders/Common/Utils.hlsli b/Engine/Engine/Core/Shaders/Common/Utils.hlsli index 970feca..032b620 100644 --- a/Engine/Engine/Core/Shaders/Common/Utils.hlsli +++ b/Engine/Engine/Core/Shaders/Common/Utils.hlsli @@ -27,7 +27,63 @@ SOFTWARE. #ifndef __UTILS_HLSLI__ #define __UTILS_HLSLI__ -float Epsilon = 1e-4; +static const float Epsilon = 1e-4; + +// Divide the 2D-Dispatch_Grid into tiles of dimension [N, DipatchGridDim.y] +// “CTA” (Cooperative Thread Array) == Thread Group in DirectX terminology +uint2 ThreadGroupTilingX( + const uint2 dipatchGridDim, // Arguments of the Dispatch call (typically from a ConstantBuffer) + const uint2 ctaDim, // Already known in HLSL, eg:[numthreads(8, 8, 1)] -> uint2(8, 8) + const uint maxTileWidth, // User parameter (N). Recommended values: 8, 16 or 32. + const uint2 groupThreadID, // SV_GroupThreadID + const uint2 groupId // SV_GroupID +) +{ + // A perfect tile is one with dimensions = [maxTileWidth, dipatchGridDim.y] + const uint Number_of_CTAs_in_a_perfect_tile = maxTileWidth * dipatchGridDim.y; + + // Possible number of perfect tiles + const uint Number_of_perfect_tiles = dipatchGridDim.x / maxTileWidth; + + // Total number of CTAs present in the perfect tiles + const uint Total_CTAs_in_all_perfect_tiles = Number_of_perfect_tiles * maxTileWidth * dipatchGridDim.y; + const uint vThreadGroupIDFlattened = dipatchGridDim.x * groupId.y + groupId.x; + + // Tile_ID_of_current_CTA : current CTA to TILE-ID mapping. + const uint Tile_ID_of_current_CTA = vThreadGroupIDFlattened / Number_of_CTAs_in_a_perfect_tile; + const uint Local_CTA_ID_within_current_tile = vThreadGroupIDFlattened % Number_of_CTAs_in_a_perfect_tile; + uint Local_CTA_ID_y_within_current_tile; + uint Local_CTA_ID_x_within_current_tile; + + if (Total_CTAs_in_all_perfect_tiles <= vThreadGroupIDFlattened) + { + // Path taken only if the last tile has imperfect dimensions and CTAs from the last tile are launched. + uint X_dimension_of_last_tile = dipatchGridDim.x % maxTileWidth; + X_dimension_of_last_tile = max(1, X_dimension_of_last_tile); + Local_CTA_ID_y_within_current_tile = Local_CTA_ID_within_current_tile / X_dimension_of_last_tile; + Local_CTA_ID_x_within_current_tile = Local_CTA_ID_within_current_tile % X_dimension_of_last_tile; + } + else + { + Local_CTA_ID_y_within_current_tile = Local_CTA_ID_within_current_tile / maxTileWidth; + Local_CTA_ID_x_within_current_tile = Local_CTA_ID_within_current_tile % maxTileWidth; + } + + const uint Swizzled_vThreadGroupIDFlattened = + Tile_ID_of_current_CTA * maxTileWidth + + Local_CTA_ID_y_within_current_tile * dipatchGridDim.x + + Local_CTA_ID_x_within_current_tile; + + uint2 SwizzledvThreadGroupID; + SwizzledvThreadGroupID.y = Swizzled_vThreadGroupIDFlattened / dipatchGridDim.x; + SwizzledvThreadGroupID.x = Swizzled_vThreadGroupIDFlattened % dipatchGridDim.x; + + uint2 SwizzledvThreadID; + SwizzledvThreadID.x = ctaDim.x * SwizzledvThreadGroupID.x + groupThreadID.x; + SwizzledvThreadID.y = ctaDim.y * SwizzledvThreadGroupID.y + groupThreadID.y; + + return SwizzledvThreadID.xy; +} float3 climit3(float3 color) { float m = max(color.r, max(color.g, color.b)); @@ -50,7 +106,36 @@ float4 climit4(float4 color) { float2 GetCloserPixel(float2 pixel, float ratio) { return round(round(pixel / ratio) * ratio); } + float4 GetInterpolatedColor(float2 uv, Texture2D text, float2 dimension) { + uv = saturate(uv); + // Calculate the texture coordinates in the range [0, 1] + float2 texCoords = uv * dimension; + + // Calculate the integer coordinates of the four surrounding pixels + int2 p00 = (int2)floor(texCoords); + int2 p11 = (int2)ceil(texCoords); + int2 p01 = int2(p00.x, p11.y); + int2 p10 = int2(p11.x, p00.y); + + // Calculate the fractional part of the coordinates + float2 f = frac(texCoords); + + // Calculate the weights for bilinear interpolation + float w00 = (1.0f - f.x) * (1.0f - f.y); + float w11 = f.x * f.y; + float w01 = (1.0f - f.x) * f.y; + float w10 = f.x * (1.0f - f.y); + + // Perform the bilinear interpolation + return (text[p00] * w00 + + text[p11] * w11 + + text[p01] * w01 + + text[p10] * w10); +} + +float4 GetInterpolatedColor(float2 uv, RWTexture2D text, float2 dimension) { + uv = saturate(uv); // Calculate the texture coordinates in the range [0, 1] float2 texCoords = uv * dimension; @@ -116,6 +201,61 @@ float3 GenerateDirection(int i, int N) { return float3(x, y, z); } +float2 GetPolarCoordinates(float3 dir) { + float theta = atan2(dir.z, dir.x); + float phi = acos(dir.y); + return float2(phi, theta); +} + +float3 GetCartesianCoordinates(float phi, float theta) { + float sinPhi = sin(phi); + float cosPhi = cos(phi); + float sinTheta = sin(theta); + float cosTheta = cos(theta); + + return float3(sinPhi * cosTheta, cosPhi, sinPhi * sinTheta); +} + +float3 GetCartesianCoordinates(float2 coords) { + return GetCartesianCoordinates(coords.x, coords.y); +} + +float2 GenerateHemisphereDispersedRay(float3 dir, float3 tangent, float3 bitangent, float dispersion, float N, float NLevels, float rX) +{ + float index = (rX * dispersion) % N; + + //index = (frame_count) % N; + float N_SQRT = sqrt(N); + float cumulativePoints = 1.0f; + float level = 1.0f; + float c = 1.0f; + float phi; + while (c < index) { + phi = (level * M_PI * 0.5f) / NLevels; + c = cumulativePoints + N_SQRT * sin(phi); + cumulativePoints = c; + level++; + }; + level--; + + phi = (level * M_PI * 0.5f) / NLevels; + + float pointsAtLevel = 1.0f + N_SQRT * sin(phi); + + float localIndex = index - cumulativePoints; + float theta = (2.0f * M_PI) * localIndex / pointsAtLevel; + + float3 localRay = GetCartesianCoordinates(phi, theta); + + float3 globalRay = localRay.x * tangent + localRay.y * dir + localRay.z * bitangent; + + return GetPolarCoordinates(normalize(dir + globalRay)); +} + +bool ValidUVCoord(float2 uv_coord) { + return (uv_coord.x >= 0.0f && uv_coord.x < 1.0f && + uv_coord.y >= 0.0f && uv_coord.y < 1.0f); +} void GetSpaceVectors(in float3 dir, out float3 tangent, out float3 bitangent) { float3 up = abs(dir.z) < 0.999f ? float3(0.0f, 0.0f, 1.0f) : float3(1.0f, 0.0f, 0.0f); @@ -144,6 +284,64 @@ uint ToByte(float val, float range) return (uint)val; } +float FromByte(uint val, float range) +{ + float fval = (float)val; + fval = range * clamp(fval, 0.0f, 255.0f) / 255.0f; + return fval; +} + +int ToI16(float val, float range) +{ + val = 32768.0f * clamp(val, -range, range) / range; + return (int)val; +} + +float FromI16(int val, float range) +{ + float fval = (float)val; + fval = range * clamp(fval, -32768.0f, 32768.0f) / 32768.0f; + return fval; +} + +uint PackTwoInt16(int low, int high) { + return ( ((low & 0xFFFF) << 16) | (high & 0xFFFF) ); +} + +void UnpackTwoInt16(uint packedValue, out int low, out int high) { + int intPackedValue = asint(packedValue); + low = (intPackedValue >> 16); + high = (intPackedValue << 16) >> 16; +} + +uint4 Pack4Float2ToI16(float2 values[4], float max_value) +{ + uint4 data; + data.r = PackTwoInt16(ToI16(values[0].x, max_value), ToI16(values[0].y, max_value)); + data.g = PackTwoInt16(ToI16(values[1].x, max_value), ToI16(values[1].y, max_value)); + data.b = PackTwoInt16(ToI16(values[2].x, max_value), ToI16(values[2].y, max_value)); + data.a = PackTwoInt16(ToI16(values[3].x, max_value), ToI16(values[3].y, max_value)); + return data; +} + +void Unpack4Float2FromI16(uint4 data, float max_value, out float2 values[4]) +{ + int low; + int high; + UnpackTwoInt16(data.r, low, high); + values[0].x = FromI16(low, max_value); + values[0].y = FromI16(high, max_value); + UnpackTwoInt16(data.g, low, high); + values[1].x = FromI16(low, max_value); + values[1].y = FromI16(high, max_value); + UnpackTwoInt16(data.b, low, high); + values[2].x = FromI16(low, max_value); + values[2].y = FromI16(high, max_value); + UnpackTwoInt16(data.a, low, high); + values[3].x = FromI16(low, max_value); + values[3].y = FromI16(high, max_value); +} + uint4 Pack8Bytes(float values[8], float max_value) { uint4 data; @@ -164,13 +362,6 @@ uint4 Pack16Bytes(float values[16], float max_value) return data; } -float FromByte(uint val, float range) -{ - float fval = (float)val; - fval = range * clamp(fval, 0.0f, 255.0f) / 255.0f; - return fval; -} - void Unpack8Bytes(uint4 data, float max_value, out float values[8]) { uint d0 = data.r; diff --git a/Engine/Engine/Core/Shaders/ComputeShaders/BlurCS.hlsl b/Engine/Engine/Core/Shaders/ComputeShaders/BlurCS.hlsl index aad5eaf..ae0f86f 100644 --- a/Engine/Engine/Core/Shaders/ComputeShaders/BlurCS.hlsl +++ b/Engine/Engine/Core/Shaders/ComputeShaders/BlurCS.hlsl @@ -7,7 +7,7 @@ Texture2D vol_data: register(t0); #define EPSILON 1e-6 #define VERTICAL 1 #define HORIZONTAL 2 -#define KERNEL_SIZE 19 +#define KERNEL_SIZE 1 #define HALF_KERNEL KERNEL_SIZE/2 cbuffer externalData : register(b0) { @@ -15,38 +15,24 @@ cbuffer externalData : register(b0) float variance; } -void FillGaussianArray(out float array[KERNEL_SIZE]) +static const float BlurWeights32[33] = { - float sum = 0.0; - int halfSize = KERNEL_SIZE / 2; - int i; - float v = 5.0f; - for (i = -HALF_KERNEL; i <= HALF_KERNEL; ++i) - { - int x = i; - array[i + halfSize] = exp(-(x * x) / (2.0f * v * v)) / sqrt(2.0f * 3.14159265358979323846f * v * v); - sum += array[i + halfSize]; - } + 0.0216771440357829, 0.023030174945629842, 0.024372268162712405, 0.0256920167211696, 0.026977641631473703, 0.028217160189400764, 0.02939856710486361, 0.030510024758829798, 0.03154005846550627, 0.032477752297221024, 0.033312940837257485, 0.03403639217321265, 0.034639977537105585, 0.03511682323976621, 0.035461440931519074, 0.035669832738636206, 0.03573956845982569, 0.035669832738636206, 0.035461440931519074, 0.03511682323976621, 0.034639977537105585, 0.03403639217321265, 0.033312940837257485, 0.032477752297221024, 0.03154005846550627, 0.030510024758829798, 0.02939856710486361, 0.028217160189400764, 0.026977641631473703, 0.0256920167211696, 0.024372268162712405, 0.023030174945629842, 0.0216771440357829 +}; - // Normalize the array - for (i = 0; i < KERNEL_SIZE; ++i) - { - array[i] /= sum; +float4 blur32(RWTexture2D t, float2 pos, int type) { + float4 color = float4(0.f, 0.f, 0.f, 1.f); + if (type == HORIZONTAL) { + for (int dx = -16; dx <= 16; ++dx) { + color += t.Load(float3(pos.x + dx, pos.y, 0)) * BlurWeights32[dx + 16]; + } } -} - -float4 getColor(float2 pixel, float2 dir) -{ - - float BlurWeights[KERNEL_SIZE]; - FillGaussianArray(BlurWeights); - float4 color = float4(0.f, 0.f, 0.f, 0.f); - float2 tpos; - for (int i = -HALF_KERNEL; i <= HALF_KERNEL; ++i) { - tpos = pixel + dir * i; - color += input[tpos] * BlurWeights[i + HALF_KERNEL]; + else { + for (int dy = -16; dy <= 16; ++dy) { + color += t.Load(float3(pos.x, pos.y + dy, 0)) * BlurWeights32[dy + 16]; } - return color; + } + return color; } @@ -55,28 +41,21 @@ float4 getColor(float2 pixel, float2 dir) [numthreads(NTHREADS, NTHREADS, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - uint2 dir = { 0, 0 }; - if (type == VERTICAL) { - dir = uint2(0, 1); - } - else if (type == HORIZONTAL) { - dir = uint2(1, 0); - } - uint2 dimensions; uint w, h; input.GetDimensions(w, h); float2 pixel = float2(DTid.x, DTid.y); float global = (float)vol_data[uint2(0, 0)] / (float)(w * h * 1000); //Linear function for global atenuation y = −x + (1 + (MAX_GLOBAL_ILLUMINATION) -#define MAX_GLOBAL_ILLUMINATION 0.5f +#define MAX_GLOBAL_ILLUMINATION 0.4f float att = 1.0f; global *= global; global *= global; att = -global + (1.0f + MAX_GLOBAL_ILLUMINATION); - float4 color = getColor(pixel, dir); + //float4 color = blur32(input, pixel, type); + float4 color = input.Load(float3(pixel.x, pixel.y, 0)); if (type == HORIZONTAL) { - color *= att; + //color *= att; } output[pixel] = max(color, 0); } diff --git a/Engine/Engine/Core/Shaders/ComputeShaders/HiZDownSample.hlsl b/Engine/Engine/Core/Shaders/ComputeShaders/HiZDownSample.hlsl new file mode 100644 index 0000000..ce3ebaf --- /dev/null +++ b/Engine/Engine/Core/Shaders/ComputeShaders/HiZDownSample.hlsl @@ -0,0 +1,76 @@ +/* +The HotBite Game Engine + +Copyright(c) 2024 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "..\Common\Defines.hlsli" +cbuffer externalData : register(b0) +{ + uint ratio; + uint type; +} + +Texture2D input : register(t0); +RWTexture2D output : register(u0); + +#define NTHREADS 32 +#define VERTICAL 1 +#define HORIZONTAL 2 + +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + float2 input_dimensions = { 0, 0 }; + input.GetDimensions(input_dimensions.x, input_dimensions.y); + + float2 in_pixel; + float2 out_pixel = float2(DTid.x, DTid.y); + float depth = FLT_MAX; + uint2 dir = { 0, 0 }; + int kernel_size = ratio / 2; + + if (type == VERTICAL) { + dir = uint2(0, 1); + in_pixel = float2(DTid.x, DTid.y * ratio); + } + else if (type == HORIZONTAL) { + dir = uint2(1, 0); + in_pixel = float2(DTid.x * ratio, DTid.y); + } + + uint2 tpos = in_pixel; + for (int i = -kernel_size; i <= kernel_size; ++i) { + tpos += dir; + if (tpos.x >= 0 && tpos.x < input_dimensions.x && tpos.y >= 0 && tpos.y < input_dimensions.y) { + float tmp_depth = input[tpos]; + if (tmp_depth < FLT_MAX) { + depth = min(depth, tmp_depth); + } + } + } + + if (depth < 0.0f) { + depth = FLT_MAX; + } + + output[out_pixel] = depth; +} diff --git a/Engine/Engine/Core/Shaders/ComputeShaders/RenderDustCS.hlsl b/Engine/Engine/Core/Shaders/ComputeShaders/RenderDustCS.hlsl index 7c82ce7..d11a41e 100644 --- a/Engine/Engine/Core/Shaders/ComputeShaders/RenderDustCS.hlsl +++ b/Engine/Engine/Core/Shaders/ComputeShaders/RenderDustCS.hlsl @@ -146,7 +146,7 @@ void main(uint3 DTid : SV_DispatchThreadID) color += CalcPoint(normal, wpos.xyz, pointLights[i], i); } } -#define MAX_GLOBAL_ILLUMINATION 1.0f +#define MAX_GLOBAL_ILLUMINATION 0.4f float global = (float)vol_data[uint2(0, 0)] / (float)(dimensions.x * dimensions.y * 1000); float att = 1.0f; global *= global; diff --git a/Engine/Engine/Core/Shaders/ComputeShaders/TextureMixerCS.hlsl b/Engine/Engine/Core/Shaders/ComputeShaders/TextureMixerCS.hlsl index 6c2a60f..01fbf8b 100644 --- a/Engine/Engine/Core/Shaders/ComputeShaders/TextureMixerCS.hlsl +++ b/Engine/Engine/Core/Shaders/ComputeShaders/TextureMixerCS.hlsl @@ -78,6 +78,7 @@ float4 Get3dInterpolatedColor(float2 uv, Texture2D text, float2 dimension, Textu float3 wp10 = positions[pos_p10].xyz; float3 wpxx = positions[in_pos].xyz; + [branch] if (wp00.x >= FLT_MAX || wp11.x >= FLT_MAX || wp01.x >= FLT_MAX || wp10.x >= FLT_MAX || wpxx.x >= FLT_MAX) { return GetInterpolatedColor(uv, text, dimension); } @@ -89,6 +90,7 @@ float4 Get3dInterpolatedColor(float2 uv, Texture2D text, float2 dimension, Textu float all_dist = d00 + d11 + d01 + d10; + [branch] if (all_dist < epsilon) { return GetInterpolatedColor(uv, text, dimension); } @@ -130,6 +132,7 @@ float4 Get3dInterpolatedColor(float2 uv, Texture2D text, float2 dimension, Textu // Normalize weights float totalWeight = w00 + w11 + w01 + w10; + [branch] if (totalWeight < epsilon) { return GetInterpolatedColor(uv, text, dimension); } @@ -145,29 +148,11 @@ float4 Get3dInterpolatedColor(float2 uv, Texture2D text, float2 dimension, Textu float4 readColor(float2 pixel, texture2D text, uint w, uint h) { uint w2, h2; text.GetDimensions(w2, h2); - if (w2 == w && h2 == h) { - return text.SampleLevel(basicSampler, pixel, 0); + if (w2 == w && h2 == h) { + return text[round(pixel * float2(w2, h2))]; } else { -#if 0 - float ratioW = ((float)w * 0.5f) / w2; - float ratioH = ((float)h * 0.5f) / h2; - uint n = 2; - float x = 0; - float y = 0; - float4 c = 2 * Get3dInterpolatedColor(pixel, text, float2(w2, h2), positions, normals, float2(w, h)); - for (x = -ratioW; x < ratioW; x++) { - for (y = -ratioH; y < ratioH; y++) { - c += text.SampleLevel(basicSampler, pixel + float2(x * 0.5f / w2, y * 0.5f / h2), 0); - //c += Get3dInterpolatedColor(pixel + float2(x / w, y / h), text, float2(w2, h2), positions, normals, float2(w, h)); - n++; - } - } - c /= n; - return c; -#else return Get3dInterpolatedColor(pixel, text, float2(w2, h2), positions, normals, float2(w, h)); -#endif } } @@ -194,17 +179,8 @@ void main(uint3 DTid : SV_DispatchThreadID) float4 dust = readColor(tpos, dustTexture, w, h); float4 lens_flare = readColor(tpos, lensFlareTexture, w, h); - if (rt_enabled) { - if (true) { //debug == 0) { - color = color * (l + rt0 + rt2) + rt1 + b + dust + lens_flare + vol; - } - else { - color = rt0 + rt1 + rt2; - } - } - else { - color = color * l + b + dust + lens_flare + vol; - } + color = color* (l + rt0 + rt2) + rt1 + b + dust + lens_flare + vol; + #if 1 output[pixel] = climit4(color); #else @@ -212,4 +188,5 @@ void main(uint3 DTid : SV_DispatchThreadID) float r = 1.0f + (0.1f * rgba_tnoise(p)); output[pixel] = climit4(color * r); #endif + } diff --git a/Engine/Engine/Core/Shaders/Effects/Lava/LavaPS.hlsl b/Engine/Engine/Core/Shaders/Effects/Lava/LavaPS.hlsl index cea11de..4b1b93e 100644 --- a/Engine/Engine/Core/Shaders/Effects/Lava/LavaPS.hlsl +++ b/Engine/Engine/Core/Shaders/Effects/Lava/LavaPS.hlsl @@ -120,7 +120,7 @@ float3 CalcLavaPoint(float3 normal, float3 position, float2 uv, PointLight light return finalColor; } -RenderTarget main(GSOutput input) +RenderTargetRT main(GSOutput input) { int i = 0; matrix worldViewProj = mul(view, projection); @@ -135,7 +135,7 @@ RenderTarget main(GSOutput input) float dz_pcf = depthTexture.SampleCmpLevelZero(PCFSampler, pos, depth_test); if (dz_pcf == 0.0f) { discard; } - RenderTarget output; + RenderTargetRT output; float depth = length(input.worldPos.xyz - cameraPosition); float dz = depthTexture.Sample(basicSampler, pos); @@ -209,6 +209,17 @@ RenderTarget main(GSOutput input) output.scene = finalColor * 0.6f * dz_pcf; lightColor += output.scene; output.light_map = saturate(lightColor); + + RaySource ray; + ray.orig = input.worldPos.xyz; + ray.dispersion = 0.0f; + ray.reflex = 1.0f; + ray.normal = normalize(float3(0.0f, 1.0f, 0.0f) + 0.1f * normal); + ray.density = material.density; + ray.opacity = 1.0f; + + output.rt_ray0_map = getColor0(ray); + output.rt_ray1_map = getColor1(ray); return output; } diff --git a/Engine/Engine/Core/Shaders/MainRender/MainRenderGS.hlsl b/Engine/Engine/Core/Shaders/MainRender/MainRenderGS.hlsl index 635172c..8715648 100644 --- a/Engine/Engine/Core/Shaders/MainRender/MainRenderGS.hlsl +++ b/Engine/Engine/Core/Shaders/MainRender/MainRenderGS.hlsl @@ -30,11 +30,19 @@ cbuffer externalData : register(b0) int screenH; matrix world; matrix inv_world; - matrix view; - matrix projection; + matrix view_projection; float3 cameraPosition; } +float4 frustumPlanes[6] = { + float4(1, 0, 0, 1), + float4(-1, 0, 0, 1), + float4(0, 1, 0, 1), + float4(0, -1, 0, 1), + float4(0, 0, 1, 1), + float4(0, 0, -1, 1) +}; + [maxvertexcount(3)] void main( triangle DomainOutput input[3], @@ -45,31 +53,64 @@ void main( bool process = false; float4 p[3]; - + float2 dimensions = { screenW , screenH }; + uint i = 0; for (i = 0; i < 3; i++) { - p[i] = mul(input[i].worldPos, mul(view, projection)); + p[i] = mul(input[i].worldPos, view_projection); } + + bool behind = true; for (i = 0; i < 3; i++) { - float2 pos; - pos = p[i].xy; - pos.x /= p[i].w; - pos.y /= -p[i].w; - pos.x = (pos.x + 1.0f) * 0.5f; - pos.y = (pos.y + 1.0f) * 0.5f; - if (pos.x > -screenW && pos.x < screenW && pos.y > -screenH && pos.y < screenH) { - process = true; + if (p[i].z >= 0.0f) { + behind = false; break; } } + + if (!behind) { + for (i = 0; i < 3; i++) { + float2 pos; + pos = p[i].xy; + pos.xy /= p[i].w; + pos.y *= -1.0f; + + pos.xy = (pos.xy + 1.0f) * 0.5f; + if (pos.x >= 0.0f && pos.x <= 1.0f && pos.y >= 0.0f && pos.y <= 1.0f) { + process = true; + break; + } + } + } + + if (!process) { + float3 pp[3]; + for (i = 0; i < 3; ++i) { + pp[i] = p[i].xyz / p[i].w; + } + + float3 normal = cross(pp[1].xyz - pp[0].xyz, pp[2].xyz - pp[0].xyz); + float d = dot(normal, pp[0].xyz); + float3 frustumCenter = float3(0.0f, 0.0f, 0.0f); + + for (int i = 0; i < 6; i++) { + frustumCenter += float3(frustumPlanes[i].x, frustumPlanes[i].y, frustumPlanes[i].z) * frustumPlanes[i].w; + } + frustumCenter /= 6.0f; + + if (abs(dot(normal, frustumCenter) + d) < length(normal)) { + process = true; + } + } #else bool process = true; float4 p[3]; uint i = 0; for (i = 0; i < 3; i++) { - p[i] = mul(input[i].worldPos, mul(view, projection)); + p[i] = mul(input[i].worldPos, view_projection); } #endif + if (process) { // Edges of the triangle : postion delta float3 edge1 = input[1].position.xyz - input[0].position.xyz; @@ -92,7 +133,6 @@ void main( bitangent.y = r * (-deltaUV2.x * edge1.y + deltaUV1.x * edge2.y); bitangent.z = r * (-deltaUV2.x * edge1.z + deltaUV1.x * edge2.z); } - matrix worldViewProj = mul(view, projection); for (uint i = 0; i < 3; i++) { GSOutput element; diff --git a/Engine/Engine/Core/Shaders/MainRender/MainRenderPS.hlsli b/Engine/Engine/Core/Shaders/MainRender/MainRenderPS.hlsli index 9e6eab9..b6d8767 100644 --- a/Engine/Engine/Core/Shaders/MainRender/MainRenderPS.hlsli +++ b/Engine/Engine/Core/Shaders/MainRender/MainRenderPS.hlsli @@ -57,7 +57,7 @@ RenderTargetRT MainRenderPS(GSOutput input) PointLightParallaxAtt[i] = 1.0f; } //wpos without parallax displacement - float3 wpos2 = wpos.xyz; + float3 wpos2 = wpos.xyz / wpos.w; if (material.flags & NORMAL_MAP_ENABLED_FLAG || multi_texture_count > 0) { // Build orthonormal basis. float3 N = normal; @@ -81,8 +81,8 @@ RenderTargetRT MainRenderPS(GSOutput input) } scale = abs(scale); + matrix global_to_tbn = inverse(tbn); if ((material.flags & PARALLAX_MAP_ENABLED_FLAG || multi_texture_count > 0 ) && scale != 0.0f) { - matrix global_to_tbn = inverse(tbn); float h = 0; float3 tbn_cam_pos = mul(float4(cameraPosition, 0.0f), global_to_tbn).xyz; float3 tbn_fragment_pos = mul(input.worldPos, global_to_tbn).xyz; @@ -122,11 +122,12 @@ RenderTargetRT MainRenderPS(GSOutput input) texture_normal = normalTexture.Sample(basicSampler, input.uv); } texture_normal = texture_normal * 2.0f - 1.0f; - normal = normalize(mul(texture_normal, (float3x3)tbn) + normal); + normal = normalize(mul(texture_normal, (float3x3)tbn) + normal); + } #if 1 - float4 lumColor = float4(0.0f, 0.0f, 0.0f, 0.0f); + float4 lumColor = float4(0.0f, 0.0f, 0.0f, 1.0f); // Calculate the ambient light lumColor.rgb += CalcAmbient(normal); #endif @@ -148,30 +149,32 @@ RenderTargetRT MainRenderPS(GSOutput input) #if 1 // Apply textures if (material.flags & DIFFUSSE_MAP_ENABLED_FLAG || multi_texture_count > 0) { - float3 text_color; + float4 text_color; if (multi_texture_count > 0) { text_color = getMutliTextureValue(basicSampler, MULTITEXT_DIFF, multi_texture_count, multi_texture_operations, - calculated_values, multi_texture_uv_scales, input.uv, multi_diffuseTexture).rgb; + calculated_values, multi_texture_uv_scales, input.uv, multi_diffuseTexture); } else { - text_color = diffuseTexture.Sample(basicSampler, input.uv).rgb; + text_color = diffuseTexture.Sample(basicSampler, input.uv); } if (material.flags & ALPHA_ENABLED_FLAG) { - if (length(material.alphaColor - text_color) > 0.4f) { - finalColor.rgb = text_color; + if (length(material.alphaColor - text_color) > material.alphaThreshold) { + finalColor = text_color; } else { discard; } } else { - finalColor.rgb = text_color; + finalColor = text_color; } } else { finalColor = material.diffuseColor; } + #endif + lumColor.a = finalColor.a; // Apply ambient occlusion if (multi_texture_count > 0) { @@ -205,13 +208,12 @@ RenderTargetRT MainRenderPS(GSOutput input) } opacity = saturate(opacity); finalColor *= opacity; - output.scene = finalColor; - output.light_map = lumColor + prevLightTexture[input.position.xy]; + output.light_map = lerp(prevLightTexture[input.position.xy], lumColor, lumColor.a); output.bloom_map = saturate(lightColor); RaySource ray; - ray.orig = wpos2.xyz; + ray.orig = wpos2; if (disable_rt == 0 && (material.flags & RAYTRACING_ENABLED)) { ray.dispersion = saturate(1.0f - spec_intensity); ray.reflex = material.rt_reflex; diff --git a/Engine/Engine/Core/Shaders/PostProcess/PostBlur.hlsl b/Engine/Engine/Core/Shaders/PostProcess/PostBlur.hlsl index 606f5f0..e1231f5 100644 --- a/Engine/Engine/Core/Shaders/PostProcess/PostBlur.hlsl +++ b/Engine/Engine/Core/Shaders/PostProcess/PostBlur.hlsl @@ -34,7 +34,7 @@ SamplerState basicSampler; static const float BlurWeights32[33] = { -0.0216771440357829, 0.023030174945629842, 0.024372268162712405, 0.0256920167211696, 0.026977641631473703, 0.028217160189400764, 0.02939856710486361, 0.030510024758829798, 0.03154005846550627, 0.032477752297221024, 0.033312940837257485, 0.03403639217321265, 0.034639977537105585, 0.03511682323976621, 0.035461440931519074, 0.035669832738636206, 0.03573956845982569, 0.035669832738636206, 0.035461440931519074, 0.03511682323976621, 0.034639977537105585, 0.03403639217321265, 0.033312940837257485, 0.032477752297221024, 0.03154005846550627, 0.030510024758829798, 0.02939856710486361, 0.028217160189400764, 0.026977641631473703, 0.0256920167211696, 0.024372268162712405, 0.023030174945629842, 0.0216771440357829 + 0.0216771440357829, 0.023030174945629842, 0.024372268162712405, 0.0256920167211696, 0.026977641631473703, 0.028217160189400764, 0.02939856710486361, 0.030510024758829798, 0.03154005846550627, 0.032477752297221024, 0.033312940837257485, 0.03403639217321265, 0.034639977537105585, 0.03511682323976621, 0.035461440931519074, 0.035669832738636206, 0.03573956845982569, 0.035669832738636206, 0.035461440931519074, 0.03511682323976621, 0.034639977537105585, 0.03403639217321265, 0.033312940837257485, 0.032477752297221024, 0.03154005846550627, 0.030510024758829798, 0.02939856710486361, 0.028217160189400764, 0.026977641631473703, 0.0256920167211696, 0.024372268162712405, 0.023030174945629842, 0.0216771440357829 }; static const float BlurWeights16[17] = diff --git a/Engine/Engine/Core/Shaders/Radiance/GIAverageCS.hlsl b/Engine/Engine/Core/Shaders/Radiance/GIAverageCS.hlsl index 6549568..93d454d 100644 --- a/Engine/Engine/Core/Shaders/Radiance/GIAverageCS.hlsl +++ b/Engine/Engine/Core/Shaders/Radiance/GIAverageCS.hlsl @@ -5,39 +5,41 @@ cbuffer externalData : register(b0) { uint debug; uint type; - matrix view; - matrix projection; + matrix prev_view_proj; float3 cameraPosition; uint frame_count; int kernel_size; } Texture2D input : register(t0); +Texture2D orig_input : register(t1); RWTexture2D output : register(u0); Texture2D positions : register(t2); Texture2D normals : register(t3); Texture2D prev_output : register(t4); Texture2D motion_texture : register(t5); Texture2D prev_position_map: register(t6); +Texture2D tiles_output: register(t7); + + +float GetPosW(int pos, float wk) { + return cos(pos * wk); +} + +//#define DEBUG +#define MIN_W 0.00001f #define NTHREADS 32 [numthreads(NTHREADS, NTHREADS, 1)] -void main(uint3 DTid : SV_DispatchThreadID) +void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID) { - float2 pixel = float2(DTid.x, DTid.y); - - if (debug == 1) { - output[pixel] = input[pixel]; - return; - } - - uint2 input_dimensions; - uint2 info_dimensions; + float2 input_dimensions; + float2 info_dimensions; { - uint w = 0; - uint h = 0; - uint w2 = 0; - uint h2 = 0; + int w = 0; + int h = 0; + int w2 = 0; + int h2 = 0; input.GetDimensions(w, h); output.GetDimensions(w2, h2); input_dimensions.x = min(w, w2); @@ -47,129 +49,182 @@ void main(uint3 DTid : SV_DispatchThreadID) info_dimensions.x = w; info_dimensions.y = h; } + + float2 pixel = ThreadGroupTilingX(input_dimensions / NTHREADS, uint2(NTHREADS, NTHREADS), 32, GTid.xy, Gid.xy); + +#ifdef DEBUG + if (debug == 1) { + output[pixel] = input[pixel]; + return; + } +#endif + float2 infoRatio = info_dimensions / input_dimensions; float2 rpixel = pixel * infoRatio; - //rpixel.x += frame_count % (infoRatio.x * 0.5f); - //rpixel.y += frame_count % (infoRatio.y * 0.5f) / 2.0f; float2 info_pixel = round(rpixel); float3 p0_position = positions[info_pixel].xyz; float3 p0_normal = normals[info_pixel].xyz; - float pixelMaxDist = 0.0f; - float worldMaxDist = 0.0f; - + float dist_to_cam = dist2(p0_position - cameraPosition); int x; int y; - float sigma = 1.0f; + static const float NORMAL_RATIO = 10.0f; + static const float sigma = 0.1f; + float total_w = 0.0f; float ww = 1.0f; float4 c = float4(0.0f, 0.0f, 0.0f, 0.0f); int full_kernel = 2 * kernel_size + 1; - int k = kernel_size + full_kernel * 2; - -#if 1 - //Convolution type - float2 dir = lerp(float2(1.0f, 0.0f), float2(0.0f, 1.0f), step(1.5, type)); - for (x = -k; x <= k; ++x) { - int2 p = pixel + x * dir; - - float2 p1_info_pixel = round(p * infoRatio); - ww = 1.0f; - if (abs(x) > k) { - float3 p1_position = positions[p1_info_pixel].xyz; - if (p1_position.x == FLT_MAX) continue; - float world_dist = dist2(p1_position - p0_position); - ww = exp(-world_dist / (2.0f * sigma * sigma)); + + [branch] + if (tiles_output[pixel / full_kernel] != 0) { + + float input_mix = 0.0f; + + int k = kernel_size + kernel_size + full_kernel; + float prev_w = input[pixel].a; + float wk = (M_PI / (2.0f * (float)k)); + + [branch] + if (prev_w < 0.0f) { + return; } - float3 p1_normal = normals[p1_info_pixel].xyz; - float n = saturate(dot(p1_normal, p0_normal)); - ww *= pow(n, max(5.0f / infoRatio.x, 1.0f)); + uint count = 0; + + [branch] + switch (type) + { + + //Execute pass 1 + case 1: { + //Pass 1 horizontal convolution + float2 dir = float2(1.0f, 0.0f); + + for (x = -k; x <= k; ++x) { + int2 p = (pixel + x * dir); + p.x += step(Epsilon, -p.x) * k; + p.x += step(Epsilon, p.x - input_dimensions.x) * -k; + + float2 p1_info_pixel = round(p * infoRatio); + ww = 1.0f; + + float3 p1_position = positions[p1_info_pixel].xyz; + float world_dist = dist2(p1_position - p0_position) / (dist_to_cam); + ww = exp(-world_dist / (2.0f * sigma * sigma)); + + float3 p1_normal = normals[p1_info_pixel].xyz; + float n = saturate(dot(p1_normal, p0_normal)); + ww *= pow(n, max(NORMAL_RATIO / infoRatio.x, 1.0f)); + ww *= GetPosW(x, wk); + ww = max(ww, MIN_W); + + c += input[p] * ww; + total_w += ww; + count++; + } + } break; + + //Execute pass 2 + case 2: { + float2 dir = float2(0.0f, 1.0f); + for (x = -k; x <= k; ++x) { + int2 p = (pixel + x * dir); + p.y += step(Epsilon, -p.y) * k; + p.y += step(Epsilon, p.y - input_dimensions.y) * -k; + + float2 p1_info_pixel = round(p * infoRatio); + ww = 1.0f; + + float3 p1_position = positions[p1_info_pixel].xyz; + float world_dist = dist2(p1_position - p0_position) / (dist_to_cam); + ww = exp(-world_dist / (2.0f * sigma * sigma)); + + float3 p1_normal = normals[p1_info_pixel].xyz; + float n = saturate(dot(p1_normal, p0_normal)); + ww *= pow(n, max(NORMAL_RATIO / infoRatio.x, 1.0f)); + ww *= GetPosW(x, wk); + ww = max(ww, MIN_W); + c.rgb += input[p].rgb * ww; + + total_w += ww; + count++; + } + } break; + + //Execute pass 3 + case 3: { + //Pass 2 convolution failed again, make a minimal 2D pass + [branch] + if (prev_w < 1.0f) { + k = kernel_size + kernel_size; + for (x = -k; x <= k; ++x) { + for (y = -k; y <= k; ++y) { + int2 p = pixel + int2(x, y); + p.x += step(Epsilon, -p.x) * k; + p.x += step(Epsilon, p.x - input_dimensions.x) * -k; + p.y += step(Epsilon, -p.y) * k; + p.y += step(Epsilon, p.y - input_dimensions.y) * -k; + float2 p1_info_pixel = round(p * infoRatio); + ww = 1.0f; + + float3 p1_position = positions[p1_info_pixel].xyz; + float world_dist = dist2(p1_position - p0_position) / (dist_to_cam); + ww = exp(-world_dist / (2.0f * sigma * sigma)); + + float3 p1_normal = normals[p1_info_pixel].xyz; + float n = saturate(dot(p1_normal, p0_normal)); + ww *= pow(n, max(NORMAL_RATIO / infoRatio.x, 1.0f)); + ww *= GetPosW(x, wk) * GetPosW(y, wk); + + c.rgb += orig_input[p].rgb * ww; + //c.rgb += float3(orig_input[p].r * ww, 0.0f, 1.0f); + total_w += ww; + count++; + } + } + input_mix = saturate(prev_w - 0.2f); + } + else { + // Pass2 convolution finished already, nothing to do in this pixel, just copy it + input_mix = 1.0f; + total_w = 1.0f; + c.a = 0.0f; + } + } break; + } - c += input[p] * ww; - total_w += ww; - } - static const float epsilon = 10e-4; - c = c * step(epsilon, total_w); - c = c / max(total_w, epsilon); + c = c / max(total_w, 1.0f); + + total_w /= k; + if (type == 1) { + c.a = total_w; + } + else { + c.a = prev_w + total_w; + } -#if 1 - if (type == 1) { + c = lerp(c, input[pixel], input_mix); + } +#if 0 + if (type < 3) { output[pixel] = c; } else { - matrix worldViewProj = mul(view, projection); - float4 prev_pos = mul(prev_position_map[info_pixel], worldViewProj); + float4 prev_pos = mul(prev_position_map[info_pixel], prev_view_proj); prev_pos.x /= prev_pos.w; prev_pos.y /= -prev_pos.w; - prev_pos.xy = (prev_pos.xy + 1.0f) * info_dimensions.xy / 2.0f; -#if 0 - float motion = length(motion_texture[prev_pos.xy].xy); - float2 mvector = motion_texture[info_pixel].xy; - if (mvector.x == -FLT_MAX) { - motion = 0.0f; - } - else { - motion = length(mvector); - } - if (motion < 0.005f) { - prev_pos.xy = pixel.xy; - } - else { - prev_pos.xy /= infoRatio; - } - float w = saturate(0.8f - motion * 100.0f); -#else - prev_pos.xy /= infoRatio; - float w = 0.3f; -#endif + prev_pos.xy = (prev_pos.xy + 1.0f) * input_dimensions.xy / 2.0f; + float w = 0.8f; float4 prev_color = prev_output[round(prev_pos.xy)]; - output[pixel] = prev_color * w + c * (1.0f - w); - } -#else - output[pixel] = c; -#endif - -#else - //Single pass type - for (x = -k; x <= k; ++x) { - for (y = -k; y <= k; ++y) { - int2 p = pixel + int2(x, y); - float2 p1_info_pixel = round(p * infoRatio); - float3 p1_position = positions[p1_info_pixel].xyz; - if (p1_position.x == FLT_MAX) continue; - - float world_dist = dist2(p1_position - p0_position); - ww = exp(-world_dist / (2.0f * sigma * sigma)); - - float3 p1_normal = normals[p1_info_pixel].xyz; - float n = saturate(dot(p1_normal, p0_normal)); - ww *= pow(n, 5.0f / infoRatio.x); - c += input[p] * ww; - total_w += ww; - } + output[pixel] = lerp(prev_color, c, w); } - static const float epsilon = 10e-4; - c = c * step(epsilon, total_w); - c = c / max(total_w, epsilon); - -#if 1 - matrix worldViewProj = mul(view, projection); - float4 prev_pos = mul(prev_position_map[info_pixel], worldViewProj); - prev_pos.x /= prev_pos.w; - prev_pos.y /= -prev_pos.w; - prev_pos.xy = (prev_pos.xy + 1.0f) * info_dimensions.xy / 2.0f; - prev_pos.xy /= infoRatio; - float4 prev_color = prev_output[floor(prev_pos.xy)]; - float w = 0.5f; - output[pixel] = prev_color * w + c * (1.0f - w); #else output[pixel] = c; #endif -#endif } diff --git a/Engine/Engine/Core/Shaders/RayTrace/DenoiserCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/DenoiserCS.hlsl index 08845f6..b424395 100644 --- a/Engine/Engine/Core/Shaders/RayTrace/DenoiserCS.hlsl +++ b/Engine/Engine/Core/Shaders/RayTrace/DenoiserCS.hlsl @@ -7,9 +7,9 @@ cbuffer externalData : register(b0) uint count; float3 cameraPosition; uint light_type; - matrix view; - matrix projection; + matrix view_projection; uint debug; + int kernel_size; } Texture2D input : register(t0); @@ -19,14 +19,12 @@ Texture2D positions : register(t2); Texture2D prev_output : register(t3); Texture2D motion_texture : register(t4); Texture2D prev_position_map: register(t5); -Texture2D dispersion: register(t6); +Texture2D tiles_output : register(t7); #define NTHREADS 32 [numthreads(NTHREADS, NTHREADS, 1)] -void main(uint3 DTid : SV_DispatchThreadID) +void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID) { - float2 pixel = float2(DTid.x, DTid.y); - uint2 input_dimensions; uint2 normals_dimensions; { @@ -43,6 +41,8 @@ void main(uint3 DTid : SV_DispatchThreadID) normals_dimensions.x = w; normals_dimensions.y = h; } + float2 pixel = ThreadGroupTilingX(input_dimensions / NTHREADS, uint2(NTHREADS, NTHREADS), 32, GTid.xy, Gid.xy); + uint2 normalRatio = normals_dimensions / input_dimensions; float2 info_pixel = round(pixel * normalRatio); @@ -51,7 +51,7 @@ void main(uint3 DTid : SV_DispatchThreadID) RaySource ray_source = fromColor(positions[info_pixel], normals[info_pixel]); float4 c = float4(0.0f, 0.0f, 0.0f, 0.0f); -#define HARD_MAX_KERNEL 40 +#define HARD_MAX_KERNEL 30 uint MAX_KERNEL = min(normals_dimensions.x / 32, HARD_MAX_KERNEL); float count = 0.0f; @@ -63,34 +63,25 @@ void main(uint3 DTid : SV_DispatchThreadID) float disp = -1.0f; uint min_dispersion = 0; - if (dist2(ray_source.orig) <= Epsilon) { - output[pixel] = float4(0.0f, 0.0f, 0.0f, 0.0f); - return; - } - - + bool skip = false; + uint tile_info = tiles_output[pixel / kernel_size]; + disp = (ray_source.dispersion); switch (light_type) { - case 0: { - disp = sqrt(ray_source.dispersion); - //disp = sqrt(dispersion[pixel].r); - break; - } - case 1: { - //disp = ray_source.dispersion; - disp = dispersion[pixel].a; - break; + case 0: skip = ((tile_info & 0x01) == 0); break; + case 1: skip = (((tile_info >> 1) & 0x01) == 0); break; } - } - if (disp < Epsilon) { - output[pixel] = float4(0.0f, 0.0f, 0.0f, 0.0f); + [branch] + if (disp < Epsilon || skip) { + output[pixel] = input[pixel]; return; } - uint min_k = max(normalRatio.x * 0.25f, 0); + uint min_k = max(normalRatio.x * 0.5f, 0); int kernel = clamp(floor(max(MAX_KERNEL * disp, min_dispersion)), min_k, MAX_KERNEL); float motion = 0.0f; float camDist = dist2(cameraPosition - p0_position); uint2 ipixel = pixel; + for (int i = -kernel; i <= kernel; ++i) { float2 p = ipixel + dir * i; if ((p.x < 0 || p.x >= input_dimensions.x) && (p.y < 0 || p.y >= input_dimensions.y)) { @@ -101,10 +92,11 @@ void main(uint3 DTid : SV_DispatchThreadID) float3 p1_normal = normals[p1_info_pixel].xyz; float n = saturate(dot(p1_normal, p0_normal)); float dist = max(dist2(p1_position - p0_position) / camDist, 0.1f); - float w = pow(n, 20.0f / normalRatio) / dist; + float w = pow(n, 5.0f / normalRatio.x) / dist; if (kernel > 1) { w *= cos((M_PI * abs((float)i)) / (2.0 * (float)kernel)); } + w = max(w, 0.1f); count += w; c0 += input[p] * w; } @@ -115,13 +107,12 @@ void main(uint3 DTid : SV_DispatchThreadID) else { c0 *= 0.0f; } -#if 1 +#if 0 if (type == 1) { output[pixel] = c0; } else { - matrix worldViewProj = mul(view, projection); - float4 prev_pos = mul(prev_position_map[info_pixel], worldViewProj); + float4 prev_pos = mul(prev_position_map[info_pixel], view_projection); prev_pos.x /= prev_pos.w; prev_pos.y /= -prev_pos.w; prev_pos.xy = (prev_pos.xy + 1.0f) * normals_dimensions.xy / 2.0f; @@ -146,8 +137,8 @@ void main(uint3 DTid : SV_DispatchThreadID) prev_pos.xy /= normalRatio; } - float4 prev_color = prev_output[floor(prev_pos.xy)]; - float w = saturate(0.5f - motion * 50.0f); + float4 prev_color = prev_output[(prev_pos.xy)]; + float w = saturate(0.8f - motion * 100.0f); output[pixel] = prev_color * w + c0 * (1.0f - w); } #else diff --git a/Engine/Engine/Core/Shaders/RayTrace/DispersionCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/DispersionCS.hlsl deleted file mode 100644 index 6a95a39..0000000 --- a/Engine/Engine/Core/Shaders/RayTrace/DispersionCS.hlsl +++ /dev/null @@ -1,59 +0,0 @@ - -#include "../Common/ShaderStructs.hlsli" -#include "../Common/Utils.hlsli" - -cbuffer externalData : register(b0) -{ - uint type; -} - -Texture2D input : register(t0); -RWTexture2D output : register(u0); - -static const float kw[21] = { 0.000514f,0.001478f,0.003800f,0.008744f,0.018005f,0.033174f,0.054694f,0.080692f,0.106529f,0.125850f,0.133039f,0.125850f,0.106529f,0.080692f,0.054694f,0.033174f,0.018005f,0.008744f,0.003800f,0.001478f,0.000514f }; - -#define NTHREADS 32 -[numthreads(NTHREADS, NTHREADS, 1)] -void main(uint3 DTid : SV_DispatchThreadID) -{ - uint2 input_dimensions; - uint w = 0; - uint h = 0; - input.GetDimensions(w, h); - input_dimensions.x = w; - input_dimensions.y = h; - - float2 pixel = float2(DTid.x, DTid.y); - - float2 dir = lerp(float2(1.0f, 0.0f), float2(0.0f, 1.0f), step(1.5, type)); - - - int kernel = type <= 2?5:10; - if (type <= 2) { - float3 max_disp = float3(-1.0f, -1.0f, -1.0f); - for (int i = -kernel; i <= kernel; ++i) { - float2 p = pixel + dir * i; - if ((p.x < 0 || p.x >= input_dimensions.x) && (p.y < 0 || p.y >= input_dimensions.y)) { - break; - } - float3 c = input[p].rgb; - max_disp = max(max_disp, c); - } - float4 c0 = input[pixel]; - c0.rgb = max_disp; - output[pixel] = c0; - } - else { - float3 max_disp = float3(0.0f, 0.0f, 0.0f); - for (int i = -kernel; i <= kernel; ++i) { - float2 p = pixel + dir * i; - if ((p.x < 0 || p.x >= input_dimensions.x) && (p.y < 0 || p.y >= input_dimensions.y)) { - break; - } - max_disp += input[p].rgb * kw[i + 10]; - } - float4 c0 = input[pixel]; - c0.rgb = max_disp; - output[pixel] = c0; - } -} diff --git a/Engine/Engine/Core/Shaders/RayTrace/GIRayTraceCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/GIRayTraceCS.hlsl index b754c0d..f0b6c69 100644 --- a/Engine/Engine/Core/Shaders/RayTrace/GIRayTraceCS.hlsl +++ b/Engine/Engine/Core/Shaders/RayTrace/GIRayTraceCS.hlsl @@ -31,89 +31,46 @@ SOFTWARE. #define INDIRECT_ENABLED 4 #define USE_OBH 0 -#define DISABLE_RESTIR +//#define BOUNCES +//#define DISABLE_RESTIR cbuffer externalData : register(b0) { uint frame_count; float time; float3 cameraPosition; - float3 cameraDirection; - - uint ray_count; + uint divider; + matrix view_proj; int kernel_size; - - //Lights - AmbientLight ambientLight; - DirLight dirLights[MAX_LIGHTS]; - PointLight pointLights[MAX_LIGHTS]; - uint dirLightsCount; - uint pointLightsCount; - - matrix view; - matrix projection; - - float4 LightPerspectiveValues[MAX_LIGHTS / 2]; - matrix DirPerspectiveMatrix[MAX_LIGHTS]; } -cbuffer objectData : register(b1) -{ - uint nobjects; - ObjectInfo objectInfos[MAX_OBJECTS]; - MaterialColor objectMaterials[MAX_OBJECTS]; -} - -RWTexture2D output; Texture2D ray0; Texture2D ray1; -StructuredBuffer objects: register(t2); -StructuredBuffer objectBVH: register(t3); - -ByteAddressBuffer vertexBuffer : register(t4); -ByteAddressBuffer indicesBuffer : register(t5); -Texture2D position_map : register(t6); Texture2D motion_texture : register(t8); Texture2D prev_position_map: register(t9); +Texture2D restir_pdf_0: register(t10); +Texture2D restir_w_0: register(t11); +RWTexture2D ray_inputs: register(u2); +RWTexture2D restir_pdf_mask: register(u3); -Texture2D DiffuseTextures[MAX_OBJECTS]; -Texture2D DirShadowMapTexture[MAX_LIGHTS]; -TextureCube PointShadowMapTexture[MAX_LIGHTS]; - -Texture2D restir_pdf_0; -Texture2D restir_w_0; -RWTexture2D restir_pdf_1; - -//Packed array -static float2 lps[MAX_LIGHTS] = (float2[MAX_LIGHTS])LightPerspectiveValues; - -#include "../Common/SimpleLight.hlsli" #include "../Common/RayFunctions.hlsli" -#define max_distance 100.0f - -static const float inv_ray_count = 1.0f / (float)ray_count; -static const uint stride = kernel_size * ray_count; +static const float inv_ray_count = 1.0f / (float)MAX_RAYS; +static const uint stride = kernel_size * MAX_RAYS; -static const uint max_x = ray_count * kernel_size; -static const uint max_y = stride * kernel_size; +static const uint N = MAX_RAYS * kernel_size * kernel_size; +static const float space_size = (float)N / (float)MAX_RAYS; -static const uint N = ray_count * kernel_size * kernel_size; -static const float space_size = (float)N / (float)ray_count; -static const float ray_enery_unit = inv_ray_count; -#define LEVEL_RATIO level - -uint GetRayIndex(float2 pixel, float pdf_cache[MAX_RAYS], Texture2D w_data, float index) { +uint GetRayIndex(float pdf_cache[MAX_RAYS], float w, float index) { #ifdef DISABLE_RESTIR return index; #endif - float w = max(w_data[pixel], RAY_W_BIAS * ray_count); float tmp_w = 0.0f; - index = index * w * inv_ray_count; + index = (index + 1.0f) * w * inv_ray_count; - for (uint i = 0; i < ray_count; i++) { + for (uint i = 0; i < MAX_RAYS; i++) { tmp_w += pdf_cache[i]; if (tmp_w > index) { break; @@ -122,31 +79,34 @@ uint GetRayIndex(float2 pixel, float pdf_cache[MAX_RAYS], Texture2D w_dat return i; } -float3 GenerateHemisphereRay(float3 dir, float3 tangent, float3 bitangent, float dispersion, float N, float NLevels, float rX) +#if 0 +float2 GenerateHemisphereRay(float3 dir, float3 tangent, float3 bitangent, float dispersion, float N, float NLevels, float rX) { float index = (rX * dispersion) % N; - //index = (frame_count / 5) % N; + //index = (frame_count) % N; + float N_SQRT = sqrt(N); float cumulativePoints = 1.0f; float level = 1.0f; float c = 1.0f; + float phi; while (c < index) { - c = cumulativePoints + level * LEVEL_RATIO; + phi = (level * M_PI * 0.5f) / NLevels; + c = cumulativePoints + N_SQRT * sin(phi); cumulativePoints = c; level++; }; level--; - float pointsAtLevel = level * LEVEL_RATIO; + + float pointsAtLevel = 1.0f + ceil(N_SQRT * sin(phi)); + phi = (level * M_PI) / NLevels; // Calculate local index within the current level float localIndex = index - cumulativePoints; - - float phi = (level * M_PI) / NLevels; - + // Azimuthal angle (theta) based on number of points at this level - float theta = (2.0f * M_PI) * localIndex / pointsAtLevel; // Spread points evenly in azimuthal direction - + float theta = (2.0f * M_PI) * localIndex / pointsAtLevel; // Spread points evenly in azimuthal direction // Convert spherical coordinates to Cartesian coordinates float sinPhi = sin(phi); @@ -160,223 +120,72 @@ float3 GenerateHemisphereRay(float3 dir, float3 tangent, float3 bitangent, float // Convert local ray to global coordinates (tangent space to world space) float3 globalRay = localRay.x * tangent + localRay.y * dir + localRay.z * bitangent; - - return normalize(dir + globalRay); + return GetPolarCoordinates(normalize(dir + globalRay)); } - -struct RayTraceColor { - float3 color; - bool hit; -}; - -void GetColor(Ray origRay, float rX, float level, uint max_bounces, out RayTraceColor out_color, float dispersion, bool mix, bool refract) -{ - out_color.color = float3(0.0f, 0.0f, 0.0f); - out_color.hit = false; - - float collision_dist = 0.0f; -#if USE_OBH - uint volumeStack[MAX_STACK_SIZE]; -#endif - uint stack[MAX_STACK_SIZE]; - RayObject oray; - IntersectionResult object_result; - - bool collide = false; - IntersectionResult result; - Ray ray = origRay; - float att_dist = 1.0f; - bool end = false; - - result.distance = FLT_MAX; - end = true; - collide = false; -#if USE_OBH - uint volumeStackSize = 0; - volumeStack[volumeStackSize++] = 0; - uint i = 0; - while (volumeStackSize > 0 && volumeStackSize < MAX_STACK_SIZE) - { #else - for (uint i = 0; i < nobjects; ++i) - { - uint objectIndex = i; -#endif - -#if USE_OBH - uint currentVolume = volumeStack[--volumeStackSize]; - BVHNode volumeNode = objectBVH[currentVolume]; - if (is_leaf(volumeNode)) - { - uint objectIndex = index(volumeNode); - ObjectInfo o = objectInfos[objectIndex]; +#define LEVEL_RATIO 3 +float2 GenerateHemisphereRay(float3 dir, float3 tangent, float3 bitangent, float dispersion, float N, float NLevels, float rX) +{ + float index = (rX * dispersion) % N; - float objectExtent = length(o.aabb_max - o.aabb_min); - float distanceToObject = length(o.position - origRay.orig.xyz) - objectExtent; + //index = (frame_count) % N; + float cumulativePoints = 1.0f; + float level = 1.0f; + float c = 1.0f; + while (c < index) { + c = cumulativePoints + level * LEVEL_RATIO; + cumulativePoints = c; + level++; + }; + level--; - if (distanceToObject < max_distance && distanceToObject < result.distance && IntersectAABB(ray, o.aabb_min, o.aabb_max)) - { -#else - ObjectInfo o = objectInfos[i]; - float objectExtent = length(o.aabb_max - o.aabb_min); - float distanceToObject = length(o.position - origRay.orig.xyz) - objectExtent; - if (distanceToObject < max_distance && distanceToObject < result.distance && IntersectAABB(ray, o.aabb_min, o.aabb_max)) - { -#endif - object_result.distance = FLT_MAX; - - // Transform the ray direction from world space to object space - oray.orig = mul(ray.orig, o.inv_world); - oray.orig /= oray.orig.w; - oray.dir = normalize(mul(ray.dir, (float3x3) o.inv_world)); - oray.t = FLT_MAX; - - uint stackSize = 0; - stack[stackSize++] = 0; - - while (stackSize > 0 && stackSize < MAX_STACK_SIZE) - { - uint current = stack[--stackSize]; - - BVHNode node = objects[o.objectOffset + current]; - if (is_leaf(node)) - { - float t; - uint idx = index(node); - idx += o.indexOffset; - - IntersectionResult tmp_result; - tmp_result.distance = FLT_MAX; - if (IntersectTri(oray, idx, o.vertexOffset, tmp_result)) - { - if (tmp_result.distance < object_result.distance) { - object_result.v0 = tmp_result.v0; - object_result.v1 = tmp_result.v1; - object_result.v2 = tmp_result.v2; - object_result.vindex = tmp_result.vindex; - object_result.distance = tmp_result.distance; - object_result.uv = tmp_result.uv; - object_result.object = objectIndex; - } - } - } - else if (IntersectAABB(oray, node)) - { - stack[stackSize++] = left_child(node); - stack[stackSize++] = right_child(node); - } - } - - if (object_result.distance < FLT_MAX) { - float3 opos = (1.0f - object_result.uv.x - object_result.uv.y) * object_result.v0 + object_result.uv.x * object_result.v1 + object_result.uv.y * object_result.v2; - float4 pos = mul(float4(opos, 1.0f), o.world); - float distance = length(pos - ray.orig); - if (distance < result.distance) - { - collide = true; - collision_dist = distance; - ray.t = distance; - result.v0 = object_result.v0; - result.v1 = object_result.v1; - result.v2 = object_result.v2; - result.vindex = object_result.vindex; - result.distance = distance; - result.uv = object_result.uv; - result.object = objectIndex; - } - } - } -#if USE_OBH - } else if (IntersectAABB(ray, volumeNode)) { - volumeStack[volumeStackSize++] = left_child(volumeNode); - volumeStack[volumeStackSize++] = right_child(volumeNode); - } - ++i; -#endif - } + float pointsAtLevel = 1.0f + level * LEVEL_RATIO; - //At this point we have the ray collision distance and a collision result - if (collide) { - // Calculate space position - ObjectInfo o = objectInfos[result.object]; - float3 normal0 = asfloat(vertexBuffer.Load3(result.vindex.x + 12)); - float3 normal1 = asfloat(vertexBuffer.Load3(result.vindex.y + 12)); - float3 normal2 = asfloat(vertexBuffer.Load3(result.vindex.z + 12)); - float3 opos = (1.0f - result.uv.x - result.uv.y) * result.v0 + result.uv.x * result.v1 + result.uv.y * result.v2; - float3 normal = (1.0f - result.uv.x - result.uv.y) * normal0 + result.uv.x * normal1 + result.uv.y * normal2; - normal = normalize(mul(normal, (float3x3)o.world)); - float4 pos = mul(float4(opos, 1.0f), o.world); - pos /= pos.w; - MaterialColor material = objectMaterials[result.object]; - - float3 color = float3(0.0f, 0.0f, 0.0f); - - color += CalcAmbient(normal) * 0.5f; - color *= o.opacity; - - uint i = 0; - for (i = 0; i < dirLightsCount; ++i) { - color += CalcDirectional(normal, pos.xyz, dirLights[i], i); - } + // Calculate local index within the current level + float localIndex = index - cumulativePoints; + float phi = (level * M_PI * 0.8f) / NLevels; + // Azimuthal angle (theta) based on number of points at this level + float theta = (2.0f * M_PI) * localIndex / pointsAtLevel; // Spread points evenly in azimuthal direction - // Calculate the point lights - for (i = 0; i < pointLightsCount; ++i) { - if (length(pos.xyz - pointLights[i].Position) < pointLights[i].Range) { - color += CalcPoint(normal, pos.xyz, pointLights[i], i); - } - } - //Calculate material color - if (material.flags & DIFFUSSE_MAP_ENABLED_FLAG) { - float2 uv0 = asfloat(vertexBuffer.Load2(result.vindex.x + 24)); - float2 uv1 = asfloat(vertexBuffer.Load2(result.vindex.y + 24)); - float2 uv2 = asfloat(vertexBuffer.Load2(result.vindex.z + 24)); - float2 uv = uv0 * (1.0f - result.uv.x - result.uv.y) + uv1 * result.uv.x + uv2 * result.uv.y; - color *= GetDiffuseColor(result.object, uv); - } - else { - color *= material.diffuseColor.rgb; - } + // Convert spherical coordinates to Cartesian coordinates + float sinPhi = sin(phi); + float cosPhi = cos(phi); + float sinTheta = sin(theta); + float cosTheta = cos(theta); - float3 emission = material.emission * material.emission_color; - color += emission; + // Local ray direction in spherical coordinates + float3 localRay = float3(sinPhi * cosTheta, cosPhi, sinPhi * sinTheta); - att_dist *= max(collision_dist * collision_dist, 1.0f); + // Convert local ray to global coordinates (tangent space to world space) + float3 globalRay = localRay.x * tangent + localRay.y * dir + localRay.z * bitangent; - out_color.color += color * ray.ratio / att_dist; - - ray.orig = pos; - out_color.hit = true; - } - } + return GetPolarCoordinates(normalize(dir + globalRay)); +} - bool IsLowEnergy(float pdf[MAX_RAYS], uint len) { +#endif +bool IsLowEnergy(float pdf[MAX_RAYS], uint len) { - float total_enery = 0.0f; - - for (int i = 0; i < len; ++i) { - total_enery += pdf[i]; - } - float threshold = len * RAY_W_BIAS; + float total_enery = 0.0f; - return (total_enery <= threshold); + for (uint i = 0; i < len; ++i) { + total_enery += pdf[i]; } + float threshold = len * 0.01f; + + return (total_enery < threshold); +} #define NTHREADS 32 [numthreads(NTHREADS, NTHREADS, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) { - float2 dimensions; float2 ray_map_dimensions; { uint w, h; - output.GetDimensions(w, h); - dimensions.x = w; - dimensions.y = h; - ray0.GetDimensions(w, h); ray_map_dimensions.x = w; ray_map_dimensions.y = h; @@ -384,40 +193,39 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thre float x = (float)DTid.x; float y = (float)DTid.y; - float2 rayMapRatio = ray_map_dimensions / dimensions; - + float rayMapRatio = divider; + dimensions = ray_map_dimensions / divider; float2 pixel = float2(x, y); - float2 rpixel = pixel * rayMapRatio; - //rpixel.x += frame_count % (rayMapRatio.x * 0.5f); - //rpixel.y += frame_count % (rayMapRatio.y * 0.5f) / 2.0f; float2 ray_pixel = round(rpixel); RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); - if (ray_source.reflex <= Epsilon || dist2(ray_source.normal) <= Epsilon) - { - return; - } + bool end = (ray_source.reflex <= Epsilon || dist2(ray_source.normal) <= Epsilon); float3 orig_pos = ray_source.orig.xyz; float toCamDistance = dist2(orig_pos - cameraPosition); float3 tangent; float3 bitangent; - RayTraceColor rc; - Ray ray = GetReflectedRayFromSource(ray_source); - - if (dist2(ray.dir) <= Epsilon) - { - return; - } + Ray ray = GetReflectedRayFromSource(ray_source, cameraPosition); + + float pdf_cache[MAX_RAYS]; - matrix worldViewProj = mul(view, projection); - float4 prev_pos = mul(prev_position_map[ray_pixel], worldViewProj); + float4 prev_pos = mul(prev_position_map[ray_pixel], view_proj); prev_pos.x /= prev_pos.w; prev_pos.y /= -prev_pos.w; - prev_pos.xy = round((prev_pos.xy + 1.0f) * dimensions.xy / 2.0f); + prev_pos.xy = (prev_pos.xy + 1.0f) * dimensions.xy * 0.5f; + UnpackRays(restir_pdf_0[prev_pos.xy], RAY_W_SCALE, pdf_cache); + uint i = 0; + + end = end || (dist2(ray.dir) <= Epsilon); + [branch] + if (end) + { + return; + } + float3 normal = ray_source.normal; float3 orig_dir = ray.dir; @@ -429,79 +237,87 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thre cumulativePoints = c; level++; }; - GetSpaceVectors(normal, tangent, bitangent); float color_w = 0.0f; - - float pdf_cache[MAX_RAYS]; - UnpackRays(restir_pdf_0[pixel], RAY_W_SCALE, pdf_cache); - - uint i; - - for (i = 0; i < ray_count; i++) { - pdf_cache[i] = max(pdf_cache[i], RAY_W_BIAS); - } float wis[MAX_RAYS]; int wis_size = 0; + uint last_wi = MAX_RAYS + 1; - - //Check if this is a low enery pixel - uint low_energy = IsLowEnergy(pdf_cache, ray_count); - float2 mvector = motion_texture[ray_pixel].xy; - float motion = 0.0f; - if (mvector.x > -FLT_MAX) { - motion = dist2(mvector); + for (i = 0; i < MAX_RAYS; i++) { + pdf_cache[i] = max(pdf_cache[i], RAY_W_BIAS); } -#ifdef DISABLE_RESTIR - uint start = 0; - uint step = 1; -#else - float motion_ratio = 1.0f / max(sqrt(motion) * toCamDistance, 0.01f); - uint start = (((pixel.x + pixel.y + frame_count)) % ray_count) * low_energy * motion_ratio; - uint step = ray_count / 4 + (ray_count * motion_ratio) * low_energy; -#endif + uint restir_mask = 0; + float w_pixel = max(restir_w_0[pixel], RAY_W_BIAS * MAX_RAYS); - for (i = start; i < ray_count; i += step) { - uint wi = GetRayIndex(prev_pos.xy, pdf_cache, restir_w_0, i); - wis[wis_size] = wi; - wis_size += (last_wi != wi); - last_wi = wi; + float unordered_wis[MAX_RAYS]; + for (i = 0; i < MAX_RAYS; ++i) { + uint wi = GetRayIndex(pdf_cache, w_pixel, i); + if (last_wi != wi) { + unordered_wis[wis_size] = wi; + wis_size++; + last_wi = wi; + } } - - float4 color_diffuse = float4(0.0f, 0.0f, 0.0f, 1.0f); - float offset = (pixel.x % kernel_size) * ray_count + (pixel.y % kernel_size) * stride; - float offset2 = space_size; - - for (i = 0; i < wis_size; ++i) { - - uint wi = wis[i]; - float n = fmod(offset + (float)wi * offset2, N); - ray.dir = GenerateHemisphereRay(normal, tangent, bitangent, 1.0f, N, level * 1.2f, n); - ray.orig.xyz = orig_pos.xyz + ray.dir * 0.001f; - float dist = FLT_MAX; - GetColor(ray, n, level, 0, rc, ray_source.dispersion, true, false); - color_diffuse.rgb += rc.color; - last_wi = wi; + for (i = 0; i < 3 && i < wis_size; ++i) { + float max_wi = 0.0f; + uint max_wi_pos = 0; + uint max_unordered_wis_pos = 0; + for (int j = 0; j < wis_size; ++j) { + if (max_wi < pdf_cache[unordered_wis[j]]) { + max_wi_pos = unordered_wis[j]; + max_wi = pdf_cache[max_wi_pos]; + max_unordered_wis_pos = j; + } + } - float w = length(rc.color.rgb); + wis[i] = max_wi_pos; + unordered_wis[max_unordered_wis_pos] = 0.0f; + restir_mask = (restir_mask << 4) | max_wi_pos; + } -#ifdef DISABLE_RESTIR - pdf_cache[wi] = 1.0f; -#else - pdf_cache[wi] = RAY_W_BIAS + w; -#endif + for (i = wis_size; i < 3; ++i) { + wis[i] = 0xF; + restir_mask = (restir_mask << 4) | 0xF; } - wis_size = max(wis_size, 1); - restir_pdf_1[pixel] = PackRays(pdf_cache, RAY_W_SCALE); - color_diffuse = color_diffuse / wis_size; - - output[pixel] = sqrt(color_diffuse) * !low_energy; - //float r = wis_size / ray_count; - //output[pixel] = float4(wis_size, 0.0f, 0.0f, 1.0f); + //Add scan line in ray 4 + uint scan_ray = frame_count% MAX_RAYS; + bool found; + do { + found = false; + for (i = 0; i < 3; ++i) { + if (wis[i] == scan_ray) { + scan_ray = (scan_ray + 1) % MAX_RAYS; + found = true; + break; + } + } + + } while (found); + wis[3] = scan_ray; + restir_mask = (restir_mask << 4) | scan_ray; + + float4 color_diffuse = float4(0.0f, 0.0f, 0.0f, 1.0f); + float offset = ((pixel.x) % kernel_size) * MAX_RAYS + ((pixel.y) % kernel_size) * stride; + float offset2 = space_size; + + float2 ray_input[4]; + for (i = 0; i < 4; ++i) { + uint wi = wis[i]; + if (wi < 0xF) { + float n = fmod(offset + (float)wi * offset2, N); + ray_input[i] = GenerateHemisphereRay(normal, tangent, bitangent, 1.0f, N, level, n); + } + else { + ray_input[i] = float2(MAX_RAY_POLAR_DIR, MAX_RAY_POLAR_DIR); + } + } + uint4 data = Pack4Float2ToI16(ray_input, MAX_RAY_POLAR_DIR); + ray_inputs[pixel] = data; + restir_pdf_mask[pixel] = restir_mask; } diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayGIScreenSolverCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/RayGIScreenSolverCS.hlsl new file mode 100644 index 0000000..bae8c01 --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayGIScreenSolverCS.hlsl @@ -0,0 +1,192 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "RayScreenSolver.hlsli" + +cbuffer externalData : register(b0) +{ + uint frame_count; + float time; + uint type; + float hiz_ratio; + uint divider; + int kernel_size; + float3 cameraPosition; + matrix view; + matrix projection; + matrix inv_projection; + matrix prev_view_proj; +} + +#include "../Common/RayFunctions.hlsli" + +RWTexture2D ray_inputs: register(u0); +RWTexture2D output : register(u1); +RWTexture2D tiles_output: register(u2); +RWTexture2D restir_pdf_1: register(u3); + +Texture2D ray0: register(t1); +Texture2D ray1: register(t2); +Texture2D colorTexture: register(t3); +Texture2D lightTexture: register(t4); +Texture2D bloomTexture: register(t5); +Texture2D restir_pdf_mask: register(t6); +Texture2D restir_pdf_0: register(t7); +Texture2D restir_w_0: register(t11); + +Texture2D prev_position_map: register(t8); +Texture2D hiz_textures[HIZ_TEXTURES]; + +#define NTHREADS 11 +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) +{ +#if GI_SCREEN + float2 dimensions; + float2 ray_map_dimensions; + { + uint w, h; + output.GetDimensions(w, h); + dimensions.x = w; + dimensions.y = h; + + ray0.GetDimensions(w, h); + ray_map_dimensions.x = w; + ray_map_dimensions.y = h; + } + float x = (float)DTid.x; + float y = (float)DTid.y; + + float2 rayMapRatio = divider; + + float2 pixel = float2(x, y); + + float2 ray_pixel = round(pixel * rayMapRatio); + + RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); + + float2 color_uv = float2(0.0f, 0.0f); + float z_diff = FLT_MAX; + + float hit_distance; + //Get rays to be solved in the pixel + float2 ray_input[4]; + Unpack4Float2FromI16(ray_inputs[pixel], MAX_RAY_POLAR_DIR, ray_input); + + float3 final_color = float3(0.0f, 0.0f, 0.0f); + float n = 0.0f; + float ratio = 0.0f; + ratio = ray_source.dispersion; + + uint i = 0; + float pdf_cache[MAX_RAYS]; + UnpackRays(restir_pdf_0[pixel], RAY_W_SCALE, pdf_cache); + + float wis[MAX_RAYS]; + int wis_size = 0; + uint mask = restir_pdf_mask[pixel]; + for (i = 0; i < 4; ++i) { + uint wi = (mask & 0xF000) >> 12; + wis[wis_size++] = wi; + mask <<= 4; + } + + for (i = 0; i < 4; ++i) { + uint wi = wis[i]; + if (wi == 0xF) continue; + + z_diff = FLT_MAX; + Ray ray = GetRayInfoFromSourceWithNoDir(ray_source); + if (abs(ray_input[i].x) < MAX_RAY_POLAR_DIR && dist2(ray_input[i]) > Epsilon) { + ray.dir = GetCartesianCoordinates(ray_input[i]); + ray.dir = normalize(mul(ray.dir, (float3x3)view)); + ray.orig = mul(ray.orig, view); + ray.orig /= ray.orig.w; + ray.orig.xyz += ray.dir * 0.5f; + float reflex_ratio = (1.0f - ray_source.dispersion); + color_uv = GetColor(ray, projection, inv_projection, hiz_textures, hiz_ratio, ray_map_dimensions, dimensions, z_diff, hit_distance); + + float max_diff = GetMaxDiff(hiz_textures[0], color_uv, ray_map_dimensions); + float3 color = float3(0.0f, 0.0f, 0.0f); + if (z_diff < max_diff && ValidUVCoord(color_uv)) { +#if 1 + float4 c = GetInterpolatedColor(color_uv, colorTexture, ray_map_dimensions); + float4 l = GetInterpolatedColor(color_uv, lightTexture, ray_map_dimensions); + float4 b = GetInterpolatedColor(color_uv, bloomTexture, ray_map_dimensions); +#else + color_uv *= ray_map_dimensions; + float4 c = colorTexture[color_uv]; + float4 l = lightTexture[color_uv]; + float4 b = bloomTexture[color_uv]; +#endif + float diff_ratio = (z_diff / 0.05f); + //Disable world resolve + ray_input[i] = float2(FLT_MAX, FLT_MAX); + color = ((c * l + b) * ray_source.opacity).rgb; + + //Do not paint scan ray + if (i < 3) { + final_color += color; + n += pdf_cache[wi]; + } + } + pdf_cache[wi] = RAY_W_BIAS + length(color); + + //Disable world resolve if hit distance is greater than 20 + if (hit_distance > 10.0f) { + ray_input[i] = float2(FLT_MAX, FLT_MAX); + } + } + } + float w_ratio = 1.0f; + if (n > 0) { + final_color = (final_color * ray_source.opacity); + w_ratio = restir_w_0[pixel] / n; + } + + restir_pdf_1[pixel] = PackRays(pdf_cache, RAY_W_SCALE); + + float4 prev_pos = mul(prev_position_map[ray_pixel], prev_view_proj); + prev_pos.x /= prev_pos.w; + prev_pos.y /= -prev_pos.w; + prev_pos.xy = (prev_pos.xy + 1.0f) * 0.5f; + float w = 0.2f; + float4 prev_color = GetInterpolatedColor(prev_pos.xy, output, dimensions); + + output[pixel] = lerp(prev_color, float4(sqrt(final_color * w_ratio / 3) , 1.0f), w); + //output[pixel] = float4(sqrt(final_color * w_ratio / 3), 1.0f); + ray_inputs[pixel] = Pack4Float2ToI16(ray_input, MAX_RAY_POLAR_DIR); + + if (n > 0) { + [unroll] + for (int x = -2; x <= 2; ++x) { + [unroll] + for (int y = -2; y <= 2; ++y) { + int2 p = pixel / kernel_size + int2(x, y); + tiles_output[p] = 1; + } + } + } +#endif + +} diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayGIWorldSolverCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/RayGIWorldSolverCS.hlsl new file mode 100644 index 0000000..cec9329 --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayGIWorldSolverCS.hlsl @@ -0,0 +1,187 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "../Common/ShaderStructs.hlsli" +#include "../Common/PixelCommon.hlsli" +#include "../Common/RayDefines.hlsli" +#include "../Common/RGBANoise.hlsli" + +#define REFLEX_ENABLED 1 +#define REFRACT_ENABLED 2 +#define USE_OBH 0 + +cbuffer externalData : register(b0) +{ + uint frame_count; + float time; + uint enabled; + int kernel_size; + float3 cameraPosition; + + //Lights + AmbientLight ambientLight; + DirLight dirLights[MAX_LIGHTS]; + PointLight pointLights[MAX_LIGHTS]; + uint dirLightsCount; + uint pointLightsCount; + + float4 LightPerspectiveValues[MAX_LIGHTS / 2]; + matrix DirPerspectiveMatrix[MAX_LIGHTS]; +} + +cbuffer objectData : register(b1) +{ + uint nobjects; + ObjectInfo objectInfos[MAX_OBJECTS]; + MaterialColor objectMaterials[MAX_OBJECTS]; +} + +RWTexture2D output : register(u0); +RWTexture2D tiles_output: register(u2); +RWTexture2D restir_pdf_1: register(u3); + +Texture2D restir_pdf_0: register(t7); +Texture2D ray0; +Texture2D ray1; +Texture2D ray_inputs: register(t0); + +Texture2D restir_pdf_mask: register(t6); +Texture2D restir_w_0: register(t11); + +StructuredBuffer objects: register(t2); +StructuredBuffer objectBVH: register(t3); + +Texture2D DirShadowMapTexture[MAX_LIGHTS]; +TextureCube PointShadowMapTexture[MAX_LIGHTS]; + +//Packed array +static float2 lps[MAX_LIGHTS] = (float2[MAX_LIGHTS])LightPerspectiveValues; + +#include "../Common/SimpleLight.hlsli" +#include "../Common/RayFunctions.hlsli" +#include "RayWorldSolver.hlsli" + +#define NTHREADS 11 + +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) +{ +#if GI_WORLD + float2 dimensions; + float2 ray_map_dimensions; + { + uint w, h; + output.GetDimensions(w, h); + dimensions.x = w; + dimensions.y = h; + + ray0.GetDimensions(w, h); + ray_map_dimensions.x = w; + ray_map_dimensions.y = h; + } + float x = (float)DTid.x; + float y = (float)DTid.y; + + float2 rayMapRatio = ray_map_dimensions / dimensions; + + float2 pixel = float2(x, y); + + + float2 ray_pixel = round(pixel * rayMapRatio); + + RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); + + float4 color_reflex = float4(0.0f, 0.0f, 0.0f, 1.0f); + float4 color_refrac = float4(0.0f, 0.0f, 0.0f, 1.0f); + uint2 hits = uint2(0, 0); + Ray ray = GetRayInfoFromSourceWithNoDir(ray_source); + float3 orig = ray.orig.xyz; + + //Get rays to be solved in the pixel + RayTraceColor rc; + float2 ray_input[4]; + Unpack4Float2FromI16(ray_inputs[pixel], MAX_RAY_POLAR_DIR, ray_input); + float reflex_ratio = (1.0f - ray_source.dispersion); + + float pdf_cache[MAX_RAYS]; + UnpackRays(restir_pdf_1[pixel], RAY_W_SCALE, pdf_cache); + uint i = 0; + + float wis[MAX_RAYS]; + uint mask = restir_pdf_mask[pixel]; + for (i = 0; i < 4; ++i) { + uint wi = (mask & 0xF000) >> 12; + wis[i] = wi; + mask <<= 4; + } + + float n = 0.0f; + float4 final_color = float4(0.0f, 0.0f, 0.0f, 1.0f); + for (i = 0; i < 4; ++i) { + uint wi = wis[i]; + if (wi == 0xF) continue; + + Ray ray = GetRayInfoFromSourceWithNoDir(ray_source); + ray.dir = GetCartesianCoordinates(ray_input[i]); + ray.orig.xyz += ray.dir * 0.05f; + if (abs(ray_input[i].x) < MAX_RAY_POLAR_DIR && dist2(ray_input[i]) > Epsilon) { + ray.orig.xyz += ray.dir * 0.5f; + if (GetColor(ray, 0, rc, ray_source.dispersion, false)) { + hits.x = rc.hit != 0; + if (i < 3) { + final_color.rgb += rc.color.rgb; + n += pdf_cache[wi]; + } + } + pdf_cache[wi] = RAY_W_BIAS + length(rc.color.rgb); + } + } + float w_ratio = 1.0f; + if (n > Epsilon) { + final_color = (final_color * ray_source.opacity); + w_ratio = restir_w_0[pixel] / n; +#if GI_SCREEN + float4 gi_screen_color = output[pixel]; + final_color = ((final_color * w_ratio) / 3); + gi_screen_color.rgb += final_color.rgb; + output[pixel] = gi_screen_color; +#endif + } +#if !GI_SCREEN + output[pixel] = ((final_color * w_ratio) / 3); +#endif + restir_pdf_1[pixel] = PackRays(pdf_cache, RAY_W_SCALE); + + uint hit = (hits.y & 0x01) << 1 | (hits.x & 0x01); + if (hit != 0) { + for (int x = -2; x <= 2; ++x) { + for (int y = -2; y <= 2; ++y) { + int2 p = pixel / kernel_size + int2(x, y); + tiles_output[p] = tiles_output[p] | hit; + } + } + } +#endif +} + \ No newline at end of file diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayReflexScreenSolverCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/RayReflexScreenSolverCS.hlsl new file mode 100644 index 0000000..c364674 --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayReflexScreenSolverCS.hlsl @@ -0,0 +1,139 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "RayScreenSolver.hlsli" + +cbuffer externalData : register(b0) +{ + uint frame_count; + float time; + uint type; + float hiz_ratio; + uint divider; + int kernel_size; + float3 cameraPosition; + matrix view; + matrix projection; + matrix inv_projection; +} + +#include "../Common/RayFunctions.hlsli" + +RWTexture2D ray_inputs: register(u0); +RWTexture2D output : register(u1); +RWTexture2D tiles_output: register(u2); + +Texture2D ray0: register(t1); +Texture2D ray1: register(t2); +Texture2D colorTexture: register(t3); +Texture2D lightTexture: register(t4); +Texture2D bloomTexture: register(t5); + +Texture2D hiz_textures[HIZ_TEXTURES]; + +#define NTHREADS 16 +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) +{ +#if REFLEX_SCREEN + float2 dimensions; + float2 ray_map_dimensions; + { + uint w, h; + output.GetDimensions(w, h); + dimensions.x = w; + dimensions.y = h; + + ray0.GetDimensions(w, h); + ray_map_dimensions.x = w; + ray_map_dimensions.y = h; + } + float x = (float)DTid.x; + float y = (float)DTid.y; + + float2 rayMapRatio = divider; + + float2 pixel = float2(x, y); + + float2 ray_pixel = round(pixel * rayMapRatio); + + RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); + + float2 color_uv = float2(0.0f, 0.0f); + float z_diff = FLT_MAX; + + float hit_distance; + //Get rays to be solved in the pixel + float2 ray_input[4]; + Unpack4Float2FromI16(ray_inputs[pixel], MAX_RAY_POLAR_DIR, ray_input); + + float3 final_color = float3(0.0f, 0.0f, 0.0f); + float n = 0.0f; + float ratio = 0.0f; + ratio = (1.0f - ray_source.dispersion); + + //Only work with 1 ray for DI + float reflex_ratio = (1.0f - ray_source.dispersion); + z_diff = FLT_MAX; + Ray ray = GetRayInfoFromSourceWithNoDir(ray_source); + if (abs(ray_input[0].x) < MAX_RAY_POLAR_DIR && dist2(ray_input[0]) > Epsilon) { + ray.dir = GetCartesianCoordinates(ray_input[0]); + ray.dir = normalize(mul(ray.dir, (float3x3)view)); + ray.orig = mul(ray.orig, view); + ray.orig /= ray.orig.w; + ray.orig.xyz += ray.dir * 0.1f; + float reflex_ratio = (1.0f - ray_source.dispersion); + color_uv = GetColor(ray, projection, inv_projection, hiz_textures, hiz_ratio, ray_map_dimensions, dimensions, z_diff, hit_distance); + + float max_diff = GetMaxDiff(hiz_textures[0], color_uv, ray_map_dimensions); + if (z_diff < max_diff && ValidUVCoord(color_uv)) { +#if 0 + float4 c = GetInterpolatedColor(color_uv, colorTexture, ray_map_dimensions); + float4 l = GetInterpolatedColor(color_uv, lightTexture, ray_map_dimensions); + float4 b = GetInterpolatedColor(color_uv, bloomTexture, ray_map_dimensions); +#else + color_uv *= ray_map_dimensions; + float4 c = colorTexture[color_uv]; + float4 l = lightTexture[color_uv]; + float4 b = bloomTexture[color_uv]; +#endif + ray_input[0] = float2(FLT_MAX, FLT_MAX); + final_color += ((c * l + b) * reflex_ratio * ray_source.opacity).rgb; + n++; + } + } + output[pixel] = float4(sqrt(final_color), 1.0f); + + if (n > 0) { + [unroll] + for (int x = -2; x <= 2; ++x) { + [unroll] + for (int y = -2; y <= 2; ++y) { + int2 p = pixel / kernel_size + int2(x, y); + tiles_output[p] = 1; + } + } + } + ray_inputs[pixel] = Pack4Float2ToI16(ray_input, MAX_RAY_POLAR_DIR); +#endif +} diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayReflexWorldSolverCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/RayReflexWorldSolverCS.hlsl new file mode 100644 index 0000000..509e72b --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayReflexWorldSolverCS.hlsl @@ -0,0 +1,176 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#include "../Common/ShaderStructs.hlsli" +#include "../Common/PixelCommon.hlsli" +#include "../Common/RayDefines.hlsli" +#include "../Common/RGBANoise.hlsli" + +#define REFLEX_ENABLED 1 +#define REFRACT_ENABLED 2 +#define USE_OBH 0 + +cbuffer externalData : register(b0) +{ + uint frame_count; + float time; + uint enabled; + int kernel_size; + float3 cameraPosition; + uint type; + + //Lights + AmbientLight ambientLight; + DirLight dirLights[MAX_LIGHTS]; + PointLight pointLights[MAX_LIGHTS]; + uint dirLightsCount; + uint pointLightsCount; + + float4 LightPerspectiveValues[MAX_LIGHTS / 2]; + matrix DirPerspectiveMatrix[MAX_LIGHTS]; +} + +cbuffer objectData : register(b1) +{ + uint nobjects; + ObjectInfo objectInfos[MAX_OBJECTS]; + MaterialColor objectMaterials[MAX_OBJECTS]; +} + +RWTexture2D output0 : register(u0); +RWTexture2D output1 : register(u1); +RWTexture2D tiles_output: register(u2); +RWTexture2D restir_pdf_1: register(u3); + +Texture2D restir_pdf_0: register(t7); +Texture2D ray0; +Texture2D ray1; +Texture2D ray_inputs: register(t0); + +Texture2D restir_pdf_mask: register(t6); +Texture2D restir_w_0: register(t11); + +StructuredBuffer objects: register(t2); +StructuredBuffer objectBVH: register(t3); + +Texture2D DirShadowMapTexture[MAX_LIGHTS]; +TextureCube PointShadowMapTexture[MAX_LIGHTS]; + +//Packed array +static float2 lps[MAX_LIGHTS] = (float2[MAX_LIGHTS])LightPerspectiveValues; + +#include "../Common/SimpleLight.hlsli" +#include "../Common/RayFunctions.hlsli" +#include "RayWorldSolver.hlsli" + +#define NTHREADS 11 + +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) +{ +#if REFLEX_WORLD + float2 dimensions; + float2 ray_map_dimensions; + { + uint w, h; + output0.GetDimensions(w, h); + dimensions.x = w; + dimensions.y = h; + + ray0.GetDimensions(w, h); + ray_map_dimensions.x = w; + ray_map_dimensions.y = h; + } + float x = (float)DTid.x; + float y = (float)DTid.y; + + float2 rayMapRatio = ray_map_dimensions / dimensions; + + float2 pixel = float2(x, y); + + + float2 ray_pixel = round(pixel * rayMapRatio); + + RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); + + float4 color_reflex = float4(0.0f, 0.0f, 0.0f, 1.0f); + float4 color_refrac = float4(0.0f, 0.0f, 0.0f, 1.0f); + uint2 hits = uint2(0, 0); + Ray ray = GetRayInfoFromSourceWithNoDir(ray_source); + float3 orig = ray.orig.xyz; + + //Get rays to be solved in the pixel + RayTraceColor rc; + float2 ray_input[4]; + Unpack4Float2FromI16(ray_inputs[pixel], MAX_RAY_POLAR_DIR, ray_input); + float reflex_ratio = (1.0f - ray_source.dispersion); + +#if 1 +#if !REFLEX_SCREEN + output0[pixel] = float4(0.0f, 0.0f, 0.0f, 1.0f); +#endif + if (abs(ray_input[0].x) < MAX_RAY_POLAR_DIR) { + if (dist2(ray_input[0]) <= Epsilon) { + color_reflex.rgb = float3(1.0f, 0.0f, 0.0f); + } + else { + ray.dir = GetCartesianCoordinates(ray_input[0]); + ray.orig.xyz = orig + ray.dir * 0.01f; + GetColor(ray, 0, rc, ray_source.dispersion, false); + color_reflex.rgb += rc.color * reflex_ratio * ray_source.opacity; + hits.x = rc.hit != 0; + } + output0[pixel] = color_reflex; + } +#endif +#if 1 + if (abs(ray_input[1].x) < MAX_RAY_POLAR_DIR) { + if (dist2(ray_input[1]) <= Epsilon) { + color_reflex.rgb = float3(1.0f, 0.0f, 0.0f); + } + else { + ray.dir = GetCartesianCoordinates(ray_input[1]); + ray.orig.xyz = orig + ray.dir * 0.01f; + + GetColor(ray, 0, rc, ray_source.dispersion, true); + color_refrac.rgb += rc.color * (1.0f - ray_source.opacity); + hits.y = rc.hit != 0; + } + output1[pixel] = color_refrac; + } +#endif + + uint hit = (hits.y & 0x01) << 1 | hits.x & 0x01; + if (hit != 0) { + [unroll] + for (int x = -2; x <= 2; ++x) { + [unroll] + for (int y = -2; y <= 2; ++y) { + int2 p = pixel / kernel_size + int2(x, y); + tiles_output[p] = tiles_output[p] | hit; + } + } + } +#endif +} diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayScreenSolver.hlsli b/Engine/Engine/Core/Shaders/RayTrace/RayScreenSolver.hlsli new file mode 100644 index 0000000..9931d6c --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayScreenSolver.hlsli @@ -0,0 +1,200 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include "../Common/ShaderStructs.hlsli" +#include "../Common/PixelCommon.hlsli" +#include "../Common/RayDefines.hlsli" +#include "../Common/RGBANoise.hlsli" + +#define HIZ_TEXTURES 4 + +struct Line { + float3 P0; // Point on the line + float3 d; // Direction vector of the line +}; + +struct Plane { + float3 Q; // Point on the plane + float3 n; // Normal vector of the plane +}; + +float3 IntersectLinePlane(Line l, Plane p) { + float3 P0 = l.P0; + float3 d = l.d; + float3 Q = p.Q; + float3 n = p.n; + + float denom = dot(n, d); + denom = max(abs(denom), 1e-6) * sign(denom); + float t = dot(n, Q - P0) / denom; + return (P0 + t * d); +} + +float GetRayDepth(in matrix inv_projection, Plane rayPlane, float2 grid_pos, out float3 intersection_point) { + float4 H = float4(grid_pos.x * 2.0f - 1.0f, (1.0f - grid_pos.y) * 2.0f - 1.0f, 0.0f, 1.0f); + float4 D = mul(H, inv_projection); + float4 eyepos = D / D.w; + + Line eyeLine; + eyeLine.P0 = eyepos.xyz; + eyeLine.d = eyepos.xyz; + intersection_point = IntersectLinePlane(eyeLine, rayPlane); + return length(intersection_point); +} + +float2 GetNextGrid(float2 dir, float2 pixel) { + float2 p0 = pixel; + float2 invDir = 1.0f / dir; + float2 currentGrid = floor(p0); + float2 nextGrid; + + // Calculate initial intersection points with the grid lines + nextGrid.x = currentGrid.x + sign(dir.x); + nextGrid.y = currentGrid.y + sign(dir.y); + + // Calculate the step size to the next grid for x and y + float2 tMax; + tMax.x = (nextGrid.x - p0.x) * invDir.x; + tMax.y = (nextGrid.y - p0.y) * invDir.y; + + if (tMax.x < tMax.y) { + return float2(nextGrid.x, p0.y + (nextGrid.x - p0.x) * dir.y / dir.x); + } + else { + return float2(p0.x + (nextGrid.y - p0.y) * dir.x / dir.y, nextGrid.y); + } +} + +float GetHiZ(Texture2D hiz_textures[HIZ_TEXTURES], uint level, float2 pixel) { + switch (level) { + case 0: return hiz_textures[0][pixel]; + case 1: return hiz_textures[1][pixel]; + case 2: return hiz_textures[2][pixel]; + case 3: return hiz_textures[3][pixel]; + } + return FLT_MAX; +} + +float2 GetColor(Ray ray, in matrix projection, in matrix inv_projection, Texture2D hiz_textures[HIZ_TEXTURES], float hiz_ratio, float2 depth_dimensions, float2 output_dimensions, out float z_diff, out float hit_distance) { + + float4 pixel0 = mul(ray.orig, projection); + pixel0 /= pixel0.w; + pixel0.y *= -1.0f; + pixel0.xy = (pixel0.xy + 1.0f) * 0.5f; + float2 pStartProj = pixel0.xy; + + float4 p1 = ray.orig; + p1.xyz += ray.dir; + + float4 pixel1 = mul(p1, projection); + pixel1 /= pixel1.w; + pixel1.y *= -1.0f; + pixel1.xy = (pixel1.xy + 1.0f) * 0.5f; + float2 pEndProj = pixel1.xy; + + float2 dir = normalize((pixel1.xy - pStartProj) * depth_dimensions); + + + float2 screen_pixel = pixel0.xy * depth_dimensions; + float3 color = float3(0.0f, 0.0f, 0.0f); + int current_level = HIZ_TEXTURES - 1; + float current_divider = pow(hiz_ratio, current_level); + + float2 grid_pixel = screen_pixel / current_divider; + float2 grid_pos = pixel0.xy; + float2 last_valid_grid_pos = grid_pos; + + float grid_high_z = 0.0f; + + float3 intersection_point; + + float ray_z = 0.0f; + + float n = 0.0f; + + float3 up = float3(0.0f, 1.0f, 0.0f); + float3 normal = normalize(cross(up, ray.dir)); + float2 grid_size = current_divider / depth_dimensions; + + Plane rayPlane; + rayPlane.Q = ray.orig.xyz; + rayPlane.n = normal; + + z_diff = FLT_MAX; + hit_distance = FLT_MAX; + + while (current_level >= 0) { + //Calculate ray z, grid_pos in NDC coords + + grid_pos = grid_pixel * grid_size; + if (!ValidUVCoord(grid_pos)) { + return float2(-1, -1); + } + grid_high_z = GetHiZ(hiz_textures, current_level, grid_pixel); + ray_z = GetRayDepth(inv_projection, rayPlane, grid_pos, intersection_point); + if (grid_high_z <= ray_z) { + current_level--; + current_divider = pow(hiz_ratio, current_level); + grid_pos = last_valid_grid_pos; + grid_size = current_divider / depth_dimensions; + grid_pixel = (grid_pos * depth_dimensions) / current_divider; + } + last_valid_grid_pos = grid_pos; + grid_pixel = GetNextGrid(dir, grid_pixel); + } + + z_diff = abs(ray_z - grid_high_z); + hit_distance = length(intersection_point - ray.orig.xyz); + + return last_valid_grid_pos + dir * grid_size * 0.5f; +} + +//Max diff depends on the distance gap between adyacent pixels and distance to camera +float GetMaxDiff(in Texture2D hiz_texture, float2 uv, float2 dimension) { + float2 texCoords = uv * dimension; + + int2 p00 = (int2)floor(texCoords); + int2 p11 = (int2)ceil(texCoords); + int2 p01 = int2(p00.x, p11.y); + int2 p10 = int2(p11.x, p00.y); + + p00 += int2(-1, -1); + p11 += int2(1, 1); + p01 += int2(-1, 1); + p10 += int2(1, -1); + + float z00 = (hiz_texture[p00]); + float z11 = (hiz_texture[p11]); + float z01 = (hiz_texture[p10]); + float z10 = (hiz_texture[p01]); + + float d00_11 = abs(z00 - z11); + float d00_10 = abs(z00 - z10); + float d00_01 = abs(z00 - z01); + float d11_01 = abs(z11 - z01); + float d11_10 = abs(z11 - z10); + float d01_10 = abs(z01 - z10); + + float diff = min(max(d00_11, max(d00_10, max(d00_01, max(d11_01, max(d11_10, d01_10))))), 0.299f); + return saturate(0.3f - diff); +} diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayTraceCS.hlsl b/Engine/Engine/Core/Shaders/RayTrace/RayTraceCS.hlsl index 473f491..48a60d4 100644 --- a/Engine/Engine/Core/Shaders/RayTrace/RayTraceCS.hlsl +++ b/Engine/Engine/Core/Shaders/RayTrace/RayTraceCS.hlsl @@ -34,452 +34,81 @@ SOFTWARE. cbuffer externalData : register(b0) { uint frame_count; + uint enabled; + uint divider; float time; float3 cameraPosition; - float3 cameraDirection; - uint enabled; - - //Lights - AmbientLight ambientLight; - DirLight dirLights[MAX_LIGHTS]; - PointLight pointLights[MAX_LIGHTS]; - uint dirLightsCount; - uint pointLightsCount; - - float4 LightPerspectiveValues[MAX_LIGHTS / 2]; - matrix DirPerspectiveMatrix[MAX_LIGHTS]; } -cbuffer objectData : register(b1) -{ - uint nobjects; - ObjectInfo objectInfos[MAX_OBJECTS]; - MaterialColor objectMaterials[MAX_OBJECTS]; -} - -RWTexture2D output0 : register(u0); -RWTexture2D output1 : register(u1); -RWTexture2D dispersion : register(u3); -RWTexture2D bloom : register(u7); - -Texture2D ray0; -Texture2D ray1; - -StructuredBuffer objects: register(t2); -StructuredBuffer objectBVH: register(t3); - -ByteAddressBuffer vertexBuffer : register(t4); -ByteAddressBuffer indicesBuffer : register(t5); -Texture2D position_map : register(t6); -Texture2D motion_texture : register(t8); - -Texture2D DiffuseTextures[MAX_OBJECTS]; -Texture2D DirShadowMapTexture[MAX_LIGHTS]; -TextureCube PointShadowMapTexture[MAX_LIGHTS]; +Texture2D ray0: register(t0); +Texture2D ray1: register(t1); +RWTexture2D ray_inputs: register(u0); -//Packed array -static float2 lps[MAX_LIGHTS] = (float2[MAX_LIGHTS])LightPerspectiveValues; - -#include "../Common/SimpleLight.hlsli" +#include "../Common/Utils.hlsli" #include "../Common/RayFunctions.hlsli" -#define max_distance 100.0f - -float3 GenerateHemisphereRay(float3 dir, float3 tangent, float3 bitangent, float dispersion, float N, float NLevels, float rX) -{ - float index = rX * N * dispersion; - - // First point at the top (up direction) - if (index < 1.0f) { - return dir; // The first point is directly at the top - } - - float cumulativePoints = 1; - float level = 1; - while (true) { - float c = cumulativePoints + level * 2; - if (c < index) { - cumulativePoints = c; - } - else { - break; - } - level++; - }; - - float pointsAtLevel = level * 2; // Quadratic growth - - // Calculate local index within the current level - float localIndex = index - cumulativePoints; - - float phi = level / NLevels * M_PI * (0.4 + rX); - - // Azimuthal angle (theta) based on number of points at this level - float theta = (2.0f * M_PI + rX) * localIndex / pointsAtLevel; // Spread points evenly in azimuthal direction - - // Convert spherical coordinates to Cartesian coordinates - float sinPhi = sin(phi); - float cosPhi = cos(phi); - float sinTheta = sin(theta); - float cosTheta = cos(theta); - - // Local ray direction in spherical coordinates - float3 localRay = float3(sinPhi * cosTheta, sinPhi * sinTheta, cosPhi); - - // Convert local ray to global coordinates (tangent space to world space) - float3 globalRay = localRay.x * tangent + localRay.y * bitangent + localRay.z * dir; - - - return normalize(dir + globalRay); -} - static float NCOUNT = 32.0f; static uint N2 = 32; static float N = N2 * NCOUNT; +static float max_distance = 50.0f; +#define NTHREADS 32 -struct RayTraceColor { - float3 color[2]; - float dispersion[2]; - float3 bloom; - bool hit; -}; - -bool GetColor(Ray origRay, float rX, float level, uint max_bounces, out RayTraceColor out_color, float dispersion, bool mix, bool refract) +[numthreads(NTHREADS, NTHREADS, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) { - out_color.color[0] = float3(0.0f, 0.0f, 0.0f); - out_color.color[1] = float3(0.0f, 0.0f, 0.0f); - out_color.bloom = float3(0.0f, 0.0f, 0.0f); - out_color.dispersion[0] = -1.0f; - out_color.dispersion[1] = -1.0f; - - float last_dispersion = dispersion; - float acc_dispersion = dispersion; - float collision_dist = 0.0f; - float att_dist = 0.0f; -#if USE_OBH - uint volumeStack[MAX_STACK_SIZE]; -#endif - uint stack[MAX_STACK_SIZE]; - RayObject oray; - IntersectionResult object_result; - - bool collide = false; - IntersectionResult result; - Ray ray = origRay; - bool end = false; - - for (uint bounce = 0; !end; ++bounce) + float2 ray_input_dimension; + float2 ray_map_dimensions; { - result.distance = FLT_MAX; - end = true; - collide = false; -#if USE_OBH - uint volumeStackSize = 0; - volumeStack[volumeStackSize++] = 0; - uint i = 0; - while (volumeStackSize > 0 && volumeStackSize < MAX_STACK_SIZE) - { -#else - for (uint i = 0; i < nobjects; ++i) - { - uint objectIndex = i; -#endif - -#if USE_OBH - uint currentVolume = volumeStack[--volumeStackSize]; - - BVHNode volumeNode = objectBVH[currentVolume]; - if (is_leaf(volumeNode)) - { - uint objectIndex = index(volumeNode); - ObjectInfo o = objectInfos[objectIndex]; - - float objectExtent = length(o.aabb_max - o.aabb_min); - float distanceToObject = length(o.position - origRay.orig.xyz) - objectExtent; - - if (distanceToObject < max_distance && distanceToObject < result.distance && IntersectAABB(ray, o.aabb_min, o.aabb_max)) - { -#else - ObjectInfo o = objectInfos[i]; - float objectExtent = length(o.aabb_max - o.aabb_min); - float distanceToObject = length(o.position - origRay.orig.xyz) - objectExtent; - if (distanceToObject < max_distance && distanceToObject < result.distance && IntersectAABB(ray, o.aabb_min, o.aabb_max)) - { -#endif - object_result.distance = FLT_MAX; - - // Transform the ray direction from world space to object space - oray.orig = mul(ray.orig, o.inv_world); - oray.orig /= oray.orig.w; - oray.dir = normalize(mul(ray.dir, (float3x3) o.inv_world)); - oray.t = FLT_MAX; - - uint stackSize = 0; - stack[stackSize++] = 0; - - while (stackSize > 0 && stackSize < MAX_STACK_SIZE) - { - uint current = stack[--stackSize]; - - BVHNode node = objects[o.objectOffset + current]; - if (is_leaf(node)) - { - float t; - uint idx = index(node); - idx += o.indexOffset; - - IntersectionResult tmp_result; - tmp_result.distance = FLT_MAX; - if (IntersectTri(oray, idx, o.vertexOffset, tmp_result)) - { - if (tmp_result.distance < object_result.distance) { - object_result.v0 = tmp_result.v0; - object_result.v1 = tmp_result.v1; - object_result.v2 = tmp_result.v2; - object_result.vindex = tmp_result.vindex; - object_result.distance = tmp_result.distance; - object_result.uv = tmp_result.uv; - object_result.object = objectIndex; - } - } - } - else if (IntersectAABB(oray, node)) - { - stack[stackSize++] = left_child(node); - stack[stackSize++] = right_child(node); - } - } - - if (object_result.distance < FLT_MAX) { - float3 opos = (1.0f - object_result.uv.x - object_result.uv.y) * object_result.v0 + object_result.uv.x * object_result.v1 + object_result.uv.y * object_result.v2; - float4 pos = mul(float4(opos, 1.0f), o.world); - float distance = length(pos - ray.orig); - if (distance < result.distance) - { - collide = true; - collision_dist = length(pos - ray.orig); - ray.t = distance; - result.v0 = object_result.v0; - result.v1 = object_result.v1; - result.v2 = object_result.v2; - result.vindex = object_result.vindex; - result.distance = distance; - result.uv = object_result.uv; - result.object = objectIndex; - } - } - } -#if USE_OBH - } - else if (IntersectAABB(ray, volumeNode)) { - volumeStack[volumeStackSize++] = left_child(volumeNode); - volumeStack[volumeStackSize++] = right_child(volumeNode); - } - ++i; -#endif - } - - //At this point we have the ray collision distance and a collision result - if (collide) { - // Calculate space position - ObjectInfo o = objectInfos[result.object]; - float3 normal0 = asfloat(vertexBuffer.Load3(result.vindex.x + 12)); - float3 normal1 = asfloat(vertexBuffer.Load3(result.vindex.y + 12)); - float3 normal2 = asfloat(vertexBuffer.Load3(result.vindex.z + 12)); - float3 opos = (1.0f - result.uv.x - result.uv.y) * result.v0 + result.uv.x * result.v1 + result.uv.y * result.v2; - float3 normal = (1.0f - result.uv.x - result.uv.y) * normal0 + result.uv.x * normal1 + result.uv.y * normal2; - normal = normalize(mul(normal, (float3x3)o.world)); - float4 pos = mul(float4(opos, 1.0f), o.world); - pos /= pos.w; - MaterialColor material = objectMaterials[result.object]; - - float3 color = float3(0.0f, 0.0f, 0.0f); - - color += CalcAmbient(normal) * 0.5f; - color *= o.opacity; - - uint i = 0; - for (i = 0; i < dirLightsCount; ++i) { - color += CalcDirectional(normal, pos.xyz, dirLights[i], i); - } - - // Calculate the point lights - for (i = 0; i < pointLightsCount; ++i) { - if (length(pos.xyz - pointLights[i].Position) < pointLights[i].Range) { - color += CalcPoint(normal, pos.xyz, pointLights[i], i); - } - } - - //Calculate material color - if (material.flags & DIFFUSSE_MAP_ENABLED_FLAG) { - float2 uv0 = asfloat(vertexBuffer.Load2(result.vindex.x + 24)); - float2 uv1 = asfloat(vertexBuffer.Load2(result.vindex.y + 24)); - float2 uv2 = asfloat(vertexBuffer.Load2(result.vindex.z + 24)); - float2 uv = uv0 * (1.0f - result.uv.x - result.uv.y) + uv1 * result.uv.x + uv2 * result.uv.y; - color *= GetDiffuseColor(result.object, uv); - } - else { - color *= material.diffuseColor.rgb; - } - - float3 emission = material.emission * material.emission_color; - color += emission; - - float material_dispersion = saturate(1.0f - material.specIntensity); - att_dist += collision_dist * material_dispersion; - if (refract) { - att_dist = 1.0f; - } - float curr_att_dist = max(att_dist, 1.0f); - if (ray.bounces == 0 || mix) { - out_color.color[0] += color * ray.ratio / curr_att_dist; - out_color.dispersion[0] = acc_dispersion; - if (!refract) { - out_color.bloom += emission / curr_att_dist; - } - } - else { - out_color.color[1] += color * ray.ratio / curr_att_dist; - out_color.dispersion[1] = acc_dispersion; - } - acc_dispersion += material_dispersion; - last_dispersion = material_dispersion; - ray.orig = pos; - out_color.hit = true; - //If not opaque surface, generate a refraction ray - if (ray.bounces < 5 && o.opacity < 1.0f) { - if (ray.bounces % 2 == 0) { - normal = -normal; - } - ray = GetRefractedRayFromRay(ray, ray.density, - ray.density != 1.0 ? 1.0f : o.density, - normal, ray.ratio * (1.0f - o.opacity)); - end = false; - } + uint w, h; + ray0.GetDimensions(w, h); + ray_map_dimensions.x = w; + ray_map_dimensions.y = h; + ray_input_dimension.x = w / divider; + ray_input_dimension.y = h / divider; } - else { - //Color background - + int i = 0; + float x = (float)DTid.x; + float y = (float)DTid.y; + float2 pixel = float2(x, y); + float2 ray_pixel = round(pixel * divider); + + RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); + + float3 orig_pos = ray_source.orig.xyz; + bool process = length(orig_pos - cameraPosition) < max_distance; + + float3 normal; + float3 tangent; + float3 bitangent; + int count = 0; + + float cumulativePoints = 0; + float level = NCOUNT; + + float2 dirs[4]; + for (i = 0; i < 4; ++i) { + dirs[i] = float2(MAX_RAY_POLAR_DIR, MAX_RAY_POLAR_DIR); } - } -return out_color.hit; - } - -#define DENSITY 1.0f -#define NTHREADS 32 - [numthreads(NTHREADS, NTHREADS, 1)] - void main(uint3 DTid : SV_DispatchThreadID, uint3 group : SV_GroupID, uint3 thread : SV_GroupThreadID) + //Reflected ray + if (ray_source.opacity > Epsilon && ray_source.dispersion < 1.0f && (enabled & REFLEX_ENABLED)) { + Ray ray = GetReflectedRayFromSource(ray_source, cameraPosition); + float3 seed = DTid + float3(frame_count, frame_count, frame_count); + float rX = rgba_tnoise(seed); + rX = pow(rX, 1.0f + (1.0f - ray_source.dispersion)); + normal = ray.dir; + GetSpaceVectors(normal, tangent, bitangent); + dirs[0] = GenerateHemisphereDispersedRay(normal, tangent, bitangent, ray_source.dispersion, N, level, rX); + + } + //Refracted ray + if (ray_source.opacity < 0.99f && (enabled & REFRACT_ENABLED)) { + Ray ray = GetRefractedRayFromSource(ray_source, cameraPosition); + if (dist2(ray.dir) > Epsilon) { - float2 dimensions; - float2 ray_map_dimensions; - float2 bloom_dimensions; - { - uint w, h; - output0.GetDimensions(w, h); - dimensions.x = w; - dimensions.y = h; - - ray0.GetDimensions(w, h); - ray_map_dimensions.x = w; - ray_map_dimensions.y = h; - - bloom.GetDimensions(w, h); - bloom_dimensions.x = w; - bloom_dimensions.y = h; - } - float x = (float)DTid.x; - float y = (float)DTid.y; - - float2 rayMapRatio = ray_map_dimensions / dimensions; - float2 bloomRatio = bloom_dimensions / dimensions; - - float4 color_reflex = float4(0.0f, 0.0f, 0.0f, 1.0f); - float4 color_reflex2 = float4(0.0f, 0.0f, 0.0f, 1.0f); - float4 color_refrac = float4(0.0f, 0.0f, 0.0f, 1.0f); - - float2 pixel = float2(x, y); - - float2 ray_pixel = round(pixel * rayMapRatio); - - RaySource ray_source = fromColor(ray0[ray_pixel], ray1[ray_pixel]); - if (ray_source.reflex <= Epsilon || dist2(ray_source.normal) <= Epsilon || ray_source.dispersion < 0.0f) - { - return; - } - - //Reflected ray - float3 orig_pos = ray_source.orig.xyz; - bool process = length(orig_pos - cameraPosition) < max_distance; - - float3 tangent; - float3 bitangent; - RayTraceColor rc; - Ray ray = GetReflectedRayFromSource(ray_source); - if (dist2(ray.dir) > Epsilon) - { - float3 normal = ray_source.normal; - float3 orig_dir = ray.dir; - int count = 0; - - float cumulativePoints = 0; - float level = 1; - while (true) { - float c = cumulativePoints + level * 2; - if (c < N) { - cumulativePoints = c; - } - else { - break; - } - level++; - }; - - rc.hit = false; + dirs[1] = GetPolarCoordinates(ray.dir); + } + } - if (DTid.z == 0) { - float3 seed = orig_pos * 100.0f; - float rX = rgba_tnoise(seed); - rX = pow(rX, 5.0f); - GetSpaceVectors(orig_dir, tangent, bitangent); - ray.dir = GenerateHemisphereRay(orig_dir, tangent, bitangent, ray_source.dispersion, N, level, rX); - ray.orig.xyz = orig_pos.xyz + ray.dir * 0.001f; - float dist = FLT_MAX; - if (GetColor(ray, rX, level, 0, rc, ray_source.dispersion, true, false)) { - color_reflex.rgb += rc.color[0] * ray_source.opacity; - color_reflex2.rgb += rc.color[1] * ray_source.opacity; - } - float2 rc_disp = float2(rc.dispersion[0], rc.dispersion[1]); - float reflex_ratio = (1.0f - ray_source.dispersion); - output0[pixel] = color_reflex * reflex_ratio; - float4 d = dispersion[pixel]; - if (rc.hit) { - rc_disp = float2(max(rc_disp.x, rc.dispersion[0]), max(rc_disp.y, rc.dispersion[1])); - dispersion[pixel] = float4(rc_disp.x, rc_disp.y, d.b, d.a); - } - else { - dispersion[pixel] = float4(-1.0f, -1.0f, d.b, d.a); - } - } - else { - //Refracted ray - if (ray_source.opacity < 1.0f && (enabled & REFRACT_ENABLED)) { - float3 seed = orig_pos * 100.0f; - float rX = rgba_tnoise(seed); - Ray ray = GetRefractedRayFromSource(ray_source); - if (dist2(ray.dir) > Epsilon) - { - if (GetColor(ray, rX, level, 0, rc, ray_source.dispersion, true, true)) { - color_refrac.rgb += rc.color[0] * (1.0f - ray_source.opacity); - } - } - } - output1[pixel] = color_refrac; - float4 d = dispersion[pixel]; - dispersion[pixel] = float4(d.r, d.g, d.b, ray_source.dispersion); - } - } - else { - dispersion[pixel] = float4(-1.0f, -1.0f, -1.0f, -1.0f); - } - } \ No newline at end of file + ray_inputs[pixel] = Pack4Float2ToI16(dirs, MAX_RAY_POLAR_DIR); +} \ No newline at end of file diff --git a/Engine/Engine/Core/Shaders/RayTrace/RayWorldSolver.hlsli b/Engine/Engine/Core/Shaders/RayTrace/RayWorldSolver.hlsli new file mode 100644 index 0000000..6abb1c3 --- /dev/null +++ b/Engine/Engine/Core/Shaders/RayTrace/RayWorldSolver.hlsli @@ -0,0 +1,288 @@ +/* +The HotBite Game Engine + +Copyright(c) 2023 Vicente Sirvent Orts + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#define USE_OBH 0 +#define max_distance 50.0f + +struct RayTraceColor { + float3 color; + bool hit; +}; + +bool GetColor(Ray origRay, uint max_bounces, out RayTraceColor out_color, float dispersion, bool refract) +{ + out_color.color = float3(0.0f, 0.0f, 0.0f); + out_color.hit = false; + + float last_dispersion = dispersion; + float acc_dispersion = dispersion; + float att_dist = 0.0f; +#if USE_OBH + uint volumeStack[MAX_STACK_SIZE]; +#endif + uint stack[MAX_STACK_SIZE]; + RayObject oray; + IntersectionResult object_result; + + bool collide = false; + IntersectionResult result; + Ray ray = origRay; + bool end = false; + + while (!end) + { + result.distance = FLT_MAX; + end = true; + collide = false; +#if USE_OBH + uint volumeStackSize = 0; + volumeStack[volumeStackSize++] = 0; + uint i = 0; + while (volumeStackSize > 0 && volumeStackSize < MAX_STACK_SIZE) + { +#else + for (uint i = 0; i < nobjects; ++i) + { + uint objectIndex = i; +#endif + +#if USE_OBH + uint currentVolume = volumeStack[--volumeStackSize]; + + BVHNode volumeNode = objectBVH[currentVolume]; + + if (is_leaf(volumeNode)) + { + uint objectIndex = index(volumeNode); + ObjectInfo o = objectInfos[objectIndex]; + + if (IntersectAABB(ray, o.aabb_min, o.aabb_max)) + { +#else + ObjectInfo o = objectInfos[i]; + float objectExtent = length(o.aabb_max - o.aabb_min); + float distanceToObject = length(o.position - origRay.orig.xyz) - objectExtent; + + if (distanceToObject < max_distance && distanceToObject < result.distance && IntersectAABB(ray, o.aabb_min, o.aabb_max)) + { +#endif + object_result.distance = FLT_MAX; + + // Transform the ray direction from world space to object space + oray.orig = mul(ray.orig, o.inv_world); + oray.orig /= oray.orig.w; + oray.dir = normalize(mul(ray.dir, (float3x3) o.inv_world)); + oray.t = FLT_MAX; + + uint stackSize = 0; + stack[stackSize++] = 0; + + while (stackSize > 0 && stackSize < MAX_STACK_SIZE) + { + uint current = stack[--stackSize]; + + BVHNode node = objects[o.objectOffset + current]; + if (is_leaf(node)) + { + float t; + uint idx = index(node); + idx += o.indexOffset; + + IntersectionResult tmp_result; + tmp_result.distance = FLT_MAX; + if (IntersectTri(oray, idx, o.vertexOffset, tmp_result)) + { + if (tmp_result.distance < object_result.distance) { + object_result.v0 = tmp_result.v0; + object_result.v1 = tmp_result.v1; + object_result.v2 = tmp_result.v2; + object_result.vindex = tmp_result.vindex; + object_result.distance = tmp_result.distance; + object_result.u = tmp_result.u; + object_result.v = tmp_result.v; + object_result.object = objectIndex; + } + } + } + else if (IntersectAABB(oray, node)) + { + uint left_node_index = left_child(node); + uint right_node_index = right_child(node); + + BVHNode left_node = objects[o.objectOffset + left_node_index]; + BVHNode right_node = objects[o.objectOffset + right_node_index]; + + float left_dist = node_distance(left_node, oray.orig.xyz); + float right_dist = node_distance(right_node, oray.orig.xyz); + + if (left_dist < right_dist) { + if (right_dist < object_result.distance && right_dist < max_distance) { + stack[stackSize++] = right_node_index; + } + if (left_dist < object_result.distance && left_dist < max_distance) { + stack[stackSize++] = left_node_index; + } + } + else { + if (left_dist < object_result.distance && left_dist < max_distance) { + stack[stackSize++] = left_node_index; + } + if (right_dist < object_result.distance && right_dist < max_distance) { + stack[stackSize++] = right_node_index; + } + } + } + } + + if (object_result.distance < FLT_MAX) { + float3 opos = (1.0f - object_result.u - object_result.v) * object_result.v0 + object_result.u * object_result.v1 + object_result.v * object_result.v2; + float4 pos = mul(float4(opos, 1.0f), o.world); + float distance = length(pos - ray.orig); + if (distance < result.distance) + { + collide = true; + ray.t = distance; + result.v0 = object_result.v0; + result.v1 = object_result.v1; + result.v2 = object_result.v2; + result.vindex = object_result.vindex; + result.distance = distance; + result.u = object_result.u; + result.v = object_result.v; + result.object = objectIndex; + } + } + } +#if USE_OBH + } + else + + if (IntersectAABB(ray, volumeNode)) { + + uint left_node_index = left_child(volumeNode); + uint right_node_index = right_child(volumeNode); + + BVHNode left_node = objectBVH[left_node_index]; + BVHNode right_node = objectBVH[right_node_index]; + + float left_dist = node_distance(left_node, ray.orig.xyz); + float right_dist = node_distance(right_node, ray.orig.xyz); + + if (left_dist < right_dist) { + if (right_dist < result.distance && right_dist < max_distance) { + volumeStack[volumeStackSize++] = right_node_index; + } + if (left_dist < result.distance && left_dist < max_distance) { + volumeStack[volumeStackSize++] = left_node_index; + } + } + else { + if (left_dist < result.distance && left_dist < max_distance) { + volumeStack[volumeStackSize++] = left_node_index; + } + if (right_dist < result.distance && right_dist < max_distance) { + volumeStack[volumeStackSize++] = right_node_index; + } + } + } + ++i; +#endif + } + + //At this point we have the ray collision distance and a collision result + if (collide) { + // Calculate space position + ObjectInfo o = objectInfos[result.object]; + float3 normal0 = asfloat(vertexBuffer.Load3(result.vindex.x + 12)); + float3 normal1 = asfloat(vertexBuffer.Load3(result.vindex.y + 12)); + float3 normal2 = asfloat(vertexBuffer.Load3(result.vindex.z + 12)); + float3 opos = (1.0f - result.u - result.v) * result.v0 + result.u * result.v1 + result.v * result.v2; + float3 normal = (1.0f - result.u - result.v) * normal0 + result.u * normal1 + result.v * normal2; + normal = normalize(mul(normal, (float3x3)o.world)); + float4 pos = mul(float4(opos, 1.0f), o.world); + pos /= pos.w; + MaterialColor material = objectMaterials[result.object]; + + float3 color = float3(0.0f, 0.0f, 0.0f); + + color += CalcAmbient(normal) * 0.5f; + + + uint i = 0; + for (i = 0; i < dirLightsCount; ++i) { + color += CalcDirectional(normal, pos.xyz, dirLights[i], i); + } + + // Calculate the point lights + for (i = 0; i < pointLightsCount; ++i) { + if (length(pos.xyz - pointLights[i].Position) < pointLights[i].Range) { + color += CalcPoint(normal, pos.xyz, pointLights[i], i); + } + } + + bool use_mat_texture = material.flags & DIFFUSSE_MAP_ENABLED_FLAG; + float3 mat_color = material.diffuseColor.rgb * !use_mat_texture; + + float2 uv0 = asfloat(vertexBuffer.Load2(result.vindex.x + 24)); + float2 uv1 = asfloat(vertexBuffer.Load2(result.vindex.y + 24)); + float2 uv2 = asfloat(vertexBuffer.Load2(result.vindex.z + 24)); + float2 uv = uv0 * (1.0f - result.u - result.v) + uv1 * result.u + uv2 * result.v; + + mat_color += GetDiffuseColor(result.object, uv) * use_mat_texture; + + color.rgb *= mat_color * o.opacity; + + float3 emission = material.emission * material.emission_color; + color += emission; + + float material_dispersion = saturate(1.0f - material.specIntensity); + + if (refract) { + att_dist = 1.0f; + } + float curr_att_dist = max(att_dist, 1.0f); + out_color.color += color * ray.ratio; + acc_dispersion += material_dispersion; + last_dispersion = material_dispersion; + ray.orig = pos; + out_color.hit = true; + + //If not opaque surface, generate a refraction ray + if (ray.bounces < 5 && o.opacity < 1.0f) { + if (ray.bounces % 2 == 0) { + normal = -normal; + } + ray = GetRefractedRayFromRay(ray, ray.density, + ray.density != 1.0 ? 1.0f : o.density, + normal, ray.ratio * (1.0f - o.opacity)); + end = false; + } + } + else { + //Color background + + } + } +return out_color.hit; + } diff --git a/Engine/Engine/Core/SimpleShader.cpp b/Engine/Engine/Core/SimpleShader.cpp index fc3e933..55ab228 100644 --- a/Engine/Engine/Core/SimpleShader.cpp +++ b/Engine/Engine/Core/SimpleShader.cpp @@ -198,7 +198,7 @@ namespace HotBite { break; } } - + uint32_t realConstantBufferCount = 0; // Loop through all constant buffers for (unsigned int b = 0; b < constantBufferCount; b++) { @@ -215,6 +215,10 @@ namespace HotBite { D3D11_SHADER_INPUT_BIND_DESC bindDesc; refl->GetResourceBindingDescByName(bufferDesc.Name, &bindDesc); + if (bindDesc.Type != D3D_SIT_CBUFFER) { + continue; + } + realConstantBufferCount++; // Set up the buffer and put its pointer in the table constantBuffers[b].BindIndex = bindDesc.BindPoint; constantBuffers[b].Name = bufferDesc.Name; @@ -260,6 +264,7 @@ namespace HotBite { constantBuffers[b].Variables.push_back(varStruct); } } + constantBufferCount = realConstantBufferCount; // All set refl->Release(); diff --git a/Engine/Engine/Core/Texture.cpp b/Engine/Engine/Core/Texture.cpp index fa88b50..890f762 100644 --- a/Engine/Engine/Core/Texture.cpp +++ b/Engine/Engine/Core/Texture.cpp @@ -376,6 +376,7 @@ namespace HotBite { ID3D11Device* device = DXCore::Get()->device; HRESULT hr = S_OK; init = true; + width = w; height = h; //Description of each face @@ -439,7 +440,6 @@ namespace HotBite { renderTargetViewDesc.Texture2D.MipSlice = 0; // Create the render target view. hr = device->CreateRenderTargetView(texture, &renderTargetViewDesc, &render_view); - return hr; } diff --git a/Engine/Engine/Core/Utils.h b/Engine/Engine/Core/Utils.h index 095c3f4..8cc1725 100644 --- a/Engine/Engine/Core/Utils.h +++ b/Engine/Engine/Core/Utils.h @@ -97,61 +97,7 @@ namespace HotBite { } }; - template - class SpaceTree { - public: - struct Cube { - float3 p0; - float3 p1; - - bool operator>(const Cube& other) { - return DIST2(p0) > DIST2(other.p0); - } - - bool operator==(const Cube& other) { - return DIST2(p0) == DIST2(other.p0); - } - - static Cube Get(const float3& pos) { - p0 = pos.x / grid_value; - p0 = pos.y / grid_value; - p0 = pos.z / grid_value; - p1.x = p0.x + 1; - p1.y = p0.y + 1; - p1.z = p0.z + 1; - return { p0, p1 }; - } - - static bool Inside(const float3& p) { - return ((p.x >= p0.x && p.x < p0.x + p1.x) && - (p.y >= p0.y && p.y < p0.y + p1.y) && - (p.z >= p0.z && p.z < p0.z + p1.z)); - } - }; - - private: - using SpaceMap = std::unordered_map>; - SpaceMap data; - - public: - void Insert(const float3& position, const T& v) { - auto k = Cube::Get(position); - data[k].push_back(v); - } - - void Remove(const float3& position) { - for (auto& quad: data) { - for (auto it = quad.being(); it != quad.end(); ++it) { - if (it->p0 == position) { - quad.erase(position); - return; - } - } - } - } - - const std::unordered_map>& Data() { return data; } - }; + /** * This is an map that stores data in vectors in order to allow fast access and * and be cache friendly. diff --git a/Engine/Engine/Defines.h b/Engine/Engine/Defines.h index 786da81..9513f1b 100644 --- a/Engine/Engine/Defines.h +++ b/Engine/Engine/Defines.h @@ -183,6 +183,11 @@ namespace HotBite { return (a.x == b.x && a.y == b.y); } + // MAX + inline float3 MAX_F3_F3(const float3& a, const float3& b) { + return { max(a.x, b.x), max(a.y, b.y), max(a.z, b.z) }; + } + // ADD inline float4 ADD_F4_F4(const float4& a, const float4& b) { __m128 va = _mm_load_ps(&a.x); diff --git a/Engine/Engine/Systems/RenderSystem.cpp b/Engine/Engine/Systems/RenderSystem.cpp index aead8f2..2d0357e 100644 --- a/Engine/Engine/Systems/RenderSystem.cpp +++ b/Engine/Engine/Systems/RenderSystem.cpp @@ -38,6 +38,8 @@ using namespace DirectX; static const float zero[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; static const float ones[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; +static const float max_floats[4] = { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX }; +static const uint32_t max_uint[4] = { UINT_MAX, UINT_MAX, UINT_MAX, UINT_MAX }; static const float minus_one[4] = { -1.0f, -1.0f, -1.0f, -1.0f }; @@ -246,11 +248,11 @@ bool RenderSystem::Init(DXCore* dx_core, Core::VertexBuffer* vb, Core::B vertex_buffer = vb; bvh_buffer = bvh; tbvh_buffer.Prepare(MAX_OBJECTS * 2 - 1); - first_pass_target = dxcore; + first_pass_target = dxcore; depth_target = dxcore; int w = dxcore->GetWidth(); int h = dxcore->GetHeight(); - + for (int i = 0; i < 2; ++i) { if (FAILED(light_map[i].Init(w, h, DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { @@ -266,7 +268,7 @@ bool RenderSystem::Init(DXCore* dx_core, Core::VertexBuffer* vb, Core::B if (FAILED(dust_render_map.Init(w / 2, h / 2, DXGI_FORMAT::DXGI_FORMAT_R11G11B10_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("dust_render_map.Init failed"); } - if (FAILED(vol_light_map2.Init(w / 2, h / 2, DXGI_FORMAT::DXGI_FORMAT_R11G11B10_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + if (FAILED(vol_light_map2.Init(w, h, DXGI_FORMAT::DXGI_FORMAT_R11G11B10_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("vol_light_map2.Init failed"); } if (FAILED(position_map.Init(w, h, DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT))) { @@ -284,6 +286,23 @@ bool RenderSystem::Init(DXCore* dx_core, Core::VertexBuffer* vb, Core::B if (FAILED(depth_map.Init(w, h, DXGI_FORMAT::DXGI_FORMAT_R32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("depth_map.Init failed"); } + + if (FAILED(high_z_tmp_map.Init(w, h, DXGI_FORMAT::DXGI_FORMAT_R32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("high_z_tmp_map.Init failed"); + } + + uint32_t hiz_w = w; + uint32_t hiz_h = h; + high_z_maps[0] = depth_map.SRV(); + for (int i = 0; i < HIZ_DOWNSAMPLED_NTEXTURES; ++i) { + hiz_w = (uint32_t)ceil((float)hiz_w / (float)HIZ_RATIO); + hiz_h = (uint32_t)ceil((float)hiz_h / (float)HIZ_RATIO); + if (FAILED(high_z_downsampled_map[i].Init(hiz_w, hiz_h, DXGI_FORMAT::DXGI_FORMAT_R32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("high_z_downsampled_map.Init failed"); + } + high_z_maps[i + 1] = high_z_downsampled_map[i].SRV(); + } + if (FAILED(depth_view.Init(w, h))) { throw std::exception("depth_view.Init failed"); } @@ -346,10 +365,6 @@ bool RenderSystem::Init(DXCore* dx_core, Core::VertexBuffer* vb, Core::B if (rt_di_denoiser == nullptr) { throw std::exception("DenoiserCS shader.Init failed"); } - rt_disp = ShaderFactory::Get()->GetShader("DispersionCS.cso"); - if (rt_disp == nullptr) { - throw std::exception("DispersionCS shader.Init failed"); - } gi_average = ShaderFactory::Get()->GetShader("GIAverageCS.cso"); if (gi_average == nullptr) { throw std::exception("GIAverageCS shader.Init failed"); @@ -378,6 +393,30 @@ bool RenderSystem::Init(DXCore* dx_core, Core::VertexBuffer* vb, Core::B if (copy_texture == nullptr) { throw std::exception("Copy textures shader.Init failed"); } + high_z_shader = ShaderFactory::Get()->GetShader("HiZDownSample.cso"); + if (high_z_shader == nullptr) { + throw std::exception("HiZDownSample shader.Init failed"); + } + + ray_reflex_screen_solver = ShaderFactory::Get()->GetShader("RayReflexScreenSolverCS.cso"); + if (ray_reflex_screen_solver == nullptr) { + throw std::exception("RayReflexScreenSolverCS shader.Init failed"); + } + + ray_reflex_world_solver = ShaderFactory::Get()->GetShader("RayReflexWorldSolverCS.cso"); + if (ray_reflex_world_solver == nullptr) { + throw std::exception("RayReflexWorldSolverCS shader.Init failed"); + } + + ray_gi_screen_solver = ShaderFactory::Get()->GetShader("RayGIScreenSolverCS.cso"); + if (ray_gi_screen_solver == nullptr) { + throw std::exception("RayGIScreenSolverCS shader.Init failed"); + } + + ray_gi_world_solver = ShaderFactory::Get()->GetShader("RayGIWorldSolverCS.cso"); + if (ray_gi_world_solver == nullptr) { + throw std::exception("RayGIWorldSolverCS shader.Init failed"); + } LoadRTResources(); @@ -427,21 +466,30 @@ RenderSystem::~RenderSystem() { rgba_noise_texture.Release(); motion_texture.Release(); depth_map.Release(); + high_z_tmp_map.Release(); + for (int i = 0; i < HIZ_DOWNSAMPLED_NTEXTURES; ++i) { + high_z_downsampled_map[i].Release(); + } for (int i = 0; i < RT_NTEXTURES; ++i) { for (int x = 0; x < 2; ++x) { - rt_textures[x][i].Release(); + rt_textures_di[x][i].Release(); } } + for (int x = 0; x < RT_GI_NTEXTURES; ++x) { + rt_textures_gi[x].Release(); + } + + rt_textures_gi_tiles.Release(); for (int x = 0; x < 2; ++x) { restir_pdf[x].Release(); } + restir_pdf_mask.Release(); restir_w.Release(); texture_tmp.Release(); rt_texture_props.Release(); - rt_dispersion.Release(); rt_ray_sources0.Release(); rt_ray_sources1.Release(); vol_data.Release(); @@ -453,24 +501,47 @@ void RenderSystem::LoadRTResources() { int h = dxcore->GetHeight(); for (int x = 0; x < RT_NTEXTURES; ++x) { int div = RT_TEXTURE_RESOLUTION_DIVIDER; - if (x == RT_TEXTURE_INDIRECT) { - div = max(RT_TEXTURE_RESOLUTION_DIVIDER, 2); - } for (int n = 0; n < 2; ++n) { - rt_textures[n][x].Release(); - if (FAILED(rt_textures[n][x].Init(w / div, h / div, DXGI_FORMAT::DXGI_FORMAT_R11G11B10_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + rt_textures_di[n][x].Release(); + if (FAILED(rt_textures_di[n][x].Init(w / div, h / div, DXGI_FORMAT::DXGI_FORMAT_R16G16B16A16_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("rt_texture.Init failed"); } + rt_textures_di[n][x].Clear(zero); } } - int restir_div = max(RT_TEXTURE_RESOLUTION_DIVIDER, 2); + input_rays.Release(); + if (FAILED(input_rays.Init(w / RT_TEXTURE_RESOLUTION_DIVIDER, h / RT_TEXTURE_RESOLUTION_DIVIDER, DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_UINT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("input_rays.Init failed"); + } + + uint32_t restir_div = GI_TEXTURE_RESOLUTION_DIVIDER; + + for (int n = 0; n < RT_GI_NTEXTURES; ++n) { + rt_textures_gi[n].Release(); + if (FAILED(rt_textures_gi[n].Init(w / restir_div, h / restir_div, DXGI_FORMAT::DXGI_FORMAT_R16G16B16A16_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("rt_texture.Init failed"); + } + rt_textures_gi[n].Clear(zero); + } + + uint32_t tile_div = min(restir_div, RT_TEXTURE_RESOLUTION_DIVIDER) * RESTIR_KERNEL; + rt_textures_gi_tiles.Release(); + if (FAILED(rt_textures_gi_tiles.Init(w / tile_div + 1, h/ tile_div + 1, DXGI_FORMAT::DXGI_FORMAT_R8_UINT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("rt_texture.Init failed"); + } + for (int n = 0; n < 2; ++n) { restir_pdf[n].Release(); if (FAILED(restir_pdf[n].Init(w / restir_div, h / restir_div, DXGI_FORMAT_R32G32B32A32_UINT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("restir_pdf.Init failed"); } } + + restir_pdf_mask.Release(); + if (FAILED(restir_pdf_mask.Init(w / restir_div, h / restir_div, DXGI_FORMAT::DXGI_FORMAT_R16_UINT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { + throw std::exception("restir_w.Init failed"); + } restir_w.Release(); if (FAILED(restir_w.Init(w / restir_div, h / restir_div, DXGI_FORMAT::DXGI_FORMAT_R32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { throw std::exception("restir_w.Init failed"); @@ -486,10 +557,6 @@ void RenderSystem::LoadRTResources() { throw std::exception("rt_texture_props.Init failed"); } - rt_dispersion.Release(); - if (FAILED(rt_dispersion.Init(w / RT_TEXTURE_RESOLUTION_DIVIDER, h / RT_TEXTURE_RESOLUTION_DIVIDER, DXGI_FORMAT::DXGI_FORMAT_R32G32B32A32_FLOAT, nullptr, 0, D3D11_BIND_UNORDERED_ACCESS))) { - throw std::exception("rt_dispersion.Init failed"); - } ResetRTBBuffers(); } @@ -1263,8 +1330,7 @@ void RenderSystem::DrawScene(int w, int h, const float3& camera_position, const gs->SetInt(SCREEN_W, w); gs->SetInt(SCREEN_H, h); gs->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); - gs->SetMatrix4x4(VIEW, cam_entity.camera->view); - gs->SetMatrix4x4(PROJECTION, cam_entity.camera->projection); + gs->SetMatrix4x4("view_projection", cam_entity.camera->view_projection); gs->SetFloat(TIME, time); gs->SetShader(); } @@ -1408,7 +1474,8 @@ void RenderSystem::ProcessMix() { if (post_process_pipeline == nullptr) { return; } - + ID3D11RenderTargetView* rv_zero[1] = { nullptr }; + dxcore->context->OMSetRenderTargets(1, rv_zero, nullptr); ID3D11UnorderedAccessView* image = temp_map.UAV(); int32_t groupsX = (int32_t)(ceil((float)temp_map.Width() / 32.0f)); @@ -1422,12 +1489,16 @@ void RenderSystem::ProcessMix() { mixer_shader->SetShaderResourceView("lightTexture", current_light_map->SRV()); mixer_shader->SetShaderResourceView("volLightTexture", vol_light_map.SRV()); mixer_shader->SetShaderResourceView("bloomTexture", bloom_map.SRV()); - mixer_shader->SetShaderResourceView("emissionTexture", rt_texture_curr[RT_TEXTURE_EMISSION].SRV()); mixer_shader->SetShaderResourceView("dustTexture", dust_render_map.SRV()); mixer_shader->SetShaderResourceView("lensFlareTexture", lens_flare_map.SRV()); - mixer_shader->SetShaderResourceView("rtTexture0", rt_texture_curr[RT_TEXTURE_REFLEX].SRV()); - mixer_shader->SetShaderResourceView("rtTexture1", rt_texture_curr[RT_TEXTURE_REFRACT].SRV()); - mixer_shader->SetShaderResourceView("rtTexture2", rt_texture_curr[RT_TEXTURE_INDIRECT].SRV()); + if (rt_texture_di_curr != nullptr) { + mixer_shader->SetShaderResourceView("emissionTexture", rt_texture_di_curr[RT_TEXTURE_EMISSION].SRV()); + mixer_shader->SetShaderResourceView("rtTexture0", rt_texture_di_curr[RT_TEXTURE_REFLEX].SRV()); + mixer_shader->SetShaderResourceView("rtTexture1", rt_texture_di_curr[RT_TEXTURE_REFRACT].SRV()); + } + if (rt_texture_gi_curr != nullptr) { + mixer_shader->SetShaderResourceView("rtTexture2", rt_texture_gi_curr->SRV()); + } mixer_shader->SetShaderResourceView("positions", rt_ray_sources0.SRV()); mixer_shader->SetShaderResourceView("normals", rt_ray_sources1.SRV()); mixer_shader->SetShaderResourceView("input", post_process_pipeline->RenderResource()); @@ -1444,11 +1515,14 @@ void RenderSystem::ProcessMix() { mixer_shader->SetShaderResourceView("rtTexture1", nullptr); mixer_shader->SetShaderResourceView("rtTexture2", nullptr); mixer_shader->SetShaderResourceView("rtTexture3", nullptr); + mixer_shader->SetShaderResourceView("rtTextureUV", nullptr); mixer_shader->SetShaderResourceView("volLightTexture", nullptr); mixer_shader->SetShaderResourceView("dustTexture", nullptr); mixer_shader->SetShaderResourceView("input", nullptr); mixer_shader->SetShaderResourceView("lensFlareTexture", nullptr); mixer_shader->SetShaderResourceView("rgbaNoise", nullptr); + mixer_shader->SetShaderResourceView("positions", nullptr); + mixer_shader->SetShaderResourceView("normals", nullptr); mixer_shader->CopyAllBufferData(); } @@ -1627,6 +1701,47 @@ void RenderSystem::ProcessMotion() { } } +void RenderSystem::ProcessHighZ() { + + high_z_shader->SetInt("ratio", HIZ_RATIO); + high_z_shader->SetShader(); + + Core::RenderTexture2D* input; + Core::RenderTexture2D* output; + + for (uint32_t i = 0; i < HIZ_DOWNSAMPLED_NTEXTURES; ++i) { + if (i == 0) { + input = &depth_map; + } + else { + input = &high_z_downsampled_map[i - 1]; + } + output = &high_z_downsampled_map[i]; + + int32_t groupsX = (int32_t)(ceil((float)input->Width() / 32.0f)); + int32_t groupsY = (int32_t)(ceil((float)output->Height() / 32.0f)); + + high_z_shader->SetInt("type", 1); + high_z_shader->SetShaderResourceView("input", input->SRV()); + high_z_shader->SetUnorderedAccessView("output", high_z_tmp_map.UAV()); + high_z_shader->CopyAllBufferData(); + dxcore->context->Dispatch(groupsX, groupsY, 1); + + groupsX = (int32_t)(ceil((float)output->Width() / 32.0f)); + groupsY = (int32_t)(ceil((float)input->Height() / 32.0f)); + + high_z_shader->SetInt("type", 2); + high_z_shader->SetShaderResourceView("input", nullptr); + high_z_shader->SetUnorderedAccessView("output", nullptr); + high_z_shader->SetShaderResourceView("input", high_z_tmp_map.SRV()); + high_z_shader->SetUnorderedAccessView("output", output->UAV()); + high_z_shader->CopyAllBufferData(); + dxcore->context->Dispatch(groupsX, groupsY, 1); + high_z_shader->SetShaderResourceView("input", nullptr); + high_z_shader->SetUnorderedAccessView("output", nullptr); + } +} + void RenderSystem::PrepareRT() { if (rt_quality != eRtQuality::OFF && rt_enabled && bvh_buffer != nullptr) { auto& device = dxcore->device; @@ -1648,7 +1763,13 @@ void RenderSystem::PrepareRT() { for (const auto& mat : shaders.second) { for (const auto& de : mat.second.second.GetConstData()) { if (de.base->visible && de.mesh->GetData()->skeletons.empty()) { - float distance = LENGHT_F3(de.transform->position - (ADD_F3_F3(ca->camera->world_position, ca->camera->direction))); + + // Get the center and extents of the oriented box + const float3& orientedBoxCenter = de.bounds->final_box.Center; + const float3& orientedBoxExtents = de.bounds->final_box.Extents; + + //float distance = LENGHT_F3(de.transform->position - (ADD_F3_F3(ca->camera->world_position, ca->camera->direction))); + float distance = LENGHT_F3(MAX_F3_F3(SUB_F3_F3(orientedBoxCenter - ca->transform->position, orientedBoxExtents), { 0.0f, 0.0f, 0.0f })); MaterialProps mo = de.mat->data->props; @@ -1656,10 +1777,6 @@ void RenderSystem::PrepareRT() { ObjectInfo o; - // Get the center and extents of the oriented box - const float3& orientedBoxCenter = de.bounds->final_box.Center; - const float3& orientedBoxExtents = de.bounds->final_box.Extents; - // Calculate the minimum and maximum points of the AABB o.aabb_min = { orientedBoxCenter.x - orientedBoxExtents.x, orientedBoxCenter.y - orientedBoxExtents.y, @@ -1692,7 +1809,7 @@ void RenderSystem::PrepareRT() { break; } else { - distance += 0.001f; + distance += 1.0f; } } } @@ -1724,81 +1841,184 @@ void RenderSystem::PrepareRT() { } void RenderSystem::ProcessGI() { + if (rt_enabled & RT_INDIRECT_ENABLE && rt_quality != eRtQuality::OFF && rt_enabled && bvh_buffer != nullptr && nobjects > 0) { + ID3D11ShaderResourceView* nullsrc = nullptr; restir_pdf_curr = &restir_pdf[0]; restir_pdf_prev = &restir_pdf[1]; - rt_texture_curr = rt_textures[current]; - rt_texture_prev = rt_textures[prev]; + rt_texture_gi_curr = &rt_textures_gi[current]; + rt_texture_gi_prev = &rt_textures_gi[prev]; + rt_texture_gi_tmp[0] = &rt_textures_gi[2]; + rt_texture_gi_tmp[1] = &rt_textures_gi[3]; + rt_texture_gi_trace = &rt_textures_gi[4]; + rt_textures_gi_tiles.Clear(zero); std::lock_guard lock(rt_mutex); CameraEntity& cam_entity = cameras.GetData()[0]; + input_rays.Clear((float*)max_uint); + restir_pdf_mask.Clear(zero); gi_shader->SetInt("kernel_size", RESTIR_KERNEL); gi_shader->SetInt("ray_count", RESTIR_PIXEL_RAYS); + gi_shader->SetFloat(TIME, time); + gi_shader->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); - gi_shader->SetInt("nobjects", nobjects); - gi_shader->SetInt("enabled", rt_enabled & (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); gi_shader->SetMatrix4x4("view_proj", cam_entity.camera->view_projection); - gi_shader->SetMatrix4x4("prev_view_proj", cam_entity.camera->prev_view_projection); gi_shader->SetInt("frame_count", frame_count); - gi_shader->SetData("objectMaterials", objectMaterials, nobjects * sizeof(MaterialProps)); - gi_shader->SetData("objectInfos", objects, nobjects * sizeof(ObjectInfo)); - gi_shader->SetMatrix4x4(VIEW, cam_entity.camera->view); - gi_shader->SetMatrix4x4(PROJECTION, cam_entity.camera->projection); - gi_shader->SetShaderResourceView("position_map", position_map.SRV()); - gi_shader->SetShaderResourceView("depth_map", depth_map.SRV()); + gi_shader->SetInt("divider", GI_TEXTURE_RESOLUTION_DIVIDER); + + gi_shader->SetUnorderedAccessView("restir_pdf_mask", restir_pdf_mask.UAV()); + gi_shader->SetUnorderedAccessView("ray_inputs", input_rays.UAV()); gi_shader->SetShaderResourceView("motion_texture", motion_texture.SRV()); gi_shader->SetShaderResourceView("prev_position_map", prev_position_map.SRV()); gi_shader->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); gi_shader->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); - gi_shader->SetUnorderedAccessView("props", rt_texture_props.UAV()); - - float3 dir; - XMStoreFloat3(&dir, cam_entity.camera->xm_direction); - gi_shader->SetFloat(TIME, time); - gi_shader->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); - gi_shader->SetFloat3("cameraDirection", dir); - gi_shader->SetSamplerState(PCF_SAMPLER, dxcore->shadow_sampler); - gi_shader->SetSamplerState(BASIC_SAMPLER, dxcore->basic_sampler); - gi_shader->SetShaderResourceViewArray("DiffuseTextures[0]", diffuseTextures, nobjects); - - PrepareLights(gi_shader); + gi_shader->SetShaderResourceView("restir_pdf_0", restir_pdf_prev->SRV()); + gi_shader->SetShaderResourceView("restir_w_0", restir_w.SRV()); gi_shader->CopyAllBufferData(); gi_shader->SetShader(); + + int groupsX = (int32_t)(ceil((float)rt_texture_gi_curr->Width() / (32.0f))); + int groupsY = (int32_t)(ceil((float)rt_texture_gi_curr->Height() / (32.0f))); + dxcore->context->Dispatch((uint32_t)ceil((float)groupsX), (uint32_t)ceil((float)groupsY), 1); + + gi_shader->SetUnorderedAccessView("restir_pdf_mask", nullptr); + gi_shader->SetUnorderedAccessView("ray_inputs", nullptr); + gi_shader->SetShaderResourceView("motion_texture", nullptr); + gi_shader->SetShaderResourceView("prev_position_map", nullptr); + gi_shader->SetShaderResourceView("ray0", nullptr); + gi_shader->SetShaderResourceView("ray1", nullptr); + gi_shader->SetShaderResourceView("restir_pdf_0", nullptr); + gi_shader->SetShaderResourceView("restir_w_0", nullptr); + +#if 1 + //Resolve rays with screen space Ray Tracing + ray_gi_screen_solver->SetInt("enabled", rt_enabled & (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); + ray_gi_screen_solver->SetInt("frame_count", frame_count); + ray_gi_screen_solver->SetFloat(TIME, time); + ray_gi_screen_solver->SetInt("kernel_size", RESTIR_KERNEL); + ray_gi_screen_solver->SetInt("type", 2); + ray_gi_screen_solver->SetInt("divider", GI_TEXTURE_RESOLUTION_DIVIDER); + ray_gi_screen_solver->SetFloat("hiz_ratio", HIZ_RATIO); + ray_gi_screen_solver->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); + ray_gi_screen_solver->SetMatrix4x4("view", cam_entity.camera->view); + ray_gi_screen_solver->SetMatrix4x4("projection", cam_entity.camera->projection); + ray_gi_screen_solver->SetMatrix4x4("inv_projection", cam_entity.camera->inverse_projection); + ray_gi_screen_solver->SetMatrix4x4("prev_view_proj", cam_entity.camera->prev_view_projection); + + ray_gi_screen_solver->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); + ray_gi_screen_solver->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); + ray_gi_screen_solver->SetUnorderedAccessView("ray_inputs", input_rays.UAV()); + ray_gi_screen_solver->SetUnorderedAccessView("output", rt_texture_gi_trace->UAV()); + ray_gi_screen_solver->SetUnorderedAccessView("tiles_output", rt_textures_gi_tiles.UAV()); + ray_gi_screen_solver->SetShaderResourceViewArray("hiz_textures[0]", high_z_maps, HIZ_NTEXTURES); + ray_gi_screen_solver->SetShaderResourceView("prev_position_map", prev_position_map.SRV()); + ray_gi_screen_solver->SetShaderResourceView("restir_pdf_mask", restir_pdf_mask.SRV()); + ray_gi_screen_solver->SetShaderResourceView("restir_pdf_0", restir_pdf_prev->SRV()); + ray_gi_screen_solver->SetUnorderedAccessView("restir_pdf_1", restir_pdf_curr->UAV()); + ray_gi_screen_solver->SetShaderResourceView("restir_w_0", restir_w.SRV()); + + ray_gi_screen_solver->SetShaderResourceView("colorTexture", post_process_pipeline->RenderResource()); + ray_gi_screen_solver->SetShaderResourceView("lightTexture", current_light_map->SRV()); + ray_gi_screen_solver->SetShaderResourceView("bloomTexture", bloom_map.SRV()); + + groupsX = (int32_t)(ceil((float)rt_texture_gi_curr->Width() / (RESTIR_KERNEL))); + groupsY = (int32_t)(ceil((float)rt_texture_gi_curr->Height() / (RESTIR_KERNEL))); + ray_gi_screen_solver->CopyAllBufferData(); + ray_gi_screen_solver->SetShader(); + dxcore->context->Dispatch(groupsX, groupsY, 1); + + ray_gi_screen_solver->SetShaderResourceView("ray0", nullptr); + ray_gi_screen_solver->SetShaderResourceView("ray1", nullptr); + ray_gi_screen_solver->SetUnorderedAccessView("ray_inputs", nullptr); + ray_gi_screen_solver->SetUnorderedAccessView("output", nullptr); + ray_gi_screen_solver->SetUnorderedAccessView("tiles_output", nullptr); + + + ID3D11ShaderResourceView* no_data[MAX_OBJECTS] = {}; + ray_gi_screen_solver->SetShaderResourceViewArray("hiz_textures[0]", no_data, HIZ_NTEXTURES); + ray_gi_screen_solver->SetShaderResourceView("prev_position_map", nullptr); + ray_gi_screen_solver->SetShaderResourceView("restir_pdf_mask", nullptr); + ray_gi_screen_solver->SetShaderResourceView("restir_pdf_0", nullptr); + ray_gi_screen_solver->SetUnorderedAccessView("restir_pdf_1", nullptr); + + ray_gi_screen_solver->SetShaderResourceView("colorTexture", nullptr); + ray_gi_screen_solver->SetShaderResourceView("lightTexture", nullptr); + ray_gi_screen_solver->SetShaderResourceView("bloomTexture", nullptr); + ray_gi_screen_solver->SetShaderResourceView("restir_w_0", nullptr); + + ray_gi_screen_solver->CopyAllBufferData(); +#endif +#if 1 + // Resolve rays with world space Ray Tracing + ray_gi_world_solver->SetInt("enabled", rt_enabled& (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); + ray_gi_world_solver->SetInt("frame_count", frame_count); + ray_gi_world_solver->SetInt("type", 2); + ray_gi_world_solver->SetFloat(TIME, time); + ray_gi_world_solver->SetInt("kernel_size", RESTIR_KERNEL); + ray_gi_world_solver->SetInt("nobjects", nobjects); + ray_gi_world_solver->SetData("objectMaterials", objectMaterials, nobjects * sizeof(MaterialProps)); + ray_gi_world_solver->SetData("objectInfos", objects, nobjects * sizeof(ObjectInfo)); + ray_gi_world_solver->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); + + ray_gi_world_solver->SetUnorderedAccessView("output", rt_texture_gi_trace->UAV()); + ray_gi_world_solver->SetUnorderedAccessView("tiles_output", rt_textures_gi_tiles.UAV()); + ray_gi_world_solver->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); + ray_gi_world_solver->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); + ray_gi_world_solver->SetShaderResourceView("ray_inputs", input_rays.SRV()); + ray_gi_world_solver->SetShaderResourceViewArray("DiffuseTextures[0]", diffuseTextures, nobjects); + ray_gi_world_solver->SetSamplerState(PCF_SAMPLER, dxcore->shadow_sampler); + ray_gi_world_solver->SetSamplerState(BASIC_SAMPLER, dxcore->basic_sampler); + + ray_gi_world_solver->SetShaderResourceView("restir_pdf_mask", restir_pdf_mask.SRV()); + ray_gi_world_solver->SetUnorderedAccessView("restir_pdf_1", restir_pdf_curr->UAV()); + ray_gi_world_solver->SetShaderResourceView("restir_pdf_0", restir_pdf_prev->SRV()); + ray_gi_world_solver->SetShaderResourceView("restir_w_0", restir_w.SRV()); + + PrepareLights(ray_gi_world_solver); + + ray_gi_world_solver->CopyAllBufferData(); + dxcore->context->CSSetShaderResources(2, 1, bvh_buffer->SRV()); dxcore->context->CSSetShaderResources(3, 1, tbvh_buffer.SRV()); dxcore->context->CSSetShaderResources(4, 1, vertex_buffer->VertexSRV()); dxcore->context->CSSetShaderResources(5, 1, vertex_buffer->IndexSRV()); + ray_gi_world_solver->SetShader(); - gi_shader->SetShaderResourceView("restir_pdf_0", restir_pdf_prev->SRV()); - gi_shader->SetShaderResourceView("restir_w_0", restir_w.SRV()); - gi_shader->SetUnorderedAccessView("restir_pdf_1", restir_pdf_curr->UAV()); + groupsX = (int32_t)(ceil((float)rt_texture_gi_trace->Width() / (RESTIR_KERNEL))); + groupsY = (int32_t)(ceil((float)rt_texture_gi_trace->Height() / (RESTIR_KERNEL))); + dxcore->context->Dispatch(groupsX, groupsY, 1); - gi_shader->SetUnorderedAccessView("output", rt_texture_curr[RT_TEXTURE_INDIRECT].UAV()); + ray_gi_world_solver->SetUnorderedAccessView("output", nullptr); + ray_gi_world_solver->SetShaderResourceView("ray0", nullptr); + ray_gi_world_solver->SetShaderResourceView("ray1", nullptr); + ray_gi_world_solver->SetUnorderedAccessView("bloom", nullptr); + ray_gi_world_solver->SetUnorderedAccessView("tiles_output", nullptr); + ray_gi_world_solver->SetShaderResourceView("ray_inputs", nullptr); - int groupsX = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_INDIRECT].Width() / (32.0f))); - int groupsY = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_INDIRECT].Height() / (32.0f))); - dxcore->context->Dispatch((uint32_t)ceil((float)groupsX), (uint32_t)ceil((float)groupsY), 1); + dxcore->context->CSSetShaderResources(2, 1, &nullsrc); + dxcore->context->CSSetShaderResources(3, 1, &nullsrc); + dxcore->context->CSSetShaderResources(4, 1, &nullsrc); + dxcore->context->CSSetShaderResources(5, 1, &nullsrc); - gi_shader->SetShaderResourceView("restir_pdf_0", nullptr); - gi_shader->SetShaderResourceView("restir_w_0", nullptr); - gi_shader->SetUnorderedAccessView("restir_pdf_1", nullptr); + ray_gi_world_solver->SetShaderResourceView("restir_pdf_mask", nullptr); + ray_gi_world_solver->SetUnorderedAccessView("restir_pdf_1", nullptr); + ray_gi_world_solver->SetShaderResourceView("restir_pdf_0", nullptr); + ray_gi_world_solver->SetShaderResourceView("restir_w_0", nullptr); - gi_shader->SetUnorderedAccessView("output", nullptr); - gi_shader->SetShaderResourceView("position_map", nullptr); - gi_shader->SetShaderResourceView("motion_texture", nullptr); - gi_shader->SetShaderResourceView("ray0", nullptr); - gi_shader->SetShaderResourceView("ray1", nullptr); - gi_shader->SetUnorderedAccessView("props", nullptr); - gi_shader->SetShaderResourceView("prev_position_map", nullptr); + ray_gi_world_solver->SetShaderResourceViewArray("DiffuseTextures[0]", no_data, nobjects); - UnprepareLights(gi_shader); - gi_shader->CopyAllBufferData(); + UnprepareLights(ray_gi_world_solver); + ray_gi_world_solver->CopyAllBufferData(); +#endif +#if 1 + groupsX = (int32_t)(ceil((float)rt_texture_gi_curr->Width() / (32.0f))); + groupsY = (int32_t)(ceil((float)rt_texture_gi_curr->Height() / (32.0f))); gi_weights->SetShader(); gi_weights->SetInt("ray_count", RESTIR_PIXEL_RAYS); @@ -1816,41 +2036,81 @@ void RenderSystem::ProcessGI() { gi_weights->CopyAllBufferData(); gi_average->SetInt("debug", rt_debug); - gi_average->SetMatrix4x4(VIEW, cam_entity.camera->view); - gi_average->SetMatrix4x4(PROJECTION, cam_entity.camera->projection); + gi_average->SetMatrix4x4("prev_view_proj", cam_entity.camera->prev_view_projection); gi_average->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); gi_average->SetShaderResourceView("positions", rt_ray_sources0.SRV()); gi_average->SetShaderResourceView("normals", rt_ray_sources1.SRV()); - gi_average->SetShaderResourceView("prev_output", rt_texture_prev[RT_TEXTURE_INDIRECT].SRV()); + gi_average->SetShaderResourceView("prev_output", rt_texture_gi_prev->SRV()); gi_average->SetShaderResourceView("motion_texture", motion_texture.SRV()); gi_average->SetShaderResourceView("prev_position_map", prev_position_map.SRV()); + gi_average->SetShaderResourceView("tiles_output", rt_textures_gi_tiles.SRV()); gi_average->SetInt("kernel_size", RESTIR_HALF_KERNEL); gi_average->SetInt("frame_count", frame_count); +#if 1 + //Pass 1 gi_average->SetInt("type", 1); - gi_average->SetShaderResourceView("input", rt_texture_curr[RT_TEXTURE_INDIRECT].SRV()); - gi_average->SetUnorderedAccessView("output", texture_tmp.UAV()); + gi_average->SetShaderResourceView("input", rt_texture_gi_trace->SRV()); + gi_average->SetUnorderedAccessView("output", rt_texture_gi_tmp[0]->UAV()); gi_average->CopyAllBufferData(); gi_average->SetShader(); dxcore->context->Dispatch(groupsX, groupsY, 1); - gi_average->SetShaderResourceView("input", nullptr); gi_average->SetUnorderedAccessView("output", nullptr); gi_average->CopyAllBufferData(); +#if 1 + //Pass 2 gi_average->SetInt("type", 2); - gi_average->SetShaderResourceView("input", texture_tmp.SRV()); - gi_average->SetUnorderedAccessView("output", rt_texture_curr[RT_TEXTURE_INDIRECT].UAV()); + gi_average->SetShaderResourceView("orig_input", rt_texture_gi_trace->SRV()); + gi_average->SetShaderResourceView("input", rt_texture_gi_tmp[0]->SRV()); + gi_average->SetUnorderedAccessView("output", rt_texture_gi_tmp[1]->UAV()); gi_average->CopyAllBufferData(); gi_average->SetShader(); dxcore->context->Dispatch(groupsX, groupsY, 1); + gi_average->SetShaderResourceView("input", nullptr); + gi_average->SetUnorderedAccessView("output", nullptr); + gi_average->CopyAllBufferData(); + //Pass 3 + gi_average->SetInt("type", 3); + gi_average->SetShaderResourceView("input", rt_texture_gi_tmp[1]->SRV()); + gi_average->SetUnorderedAccessView("output", rt_texture_gi_curr->UAV()); + gi_average->CopyAllBufferData(); + gi_average->SetShader(); + dxcore->context->Dispatch(groupsX, groupsY, 1); +#else + //Pass 2 + gi_average->SetInt("type", 2); + gi_average->SetShaderResourceView("orig_input", rt_texture_gi_trace->SRV()); + gi_average->SetShaderResourceView("input", rt_texture_gi_tmp[0]->SRV()); + gi_average->SetUnorderedAccessView("output", rt_texture_gi_curr->UAV()); + gi_average->CopyAllBufferData(); + gi_average->SetShader(); + dxcore->context->Dispatch(groupsX, groupsY, 1); gi_average->SetShaderResourceView("input", nullptr); gi_average->SetUnorderedAccessView("output", nullptr); + gi_average->CopyAllBufferData(); +#endif +#else + //Pass 3 + gi_average->SetInt("type", 3); + gi_average->SetShaderResourceView("orig_input", rt_texture_gi_trace->SRV()); + gi_average->SetShaderResourceView("input", rt_texture_gi_tmp[1]->SRV()); + gi_average->SetUnorderedAccessView("output", rt_texture_gi_curr->UAV()); + gi_average->CopyAllBufferData(); + gi_average->SetShader(); + dxcore->context->Dispatch(groupsX, groupsY, 1); +#endif + gi_average->SetShaderResourceView("input", nullptr); + gi_average->SetUnorderedAccessView("output", nullptr); + gi_average->SetShaderResourceView("tiles_output", nullptr); + gi_average->SetShaderResourceView("orig_input", nullptr); gi_average->SetShaderResourceView("positions", nullptr); gi_average->SetShaderResourceView("normals", nullptr); gi_average->SetShaderResourceView("prev_output", nullptr); gi_average->SetShaderResourceView("motion_texture", nullptr); gi_average->SetShaderResourceView("prev_position_map", nullptr); gi_average->CopyAllBufferData(); +#endif } } @@ -1858,150 +2118,184 @@ void RenderSystem::ProcessRT() { if (rt_enabled & (RT_REFLEX_ENABLE || RT_REFRACT_ENABLE)) { - rt_texture_curr = rt_textures[current]; - rt_texture_prev = rt_textures[prev]; + rt_texture_di_curr = rt_textures_di[current]; + rt_texture_di_prev = rt_textures_di[prev]; if (rt_quality != eRtQuality::OFF && rt_enabled && bvh_buffer != nullptr && nobjects > 0) { - std::lock_guard lock(rt_mutex); - CameraEntity& cam_entity = cameras.GetData()[0]; + //Reset tiles (that avoid denoising tiles with no ray color) + rt_textures_gi_tiles.Clear(zero); + input_rays.Clear((float*)max_uint); - rt_dispersion.Clear(minus_one); - tbvh_buffer.Refresh(tbvh.Root(), 0, tbvh.Size()); + ID3D11ShaderResourceView* nullsrc = nullptr; + ID3D11ShaderResourceView* no_data[MAX_OBJECTS] = {}; ID3D11RenderTargetView* nullRenderTargetViews[1] = { nullptr }; dxcore->context->OMSetRenderTargets(1, nullRenderTargetViews, nullptr); - rt_di_shader->SetInt("kernel_size", RESTIR_KERNEL); - rt_di_shader->SetInt("ray_count", RESTIR_PIXEL_RAYS); - - rt_di_shader->SetInt("nobjects", nobjects); - rt_di_shader->SetInt("enabled", rt_enabled & (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); - rt_di_shader->SetMatrix4x4("view_proj", cam_entity.camera->view_projection); - rt_di_shader->SetMatrix4x4("prev_view_proj", cam_entity.camera->prev_view_projection); - rt_di_shader->SetInt("frame_count", frame_count); - rt_di_shader->SetData("objectMaterials", objectMaterials, nobjects * sizeof(MaterialProps)); - rt_di_shader->SetData("objectInfos", objects, nobjects * sizeof(ObjectInfo)); - - rt_di_shader->SetUnorderedAccessView("output0", rt_texture_curr[RT_TEXTURE_REFLEX].UAV()); - rt_di_shader->SetUnorderedAccessView("output1", rt_texture_curr[RT_TEXTURE_REFRACT].UAV()); - rt_di_shader->SetUnorderedAccessView("dispersion", rt_dispersion.UAV()); - - rt_di_shader->SetShaderResourceView("position_map", position_map.SRV()); - rt_di_shader->SetShaderResourceView("depth_map", depth_map.SRV()); - rt_di_shader->SetShaderResourceView("motion_texture", motion_texture.SRV()); - rt_di_shader->SetUnorderedAccessView("bloom", rt_texture_curr[RT_TEXTURE_EMISSION].UAV()); - rt_di_shader->SetUnorderedAccessView("props", rt_texture_props.UAV()); + //Set ray requests rt_di_shader->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); rt_di_shader->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); rt_di_shader->SetShaderResourceView("rgbaNoise", rgba_noise_texture.SRV()); + rt_di_shader->SetUnorderedAccessView("ray_inputs", input_rays.UAV()); - float3 dir; - XMStoreFloat3(&dir, cam_entity.camera->xm_direction); + CameraEntity& cam_entity = cameras.GetData()[0]; rt_di_shader->SetFloat(TIME, time); + rt_di_shader->SetInt("enabled", rt_enabled & (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); + rt_di_shader->SetInt("frame_count", frame_count); + rt_di_shader->SetInt("divider", RT_TEXTURE_RESOLUTION_DIVIDER); rt_di_shader->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); - rt_di_shader->SetFloat3("cameraDirection", dir); + rt_di_shader->SetSamplerState(PCF_SAMPLER, dxcore->shadow_sampler); rt_di_shader->SetSamplerState(BASIC_SAMPLER, dxcore->basic_sampler); - rt_di_shader->SetShaderResourceViewArray("DiffuseTextures[0]", diffuseTextures, nobjects); - - PrepareLights(rt_di_shader); rt_di_shader->CopyAllBufferData(); - dxcore->context->CSSetShaderResources(2, 1, bvh_buffer->SRV()); - dxcore->context->CSSetShaderResources(3, 1, tbvh_buffer.SRV()); - dxcore->context->CSSetShaderResources(4, 1, vertex_buffer->VertexSRV()); - dxcore->context->CSSetShaderResources(5, 1, vertex_buffer->IndexSRV()); rt_di_shader->SetShader(); - int32_t groupsX = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_REFLEX].Width() / (32.0f))); - int32_t groupsY = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_REFLEX].Height() / (32.0f))); - dxcore->context->Dispatch(groupsX, groupsY, 2); - - rt_di_shader->SetUnorderedAccessView("output0", nullptr); - rt_di_shader->SetUnorderedAccessView("output1", nullptr); - rt_di_shader->SetShaderResourceView("position_map", nullptr); - rt_di_shader->SetShaderResourceView("motion_texture", nullptr); + int32_t groupsX = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Width() / (32.0f))); + int32_t groupsY = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Height() / (32.0f))); + dxcore->context->Dispatch(groupsX, groupsY, 1); + rt_di_shader->SetShaderResourceView("ray0", nullptr); rt_di_shader->SetShaderResourceView("ray1", nullptr); - rt_di_shader->SetUnorderedAccessView("bloom", nullptr); - rt_di_shader->SetUnorderedAccessView("props", nullptr); rt_di_shader->SetShaderResourceView("rgbaNoise", nullptr); - rt_di_shader->SetUnorderedAccessView("dispersion", nullptr); - - UnprepareLights(rt_di_shader); + rt_di_shader->SetUnorderedAccessView("ray_inputs", nullptr); rt_di_shader->CopyAllBufferData(); -#if 0 - //Smooth the dispersion textures - groupsX = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_REFLEX].Width() / (32.0f))); - groupsY = (int32_t)(ceil((float)rt_texture_curr[RT_TEXTURE_REFLEX].Height() / (32.0f))); - rt_disp->SetShaderResourceView("input", rt_dispersion.SRV()); - rt_disp->SetUnorderedAccessView("output", texture_tmp.UAV()); - rt_disp->SetInt("type", 1); - rt_disp->CopyAllBufferData(); - rt_disp->SetShader(); - dxcore->context->Dispatch(groupsX, groupsY, 1); - rt_disp->SetShaderResourceView("input", nullptr); - rt_disp->SetUnorderedAccessView("output", nullptr); - rt_disp->CopyAllBufferData(); - rt_disp->SetShaderResourceView("input", texture_tmp.SRV()); - rt_disp->SetUnorderedAccessView("output", rt_dispersion.UAV()); - rt_disp->SetInt("type", 2); - rt_disp->CopyAllBufferData(); - dxcore->context->Dispatch(groupsX, groupsY, 1); - rt_disp->SetShaderResourceView("input", nullptr); - rt_disp->SetUnorderedAccessView("output", nullptr); - rt_disp->CopyAllBufferData(); - - texture_tmp.Clear(zero); - rt_disp->SetShaderResourceView("input", rt_dispersion.SRV()); - rt_disp->SetUnorderedAccessView("output", texture_tmp.UAV()); - rt_disp->SetInt("type", 3); - rt_disp->CopyAllBufferData(); - rt_disp->SetShader(); +#if 1 + //Resolve rays with screen space Ray Tracing + ray_reflex_screen_solver->SetInt("enabled", rt_enabled& (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); + ray_reflex_screen_solver->SetInt("frame_count", frame_count); + ray_reflex_screen_solver->SetFloat(TIME, time); + ray_reflex_screen_solver->SetInt("kernel_size", RESTIR_KERNEL); + ray_reflex_screen_solver->SetInt("type", 1); + ray_reflex_screen_solver->SetFloat("hiz_ratio", HIZ_RATIO); + ray_reflex_screen_solver->SetInt("divider", RT_TEXTURE_RESOLUTION_DIVIDER); + ray_reflex_screen_solver->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); + ray_reflex_screen_solver->SetMatrix4x4("view", cam_entity.camera->view); + ray_reflex_screen_solver->SetMatrix4x4("projection", cam_entity.camera->projection); + ray_reflex_screen_solver->SetMatrix4x4("inv_projection", cam_entity.camera->inverse_projection); + + ray_reflex_screen_solver->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); + ray_reflex_screen_solver->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); + ray_reflex_screen_solver->SetUnorderedAccessView("ray_inputs", input_rays.UAV()); + ray_reflex_screen_solver->SetUnorderedAccessView("output", rt_texture_di_curr[RT_TEXTURE_REFLEX].UAV()); + ray_reflex_screen_solver->SetUnorderedAccessView("tiles_output", rt_textures_gi_tiles.UAV()); + + ray_reflex_screen_solver->SetShaderResourceView("colorTexture", post_process_pipeline->RenderResource()); + ray_reflex_screen_solver->SetShaderResourceView("lightTexture", current_light_map->SRV()); + ray_reflex_screen_solver->SetShaderResourceView("bloomTexture", bloom_map.SRV()); + + ray_reflex_screen_solver->SetShaderResourceViewArray("hiz_textures[0]", high_z_maps, HIZ_NTEXTURES); + + ray_reflex_screen_solver->CopyAllBufferData(); + ray_reflex_screen_solver->SetShader(); + + groupsX = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Width() / (16.0f))); + groupsY = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Height() / (16.0f))); dxcore->context->Dispatch(groupsX, groupsY, 1); - rt_disp->SetShaderResourceView("input", nullptr); - rt_disp->SetUnorderedAccessView("output", nullptr); - rt_disp->CopyAllBufferData(); - - rt_disp->SetShaderResourceView("input", texture_tmp.SRV()); - rt_disp->SetUnorderedAccessView("output", rt_dispersion.UAV()); - rt_disp->SetInt("type", 4); - rt_disp->CopyAllBufferData(); + + ray_reflex_screen_solver->SetShaderResourceView("ray0", nullptr); + ray_reflex_screen_solver->SetShaderResourceView("ray1", nullptr); + ray_reflex_screen_solver->SetUnorderedAccessView("ray_inputs", nullptr); + ray_reflex_screen_solver->SetUnorderedAccessView("output", nullptr); + ray_reflex_screen_solver->SetUnorderedAccessView("tiles_output", nullptr); + + ray_reflex_screen_solver->SetShaderResourceView("colorTexture", nullptr); + ray_reflex_screen_solver->SetShaderResourceView("lightTexture", nullptr); + ray_reflex_screen_solver->SetShaderResourceView("bloomTexture", nullptr); + + ray_reflex_screen_solver->SetShaderResourceViewArray("hiz_textures[0]", no_data, HIZ_NTEXTURES); + + ray_reflex_screen_solver->CopyAllBufferData(); +#endif +#if 1 + // Resolve rays with world space Ray Tracing + { + //We need at this point the BVH structures to be available + std::lock_guard lock(rt_mutex); + tbvh_buffer.Refresh(tbvh.Root(), 0, tbvh.Size()); + } + rt_texture_di_curr[RT_TEXTURE_REFRACT].Clear(zero); + ray_reflex_world_solver->SetInt("enabled", rt_enabled & (rt_quality != eRtQuality::OFF ? 0xFF : 0x00)); + ray_reflex_world_solver->SetInt("frame_count", frame_count); + ray_reflex_world_solver->SetFloat(TIME, time); + ray_reflex_world_solver->SetInt("type", 1); + ray_reflex_world_solver->SetInt("kernel_size", RESTIR_KERNEL); + ray_reflex_world_solver->SetInt("nobjects", nobjects); + ray_reflex_world_solver->SetData("objectMaterials", objectMaterials, nobjects * sizeof(MaterialProps)); + ray_reflex_world_solver->SetData("objectInfos", objects, nobjects * sizeof(ObjectInfo)); + ray_reflex_world_solver->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); + + ray_reflex_world_solver->SetUnorderedAccessView("output0", rt_texture_di_curr[RT_TEXTURE_REFLEX].UAV()); + ray_reflex_world_solver->SetUnorderedAccessView("output1", rt_texture_di_curr[RT_TEXTURE_REFRACT].UAV()); + ray_reflex_world_solver->SetUnorderedAccessView("bloom", rt_texture_di_curr[RT_TEXTURE_EMISSION].UAV()); + ray_reflex_world_solver->SetUnorderedAccessView("tiles_output", rt_textures_gi_tiles.UAV()); + ray_reflex_world_solver->SetShaderResourceView("ray0", rt_ray_sources0.SRV()); + ray_reflex_world_solver->SetShaderResourceView("ray1", rt_ray_sources1.SRV()); + ray_reflex_world_solver->SetShaderResourceView("ray_inputs", input_rays.SRV()); + ray_reflex_world_solver->SetShaderResourceViewArray("DiffuseTextures[0]", diffuseTextures, nobjects); + ray_reflex_world_solver->SetSamplerState(PCF_SAMPLER, dxcore->shadow_sampler); + ray_reflex_world_solver->SetSamplerState(BASIC_SAMPLER, dxcore->basic_sampler); + + PrepareLights(ray_reflex_world_solver); + + ray_reflex_world_solver->CopyAllBufferData(); + + dxcore->context->CSSetShaderResources(2, 1, bvh_buffer->SRV()); + dxcore->context->CSSetShaderResources(3, 1, tbvh_buffer.SRV()); + dxcore->context->CSSetShaderResources(4, 1, vertex_buffer->VertexSRV()); + dxcore->context->CSSetShaderResources(5, 1, vertex_buffer->IndexSRV()); + ray_reflex_world_solver->SetShader(); + + groupsX = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Width() / (RESTIR_KERNEL))); + groupsY = (int32_t)(ceil((float)rt_texture_di_curr[RT_TEXTURE_REFLEX].Height() / (RESTIR_KERNEL))); dxcore->context->Dispatch(groupsX, groupsY, 1); - rt_disp->SetShaderResourceView("input", nullptr); - rt_disp->SetUnorderedAccessView("output", nullptr); - rt_disp->CopyAllBufferData(); + + ray_reflex_world_solver->SetUnorderedAccessView("output0", nullptr); + ray_reflex_world_solver->SetUnorderedAccessView("output1", nullptr); + ray_reflex_world_solver->SetShaderResourceView("ray0", nullptr); + ray_reflex_world_solver->SetShaderResourceView("ray1", nullptr); + ray_reflex_world_solver->SetUnorderedAccessView("bloom", nullptr); + ray_reflex_world_solver->SetUnorderedAccessView("tiles_output", nullptr); + ray_reflex_world_solver->SetShaderResourceView("ray_inputs", nullptr); + dxcore->context->CSSetShaderResources(2, 1, &nullsrc); + dxcore->context->CSSetShaderResources(3, 1, &nullsrc); + dxcore->context->CSSetShaderResources(4, 1, &nullsrc); + dxcore->context->CSSetShaderResources(5, 1, &nullsrc); + + ray_reflex_world_solver->SetShaderResourceViewArray("DiffuseTextures[0]", no_data, nobjects); + + UnprepareLights(ray_reflex_world_solver); + ray_reflex_world_solver->CopyAllBufferData(); #endif +#if 1 //Denoiser + rt_di_denoiser->SetInt("kernel_size", RESTIR_KERNEL); rt_di_denoiser->SetInt("debug", rt_debug); rt_di_denoiser->SetShaderResourceView("positions", rt_ray_sources0.SRV()); rt_di_denoiser->SetShaderResourceView("normals", rt_ray_sources1.SRV()); rt_di_denoiser->SetShaderResourceView("motion_texture", motion_texture.SRV()); rt_di_denoiser->SetShaderResourceView("prev_position_map", prev_position_map.SRV()); - rt_di_denoiser->SetMatrix4x4(VIEW, cam_entity.camera->view); - rt_di_denoiser->SetMatrix4x4(PROJECTION, cam_entity.camera->projection); + rt_di_denoiser->SetMatrix4x4("view_projection", cam_entity.camera->view_projection); rt_di_denoiser->SetFloat3(CAMERA_POSITION, cam_entity.camera->world_position); - rt_di_denoiser->SetShaderResourceView("dispersion", rt_dispersion.SRV()); + rt_di_denoiser->SetShaderResourceView("tiles_output", rt_textures_gi_tiles.SRV()); static constexpr int textures[] = { RT_TEXTURE_REFLEX, RT_TEXTURE_REFRACT }; static constexpr int ntextures = sizeof(textures) / sizeof(int); for (int i = 0; i < ntextures; ++i) { int ntexture = textures[i]; - groupsX = (int32_t)(ceil((float)rt_texture_curr[ntexture].Width() / (32.0f))); - groupsY = (int32_t)(ceil((float)rt_texture_curr[ntexture].Height() / (32.0f))); + groupsX = (int32_t)(ceil((float)rt_texture_di_curr[ntexture].Width() / (32.0f))); + groupsY = (int32_t)(ceil((float)rt_texture_di_curr[ntexture].Height() / (32.0f))); - rt_di_denoiser->SetShaderResourceView("input", rt_texture_curr[ntexture].SRV()); + rt_di_denoiser->SetShaderResourceView("input", rt_texture_di_curr[ntexture].SRV()); rt_di_denoiser->SetUnorderedAccessView("output", texture_tmp.UAV()); - rt_di_denoiser->SetShaderResourceView("prev_output", rt_texture_prev[ntexture].SRV()); + rt_di_denoiser->SetShaderResourceView("prev_output", rt_texture_di_prev[ntexture].SRV()); rt_di_denoiser->SetInt("type", 1); rt_di_denoiser->SetInt("light_type", i); rt_di_denoiser->CopyAllBufferData(); rt_di_denoiser->SetShader(); - groupsX = (int32_t)(ceil((float)rt_texture_curr[ntexture].Width() / (32.0f))); - groupsY = (int32_t)(ceil((float)rt_texture_curr[ntexture].Height() / (32.0f))); dxcore->context->Dispatch(groupsX, groupsY, 1); rt_di_denoiser->SetShaderResourceView("input", nullptr); rt_di_denoiser->SetUnorderedAccessView("output", nullptr); @@ -2009,7 +2303,7 @@ void RenderSystem::ProcessRT() { //Denoiser rt_di_denoiser->SetShaderResourceView("input", texture_tmp.SRV()); - rt_di_denoiser->SetUnorderedAccessView("output", rt_texture_curr[ntexture].UAV()); + rt_di_denoiser->SetUnorderedAccessView("output", rt_texture_di_curr[ntexture].UAV()); rt_di_denoiser->SetInt("type", 2); rt_di_denoiser->CopyAllBufferData(); dxcore->context->Dispatch(groupsX, groupsY, 1); @@ -2025,17 +2319,19 @@ void RenderSystem::ProcessRT() { rt_di_denoiser->SetShaderResourceView("motion_texture", nullptr); rt_di_denoiser->SetShaderResourceView("prev_position_map", nullptr); rt_di_denoiser->SetShaderResourceView("dispersion", nullptr); - rt_di_denoiser->CopyAllBufferData(); + rt_di_denoiser->SetShaderResourceView("tiles_output", nullptr); + rt_di_denoiser->CopyAllBufferData(); +#endif #if 0 //Apply antialias int ntexture = RT_TEXTURE_INDIRECT; - groupsX = (int32_t)(ceil((float)rt_texture_curr[ntexture].Width() / (32.0f))); - groupsY = (int32_t)(ceil((float)rt_texture_curr[ntexture].Height() / (32.0f))); + groupsX = (int32_t)(ceil((float)rt_texture_di_curr[ntexture].Width() / (32.0f))); + groupsY = (int32_t)(ceil((float)rt_texture_di_curr[ntexture].Height() / (32.0f))); aa_shader->SetShaderResourceView("depthTexture", depth_map.SRV()); aa_shader->SetShaderResourceView("normalTexture", rt_ray_sources1.SRV()); - aa_shader->SetShaderResourceView("input", rt_texture_curr[ntexture].SRV()); + aa_shader->SetShaderResourceView("input", rt_texture_di_curr[ntexture].SRV()); aa_shader->SetInt("enabled", true); aa_shader->SetInt("size", 4); aa_shader->SetUnorderedAccessView("output", texture_tmp.UAV()); @@ -2046,7 +2342,7 @@ void RenderSystem::ProcessRT() { aa_shader->SetShaderResourceView("input", nullptr); aa_shader->CopyAllBufferData(); aa_shader->SetShaderResourceView("input", texture_tmp.SRV()); - aa_shader->SetUnorderedAccessView("output", rt_texture_curr[ntexture].UAV()); + aa_shader->SetUnorderedAccessView("output", rt_texture_di_curr[ntexture].UAV()); aa_shader->SetInt("size", 4); aa_shader->CopyAllBufferData(); aa_shader->SetShader(); @@ -2605,6 +2901,7 @@ void RenderSystem::Draw() { DrawScene(w, h, camera_position, view, projection, first_pass_texture.SRV(), second_pass_target, render_pass2_tree); } ProcessMotion(); + ProcessHighZ(); ProcessRT(); ProcessGI(); PostProcessLight(); @@ -2696,10 +2993,16 @@ void RenderSystem::SetRayTracingQuality(eRtQuality quality) { void RenderSystem::ResetRTBBuffers() { for (int i = 0; i < RT_NTEXTURES; ++i) { for (int x = 0; x < 2; ++x) { - rt_textures[x][i].Clear(zero); + rt_textures_di[x][i].Clear(zero); } } + for (int x = 0; x < RT_GI_NTEXTURES; ++x) { + rt_textures_gi[x].Clear(zero); + } + + rt_textures_gi_tiles.Clear(zero); + static const float nrays[4] = { RESTIR_PIXEL_RAYS, RESTIR_PIXEL_RAYS, RESTIR_PIXEL_RAYS, RESTIR_PIXEL_RAYS }; for (int i = 0; i < 2; ++i) @@ -2707,6 +3010,7 @@ void RenderSystem::ResetRTBBuffers() { light_map[i].Clear(zero); restir_pdf[i].Clear(zero); restir_w.Clear(nrays); + restir_pdf_mask.Clear(zero); } } diff --git a/Engine/Engine/Systems/RenderSystem.h b/Engine/Engine/Systems/RenderSystem.h index f880d34..e604d24 100644 --- a/Engine/Engine/Systems/RenderSystem.h +++ b/Engine/Engine/Systems/RenderSystem.h @@ -273,10 +273,13 @@ namespace HotBite { //Motion blur Core::SimpleComputeShader* motion_blur = nullptr; - + + + //Ray tracing eRtQuality rt_quality = eRtQuality::MID; uint32_t RT_TEXTURE_RESOLUTION_DIVIDER = 1; + uint32_t GI_TEXTURE_RESOLUTION_DIVIDER = 4; static constexpr uint32_t RT_REFLEX_ENABLE = 1; static constexpr uint32_t RT_REFRACT_ENABLE = 2; static constexpr uint32_t RT_INDIRECT_ENABLE = 4; @@ -285,39 +288,50 @@ namespace HotBite { Core::TBVH tbvh{ MAX_OBJECTS }; Core::SimpleComputeShader* rt_di_shader = nullptr; Core::SimpleComputeShader* rt_di_denoiser = nullptr; - Core::SimpleComputeShader* rt_disp = nullptr; - + Core::SimpleComputeShader* gi_shader = nullptr; Core::SimpleComputeShader* gi_average = nullptr; Core::SimpleComputeShader* gi_weights = nullptr; - //RT texture 1: Reflexed rays - //RT texture 2: Refracted rays - //RT texture 3: Indirect rays + Core::SimpleComputeShader* ray_gi_world_solver = nullptr; + Core::SimpleComputeShader* ray_gi_screen_solver = nullptr; + Core::SimpleComputeShader* ray_reflex_world_solver = nullptr; + Core::SimpleComputeShader* ray_reflex_screen_solver = nullptr; + static constexpr int RT_TEXTURE_REFLEX = 0; static constexpr int RT_TEXTURE_REFRACT = 1; - static constexpr int RT_TEXTURE_INDIRECT = 2; - static constexpr int RT_TEXTURE_EMISSION = 3; + static constexpr int RT_TEXTURE_EMISSION = 2; + + static constexpr int RT_NTEXTURES = 3; + Core::RenderTexture2D rt_textures_di[2][RT_NTEXTURES]; + + static constexpr int RT_GI_NTEXTURES = 5; + Core::RenderTexture2D rt_textures_gi[RT_GI_NTEXTURES]; + Core::RenderTexture2D rt_textures_gi_tiles; + Core::RenderTexture2D rt_inputs; - static constexpr int RT_NTEXTURES = 4; - Core::RenderTexture2D rt_textures[2][RT_NTEXTURES]; Core::RenderTexture2D restir_pdf[2]; + Core::RenderTexture2D restir_pdf_mask; + Core::RenderTexture2D restir_w; Core::RenderTexture2D* restir_pdf_curr = nullptr; Core::RenderTexture2D* restir_pdf_prev = nullptr; - static constexpr uint32_t RESTIR_HALF_KERNEL = 5; + static constexpr uint32_t RESTIR_HALF_KERNEL = 4; static constexpr uint32_t RESTIR_KERNEL = 2 * RESTIR_HALF_KERNEL + 1; static constexpr uint32_t RESTIR_PIXEL_RAYS = 16; static constexpr uint32_t RESTIR_TOTAL_RAYS = RESTIR_PIXEL_RAYS * RESTIR_KERNEL * RESTIR_KERNEL; + Core::RenderTexture2D* rt_texture_di_prev; + Core::RenderTexture2D* rt_texture_di_curr; + Core::RenderTexture2D* rt_texture_gi_prev; + Core::RenderTexture2D* rt_texture_gi_curr; + Core::RenderTexture2D* rt_texture_gi_tmp[2]; + Core::RenderTexture2D* rt_texture_gi_trace = nullptr; - Core::RenderTexture2D* rt_texture_prev; - Core::RenderTexture2D* rt_texture_curr; Core::RenderTexture2D rt_texture_props; Core::RenderTexture2D rt_ray_sources0; Core::RenderTexture2D rt_ray_sources1; - Core::RenderTexture2D rt_dispersion; Core::ExtBVHBuffer tbvh_buffer; Core::BVHBuffer* bvh_buffer = nullptr; ObjectInfo objects[MAX_OBJECTS]{}; @@ -330,6 +344,24 @@ namespace HotBite { bool rt_prepare = false; std::thread rt_thread; + struct RayData { + float2 dir0{ FLT_MAX, FLT_MAX }; + float2 dir1{ FLT_MAX, FLT_MAX }; + float2 dir2{ FLT_MAX, FLT_MAX }; + float2 dir3{ FLT_MAX, FLT_MAX }; + }; + + Core::RenderTexture2D input_rays; + + //SSR + Core::SimpleComputeShader* high_z_shader = nullptr; + static constexpr uint32_t HIZ_RATIO = 5; + static constexpr uint32_t HIZ_DOWNSAMPLED_NTEXTURES = 3; + static constexpr uint32_t HIZ_NTEXTURES = HIZ_DOWNSAMPLED_NTEXTURES + 1; + Core::RenderTexture2D high_z_tmp_map; + Core::RenderTexture2D high_z_downsampled_map[HIZ_DOWNSAMPLED_NTEXTURES]; + ID3D11ShaderResourceView* high_z_maps[HIZ_NTEXTURES]{}; + //Copy texture shader Core::SimpleComputeShader* copy_texture = nullptr; @@ -396,6 +428,7 @@ namespace HotBite { void ResetRTBBuffers(); void CopyTexture(const Core::RenderTexture2D& input, Core::RenderTexture2D& output); void ProcessMotion(); + void ProcessHighZ(); void PrepareRT(); void ProcessRT(); void ProcessGI(); diff --git a/Tests/DemoGame/DemoGame.cpp b/Tests/DemoGame/DemoGame.cpp index dd2bfeb..ab50b22 100644 --- a/Tests/DemoGame/DemoGame.cpp +++ b/Tests/DemoGame/DemoGame.cpp @@ -87,7 +87,7 @@ class GameDemoApplication : public DXCore, public ECS::EventListener AudioSystem::PlayId tone = AudioSystem::INVALID_PLAY_ID; public: - GameDemoApplication(HINSTANCE hInstance) :DXCore(hInstance, "HotBiteDemoGame", 1280, 720, true, false) { + GameDemoApplication(HINSTANCE hInstance) :DXCore(hInstance, "HotBiteDemoGame", 1920, 1080, true, false) { root = "..\\..\\..\\Tests\\DemoGame\\"; //Initialize core DirectX InitWindow(); @@ -279,6 +279,7 @@ class GameDemoApplication : public DXCore, public ECS::EventListener }; set_terrain("Terrain*"); set_terrain("Bricks*"); + set_terrain("floor*"); progress += 5.0f; render->Update(); @@ -596,6 +597,7 @@ class GameDemoApplication : public DXCore, public ECS::EventListener std::unordered_map last_ball_sound_ts; //This method spawns a new fireball in the scene void SpawnFireBall(int id) { + return; ECS::Coordinator* c = world.GetCoordinator(); //NOTE: Always lock first renderer mutex before physics mutex to avoid interlock shared_ptr rs = c->GetSystem(); diff --git a/Tests/DemoGame/GameCameraSystem.h b/Tests/DemoGame/GameCameraSystem.h index 2123350..0995516 100644 --- a/Tests/DemoGame/GameCameraSystem.h +++ b/Tests/DemoGame/GameCameraSystem.h @@ -179,6 +179,7 @@ class GameCameraSystem : public ECS::System, public EventListener { //Event CameraSystem::EVENT_ID_CAMERA_MOVED received every time the camera is moved, //we check if the camera is clipping with the terrain and if so we correct the position void CheckCameraPosition(ECS::Event& ev) { + return; if (!is_checking_camera) { this->is_checking_camera = true; //Smooth correct position to avoid camera clipping with terrain diff --git a/Tests/DemoGame/TerrainGS.hlsl b/Tests/DemoGame/TerrainGS.hlsl index d13c7fb..39b882a 100644 --- a/Tests/DemoGame/TerrainGS.hlsl +++ b/Tests/DemoGame/TerrainGS.hlsl @@ -98,6 +98,15 @@ void CreateGrass(float3 pos, matrix worldViewProj, inout TriangleStream< GSOutpu } +float4 frustumPlanes[6] = { + float4(1, 0, 0, 1), + float4(-1, 0, 0, 1), + float4(0, 1, 0, 1), + float4(0, -1, 0, 1), + float4(0, 0, 1, 1), + float4(0, 0, -1, 1) +}; + [maxvertexcount(39)] void main( triangle TerrainDomainOutput input[3], @@ -105,24 +114,58 @@ void main( ) { matrix worldViewProj = mul(view, projection); -#if 0 +#if 1 bool process = false; - uint i = 0; + float4 p[3]; + float2 dimensions = { screenW , screenH }; + + uint i = 0; for (i = 0; i < 3; i++) { p[i] = mul(input[i].worldPos, worldViewProj); } + + bool behind = true; for (i = 0; i < 3; i++) { - float2 pos; - pos = p[i].xy; - pos.x /= p[i].w; - pos.y /= -p[i].w; - pos.x = (pos.x + 1.0f) * 0.5f; - pos.y = (pos.y + 1.0f) * 0.5f; - if (pos.x > -0.2f && pos.x < 1.2f && pos.y > -0.2f && pos.y < 1.2f) { - process = true; + if (p[i].z >= 0.0f) { + behind = false; break; - } + } + } + + if (!behind) { + for (i = 0; i < 3; i++) { + float2 pos; + pos = p[i].xy; + pos.xy /= p[i].w; + pos.y *= -1.0f; + + pos.xy = (pos.xy + 1.0f) * 0.5f; + if (pos.x >= 0.0f && pos.x <= 1.0f && pos.y >= 0.0f && pos.y <= 1.0f) { + process = true; + break; + } + } + } + + if (!process) { + float3 pp[3]; + for (i = 0; i < 3; ++i) { + pp[i] = p[i].xyz / p[i].w; + } + + float3 normal = cross(pp[1].xyz - pp[0].xyz, pp[2].xyz - pp[0].xyz); + float d = dot(normal, pp[0].xyz); + float3 frustumCenter = float3(0.0f, 0.0f, 0.0f); + + for (int i = 0; i < 6; i++) { + frustumCenter += float3(frustumPlanes[i].x, frustumPlanes[i].y, frustumPlanes[i].z) * frustumPlanes[i].w; + } + frustumCenter /= 6.0f; + + if (abs(dot(normal, frustumCenter) + d) < length(normal)) { + process = true; + } } #else bool process = true; @@ -132,6 +175,7 @@ void main( p[i] = mul(input[i].worldPos, worldViewProj); } #endif + if (process) { // Edges of the triangle : postion delta diff --git a/Tests/DemoGame/assets/level.fbx b/Tests/DemoGame/assets/level.fbx new file mode 100644 index 0000000..2c49379 Binary files /dev/null and b/Tests/DemoGame/assets/level.fbx differ diff --git a/Tests/DemoGame/assets/materials/Background_Albedo.png b/Tests/DemoGame/assets/materials/Background_Albedo.png new file mode 100644 index 0000000..c87da4f Binary files /dev/null and b/Tests/DemoGame/assets/materials/Background_Albedo.png differ diff --git a/Tests/DemoGame/assets/materials/Background_Normal.png b/Tests/DemoGame/assets/materials/Background_Normal.png new file mode 100644 index 0000000..a9be84c Binary files /dev/null and b/Tests/DemoGame/assets/materials/Background_Normal.png differ diff --git a/Tests/DemoGame/assets/materials/Background_Roughness.png b/Tests/DemoGame/assets/materials/Background_Roughness.png new file mode 100644 index 0000000..55e3232 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Background_Roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Bricks076C_1K_NormalGL.jpg b/Tests/DemoGame/assets/materials/Bricks076C_1K_NormalGL.jpg new file mode 100644 index 0000000..a14d95d Binary files /dev/null and b/Tests/DemoGame/assets/materials/Bricks076C_1K_NormalGL.jpg differ diff --git a/Tests/DemoGame/assets/materials/ChainTexture_Albedo.png b/Tests/DemoGame/assets/materials/ChainTexture_Albedo.png new file mode 100644 index 0000000..59986b1 Binary files /dev/null and b/Tests/DemoGame/assets/materials/ChainTexture_Albedo.png differ diff --git a/Tests/DemoGame/assets/materials/ChainTexture_Metallic.png b/Tests/DemoGame/assets/materials/ChainTexture_Metallic.png new file mode 100644 index 0000000..01edb18 Binary files /dev/null and b/Tests/DemoGame/assets/materials/ChainTexture_Metallic.png differ diff --git a/Tests/DemoGame/assets/materials/ChainTexture_Normal.png b/Tests/DemoGame/assets/materials/ChainTexture_Normal.png new file mode 100644 index 0000000..8c8a6f8 Binary files /dev/null and b/Tests/DemoGame/assets/materials/ChainTexture_Normal.png differ diff --git a/Tests/DemoGame/assets/materials/ChainTexture_Roughness.png b/Tests/DemoGame/assets/materials/ChainTexture_Roughness.png new file mode 100644 index 0000000..2e5349d Binary files /dev/null and b/Tests/DemoGame/assets/materials/ChainTexture_Roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Dielectric_metallic.png b/Tests/DemoGame/assets/materials/Dielectric_metallic.png new file mode 100644 index 0000000..1a14068 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Dielectric_metallic.png differ diff --git a/Tests/DemoGame/assets/materials/Lion_Albedo.png b/Tests/DemoGame/assets/materials/Lion_Albedo.png new file mode 100644 index 0000000..856314b Binary files /dev/null and b/Tests/DemoGame/assets/materials/Lion_Albedo.png differ diff --git a/Tests/DemoGame/assets/materials/Lion_Normal.png b/Tests/DemoGame/assets/materials/Lion_Normal.png new file mode 100644 index 0000000..8f9f587 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Lion_Normal.png differ diff --git a/Tests/DemoGame/assets/materials/Lion_Roughness.png b/Tests/DemoGame/assets/materials/Lion_Roughness.png new file mode 100644 index 0000000..d37c9c9 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Lion_Roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Color.jpg b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Color.jpg new file mode 100644 index 0000000..7724c30 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Color.jpg differ diff --git a/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Displacement.jpg b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Displacement.jpg new file mode 100644 index 0000000..1edac04 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Displacement.jpg differ diff --git a/Tests/DemoGame/assets/materials/Marble002_4K-JPG_NormalDX.jpg b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_NormalDX.jpg new file mode 100644 index 0000000..775f58d Binary files /dev/null and b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_NormalDX.jpg differ diff --git a/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Roughness.jpg b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Roughness.jpg new file mode 100644 index 0000000..3cf88ec Binary files /dev/null and b/Tests/DemoGame/assets/materials/Marble002_4K-JPG_Roughness.jpg differ diff --git a/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Color.png b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Color.png new file mode 100644 index 0000000..4d3f152 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Color.png differ diff --git a/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Displacement.png b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Displacement.png new file mode 100644 index 0000000..6bce37b Binary files /dev/null and b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Displacement.png differ diff --git a/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_NormalDX.png b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_NormalDX.png new file mode 100644 index 0000000..0e1c765 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_NormalDX.png differ diff --git a/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Roughness.png b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Roughness.png new file mode 100644 index 0000000..e0b66bf Binary files /dev/null and b/Tests/DemoGame/assets/materials/Metal062B_2K-PNG_Roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Metallic_metallic.png b/Tests/DemoGame/assets/materials/Metallic_metallic.png new file mode 100644 index 0000000..68a2a3a Binary files /dev/null and b/Tests/DemoGame/assets/materials/Metallic_metallic.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza.fbx b/Tests/DemoGame/assets/materials/Sponza.fbx new file mode 100644 index 0000000..dd13fc7 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza.fbx differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Arch_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Arch_diffuse.png new file mode 100644 index 0000000..ca039b8 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Arch_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Arch_normal.png b/Tests/DemoGame/assets/materials/Sponza_Arch_normal.png new file mode 100644 index 0000000..c341663 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Arch_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Arch_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Arch_roughness.png new file mode 100644 index 0000000..206c311 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Arch_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Albedo.png b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Albedo.png new file mode 100644 index 0000000..cb29c44 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Albedo.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Normal.png b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Normal.png new file mode 100644 index 0000000..027b1d2 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Roughness.png b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Roughness.png new file mode 100644 index 0000000..cb68565 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Bricks_a_Roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Ceiling_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Ceiling_diffuse.png new file mode 100644 index 0000000..bac82fa Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Ceiling_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Ceiling_normal.png b/Tests/DemoGame/assets/materials/Sponza_Ceiling_normal.png new file mode 100644 index 0000000..459b7c4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Ceiling_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Ceiling_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Ceiling_roughness.png new file mode 100644 index 0000000..af12eac Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Ceiling_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_a_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Column_a_diffuse.png new file mode 100644 index 0000000..00d633c Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_a_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_a_normal.png b/Tests/DemoGame/assets/materials/Sponza_Column_a_normal.png new file mode 100644 index 0000000..7ed36a4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_a_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_a_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Column_a_roughness.png new file mode 100644 index 0000000..4cc33d5 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_a_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_b_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Column_b_diffuse.png new file mode 100644 index 0000000..8c2c3eb Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_b_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_b_normal.png b/Tests/DemoGame/assets/materials/Sponza_Column_b_normal.png new file mode 100644 index 0000000..028c728 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_b_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_b_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Column_b_roughness.png new file mode 100644 index 0000000..ee586b2 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_b_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_c_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Column_c_diffuse.png new file mode 100644 index 0000000..beb4383 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_c_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_c_normal.png b/Tests/DemoGame/assets/materials/Sponza_Column_c_normal.png new file mode 100644 index 0000000..7ce2b64 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_c_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Column_c_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Column_c_roughness.png new file mode 100644 index 0000000..ce8affd Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Column_c_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_diffuse.png new file mode 100644 index 0000000..7b7c9ca Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_normal.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_normal.png new file mode 100644 index 0000000..1cce87b Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Blue_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_diffuse.png new file mode 100644 index 0000000..df8feb6 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_normal.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_normal.png new file mode 100644 index 0000000..4f3b719 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Green_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_diffuse.png new file mode 100644 index 0000000..8e840c9 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_normal.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_normal.png new file mode 100644 index 0000000..7d2522f Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_Red_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_metallic.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_metallic.png new file mode 100644 index 0000000..f466bfd Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_metallic.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Curtain_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Curtain_roughness.png new file mode 100644 index 0000000..9454098 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Curtain_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Details_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Details_diffuse.png new file mode 100644 index 0000000..711122d Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Details_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Details_metallic.png b/Tests/DemoGame/assets/materials/Sponza_Details_metallic.png new file mode 100644 index 0000000..b7ee51c Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Details_metallic.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Details_normal.png b/Tests/DemoGame/assets/materials/Sponza_Details_normal.png new file mode 100644 index 0000000..271e1f5 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Details_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Details_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Details_roughness.png new file mode 100644 index 0000000..6cb4a89 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Details_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_diffuse.png new file mode 100644 index 0000000..199f5c0 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_normal.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_normal.png new file mode 100644 index 0000000..dd793e7 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Blue_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_diffuse.png new file mode 100644 index 0000000..9540ae4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_normal.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_normal.png new file mode 100644 index 0000000..2416735 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Green_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_diffuse.png new file mode 100644 index 0000000..76aa446 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_normal.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_normal.png new file mode 100644 index 0000000..492a4aa Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_Red_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_metallic.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_metallic.png new file mode 100644 index 0000000..7677ed4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_metallic.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Fabric_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Fabric_roughness.png new file mode 100644 index 0000000..ec2abcb Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Fabric_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_FlagPole_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_FlagPole_diffuse.png new file mode 100644 index 0000000..dd6fc4b Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_FlagPole_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_FlagPole_normal.png b/Tests/DemoGame/assets/materials/Sponza_FlagPole_normal.png new file mode 100644 index 0000000..21bb5bc Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_FlagPole_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_FlagPole_roughness.png b/Tests/DemoGame/assets/materials/Sponza_FlagPole_roughness.png new file mode 100644 index 0000000..d1bf2e8 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_FlagPole_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Floor_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Floor_diffuse.png new file mode 100644 index 0000000..ee61f34 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Floor_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Floor_normal.png b/Tests/DemoGame/assets/materials/Sponza_Floor_normal.png new file mode 100644 index 0000000..c980963 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Floor_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Floor_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Floor_roughness.png new file mode 100644 index 0000000..f62a596 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Floor_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Roof_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Roof_diffuse.png new file mode 100644 index 0000000..eed06de Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Roof_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Roof_normal.png b/Tests/DemoGame/assets/materials/Sponza_Roof_normal.png new file mode 100644 index 0000000..b294452 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Roof_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Roof_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Roof_roughness.png new file mode 100644 index 0000000..091f65f Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Roof_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Thorn_diffuse.png b/Tests/DemoGame/assets/materials/Sponza_Thorn_diffuse.png new file mode 100644 index 0000000..584d546 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Thorn_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Thorn_normal.png b/Tests/DemoGame/assets/materials/Sponza_Thorn_normal.png new file mode 100644 index 0000000..1d9e723 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Thorn_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Sponza_Thorn_roughness.png b/Tests/DemoGame/assets/materials/Sponza_Thorn_roughness.png new file mode 100644 index 0000000..1bf9129 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Sponza_Thorn_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Color.jpg b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Color.jpg new file mode 100644 index 0000000..61f8e88 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Color.jpg differ diff --git a/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Displacement.jpg b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Displacement.jpg new file mode 100644 index 0000000..6c767d2 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Displacement.jpg differ diff --git a/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_NormalDX.jpg b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_NormalDX.jpg new file mode 100644 index 0000000..7b8aa85 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_NormalDX.jpg differ diff --git a/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Roughness.jpg b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Roughness.jpg new file mode 100644 index 0000000..ae4ba56 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Tiles020_2K-JPG_Roughness.jpg differ diff --git a/Tests/DemoGame/assets/materials/VaseHanging_diffuse.png b/Tests/DemoGame/assets/materials/VaseHanging_diffuse.png new file mode 100644 index 0000000..e91b94d Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseHanging_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/VaseHanging_normal.png b/Tests/DemoGame/assets/materials/VaseHanging_normal.png new file mode 100644 index 0000000..0e6aa05 Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseHanging_normal.png differ diff --git a/Tests/DemoGame/assets/materials/VaseHanging_roughness.png b/Tests/DemoGame/assets/materials/VaseHanging_roughness.png new file mode 100644 index 0000000..6f0a326 Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseHanging_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/VasePlant_diffuse.png b/Tests/DemoGame/assets/materials/VasePlant_diffuse.png new file mode 100644 index 0000000..6f8e00b Binary files /dev/null and b/Tests/DemoGame/assets/materials/VasePlant_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/VasePlant_normal.png b/Tests/DemoGame/assets/materials/VasePlant_normal.png new file mode 100644 index 0000000..38dfedf Binary files /dev/null and b/Tests/DemoGame/assets/materials/VasePlant_normal.png differ diff --git a/Tests/DemoGame/assets/materials/VasePlant_roughness.png b/Tests/DemoGame/assets/materials/VasePlant_roughness.png new file mode 100644 index 0000000..8abffaf Binary files /dev/null and b/Tests/DemoGame/assets/materials/VasePlant_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/VaseRound_diffuse.png b/Tests/DemoGame/assets/materials/VaseRound_diffuse.png new file mode 100644 index 0000000..064698c Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseRound_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/VaseRound_normal.png b/Tests/DemoGame/assets/materials/VaseRound_normal.png new file mode 100644 index 0000000..b40f6c1 Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseRound_normal.png differ diff --git a/Tests/DemoGame/assets/materials/VaseRound_roughness.png b/Tests/DemoGame/assets/materials/VaseRound_roughness.png new file mode 100644 index 0000000..5890a11 Binary files /dev/null and b/Tests/DemoGame/assets/materials/VaseRound_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/Vase_diffuse.png b/Tests/DemoGame/assets/materials/Vase_diffuse.png new file mode 100644 index 0000000..0a3d22f Binary files /dev/null and b/Tests/DemoGame/assets/materials/Vase_diffuse.png differ diff --git a/Tests/DemoGame/assets/materials/Vase_normal.png b/Tests/DemoGame/assets/materials/Vase_normal.png new file mode 100644 index 0000000..1e45da8 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Vase_normal.png differ diff --git a/Tests/DemoGame/assets/materials/Vase_roughness.png b/Tests/DemoGame/assets/materials/Vase_roughness.png new file mode 100644 index 0000000..fd3ce25 Binary files /dev/null and b/Tests/DemoGame/assets/materials/Vase_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/gi_flag.png b/Tests/DemoGame/assets/materials/gi_flag.png new file mode 100644 index 0000000..0f9eebf Binary files /dev/null and b/Tests/DemoGame/assets/materials/gi_flag.png differ diff --git a/Tests/DemoGame/assets/materials/ground_0014_color_1k.jpg b/Tests/DemoGame/assets/materials/ground_0014_color_1k.jpg new file mode 100644 index 0000000..a6daf01 Binary files /dev/null and b/Tests/DemoGame/assets/materials/ground_0014_color_1k.jpg differ diff --git a/Tests/DemoGame/assets/materials/ground_0014_height_1k.png b/Tests/DemoGame/assets/materials/ground_0014_height_1k.png new file mode 100644 index 0000000..84d0ea4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/ground_0014_height_1k.png differ diff --git a/Tests/DemoGame/assets/materials/ground_0014_normal_directx_1k.png b/Tests/DemoGame/assets/materials/ground_0014_normal_directx_1k.png new file mode 100644 index 0000000..37b94aa Binary files /dev/null and b/Tests/DemoGame/assets/materials/ground_0014_normal_directx_1k.png differ diff --git a/Tests/DemoGame/assets/materials/herringbone-flooring_albedo.png b/Tests/DemoGame/assets/materials/herringbone-flooring_albedo.png new file mode 100644 index 0000000..09c9fca Binary files /dev/null and b/Tests/DemoGame/assets/materials/herringbone-flooring_albedo.png differ diff --git a/Tests/DemoGame/assets/materials/herringbone-flooring_ao.png b/Tests/DemoGame/assets/materials/herringbone-flooring_ao.png new file mode 100644 index 0000000..ba1d374 Binary files /dev/null and b/Tests/DemoGame/assets/materials/herringbone-flooring_ao.png differ diff --git a/Tests/DemoGame/assets/materials/herringbone-flooring_height.png b/Tests/DemoGame/assets/materials/herringbone-flooring_height.png new file mode 100644 index 0000000..7266deb Binary files /dev/null and b/Tests/DemoGame/assets/materials/herringbone-flooring_height.png differ diff --git a/Tests/DemoGame/assets/materials/herringbone-flooring_normal-ogl.png b/Tests/DemoGame/assets/materials/herringbone-flooring_normal-ogl.png new file mode 100644 index 0000000..e02295f Binary files /dev/null and b/Tests/DemoGame/assets/materials/herringbone-flooring_normal-ogl.png differ diff --git a/Tests/DemoGame/assets/materials/metal_0029_ao_1k.jpg b/Tests/DemoGame/assets/materials/metal_0029_ao_1k.jpg new file mode 100644 index 0000000..4fcb6ab Binary files /dev/null and b/Tests/DemoGame/assets/materials/metal_0029_ao_1k.jpg differ diff --git a/Tests/DemoGame/assets/materials/metal_0029_color_1k.jpg b/Tests/DemoGame/assets/materials/metal_0029_color_1k.jpg new file mode 100644 index 0000000..52c054a Binary files /dev/null and b/Tests/DemoGame/assets/materials/metal_0029_color_1k.jpg differ diff --git a/Tests/DemoGame/assets/materials/metal_0029_metallic_1k.jpg b/Tests/DemoGame/assets/materials/metal_0029_metallic_1k.jpg new file mode 100644 index 0000000..460c9f9 Binary files /dev/null and b/Tests/DemoGame/assets/materials/metal_0029_metallic_1k.jpg differ diff --git a/Tests/DemoGame/assets/materials/metal_0029_normal_directx_1k.png b/Tests/DemoGame/assets/materials/metal_0029_normal_directx_1k.png new file mode 100644 index 0000000..943068b Binary files /dev/null and b/Tests/DemoGame/assets/materials/metal_0029_normal_directx_1k.png differ diff --git a/Tests/DemoGame/assets/materials/metal_0029_roughness_1k.jpg b/Tests/DemoGame/assets/materials/metal_0029_roughness_1k.jpg new file mode 100644 index 0000000..67faa74 Binary files /dev/null and b/Tests/DemoGame/assets/materials/metal_0029_roughness_1k.jpg differ diff --git a/Tests/DemoGame/assets/materials/pitted-rusted-metal1_albedo.png b/Tests/DemoGame/assets/materials/pitted-rusted-metal1_albedo.png new file mode 100644 index 0000000..5f806ab Binary files /dev/null and b/Tests/DemoGame/assets/materials/pitted-rusted-metal1_albedo.png differ diff --git a/Tests/DemoGame/assets/materials/pitted-rusted-metal1_normal-ogl.png b/Tests/DemoGame/assets/materials/pitted-rusted-metal1_normal-ogl.png new file mode 100644 index 0000000..80c1c27 Binary files /dev/null and b/Tests/DemoGame/assets/materials/pitted-rusted-metal1_normal-ogl.png differ diff --git a/Tests/DemoGame/assets/materials/rock_0006_ao_4k.jpg b/Tests/DemoGame/assets/materials/rock_0006_ao_4k.jpg new file mode 100644 index 0000000..479f6bd Binary files /dev/null and b/Tests/DemoGame/assets/materials/rock_0006_ao_4k.jpg differ diff --git a/Tests/DemoGame/assets/materials/rock_0006_color_ice_4k.jpg b/Tests/DemoGame/assets/materials/rock_0006_color_ice_4k.jpg new file mode 100644 index 0000000..7b6ff02 Binary files /dev/null and b/Tests/DemoGame/assets/materials/rock_0006_color_ice_4k.jpg differ diff --git a/Tests/DemoGame/assets/materials/rock_0006_normal_2k.jpg b/Tests/DemoGame/assets/materials/rock_0006_normal_2k.jpg new file mode 100644 index 0000000..0ee4bcb Binary files /dev/null and b/Tests/DemoGame/assets/materials/rock_0006_normal_2k.jpg differ diff --git a/Tests/DemoGame/assets/materials/rock_0006_roughness_4k.jpg b/Tests/DemoGame/assets/materials/rock_0006_roughness_4k.jpg new file mode 100644 index 0000000..905ee9a Binary files /dev/null and b/Tests/DemoGame/assets/materials/rock_0006_roughness_4k.jpg differ diff --git a/Tests/DemoGame/assets/materials/rusty-metal_albedo.png b/Tests/DemoGame/assets/materials/rusty-metal_albedo.png new file mode 100644 index 0000000..3e21f40 Binary files /dev/null and b/Tests/DemoGame/assets/materials/rusty-metal_albedo.png differ diff --git a/Tests/DemoGame/assets/materials/rusty-metal_ao.png b/Tests/DemoGame/assets/materials/rusty-metal_ao.png new file mode 100644 index 0000000..4fce9ee Binary files /dev/null and b/Tests/DemoGame/assets/materials/rusty-metal_ao.png differ diff --git a/Tests/DemoGame/assets/materials/rusty-metal_normal-ogl.png b/Tests/DemoGame/assets/materials/rusty-metal_normal-ogl.png new file mode 100644 index 0000000..bc831da Binary files /dev/null and b/Tests/DemoGame/assets/materials/rusty-metal_normal-ogl.png differ diff --git a/Tests/DemoGame/assets/materials/speckled-rust_albedo.png b/Tests/DemoGame/assets/materials/speckled-rust_albedo.png new file mode 100644 index 0000000..c45810e Binary files /dev/null and b/Tests/DemoGame/assets/materials/speckled-rust_albedo.png differ diff --git a/Tests/DemoGame/assets/materials/speckled-rust_normal-ogl.png b/Tests/DemoGame/assets/materials/speckled-rust_normal-ogl.png new file mode 100644 index 0000000..e497fb4 Binary files /dev/null and b/Tests/DemoGame/assets/materials/speckled-rust_normal-ogl.png differ diff --git a/Tests/DemoGame/assets/materials/speckled-rust_roughness.png b/Tests/DemoGame/assets/materials/speckled-rust_roughness.png new file mode 100644 index 0000000..8424266 Binary files /dev/null and b/Tests/DemoGame/assets/materials/speckled-rust_roughness.png differ diff --git a/Tests/DemoGame/assets/materials/spotted-rust_albedo.png b/Tests/DemoGame/assets/materials/spotted-rust_albedo.png new file mode 100644 index 0000000..a397071 Binary files /dev/null and b/Tests/DemoGame/assets/materials/spotted-rust_albedo.png differ diff --git a/Tests/DemoGame/assets/materials/spotted-rust_ao.png b/Tests/DemoGame/assets/materials/spotted-rust_ao.png new file mode 100644 index 0000000..76bedc6 Binary files /dev/null and b/Tests/DemoGame/assets/materials/spotted-rust_ao.png differ diff --git a/Tests/DemoGame/assets/materials/spotted-rust_normal-ogl.png b/Tests/DemoGame/assets/materials/spotted-rust_normal-ogl.png new file mode 100644 index 0000000..a9194c5 Binary files /dev/null and b/Tests/DemoGame/assets/materials/spotted-rust_normal-ogl.png differ diff --git a/Tests/DemoGame/demo_game_scene.json b/Tests/DemoGame/demo_game_scene.json index 8ea035c..bf9ca80 100644 --- a/Tests/DemoGame/demo_game_scene.json +++ b/Tests/DemoGame/demo_game_scene.json @@ -2,7 +2,7 @@ "world": { "path": "..\\..\\..\\Tests\\DemoGame\\", "level": { - "file": ".\\Assets\\particle_test.fbx", + "file": ".\\Assets\\level.fbx", "triangulate": false }, "audio": { @@ -176,8 +176,8 @@ "ambient": { "type": "ambient", "name": "ambient", - "color_down": "008008008", - "color_up": "008008008" + "color_down": "000000000", + "color_up": "000000000" } }, "lights": [ diff --git a/Tests/DemoGame/demo_game_scene.mat b/Tests/DemoGame/demo_game_scene.mat index 06b175f..593b723 100644 --- a/Tests/DemoGame/demo_game_scene.mat +++ b/Tests/DemoGame/demo_game_scene.mat @@ -203,8 +203,8 @@ "draw_ps": "LavaPS.cso", "draw_vs": "MainRenderVS.cso", "ds": "", - "emission": 1.0, - "emission_color": "#00000000", + "emission": 2.0, + "emission_color": "#FF573300", "emission_textname": "", "gs": "", "high_textname": "", @@ -440,7 +440,7 @@ "high_textname": "Bricks076C_1K_Displacement.jpg", "hs": "", "name": "Bricks", - "normal_map_enabled": false, + "normal_map_enabled": true, "normal_textname": "Bricks076C_1K_NormalDX.jpg", "opacity": 1.0, "opacity_textname": "", @@ -450,12 +450,12 @@ "parallax_shadows": true, "parallax_steps": 10.0, "ps": "", - "raytrace": false, + "raytrace": true, "rt_reflex": 1.0, "shadow_gs": "ShadowMapCubeGS.cso", "shadow_vs": "ShadowVS.cso", "spec_textname": "Bricks076C_1K_Roughness.jpg", - "specular": 1.0, + "specular": 0.0, "tess_factor": 4.0, "tess_type": 0, "vs": "" @@ -539,6 +539,282 @@ "value": 1.0 } ] + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Bricks_a_Albedo.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_bricks", + "normal_map_enabled": false, + "normal_textname": "Sponza_Bricks_a_Normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Bricks_a_Roughness.png", + "specular": 0.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Floor_diffuse.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_floor", + "normal_map_enabled": false, + "normal_textname": "Sponza_Floor_normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Floor_roughness.png", + "specular": 1.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Fabric_Red_diffuse.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_fabric_red", + "normal_map_enabled": false, + "normal_textname": "Sponza_Fabric_Red_normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Fabric_metallic.png", + "specular": 1.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Fabric_Blue_diffuse.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_fabric_blue", + "normal_map_enabled": false, + "normal_textname": "Sponza_Fabric_Blue_normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Fabric_metallic.png", + "specular": 1.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Fabric_Green_diffuse.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_fabric_gree", + "normal_map_enabled": false, + "normal_textname": "Sponza_Fabric_Green_normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Fabric_metallic.png", + "specular": 1.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" + }, + { + "alpha_enabled": false, + "ambient_color": "#FFFFFFFF", + "ao_textname": "", + "arm_textname": "", + "blend_enabled": false, + "bloom_scale": 0.0, + "density": 1.0, + "depth_ps": "DepthPS.cso", + "depth_vs": "DepthVS.cso", + "diffuse_color": "#FFFFFFFF", + "diffuse_textname": "Sponza_Column_a_diffuse.png", + "displacement_scale": 0.0, + "draw_ds": "MainRenderDS.cso", + "draw_gs": "MainRenderGS.cso", + "draw_hs": "MainRenderHS.cso", + "draw_ps": "MainRenderPS.cso", + "draw_vs": "MainRenderVS.cso", + "ds": "", + "emission": 0.0, + "emission_color": "#00000000", + "emission_textname": "", + "gs": "", + "high_textname": "", + "hs": "", + "name": "sp_column_a", + "normal_map_enabled": false, + "normal_textname": "Sponza_Column_a_normal.png", + "opacity": 1.0, + "opacity_textname": "", + "parallax_angle_steps": 5.0, + "parallax_scale": 0.0, + "parallax_shadow_scale": 0, + "parallax_shadows": false, + "parallax_steps": 4.0, + "ps": "", + "raytrace": true, + "rt_reflex": 1.0, + "shadow_gs": "ShadowMapCubeGS.cso", + "shadow_vs": "ShadowVS.cso", + "spec_textname": "Sponza_Column_a_roughness.png", + "specular": 0.0, + "tess_factor": 32.0, + "tess_type": 0, + "vs": "" } ], "root": ".\\assets\\materials\\" diff --git a/Tools/MaterialDesigner/Materials.h b/Tools/MaterialDesigner/Materials.h index 80a321e..e68ed7f 100644 --- a/Tools/MaterialDesigner/Materials.h +++ b/Tools/MaterialDesigner/Materials.h @@ -181,6 +181,8 @@ class Material: public Element { props["bloom_scale"] = std::make_shared>(0.0f); props["normal_map_enabled"] = std::make_shared>(false); props["alpha_enabled"] = std::make_shared>(false); + props["alpha_color"] = std::make_shared>("#00000000"); + props["alpha_threshold"] = std::make_shared>(0.4f); props["blend_enabled"] = std::make_shared>(false); props["diffuse_textname"] = std::make_shared>(""); props["normal_textname"] = std::make_shared>(""); @@ -230,6 +232,8 @@ class Material: public Element { props["bloom_scale"]->SetValue(js.value("bloom_scale", 0.0f)); props["normal_map_enabled"]->SetValue(js.value("normal_map_enabled", true)); props["alpha_enabled"]->SetValue(js.value("alpha_enabled", false)); + props["alpha_color"]->SetValue(js.value("alpha_color", "#00000000")); + props["alpha_threshold"]->SetValue(js.value("alpha_threshold", 0.4f)); props["blend_enabled"]->SetValue(js.value("blend_enabled", false)); props["diffuse_textname"]->SetValue(js.value("diffuse_textname", "")); props["normal_textname"]->SetValue(js.value("normal_textname", "")); @@ -784,6 +788,35 @@ public ref class MaterialProp } } + [CategoryAttribute("Material")] + property Drawing::Color AlphaColor { + Drawing::Color get() + { + auto color = HotBite::Engine::Core::parseColorStringF4(material->props["alpha_color"]->GetValue()); + return Drawing::Color::FromArgb((int)(color.w * 255.0f), (int)(color.x * 255.0f), (int)(color.y * 255.0f), (int)(color.z * 255.0f)); + } + + void set(Drawing::Color newValue) + { + char color[64]; + snprintf(color, 64, "#%02X%02X%02X%02X", newValue.R, newValue.G, newValue.B, newValue.A); + return material->props["alpha_color"]->SetValue(color); + } + } + + [CategoryAttribute("Material")] + property float AlphaThreshold { + float get() + { + return material->props["alpha_threshold"]->GetValue(); + } + + void set(float newValue) + { + return material->props["alpha_threshold"]->SetValue((float)newValue); + } + } + [CategoryAttribute("Material")] property bool Blend { bool get() diff --git a/Tools/MaterialDesigner/material_scene.json b/Tools/MaterialDesigner/material_scene.json index 4e75178..63ffa73 100644 --- a/Tools/MaterialDesigner/material_scene.json +++ b/Tools/MaterialDesigner/material_scene.json @@ -44,6 +44,9 @@ { "name": "Floor", "material": "MaterialDesignerFloor" + },{ + "name": "Cube*", + "pass": 2 } ] }