Merge remote-tracking branch 'origin/master' into navigation-features

This commit is contained in:
2020-12-23 11:04:09 +01:00
40 changed files with 305 additions and 1029 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -34,24 +34,16 @@ if errorlevel 1 goto Error_FlaxBuildFailed
exit /B 0
:Error_InvalidLocation
echo.
echo CallBuildTool ERROR: The script is in invalid directory.
echo.
goto Exit
:Error_NoVisualStudioEnvironment
echo.
echo CallBuildTool ERROR: Missing Visual Studio 2015 or newer.
echo.
goto Exit
:Error_CompilationFailed
echo.
echo CallBuildTool ERROR: Failed to compile Flax.Build project.
echo.
goto Exit
:Error_FlaxBuildFailed
echo.
echo CallBuildTool ERROR: Flax.Build tool failed.
echo.
goto Exit
:Exit
exit /B 1
+4 -4
View File
@@ -16,10 +16,6 @@ This repository contains full source code of the Flax (excluding NDA-protected p
* [Forum](https://forum.flaxengine.com)
* [Roadmap](https://trello.com/b/NQjLXRCP/flax-roadmap)
# Flax plugin for Visual Studio
Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS).
# Screenshots
![rendering](Development/Images/flax-pic-1.jpg "Rendering")
@@ -53,6 +49,10 @@ Follow the instructions below to compile and run the engine from source.
* Open workspace with Visual Code
* Build and run
# Flax plugin for Visual Studio
Flax Visual Studio extension provides better programming workflow, C# scripts debugging functionality and allows to attach to running engine instance to debug C# source. This extension is available to download [here](https://marketplace.visualstudio.com/items?itemName=Flax.FlaxVS).
## Workspace directory
- **Binaries/** - executable files
+1 -1
View File
@@ -968,7 +968,7 @@ namespace FlaxEditor.Viewport
_wheelMovementChangeDeltaSum -= step;
MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Min(camValueIndex + 1, EditorViewportCameraSpeedValues.Length - 1)];
}
else if (_wheelMovementChangeDeltaSum <= step)
else if (_wheelMovementChangeDeltaSum <= -step)
{
_wheelMovementChangeDeltaSum += step;
MovementSpeed = EditorViewportCameraSpeedValues[Mathf.Max(camValueIndex - 1, 0)];
+8 -3
View File
@@ -296,9 +296,14 @@ namespace FlaxEditor.Windows
return;
}
// Renaming a file to an extension it already has
if (!item.IsFolder && StringUtils.NormalizeExtension(Path.GetExtension(newShortName)) == StringUtils.NormalizeExtension(Path.GetExtension(item.Path)))
{
newShortName = StringUtils.GetPathWithoutExtension(newShortName);
}
// Check if name is valid
string hint;
if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out hint))
if (!Editor.ContentEditing.IsValidAssetName(item, newShortName, out string hint))
{
// Invalid name
MessageBox.Show("Given asset name is invalid. " + hint,
@@ -317,7 +322,7 @@ namespace FlaxEditor.Windows
}
// Cache data
var extension = Path.GetExtension(item.Path);
string extension = Path.GetExtension(item.Path);
var newPath = StringUtils.CombinePaths(item.ParentFolder.Path, newShortName + extension);
// Check if was renaming mock element
+4 -50
View File
@@ -12,7 +12,7 @@
bool TAA::Init()
{
// Create pipeline state
_psTAA.CreatePipelineStates();
//_psTAA.CreatePipelineStates();
// Load shader
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/TAA"));
@@ -34,22 +34,6 @@ bool TAA::setupResources()
}
const auto shader = _shader->GetShader();
// Validate shader constant buffer size
if (shader->GetCB(0)->GetSize() != sizeof(Data))
{
REPORT_INVALID_SHADER_PASS_CB_SIZE(shader, 0, Data);
return true;
}
// Create pipeline state
GPUPipelineState::Description psDesc;
if (!_psTAA.IsValid())
{
psDesc = GPUPipelineState::Description::DefaultFullscreenTriangle;
if (_psTAA.Create(psDesc, shader, "PS"))
return true;
}
return false;
}
@@ -58,10 +42,7 @@ void TAA::Dispose()
// Base
RendererPass::Dispose();
// Delete pipeline state
_psTAA.Delete();
// Release asset
_psTAA = nullptr;
_shader.Unlink();
}
@@ -75,7 +56,7 @@ void TAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureView
auto context = GPUDevice::Instance->GetMainContext();
// Ensure to have valid data
if (checkIfSkipPass())
//if (checkIfSkipPass())
{
// Resources are missing. Do not perform rendering, just copy source frame.
context->SetRenderTarget(output);
@@ -119,32 +100,5 @@ void TAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureView
blendStrength = 0.0f;
}
// Bind input
Data data;
data.ScreenSize = renderContext.View.ScreenSize;
data.TaaJitterStrength.X = renderContext.View.TemporalAAJitter.X;
data.TaaJitterStrength.Y = renderContext.View.TemporalAAJitter.Y;
data.TaaJitterStrength.Z = data.TaaJitterStrength.X / tempDesc.Width;
data.TaaJitterStrength.W = data.TaaJitterStrength.Y / tempDesc.Height;
data.FinalBlendParameters.X = settings.TAA_StationaryBlending * blendStrength;
data.FinalBlendParameters.Y = settings.TAA_MotionBlending * blendStrength;
data.FinalBlendParameters.Z = 100.0f * 60.0f;
data.FinalBlendParameters.W = settings.TAA_Sharpness;
const auto cb = _shader->GetShader()->GetCB(0);
context->UpdateCB(cb, &data);
context->BindCB(0, cb);
context->BindSR(0, input);
context->BindSR(1, inputHistory);
context->BindSR(2, renderContext.Buffers->MotionVectors);
context->BindSR(3, renderContext.Buffers->DepthBuffer);
// Render
GPUTextureView* rts[] = { output, outputHistory->View() };
context->SetRenderTarget(nullptr, ToSpan(rts, ARRAY_COUNT(rts)));
context->SetState(_psTAA.Get(renderContext.View.IsOrthographicProjection() ? 1 : 0));
context->DrawFullscreenTriangle();
// Swap the history
RenderTargetPool::Release(inputHistory);
renderContext.Buffers->TemporalAA = outputHistory;
// ...
}
+2 -9
View File
@@ -12,15 +12,8 @@ class TAA : public RendererPass<TAA>
{
private:
PACK_STRUCT(struct Data
{
Vector4 ScreenSize;
Vector4 TaaJitterStrength;
Vector4 FinalBlendParameters;
});
AssetReference<Shader> _shader;
GPUPipelineStatePermutationsPs<2> _psTAA;
GPUPipelineState* _psTAA;
public:
@@ -44,7 +37,7 @@ private:
#if COMPILE_WITH_DEV_ENV
void OnShaderReloading(Asset* obj)
{
_psTAA.Release();
_psTAA = nullptr;
invalidateResources();
}
#endif
+10 -236
View File
@@ -11,19 +11,16 @@
#include "Engine/Graphics/RenderTargetPool.h"
#include "Engine/Graphics/RenderBuffers.h"
PACK_STRUCT(struct Data {
GBufferData GBuffer;
Matrix CurrentVP;
Matrix PreviousVP;
Vector4 TemporalAAJitter;
});
MotionBlurPass::MotionBlurPass()
: _motionVectorsFormat(PixelFormat::Unknown)
, _velocityFormat(PixelFormat::Unknown)
, _psCameraMotionVectors(nullptr)
, _psMotionVectorsDebug(nullptr)
, _psMotionVectorsDebugArrow(nullptr)
, _psVelocitySetup(nullptr)
, _psTileMax1(nullptr)
, _psTileMax2(nullptr)
, _psTileMax4(nullptr)
, _psTileMaxV(nullptr)
, _psNeighborMax(nullptr)
, _psReconstruction(nullptr)
{
}
@@ -36,15 +33,6 @@ bool MotionBlurPass::Init()
{
// Create pipeline state
_psCameraMotionVectors = GPUDevice::Instance->CreatePipelineState();
_psMotionVectorsDebug = GPUDevice::Instance->CreatePipelineState();
_psMotionVectorsDebugArrow = GPUDevice::Instance->CreatePipelineState();
_psVelocitySetup = GPUDevice::Instance->CreatePipelineState();
_psTileMax1 = GPUDevice::Instance->CreatePipelineState();
_psTileMax2 = GPUDevice::Instance->CreatePipelineState();
_psTileMax4 = GPUDevice::Instance->CreatePipelineState();
_psTileMaxV = GPUDevice::Instance->CreatePipelineState();
_psNeighborMax = GPUDevice::Instance->CreatePipelineState();
_psReconstruction = GPUDevice::Instance->CreatePipelineState();
// Load shader
_shader = Content::LoadAsyncInternal<Shader>(TEXT("Shaders/MotionBlur"));
@@ -98,62 +86,6 @@ bool MotionBlurPass::setupResources()
if (_psCameraMotionVectors->Init(psDesc))
return true;
}
if (!_psVelocitySetup->IsValid())
{
psDesc.PS = shader->GetPS("PS_VelocitySetup");
if (_psVelocitySetup->Init(psDesc))
return true;
}
if (!_psTileMax1->IsValid())
{
psDesc.PS = shader->GetPS("PS_TileMax1");
if (_psTileMax1->Init(psDesc))
return true;
}
if (!_psTileMax2->IsValid())
{
psDesc.PS = shader->GetPS("PS_TileMax2");
if (_psTileMax2->Init(psDesc))
return true;
}
if (!_psTileMax4->IsValid())
{
psDesc.PS = shader->GetPS("PS_TileMax4");
if (_psTileMax4->Init(psDesc))
return true;
}
if (!_psTileMaxV->IsValid())
{
psDesc.PS = shader->GetPS("PS_TileMaxV");
if (_psTileMaxV->Init(psDesc))
return true;
}
if (!_psNeighborMax->IsValid())
{
psDesc.PS = shader->GetPS("PS_NeighborMax");
if (_psNeighborMax->Init(psDesc))
return true;
}
if (!_psReconstruction->IsValid())
{
psDesc.PS = shader->GetPS("PS_Reconstruction");
if (_psReconstruction->Init(psDesc))
return true;
}
if (!_psMotionVectorsDebug->IsValid())
{
psDesc.PS = shader->GetPS("PS_MotionVectorsDebug");
if (_psMotionVectorsDebug->Init(psDesc))
return true;
}
if (!_psMotionVectorsDebugArrow->IsValid())
{
psDesc.PrimitiveTopologyType = PrimitiveTopologyType::Line;
psDesc.VS = shader->GetVS("VS_DebugArrow");
psDesc.PS = shader->GetPS("PS_DebugArrow");
if (_psMotionVectorsDebugArrow->Init(psDesc))
return true;
}
return false;
}
@@ -165,15 +97,6 @@ void MotionBlurPass::Dispose()
// Delete pipeline state
SAFE_DELETE_GPU_RESOURCE(_psCameraMotionVectors);
SAFE_DELETE_GPU_RESOURCE(_psMotionVectorsDebug);
SAFE_DELETE_GPU_RESOURCE(_psMotionVectorsDebugArrow);
SAFE_DELETE_GPU_RESOURCE(_psVelocitySetup);
SAFE_DELETE_GPU_RESOURCE(_psTileMax1);
SAFE_DELETE_GPU_RESOURCE(_psTileMax2);
SAFE_DELETE_GPU_RESOURCE(_psTileMax4);
SAFE_DELETE_GPU_RESOURCE(_psTileMaxV);
SAFE_DELETE_GPU_RESOURCE(_psNeighborMax);
SAFE_DELETE_GPU_RESOURCE(_psReconstruction);
// Release asset
_shader.Unlink();
@@ -275,39 +198,13 @@ void MotionBlurPass::RenderDebug(RenderContext& renderContext, GPUTextureView* f
{
auto context = GPUDevice::Instance->GetMainContext();
const auto motionVectors = renderContext.Buffers->MotionVectors;
if (!motionVectors->IsAllocated() || setupResources())
//if (!motionVectors->IsAllocated() || setupResources())
{
context->Draw(frame);
return;
}
PROFILE_GPU_CPU("Motion Vectors Debug");
// Bind input
Data data;
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
const float rows = 16.0f;
const float cols = rows * renderContext.Buffers->GetWidth() / renderContext.Buffers->GetHeight();
data.DebugBlend = 0.7f;
data.DebugAmplitude = 2.0f;
data.DebugRowCount = static_cast<int32>(rows);
data.DebugColumnCount = static_cast<int32>(cols);
auto cb = _shader->GetShader()->GetCB(0);
context->UpdateCB(cb, &data);
context->BindCB(0, cb);
context->BindSR(0, frame);
context->BindSR(1, renderContext.Buffers->MotionVectors);
// Draw motion gradient
context->SetState(_psMotionVectorsDebug);
context->DrawFullscreenTriangle();
// Draw arrows
context->SetState(_psMotionVectorsDebugArrow);
context->Draw(0, static_cast<uint32>(cols * rows * 6));
// Cleanup
context->ResetSR();
// ..
}
void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GPUTexture*& output)
@@ -335,128 +232,5 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP
return;
}
// Need to have valid motion vectors created and rendered before
ASSERT(motionVectors->IsAllocated());
PROFILE_GPU_CPU("Motion Blur");
// Calculate the maximum blur radius in pixels
const float maxBlurRadius = 5.0f;
const int32 maxBlurPixels = static_cast<int32>(maxBlurRadius * motionVectorsHeight / 100.0f);
// Calculate the TileMax size (it should be a multiple of 8 and larger than maxBlur)
const int32 tileSize = ((maxBlurPixels - 1) / 8 + 1) * 8;
// Bind input
Data data;
GBufferPass::SetInputs(renderContext.View, data.GBuffer);
Matrix::Transpose(renderContext.View.ViewProjection(), data.CurrentVP);
Matrix::Transpose(renderContext.View.PrevViewProjection, data.PreviousVP);
data.TemporalAAJitter = renderContext.View.TemporalAAJitter;
data.VelocityScale = settings.Scale;
data.MaxBlurRadius = static_cast<float>(maxBlurPixels);
data.RcpMaxBlurRadius = 1.0f / maxBlurPixels;
data.TileMaxOffs = Vector2::One * (tileSize / 8.0f - 1.0f) * -0.5f;
data.TileMaxLoop = static_cast<int32>(tileSize / 8.0f);
data.LoopCount = Math::Clamp(settings.SampleCount / 2.0f, 1.0f, 64.0f);
const float invWidth = 1.0f / motionVectorsWidth;
const float invHeight = 1.0f / motionVectorsHeight;
data.TexelSize1 = Vector2(invWidth, invHeight);
data.TexelSize2 = Vector2(invWidth * 2.0f, invHeight * 2.0f);
data.TexelSize4 = Vector2(invWidth * 4.0f, invHeight * 4.0f);
data.TexelSizeV = Vector2(invWidth * 8.0f, invHeight * 8.0f);
data.TexelSizeNM = Vector2(invWidth * tileSize, invHeight * tileSize);
data.MotionVectorsTexelSize = Vector2(1.0f / motionVectorsWidth, invHeight * tileSize);
auto cb = _shader->GetShader()->GetCB(0);
context->UpdateCB(cb, &data);
context->BindCB(0, cb);
context->BindSR(0, renderContext.Buffers->DepthBuffer);
auto rtDesc = GPUTextureDescription::New2D(motionVectorsWidth, motionVectorsHeight, _velocityFormat);
// Pass 1 - Velocity/depth packing
auto vBuffer = RenderTargetPool::Get(rtDesc);
context->SetRenderTarget(*vBuffer);
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, motionVectors->View());
context->BindSR(1, renderContext.Buffers->DepthBuffer->View());
context->SetState(_psVelocitySetup);
context->DrawFullscreenTriangle();
context->UnBindSR(1);
// Pass 2 - First TileMax filter (1/2 downsize)
rtDesc.Format = _motionVectorsFormat;
rtDesc.Width = motionVectorsWidth / 2;
rtDesc.Height = motionVectorsHeight / 2;
auto tile2 = RenderTargetPool::Get(rtDesc);
context->ResetRenderTarget();
context->SetRenderTarget(tile2->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, vBuffer->View());
context->SetState(_psTileMax1);
context->DrawFullscreenTriangle();
// Pass 3 - Second TileMax filter (1/4 downsize)
rtDesc.Width = motionVectorsWidth / 4;
rtDesc.Height = motionVectorsHeight / 4;
auto tile4 = RenderTargetPool::Get(rtDesc);
context->ResetRenderTarget();
context->SetRenderTarget(tile4->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, tile2->View());
context->SetState(_psTileMax2);
context->DrawFullscreenTriangle();
RenderTargetPool::Release(tile2);
// Pass 4 - Third TileMax filter (1/8 downsize)
rtDesc.Width = motionVectorsWidth / 8;
rtDesc.Height = motionVectorsHeight / 8;
auto tile8 = RenderTargetPool::Get(rtDesc);
context->ResetRenderTarget();
context->SetRenderTarget(tile8->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, tile4->View());
context->SetState(_psTileMax4);
context->DrawFullscreenTriangle();
RenderTargetPool::Release(tile4);
// Pass 5 - Fourth TileMax filter (reduce to tileSize)
rtDesc.Width = motionVectorsWidth / tileSize;
rtDesc.Height = motionVectorsHeight / tileSize;
auto tile = RenderTargetPool::Get(rtDesc);
context->ResetRenderTarget();
context->SetRenderTarget(tile->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, tile8->View());
context->SetState(_psTileMaxV);
context->DrawFullscreenTriangle();
RenderTargetPool::Release(tile8);
// Pass 6 - NeighborMax filter
rtDesc.Width = motionVectorsWidth / tileSize;
rtDesc.Height = motionVectorsHeight / tileSize;
auto neighborMax = RenderTargetPool::Get(rtDesc);
context->ResetRenderTarget();
context->SetRenderTarget(neighborMax->View());
context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height);
context->BindSR(0, tile->View());
context->SetState(_psNeighborMax);
context->DrawFullscreenTriangle();
RenderTargetPool::Release(tile);
// Pass 7 - Reconstruction pass
context->ResetRenderTarget();
context->SetRenderTarget(*output);
context->SetViewportAndScissors((float)screenWidth, (float)screenHeight);
context->BindSR(0, input->View());
context->BindSR(1, vBuffer->View());
context->BindSR(2, neighborMax->View());
context->SetState(_psReconstruction);
context->DrawFullscreenTriangle();
// Cleanup
context->ResetSR();
context->ResetRenderTarget();
RenderTargetPool::Release(vBuffer);
RenderTargetPool::Release(neighborMax);
Swap(output, input);
// ..
}
+1 -42
View File
@@ -10,43 +10,11 @@
class MotionBlurPass : public RendererPass<MotionBlurPass>
{
private:
PACK_STRUCT(struct Data {
GBufferData GBuffer;
Matrix CurrentVP;
Matrix PreviousVP;
Vector4 TemporalAAJitter;
Vector2 TileMaxOffs;
float VelocityScale;
int32 TileMaxLoop;
float MaxBlurRadius;
float RcpMaxBlurRadius;
Vector2 TexelSize1;
Vector2 TexelSize2;
Vector2 TexelSize4;
Vector2 TexelSizeV;
Vector2 TexelSizeNM;
float LoopCount;
float Dummy0;
Vector2 MotionVectorsTexelSize;
float DebugBlend;
float DebugAmplitude;
int32 DebugColumnCount;
int32 DebugRowCount;
});
PixelFormat _motionVectorsFormat;
PixelFormat _velocityFormat;
AssetReference<Shader> _shader;
GPUPipelineState* _psCameraMotionVectors;
GPUPipelineState* _psMotionVectorsDebug;
GPUPipelineState* _psMotionVectorsDebugArrow;
GPUPipelineState* _psVelocitySetup;
GPUPipelineState* _psTileMax1;
GPUPipelineState* _psTileMax2;
GPUPipelineState* _psTileMax4;
GPUPipelineState* _psTileMaxV;
GPUPipelineState* _psNeighborMax;
GPUPipelineState* _psReconstruction;
GPUPipelineState* _psCameraMotionVectors = nullptr;
public:
@@ -84,15 +52,6 @@ private:
void OnShaderReloading(Asset* obj)
{
_psCameraMotionVectors->ReleaseGPU();
_psMotionVectorsDebug->ReleaseGPU();
_psMotionVectorsDebugArrow->ReleaseGPU();
_psVelocitySetup->ReleaseGPU();
_psTileMax1->ReleaseGPU();
_psTileMax2->ReleaseGPU();
_psTileMax4->ReleaseGPU();
_psTileMaxV->ReleaseGPU();
_psNeighborMax->ReleaseGPU();
_psReconstruction->ReleaseGPU();
invalidateResources();
}
#endif
+3 -1
View File
@@ -306,6 +306,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
#endif
renderContext.List->Settings.AntiAliasing.Mode = aaMode;
// Prepare
renderContext.View.Prepare(renderContext);
renderContext.Buffers->Prepare();
@@ -484,7 +485,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext)
context->ResetRenderTarget();
context->SetRenderTarget(task->GetOutputView());
context->SetViewportAndScissors((float)renderContext.Buffers->GetWidth(), (float)renderContext.Buffers->GetHeight());
MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View());
context->Clear(frameBuffer->View(), Color::Black);
//MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View());
return;
}
+1 -1
View File
@@ -92,7 +92,7 @@ namespace FlaxEngine
/// <returns>The normalized extension.</returns>
public static string NormalizeExtension(string extension)
{
if (extension[0] == '.')
if (extension.Length != 0 && extension[0] == '.')
extension = extension.Remove(0, 1);
return extension.ToLower();
}
+7 -9
View File
@@ -25,9 +25,9 @@ float D_GGX(float roughness, float NoH)
float Vis_Schlick(float roughness, float NoV, float NoL)
{
float k = Square(roughness) * 0.5;
float vis_SchlickV = NoV * (1 - k) + k;
float vis_SchlickL = NoL * (1 - k) + k;
return 0.25 / (vis_SchlickV * vis_SchlickL);
float visSchlickV = NoV * (1 - k) + k;
float visSchlickL = NoL * (1 - k) + k;
return 0.25 / (visSchlickV * visSchlickL);
}
// Smith term for GGX
@@ -36,9 +36,9 @@ float Vis_Smith(float roughness, float NoV, float NoL)
{
float a = Square(roughness);
float a2 = a * a;
float vis_SmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float vis_SmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(vis_SmithV * vis_SmithL);
float visSmithV = NoV + sqrt(NoV * (NoV - NoV * a2) + a2);
float visSmithL = NoL + sqrt(NoL * (NoL - NoL * a2) + a2);
return rcp(visSmithV * visSmithL);
}
// Appoximation of joint Smith term for GGX
@@ -74,7 +74,7 @@ half SSRMipFromRoughness(half roughness)
return max(1, 10 - mip1px);
}
float ComputeReflectionCaptureRoughnessFromMip(float mip)
float ProbeRoughnessFromMip(float mip)
{
float mip1px = REFLECTION_CAPTURE_NUM_MIPS - 1 - mip;
return exp2((REFLECTION_CAPTURE_ROUGHEST_MIP - mip1px) / REFLECTION_CAPTURE_ROUGHNESS_MIP_SCALE);
@@ -99,8 +99,6 @@ float3 EnvBRDF(Texture2D preIntegratedGF, float3 specularColor, float roughness,
return specularColor * ab.x + saturate(50.0 * specularColor.g) * ab.y;
}
#define MAX_SPECULAR_POWER 10000000000.0f
float RoughnessToSpecularPower(float roughness)
{
return pow(2, 13 * (1 - roughness));
+15 -19
View File
@@ -264,37 +264,33 @@ META_VS(true, FEATURE_LEVEL_SM4)
META_FLAG(VertexToGeometryShader)
META_VS_IN_ELEMENT(POSITION, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
META_VS_IN_ELEMENT(TEXCOORD, 0, R32G32_FLOAT, 0, ALIGN, PER_VERTEX, 0, true)
Quad_VS2GS VS_WriteToSlice(float2 Position : POSITION0, float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_InstanceID)
Quad_VS2GS VS_WriteToSlice(float2 position : POSITION0, float2 texCoord : TEXCOORD0, uint layerIndex : SV_InstanceID)
{
Quad_VS2GS output;
output.Vertex.Position = float4(Position, 0, 1);
output.Vertex.TexCoord = TexCoord;
output.LayerIndex = LayerIndex;
output.Vertex.Position = float4(position, 0, 1);
output.Vertex.TexCoord = texCoord;
output.LayerIndex = layerIndex;
return output;
}
// Geometry shader that writes to a range of slices of a volume texture
META_GS(true, FEATURE_LEVEL_SM4)
[maxvertexcount(3)]
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> OutStream)
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> stream)
{
Quad_GS2PS vertex0;
vertex0.Vertex = input[0].Vertex;
vertex0.LayerIndex = input[0].LayerIndex;
Quad_GS2PS vertex;
Quad_GS2PS vertex1;
vertex1.Vertex = input[1].Vertex;
vertex1.LayerIndex = input[1].LayerIndex;
vertex.Vertex = input[0].Vertex;
vertex.LayerIndex = input[0].LayerIndex;
stream.Append(vertex);
Quad_GS2PS vertex2;
vertex2.Vertex = input[2].Vertex;
vertex2.LayerIndex = input[2].LayerIndex;
vertex.Vertex = input[1].Vertex;
vertex.LayerIndex = input[1].LayerIndex;
stream.Append(vertex);
OutStream.Append(vertex0);
OutStream.Append(vertex1);
OutStream.Append(vertex2);
vertex.Vertex = input[2].Vertex;
vertex.LayerIndex = input[2].LayerIndex;
stream.Append(vertex);
}
META_PS(true, FEATURE_LEVEL_ES2)
+5 -5
View File
@@ -571,9 +571,9 @@ StructuredBuffer<BokehPoint> BokehPointBuffer : register(t2);
// Vertex Shader, positions and scales the bokeh point
META_VS(true, FEATURE_LEVEL_SM5)
META_FLAG(VertexToGeometryShader)
BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID)
BokehVSOutput VS_Bokeh(in uint vertexID : SV_VertexID)
{
BokehPoint bPoint = BokehPointBuffer[VertexID];
BokehPoint bPoint = BokehPointBuffer[vertexID];
BokehVSOutput output;
// Position the vertex in normalized device coordinate space [-1, 1]
@@ -599,7 +599,7 @@ BokehVSOutput VS_Bokeh(in uint VertexID : SV_VertexID)
// Geometry Shader, expands a vertex into a quad with two triangles
META_GS(true, FEATURE_LEVEL_SM5)
[maxvertexcount(4)]
void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput> SpriteStream)
void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput> stream)
{
BokehGSOutput output;
@@ -613,9 +613,9 @@ void GS_Bokeh(point BokehVSOutput input[1], inout TriangleStream<BokehGSOutput>
output.Color = input[0].Color;
output.Depth = input[0].Depth;
SpriteStream.Append(output);
stream.Append(output);
}
SpriteStream.RestartStrip();
stream.RestartStrip();
}
// Pixel Shader, applies the bokeh shape texture
+22 -22
View File
@@ -29,29 +29,29 @@ struct ExponentialHeightFogData
float StartDistance;
};
half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 worldPosition, float3 cameraPosition, float excludeDistance)
float4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, float3 posWS, float3 camWS, float skipDistance)
{
float3 cameraToReceiver = worldPosition - cameraPosition;
float cameraToReceiverLengthSqr = dot(cameraToReceiver, cameraToReceiver);
float cameraToReceiverLengthInv = rsqrt(cameraToReceiverLengthSqr);
float cameraToReceiverLength = cameraToReceiverLengthSqr * cameraToReceiverLengthInv;
half3 cameraToReceiverNormalized = cameraToReceiver * cameraToReceiverLengthInv;
float3 cameraToPos = posWS - camWS;
float cameraToPosSqr = dot(cameraToPos, cameraToPos);
float cameraToPosLenInv = rsqrt(cameraToPosSqr);
float cameraToPosLen = cameraToPosSqr * cameraToPosLenInv;
float3 cameraToReceiverNorm = cameraToPos * cameraToPosLenInv;
float rayOriginTerms = exponentialHeightFog.FogAtViewPosition;
float rayLength = cameraToReceiverLength;
float rayDirectionY = cameraToReceiver.y;
float rayLength = cameraToPosLen;
float rayDirectionY = cameraToPos.y;
// Apply start distance offset
excludeDistance = max(excludeDistance, exponentialHeightFog.StartDistance);
if (excludeDistance > 0)
skipDistance = max(skipDistance, exponentialHeightFog.StartDistance);
if (skipDistance > 0)
{
float excludeIntersectionTime = excludeDistance * cameraToReceiverLengthInv;
float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToReceiver.y;
float exclusionIntersectionY = cameraPosition.y + cameraToExclusionIntersectionY;
float exclusionIntersectionToReceiverY = cameraToReceiver.y - cameraToExclusionIntersectionY;
float excludeIntersectionTime = skipDistance * cameraToPosLenInv;
float cameraToExclusionIntersectionY = excludeIntersectionTime * cameraToPos.y;
float exclusionIntersectionY = camWS.y + cameraToExclusionIntersectionY;
float exclusionIntersectionToReceiverY = cameraToPos.y - cameraToExclusionIntersectionY;
// Calculate fog off of the ray starting from the exclusion distance, instead of starting from the camera
rayLength = (1.0f - excludeIntersectionTime) * cameraToReceiverLength;
rayLength = (1.0f - excludeIntersectionTime) * cameraToPosLen;
rayDirectionY = exclusionIntersectionToReceiverY;
// Move off the viewer
@@ -67,22 +67,22 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo
float exponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * rayLength;
// Calculate the amount of light that made it through the fog using the transmission equation
half expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity);
float expFogFactor = max(saturate(exp2(-exponentialHeightLineIntegral)), exponentialHeightFog.FogMinOpacity);
// Calculate the directional light inscattering
half3 inscatteringColor = exponentialHeightFog.FogInscatteringColor;
half3 directionalInscattering = 0;
float3 inscatteringColor = exponentialHeightFog.FogInscatteringColor;
float3 directionalInscattering = 0;
BRANCH
if (exponentialHeightFog.ApplyDirectionalInscattering > 0)
{
// Setup a cosine lobe around the light direction to approximate inscattering from the directional light off of the ambient haze
half3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNormalized, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent);
float3 directionalLightInscattering = exponentialHeightFog.DirectionalInscatteringColor * pow(saturate(dot(cameraToReceiverNorm, exponentialHeightFog.InscatteringLightDirection)), exponentialHeightFog.DirectionalInscatteringExponent);
// Calculate the line integral of the eye ray through the haze, using a special starting distance to limit the inscattering to the distance
float dirExponentialHeightLineIntegral = exponentialHeightLineIntegralCalc * max(rayLength - exponentialHeightFog.DirectionalInscatteringStartDistance, 0.0f);
// Calculate the amount of light that made it through the fog using the transmission equation
half directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral));
float directionalInscatteringFogFactor = saturate(exp2(-dirExponentialHeightLineIntegral));
// Final inscattering from the light
directionalInscattering = directionalLightInscattering * (1 - directionalInscatteringFogFactor);
@@ -90,13 +90,13 @@ half4 GetExponentialHeightFog(ExponentialHeightFogData exponentialHeightFog, flo
// Disable fog after a certain distance
FLATTEN
if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToReceiverLength > exponentialHeightFog.FogCutoffDistance)
if (exponentialHeightFog.FogCutoffDistance > 0 && cameraToPosLen > exponentialHeightFog.FogCutoffDistance)
{
expFogFactor = 1;
directionalInscattering = 0;
}
return half4((inscatteringColor) * (1 - expFogFactor) + directionalInscattering, expFogFactor);
return float4(inscatteringColor * (1.0f - expFogFactor) + directionalInscattering, expFogFactor);
}
#endif
+9 -9
View File
@@ -33,15 +33,15 @@ float3 GetWorldPos(float2 uv)
return mul(float4(viewPos, 1), gBufferData.InvViewMatrix).xyz;
}
float4 CalculateCombinedFog(float3 worldPosition, float sceneDepth, float3 volumeUV)
float4 CalculateCombinedFog(float3 posWS, float sceneDepth, float3 volumeUV)
{
float excludeDistance = 0;
float skipDistance = 0;
#if VOLUMETRIC_FOG
excludeDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
skipDistance = max(ExponentialHeightFog.VolumetricFogMaxDistance - 100, 0);
#endif
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, worldPosition, GBuffer.ViewPos, excludeDistance);
float4 fog = GetExponentialHeightFog(ExponentialHeightFog, posWS, GBuffer.ViewPos, skipDistance);
#if VOLUMETRIC_FOG
float4 volumetricFog = IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0);
@@ -57,8 +57,8 @@ META_PERMUTATION_1(VOLUMETRIC_FOG=1)
float4 PS_Fog(Quad_VS2PS input) : SV_Target0
{
// Calculate pixel world space position
float3 worldPosition = GetWorldPos(input.TexCoord);
float3 viewVector = worldPosition - GBuffer.ViewPos;
float3 posWS = GetWorldPos(input.TexCoord);
float3 viewVector = posWS - GBuffer.ViewPos;
float sceneDepth = length(viewVector);
// Calculate volumetric fog coordinates
@@ -67,17 +67,17 @@ float4 PS_Fog(Quad_VS2PS input) : SV_Target0
// Debug code
#if VOLUMETRIC_FOG && 0
volumeUV = worldPosition / 1000;
volumeUV = posWS / 1000;
if (!all(volumeUV >= 0 && volumeUV <= 1))
return 0;
return float4(IntegratedLightScattering.SampleLevel(SamplerLinearClamp, volumeUV, 0).rgb, 1);
//return float4(volumeUV, 1);
//return float4(worldPosition / 100, 1);
//return float4(posWS / 100, 1);
#endif
// Calculate fog color
float4 fog = CalculateCombinedFog(worldPosition, sceneDepth, volumeUV);
float4 fog = CalculateCombinedFog(posWS, sceneDepth, volumeUV);
return fog;
}
-342
View File
@@ -14,27 +14,6 @@ float4x4 CurrentVP;
float4x4 PreviousVP;
float4 TemporalAAJitter;
// Motion Blur
float2 TileMaxOffs;
float VelocityScale;
int TileMaxLoop;
float MaxBlurRadius;
float RcpMaxBlurRadius;
float2 TexelSize1;
float2 TexelSize2;
float2 TexelSize4;
float2 TexelSizeV;
float2 TexelSizeNM;
float LoopCount;
float Dummy0;
float2 MotionVectorsTexelSize;
// Motion Vectors Debug Parameters
float DebugBlend;
float DebugAmplitude;
int DebugColumnCount;
int DebugRowCount;
META_CB_END
DECLARE_GBUFFERDATA_ACCESS(GBuffer)
@@ -43,106 +22,6 @@ Texture2D Input0 : register(t0);
Texture2D Input1 : register(t1);
Texture2D Input2 : register(t2);
// Calculates the color for the a motion vector debugging
float4 VectorToColor(float2 motionVector)
{
float phi = atan2(motionVector.x, motionVector.y);
float hue = (phi / PI + 1) * 0.5;
float r = abs(hue * 6 - 3) - 1;
float g = 2 - abs(hue * 6 - 2);
float b = 2 - abs(hue * 6 - 4);
float a = length(motionVector);
return saturate(float4(r, g, b, a));
}
// Pixel shader for motion vectors debug view
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_MotionVectorsDebug(Quad_VS2PS input) : SV_Target
{
float4 color = SAMPLE_RT(Input0, input.TexCoord);
float2 motionVector = SAMPLE_RT(Input1, input.TexCoord).rg * (DebugAmplitude * 5.0f);
float4 motionColor = VectorToColor(motionVector);
float colorRation = saturate(2 - DebugBlend * 2);
float motionColorRatio = saturate(DebugBlend * 2);
color.rgb = lerp(color.rgb * colorRation, motionColor.rgb, motionColor.a * motionColorRatio);
return color;
}
// Motion vector arrow data from VS to PS
struct ArrowVaryings
{
float4 Position : SV_POSITION;
float2 ScreenUV : TEXCOORD;
float4 Color : COLOR;
};
META_VS(true, FEATURE_LEVEL_ES2)
ArrowVaryings VS_DebugArrow(uint VertexId : SV_VertexID)
{
// Screen aspect ratio
float aspect = GBuffer.ScreenSize.x * GBuffer.ScreenSize.w;
float aspectInv = GBuffer.ScreenSize.y * GBuffer.ScreenSize.z;
// Vertex IDs
uint arrowId = VertexId / 6;
uint pointId = VertexId - arrowId * 6;
// Column and row number of the arrow
uint row = arrowId / DebugColumnCount;
uint col = arrowId - row * DebugColumnCount;
// Get the motion vector
float2 uv = float2((col + 0.5) / DebugColumnCount, (row + 0.5) / DebugRowCount);
float2 motionVector = SAMPLE_RT(Input1, uv).rg * DebugAmplitude;
// Arrow color
float4 color = VectorToColor(motionVector);
// Arrow transformation
float isEnd = pointId > 0;
float2 direction = normalize(motionVector * float2(aspect, 1));
float2x2 rotation = float2x2(direction.y, direction.x, -direction.x, direction.y);
float offsetStart = pointId == 3 ? -1 : (pointId == 5 ? 1 : 0);
offsetStart *= isEnd * 0.3f * saturate(length(motionVector) * DebugRowCount);
float2 offset = float2(offsetStart, -abs(offsetStart));
offset = mul(rotation, offset) * float2(aspectInv, 1);
// Vertex position in the clip space
float2 pos = motionVector * isEnd + offset * 2 / DebugRowCount + uv * 2.0f - 1.0f;
// Convert to the screen coordinates
float2 posSS = (pos + 1) * 0.5f * GBuffer.ScreenSize.xy;
posSS = round(posSS);
// Bring back to the clip space
pos = (posSS + 0.5f) * GBuffer.ScreenSize.zw * 2.0f - 1.0f;
pos.y *= -1;
// Color tweaks
color.rgb = lerp(color.rgb, 1, 0.5f);
color.a = DebugBlend;
// Output
ArrowVaryings output;
output.Position = float4(pos, 0, 1);
output.ScreenUV = posSS;
output.Color = color;
return output;
}
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_DebugArrow(ArrowVaryings input) : SV_Target
{
// Pseudo anti-aliasing
float aa = length(frac(input.ScreenUV) - 0.5f) / 0.707f;
aa *= (aa * (aa * 0.305306011f + 0.682171111f) + 0.012522878f);
return float4(input.Color.rgb, input.Color.a * aa);
}
// Pixel shader for camera motion vectors
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_CameraMotionVectors(Quad_VS2PS input) : SV_Target
@@ -169,224 +48,3 @@ float4 PS_CameraMotionVectors(Quad_VS2PS input) : SV_Target
return float4(vPosCur - vPosPrev, 0, 1);
}
// Pixel Shader for velocity texture setup
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_VelocitySetup(Quad_VS2PS input) : SV_Target
{
// Sample the motion vector
float2 v = SAMPLE_RT(Input0, input.TexCoord).rg;
// Apply the exposure time and convert to the pixel space
v *= (VelocityScale * 0.5f) * GBuffer.ScreenSize.xy;
// Clamp the vector with the maximum blur radius
v /= max(1.0f, length(v) * RcpMaxBlurRadius);
// Sample the depth of the pixel
float depth = SAMPLE_RT(Input1, input.TexCoord).r;
GBufferData gBufferData = GetGBufferData();
depth = LinearizeZ(gBufferData, depth);
// Pack into 10/10/10/2 format
return float4((v * RcpMaxBlurRadius + 1.0f) * 0.5f, depth, 0.0f);
}
float2 MaxV(float2 v1, float2 v2)
{
return dot(v1, v1) < dot(v2, v2) ? v2 : v1;
}
// Pixel Shader for TileMax filter (2 pixel width with normalization)
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_TileMax1(Quad_VS2PS input) : SV_Target
{
float4 d = TexelSize1.xyxy * float4(-0.5, -0.5, 0.5, 0.5);
float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg;
float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg;
float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg;
float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg;
v1 = (v1 * 2.0f - 1.0f) * MaxBlurRadius;
v2 = (v2 * 2.0f - 1.0f) * MaxBlurRadius;
v3 = (v3 * 2.0f - 1.0f) * MaxBlurRadius;
v4 = (v4 * 2.0f - 1.0f) * MaxBlurRadius;
return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f);
}
// Pixel Shader for TileMax filter (2 pixel width)
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_TileMax2(Quad_VS2PS input) : SV_Target
{
float4 d = TexelSize2.xyxy * float4(-0.5f, -0.5f, 0.5f, 0.5f);
float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg;
float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg;
float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg;
float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg;
return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f);
}
// Pixel Shader for TileMax filter (2 pixel width)
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_TileMax4(Quad_VS2PS input) : SV_Target
{
float4 d = TexelSize4.xyxy * float4(-0.5f, -0.5f, 0.5f, 0.5f);
float2 v1 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg;
float2 v2 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg;
float2 v3 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg;
float2 v4 = SAMPLE_RT(Input0, input.TexCoord + d.zw).rg;
return float4(MaxV(MaxV(MaxV(v1, v2), v3), v4), 0.0f, 0.0f);
}
// Pixel Shader for TileMax filter (variable width)
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_TileMaxV(Quad_VS2PS input) : SV_Target
{
float2 uv0 = input.TexCoord + TexelSizeV.xy * TileMaxOffs.xy;
float2 du = float2(TexelSizeV.x, 0.0);
float2 dv = float2(0.0, TexelSizeV.y);
float2 vo = 0.0;
LOOP
for (int x = 0; x < TileMaxLoop; x++)
{
LOOP
for (int y = 0; y < TileMaxLoop; y++)
{
float2 uv = uv0 + du * x + dv * y;
vo = MaxV(vo, SAMPLE_RT(Input0, uv).rg);
}
}
return float4(vo, 0.0, 0.0);
}
// Pixel Shader for NeighborMax filter
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_NeighborMax(Quad_VS2PS input) : SV_Target
{
// Center weight tweak
const float cw = 1.01;
float4 d = TexelSizeNM.xyxy * float4(1.0, 1.0, -1.0, 0.0);
float2 v1 = SAMPLE_RT(Input0, input.TexCoord - d.xy).rg;
float2 v2 = SAMPLE_RT(Input0, input.TexCoord - d.wy).rg;
float2 v3 = SAMPLE_RT(Input0, input.TexCoord - d.zy).rg;
float2 v4 = SAMPLE_RT(Input0, input.TexCoord - d.xw).rg;
float2 v5 = SAMPLE_RT(Input0, input.TexCoord).rg * cw;
float2 v6 = SAMPLE_RT(Input0, input.TexCoord + d.xw).rg;
float2 v7 = SAMPLE_RT(Input0, input.TexCoord + d.zy).rg;
float2 v8 = SAMPLE_RT(Input0, input.TexCoord + d.wy).rg;
float2 v9 = SAMPLE_RT(Input0, input.TexCoord + d.xy).rg;
float2 va = MaxV(v1, MaxV(v2, v3));
float2 vb = MaxV(v4, MaxV(v5, v6));
float2 vc = MaxV(v7, MaxV(v8, v9));
return float4(MaxV(va, MaxV(vb, vc)) * (1.0f / cw), 0.0f, 0.0f);
}
// Interleaved gradient function from Jimenez 2014
// http://www.iryoku.com/next-generation-post-processing-in-call-of-duty-advanced-warfare
float GradientNoise(float2 uv)
{
uv = floor(uv * GBuffer.ScreenSize.xy);
float f = dot(float2(0.06711056f, 0.00583715f), uv);
return frac(52.9829189f * frac(f));
}
// Returns true or false with a given interval
bool Interval(float phase, float interval)
{
return frac(phase / interval) > 0.499;
}
// Jitter function for tile lookup
float2 JitterTile(float2 uv)
{
float rx, ry;
sincos(GradientNoise(uv + float2(2.0f, 0.0f)) * (2.0f * PI), ry, rx);
return float2(rx, ry) * TexelSizeNM.xy * 0.25f;
}
// Velocity sampling function
float3 SampleVelocity(float2 uv)
{
float3 v = SAMPLE_RT(Input1, uv).xyz;
return float3((v.xy * 2.0f - 1.0f) * MaxBlurRadius, v.z);
}
// Pixel Shader for reconstruction filter (applies the motion blur to the frame)
META_PS(true, FEATURE_LEVEL_ES2)
float4 PS_Reconstruction(Quad_VS2PS input) : SV_Target
{
// Sample at the current location
const float4 color = SAMPLE_RT(Input0, input.TexCoord);
const float3 velocity = SampleVelocity(input.TexCoord);
const float velocityLen = max(length(velocity.xy), 0.5);
const float depthInv = 1.0 / velocity.z;
const float2 velocityMax = SAMPLE_RT(Input2, input.TexCoord + JitterTile(input.TexCoord)).xy;
const float velocityMaxLength = length(velocityMax);
if (velocityMaxLength < 2.0f)
return color;
const float2 velocityWeighted = (velocityLen * 2.0f > velocityMaxLength) ? velocity.xy * (velocityMaxLength / velocityLen) : velocityMax;
// Calculate the amount of samples
const float sc = floor(min(LoopCount, velocityMaxLength * 0.5f));
// Accumlation loop
float backgroudVelocity = max(velocityLen, 1.0f);
const float dt = 1.0f / sc;
const float offsetNoise = (GradientNoise(input.TexCoord) - 0.5f) * dt;
float t = 1.0f - dt * 0.5f;
float count = 0.0f;
float4 sum = 0.0f;
LOOP
while (t > dt * 0.25)
{
// Sampling direction (switched per every two samples)
const float2 sampleVelocity = Interval(count, 4.0) ? velocityWeighted : velocityMax;
// Sample position (inverted per every sample)
const float samplePosition = (Interval(count, 2.0) ? -t : t) + offsetNoise;
// Calculate UVs for the sample position
const float2 sampleUV = input.TexCoord + sampleVelocity * samplePosition * GBuffer.ScreenSize.zw;
// Sample color and velocity with depth
const float3 c = SAMPLE_RT(Input0, sampleUV).rgb;
const float3 velocityDepth = SampleVelocity(sampleUV);
// Length of the velocity vector
const float foreground = saturate((velocity.z - velocityDepth.z) * 20.0f * depthInv);
const float sampleVelocityLength = lerp(backgroudVelocity, length(velocityDepth.xy), foreground);
// Apply color accumulation
float weight = saturate(sampleVelocityLength - (velocityMaxLength * abs(samplePosition))) / sampleVelocityLength * (1.2f - t);
sum += float4(c, 1.0) * weight;
// Calculate the background velocity
backgroudVelocity = max(backgroudVelocity, sampleVelocityLength);
// Move to the next sample
t = Interval(count, 2.0f) ? t - dt : t;
count += 1.0f;
}
// Add the center sample
sum += float4(color.rgb, 1.0f) * (1.2f / (backgroudVelocity * sc * 2.0f));
return float4(sum.rgb / sum.a, color.a);
}
+1 -1
View File
@@ -65,7 +65,7 @@ float4 PS_FilterFace(Quad_VS2PS input) : SV_Target
#define NUM_FILTER_SAMPLES 512
float3 N = normalize(cubeCoordinates);
float roughness = ComputeReflectionCaptureRoughnessFromMip(SourceMipIndex);
float roughness = ProbeRoughnessFromMip(SourceMipIndex);
float4 filteredColor = 0;
float weight = 0;
+2 -143
View File
@@ -1,151 +1,10 @@
// Copyright (c) 2012-2020 Wojciech Figat. All rights reserved.
#include "./Flax/Common.hlsl"
#include "./Flax/GammaCorrectionCommon.hlsl"
#define USE_TONEMAP 0
META_CB_BEGIN(0, Data)
float4 ScreenSize;// x-width, y-height, z-1/width, w-1/height
float4 TaaJitterStrength; // x, y, x/width, y/height
float4 FinalBlendParameters; // x: static, y: dynamic, z: motion amplification, w; sharpness
META_CB_END
Texture2D Input : register(t0);
Texture2D InputHistory : register(t1);
Texture2D MotionVectors : register(t2);
Texture2D Depth : register(t3);
float3 Fetch(Texture2D tex, float2 coords)
{
return tex.SampleLevel(SamplerLinearClamp, coords, 0).rgb;
}
float3 Map(float3 x)
{
#if USE_TONEMAP
return FastTonemap(x);
#else
return x;
#endif
}
float3 Unmap(float3 x)
{
#if USE_TONEMAP
return FastTonemapInvert(x);
#else
return x;
#endif
}
float3 ClipToAABB(float3 color, float3 minimum, float3 maximum)
{
// Note: only clips towards aabb center (but fast!)
float3 center = 0.5 * (maximum + minimum);
float3 extents = 0.5 * (maximum - minimum);
// This is actually `distance`, however the keyword is reserved
float3 offset = color - center;
float3 ts = abs(extents / max(offset, 0.0001));
float t = saturate(min(min(ts.x, ts.y), ts.z));
return center + offset * t;
}
float2 GetClosestFragment(float2 uv)
{
const float2 k = ScreenSize.zw;
const float4 neighborhood = float4(
SAMPLE_RT(Depth, uv - k).r,
SAMPLE_RT(Depth, uv + float2(k.x, -k.y)).r,
SAMPLE_RT(Depth, uv + float2(-k.x, k.y)).r,
SAMPLE_RT(Depth, uv + k).r
);
#if defined(REVERSED_Z)
#define COMPARE_DEPTH(a, b) step(b, a)
#else
#define COMPARE_DEPTH(a, b) step(a, b)
#endif
float3 result = float3(0.0, 0.0, SAMPLE_RT(Depth, uv).r);
result = lerp(result, float3(-1.0, -1.0, neighborhood.x), COMPARE_DEPTH(neighborhood.x, result.z));
result = lerp(result, float3( 1.0, -1.0, neighborhood.y), COMPARE_DEPTH(neighborhood.y, result.z));
result = lerp(result, float3(-1.0, 1.0, neighborhood.z), COMPARE_DEPTH(neighborhood.z, result.z));
result = lerp(result, float3( 1.0, 1.0, neighborhood.w), COMPARE_DEPTH(neighborhood.w, result.z));
return (uv + result.xy * k);
}
// Pixel Shader for Temporal Anti-Aliasing
META_PS(true, FEATURE_LEVEL_ES2)
META_PERMUTATION_1(IS_ORTHO=0)
META_PERMUTATION_1(IS_ORTHO=1)
void PS(Quad_VS2PS input, out float4 output : SV_Target0, out float4 outputHistory : SV_Target1)
float4 PS(Quad_VS2PS input) : SV_Target0
{
float2 jitter = TaaJitterStrength.zw;
float2 texcoord = input.TexCoord;
const float2 k = ScreenSize.zw;
#if IS_ORTHO
float2 closest = texcoord;
#else
float2 closest = GetClosestFragment(texcoord);
#endif
// Sample velocity
float2 velocity = MotionVectors.SampleLevel(SamplerLinearClamp, closest, 0).xy;
// Sample color and surround
float2 uv = texcoord - jitter;
float3 color = Fetch(Input, uv);
float3 topLeft = Fetch(Input, uv - k);
float3 bottomRight = Fetch(Input, uv + k);
float3 topRight = Fetch(Input, uv + float2(k.x, -k.y));
float3 bottomLeft = Fetch(Input, uv + float2(-k.x, k.y));
float3 corners = 4.0 * (topLeft + bottomRight) - 2.0 * color;
// Sharpen output
float sharpness = FinalBlendParameters.w;
float3 blur = (topLeft + topRight + bottomLeft + bottomRight) * 0.25;
color += (color - blur) * sharpness;
color = clamp(color, 0.0, HDR_CLAMP_MAX);
// Tonemap color
float3 average = Map((corners + color) / 7.0);
topLeft = Map(topLeft);
bottomRight = Map(bottomRight);
color = Map(color);
// Sample history
float3 history = Fetch(InputHistory, texcoord - velocity);
history = Map(history);
float colorLuma = Luminance(color);
float averageLuma = Luminance(average);
float velocityLength = length(velocity);
float nudge = lerp(4.0, 0.25, velocityLength * 100.0) * abs(averageLuma - colorLuma);
float3 minimum = min(bottomRight, topLeft) - nudge;
float3 maximum = max(topLeft, bottomRight) + nudge;
// Clip history sample
history = ClipToAABB(history, minimum, maximum);
// Blend color with history
//float historyLuma = Luminance(history);
//float weight = 1.0f - saturate(abs(colorLuma - historyLuma) / max(max(colorLuma, historyLuma), 0.2));
float weight = saturate(velocityLength * FinalBlendParameters.z);
float feedback = lerp(FinalBlendParameters.x, FinalBlendParameters.y, weight * weight);
//feedback = lerp(feedback, 0.02, velocityWeight);
color = Unmap(lerp(color, history, feedback));
color = clamp(color, 0.0, HDR_CLAMP_MAX);
output = float4(color, 1);
outputHistory = output;
//output = float4(1, 0, 0, 1) * feedback;
return float4(0, 0, 0, 0);
}
+82 -107
View File
@@ -61,7 +61,7 @@ META_CB_END
META_CB_BEGIN(1, PerLight)
float2 Dummy1;
int MinZ; // Z index of the minimum slice in the range
int MinZ;
float LocalLightScatteringIntensity;
float4 ViewSpaceBoundingSphere;
@@ -72,48 +72,44 @@ LightShadowData LocalLightShadow;
META_CB_END
float ComputeDepthFromZSlice(float zSlice)
{
return (zSlice / GridSize.z) * VolumetricFogMaxDistance;
}
float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth)
{
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
sceneDepth = ComputeDepthFromZSlice(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar;
float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth);
return GetWorldPos(GBuffer, volumeUV, deviceDepth);
}
float3 ComputeCellWorldPosition(uint3 gridCoordinate, float3 cellOffset)
{
float unused;
return ComputeCellWorldPosition(gridCoordinate, cellOffset, unused);
}
float ComputeNormalizedZSliceFromDepth(float sceneDepth)
{
return sceneDepth / VolumetricFogMaxDistance;
}
float3 ComputeVolumeUV(float3 worldPosition, float4x4 worldToClip)
{
float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip);
ndcPosition.xy /= ndcPosition.w;
return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ComputeNormalizedZSliceFromDepth(ndcPosition.w));
}
// The Henyey-Greenstein phase function
// [Henyey and Greenstein 1941, https://www.astro.umd.edu/~jph/HG_note.pdf]
float HenyeyGreensteinPhase(float g, float cosTheta)
{
return (1 - g * g) / (4 * PI * pow(1 + g * g + 2 * g * cosTheta, 1.5f));
}
// +g = forward scattering, 0=g = isotropic, -g = backward scattering
float PhaseFunction(float g, float cosTheta)
float GetPhase(float g, float cosTheta)
{
return HenyeyGreensteinPhase(g, cosTheta);
}
float GetSliceDepth(float zSlice)
{
return (zSlice / GridSize.z) * VolumetricFogMaxDistance;
}
float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset, out float sceneDepth)
{
float2 volumeUV = (gridCoordinate.xy + cellOffset.xy) / GridSize.xy;
sceneDepth = GetSliceDepth(gridCoordinate.z + cellOffset.z) / GBuffer.ViewFar;
float deviceDepth = LinearZ2DeviceDepth(GBuffer, sceneDepth);
return GetWorldPos(GBuffer, volumeUV, deviceDepth);
}
float3 GetCellPositionWS(uint3 gridCoordinate, float3 cellOffset)
{
float temp;
return GetCellPositionWS(gridCoordinate, cellOffset, temp);
}
float3 GetVolumeUV(float3 worldPosition, float4x4 worldToClip)
{
float4 ndcPosition = mul(float4(worldPosition, 1), worldToClip);
ndcPosition.xy /= ndcPosition.w;
return float3(ndcPosition.xy * float2(0.5f, -0.5f) + 0.5f, ndcPosition.w / VolumetricFogMaxDistance);
}
// Vertex shader that writes to a range of slices of a volume texture
META_VS(true, FEATURE_LEVEL_SM5)
META_FLAG(VertexToGeometryShader)
@@ -123,22 +119,18 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins
Quad_VS2GS output;
uint slice = LayerIndex + MinZ;
float sliceDepth = ComputeDepthFromZSlice(slice);
float sliceDepthOffset = abs(sliceDepth - ViewSpaceBoundingSphere.z);
float depth = GetSliceDepth(slice);
float depthOffset = abs(depth - ViewSpaceBoundingSphere.z);
if (sliceDepthOffset < ViewSpaceBoundingSphere.w)
if (depthOffset < ViewSpaceBoundingSphere.w)
{
// Compute the radius of the circle formed by the intersection of the bounding sphere and the current depth slice
float sliceRadius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - sliceDepthOffset * sliceDepthOffset);
// Place the quad vertex to tightly bound the circle
float3 viewSpaceVertexPosition = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * sliceRadius, sliceDepth);
output.Vertex.Position = mul(float4(viewSpaceVertexPosition, 1), ViewToVolumeClip);
float radius = sqrt(ViewSpaceBoundingSphere.w * ViewSpaceBoundingSphere.w - depthOffset * depthOffset);
float3 positionVS = float3(ViewSpaceBoundingSphere.xy + (TexCoord * 2 - 1) * radius, depth);
output.Vertex.Position = mul(float4(positionVS, 1), ViewToVolumeClip);
}
else
{
// Slice does not intersect bounding sphere, emit degenerate triangle
output.Vertex.Position = 0;
output.Vertex.Position = float4(0, 0, 0, 0);
}
output.Vertex.TexCoord = 0;
@@ -150,23 +142,21 @@ Quad_VS2GS VS_WriteToSlice(float2 TexCoord : TEXCOORD0, uint LayerIndex : SV_Ins
// Geometry shader that writes to a range of slices of a volume texture
META_GS(true, FEATURE_LEVEL_SM5)
[maxvertexcount(3)]
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> OutStream)
void GS_WriteToSlice(triangle Quad_VS2GS input[3], inout TriangleStream<Quad_GS2PS> stream)
{
Quad_GS2PS vertex0;
vertex0.Vertex = input[0].Vertex;
vertex0.LayerIndex = input[0].LayerIndex;
Quad_GS2PS vertex;
Quad_GS2PS vertex1;
vertex1.Vertex = input[1].Vertex;
vertex1.LayerIndex = input[1].LayerIndex;
vertex.Vertex = input[0].Vertex;
vertex.LayerIndex = input[0].LayerIndex;
stream.Append(vertex);
Quad_GS2PS vertex2;
vertex2.Vertex = input[2].Vertex;
vertex2.LayerIndex = input[2].LayerIndex;
vertex.Vertex = input[1].Vertex;
vertex.LayerIndex = input[1].LayerIndex;
stream.Append(vertex);
OutStream.Append(vertex0);
OutStream.Append(vertex1);
OutStream.Append(vertex2);
vertex.Vertex = input[2].Vertex;
vertex.LayerIndex = input[2].LayerIndex;
stream.Append(vertex);
}
#if USE_SHADOW
@@ -208,18 +198,16 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
return 0;
#if USE_TEMPORAL_REPROJECTION
float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip);
float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip);
float historyAlpha = HistoryWeight;
FLATTEN
if (any(historyUV < 0) || any(historyUV > 1))
{
historyAlpha = 0;
}
uint numSuperSamples = historyAlpha < .001f ? HistoryMissSuperSampleCount : 1;
uint samplesCount = historyAlpha < 0.001f ? HistoryMissSuperSampleCount : 1;
#else
uint numSuperSamples = 1;
uint samplesCount = 1;
#endif
float3 L = 0;
@@ -229,22 +217,19 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
float lightRadiusMask = 1;
float spotAttenuation = 1;
bool isSpotLight = LocalLight.SpotAngles.x > -2.0f;
float4 scattering = 0;
for (uint sampleIndex = 0; sampleIndex < numSuperSamples; sampleIndex++)
for (uint sampleIndex = 0; sampleIndex < samplesCount; sampleIndex++)
{
float3 cellOffset = FrameJitterOffsets[sampleIndex].xyz;
//float cellOffset = 0.5f;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset);
float3 cameraVector = normalize(worldPosition - GBuffer.ViewPos);
float cellRadius = length(worldPosition - ComputeCellWorldPosition(gridCoordinate + uint3(1, 1, 1), cellOffset));
// Bias the inverse squared light falloff based on voxel size to prevent aliasing near the light source
float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset);
float3 cameraVector = normalize(positionWS - GBuffer.ViewPos);
float cellRadius = length(positionWS - GetCellPositionWS(gridCoordinate + uint3(1, 1, 1), cellOffset));
float distanceBias = max(cellRadius * InverseSquaredLightDistanceBiasScale, 1);
// Get the light attenuation
GetRadialLightAttenuation(LocalLight, isSpotLight, worldPosition, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
// Calculate the light attenuation
GetRadialLightAttenuation(LocalLight, isSpotLight, positionWS, float3(0, 0, 1), distanceBias * distanceBias, toLight, L, NoL, distanceAttenuation, lightRadiusMask, spotAttenuation);
float combinedAttenuation = distanceAttenuation * lightRadiusMask * spotAttenuation;
// Peek the shadow
@@ -252,16 +237,14 @@ float4 PS_InjectLight(Quad_GS2PS input) : SV_Target0
#if USE_SHADOW
if (combinedAttenuation > 0)
{
shadowFactor = ComputeVolumeShadowing(worldPosition, isSpotLight);
shadowFactor = ComputeVolumeShadowing(positionWS, isSpotLight);
}
#endif
scattering.rgb += LocalLight.Color * (PhaseFunction(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity);
scattering.rgb += LocalLight.Color * (GetPhase(PhaseG, dot(L, -cameraVector)) * combinedAttenuation * shadowFactor * LocalLightScatteringIntensity);
}
// Normalize
scattering.rgb /= (float)numSuperSamples;
scattering.rgb /= (float)samplesCount;
return scattering;
}
@@ -280,7 +263,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa
// Center of the voxel
float voxelOffset = 0.5f;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, voxelOffset);
float3 positionWS = GetCellPositionWS(gridCoordinate, voxelOffset);
// Unpack the fog parameters (packing done in C++ ExponentialHeightFog::GetVolumetricFogOptions)
float fogDensity = FogParameters.x;
@@ -288,7 +271,7 @@ void CS_Initialize(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_Dispa
float fogHeightFalloff = FogParameters.z;
// Calculate the global fog density that matches the exponential height fog density
float globalDensity = fogDensity * exp2(-fogHeightFalloff * (worldPosition.y - fogHeight));
float globalDensity = fogDensity * exp2(-fogHeightFalloff * (positionWS.y - fogHeight));
float matchFactor = 0.24f;
float extinction = max(globalDensity * GlobalExtinctionScale * matchFactor, 0);
@@ -326,7 +309,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
uint numSuperSamples = 1;
#if USE_TEMPORAL_REPROJECTION
float3 historyUV = ComputeVolumeUV(ComputeCellWorldPosition(gridCoordinate, 0.5f), PrevWorldToClip);
float3 historyUV = GetVolumeUV(GetCellPositionWS(gridCoordinate, 0.5f), PrevWorldToClip);
float historyAlpha = HistoryWeight;
// Discard history if it lays outside the current view
@@ -347,8 +330,8 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
//float3 cellOffset = 0.5f;
float sceneDepth;
float3 worldPosition = ComputeCellWorldPosition(gridCoordinate, cellOffset, sceneDepth);
float3 cameraVector = worldPosition - GBuffer.ViewPos;
float3 positionWS = GetCellPositionWS(gridCoordinate, cellOffset, sceneDepth);
float3 cameraVector = positionWS - GBuffer.ViewPos;
float cameraVectorLength = length(cameraVector);
float3 cameraVectorNormalized = cameraVector / cameraVectorLength;
@@ -360,10 +343,10 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_
float shadow = 1;
if (DirectionalLightShadow.NumCascades > 0)
{
shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, worldPosition, cameraVectorLength);
shadow = SampleShadow(DirectionalLight, DirectionalLightShadow, ShadowMapCSM, positionWS, cameraVectorLength);
}
lightScattering += DirectionalLight.Color * (8 * shadow * PhaseFunction(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized)));
lightScattering += DirectionalLight.Color * (8 * shadow * GetPhase(PhaseG, dot(DirectionalLight.Direction, cameraVectorNormalized)));
}
// Sky light
@@ -414,38 +397,30 @@ META_CS(true, FEATURE_LEVEL_SM5)
void CS_FinalIntegration(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_DispatchThreadID, uint3 GroupThreadId : SV_GroupThreadID)
{
uint3 gridCoordinate = DispatchThreadId;
float4 accumulatedLightingAndTransmittance = float4(0, 0, 0, 1);
float3 previousSliceWorldPosition = GBuffer.ViewPos;
float4 acc = float4(0, 0, 0, 1);
float3 prevPositionWS = GBuffer.ViewPos;
for (uint layerIndex = 0; layerIndex < GridSizeInt.z; layerIndex++)
{
uint3 layerCoordinate = uint3(gridCoordinate.xy, layerIndex);
float4 scatteringAndExtinction = LightScattering[layerCoordinate];
float3 layerWorldPosition = ComputeCellWorldPosition(layerCoordinate, 0.5f);
float stepLength = length(layerWorldPosition - previousSliceWorldPosition);
previousSliceWorldPosition = layerWorldPosition;
float transmittance = exp(-scatteringAndExtinction.w * stepLength);
uint3 coords = uint3(gridCoordinate.xy, layerIndex);
float4 scatteringExtinction = LightScattering[coords];
float3 positionWS = GetCellPositionWS(coords, 0.5f);
// Ref: "Physically Based and Unified Volumetric Rendering in Frostbite"
#define ENERGY_CONSERVING_INTEGRATION 1
#if ENERGY_CONSERVING_INTEGRATION
float3 scatteringIntegratedOverSlice = (scatteringAndExtinction.rgb - scatteringAndExtinction.rgb * transmittance) / max(scatteringAndExtinction.w, .00001f);
accumulatedLightingAndTransmittance.rgb += scatteringIntegratedOverSlice * accumulatedLightingAndTransmittance.a;
#else
accumulatedLightingAndTransmittance.rgb += scatteringAndExtinction.rgb * accumulatedLightingAndTransmittance.a;
#endif
accumulatedLightingAndTransmittance.a *= transmittance;
float transmittance = exp(-scatteringExtinction.w * length(positionWS - prevPositionWS));
float3 scatteringIntegratedOverSlice = (scatteringExtinction.rgb - scatteringExtinction.rgb * transmittance) / max(scatteringExtinction.w, 0.00001f);
acc.rgb += scatteringIntegratedOverSlice * acc.a;
acc.a *= transmittance;
#if DEBUG_VOXELS
RWIntegratedLightScattering[layerCoordinate] = float4(scatteringAndExtinction.rgb, 1.0f);
RWIntegratedLightScattering[coords] = float4(scatteringExtinction.rgb, 1.0f);
#elif DEBUG_VOXEL_WS_POS
RWIntegratedLightScattering[layerCoordinate] = float4(layerWorldPosition.rgb, 1.0f);
RWIntegratedLightScattering[coords] = float4(positionWS.rgb, 1.0f);
#else
RWIntegratedLightScattering[layerCoordinate] = accumulatedLightingAndTransmittance;
RWIntegratedLightScattering[coords] = acc;
#endif
prevPositionWS = positionWS;
}
}
+33
View File
@@ -0,0 +1,33 @@
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2017, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 homepage : http://www.lz4.org
- LZ4 source repository : https://github.com/lz4/lz4
*/
+1
View File
@@ -13,5 +13,6 @@ public class lz4 : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.BSD2Clause;
LicenseFilePath = "LICENSE.txt";
}
}
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Mikulas Florek
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.
+1
View File
@@ -13,5 +13,6 @@ public class OpenFBX : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "LICENSE.txt";
}
}
+29
View File
@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2013-2014, Adswerve, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -14,6 +14,7 @@ public class UniversalAnalytics : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.BSD3Clause;
LicenseFilePath = "LICENSE.txt";
}
/// <inheritdoc />
+1
View File
@@ -15,6 +15,7 @@ public class fmt : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.BSD2Clause;
LicenseFilePath = "cppformat license.txt";
}
/// <inheritdoc />
@@ -13,5 +13,6 @@ public class meshoptimizer : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "LICENSE.md";
}
}
+1
View File
@@ -13,5 +13,6 @@ public class pugixml : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "pugixml license.txt";
}
}
+1
View File
@@ -15,6 +15,7 @@ public class rapidjson : HeaderOnlyModule
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "RapidJSON license.txt";
}
/// <inheritdoc />
@@ -13,5 +13,6 @@ public class recastnavigation : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.zLib;
LicenseFilePath = "License.txt";
}
}
+19
View File
@@ -0,0 +1,19 @@
Copyright (c) 2018-2019 Arseny Kapoulkine
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.
+1
View File
@@ -14,6 +14,7 @@ public class volk : ThirdPartyModule
base.Init();
LicenseType = LicenseTypes.MIT;
LicenseFilePath = "LICENSE.txt";
}
/// <inheritdoc />
@@ -199,9 +199,9 @@ namespace Flax.Build
// Perform license validation
if (LicenseType == LicenseTypes.Invalid)
throw new Exception(string.Format("Cannot build module {0}. Third Party modules must have license type specified.", Name));
if (LicenseType == LicenseTypes.Custom && LicenseFilePath == null)
throw new Exception(string.Format("Cannot build module {0}. Third Party modules with Custom license must have license file specified.", Name));
if (LicenseFilePath != null && !File.Exists(Path.Combine(FolderPath, LicenseFilePath)))
if (LicenseFilePath == null)
throw new Exception(string.Format("Cannot build module {0}. Third Party modules must have license file specified.", Name));
if (!File.Exists(Path.Combine(FolderPath, LicenseFilePath)))
throw new Exception(string.Format("Cannot build module {0}. Specified license file does not exist.", Name));
}