You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Disabled by default, need a movable skylight with r.DistanceFieldGI enabled at load time (ConsoleVariables.ini) * Surfels (oriented disks) are placed on mesh surfaces and capture diffuse color by evaluating the material with actual UVs and world position * Surfels are lit and shadowed by ray tracing through mesh distance fields (directional light only so far) * Irradiance cache records are lit with nearby Virtual Point Lights created from lit surfels. Only using camera based LOD of the surfel representation and object based surfel culling, no hierarchy yet. * Shadowing of the VPLs is provided by distance field cone tracing. A depth visibility function is constructed along each of the 9 cone trace directions, and used to shadow the incoming VPL lighting. * Component reregistration and transform updating causes surfels to be generated again which can be slow. In the future only the material needs to be re-evaluated. * Geometry shaders with stream out are now supported, by implementing FShader::GetStreamOutElements * Compute shaders can now evaluate materal attributes like BaseColor * SkyLight MaxOcclusionDistance increased to 10m, which is the minimum useful amount for GI [CL 2424208 by Daniel Wright in Main branch]
235 lines
8.5 KiB
Plaintext
235 lines
8.5 KiB
Plaintext
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
SurfelTree.usf
|
|
=============================================================================*/
|
|
|
|
#include "Common.usf"
|
|
#include "DeferredShadingCommon.usf"
|
|
#include "DistanceFieldLightingShared.usf"
|
|
#include "DistanceFieldAOShared.usf"
|
|
#include "MonteCarlo.usf"
|
|
|
|
uint NumSurfels;
|
|
RWBuffer<float4> RWCopyInterpolatedVertexData;
|
|
RWBuffer<float4> RWCopySurfelData;
|
|
Buffer<float4> InterpolatedVertexData;
|
|
|
|
[numthreads(UPDATEOBJECTS_THREADGROUP_SIZE, 1, 1)]
|
|
void CopySurfelBufferCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint CopyOperationIndex = DispatchThreadId.x;
|
|
|
|
if (CopyOperationIndex < NumSurfels)
|
|
{
|
|
uint SourceIndex = CopyOperationIndex;
|
|
uint DestIndex = CopyOperationIndex;
|
|
|
|
UNROLL
|
|
for (uint VectorIndex = 0; VectorIndex < INTERPOLATED_VERTEX_DATA_STRIDE; VectorIndex++)
|
|
{
|
|
RWCopyInterpolatedVertexData[DestIndex * INTERPOLATED_VERTEX_DATA_STRIDE + VectorIndex] = InterpolatedVertexData[SourceIndex * INTERPOLATED_VERTEX_DATA_STRIDE + VectorIndex];
|
|
}
|
|
|
|
UNROLL
|
|
for (uint VectorIndex = 0; VectorIndex < SURFEL_DATA_STRIDE; VectorIndex++)
|
|
{
|
|
RWCopySurfelData[DestIndex * SURFEL_DATA_STRIDE + VectorIndex] = SurfelData[SourceIndex * SURFEL_DATA_STRIDE + VectorIndex];
|
|
}
|
|
}
|
|
}
|
|
|
|
Buffer<float4> VPLFlux;
|
|
RWBuffer<float4> RWCopyVPLFlux;
|
|
|
|
[numthreads(UPDATEOBJECTS_THREADGROUP_SIZE, 1, 1)]
|
|
void CopyVPLFluxBufferCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint CopyOperationIndex = DispatchThreadId.x;
|
|
|
|
if (CopyOperationIndex < NumSurfels)
|
|
{
|
|
uint SourceIndex = CopyOperationIndex;
|
|
uint DestIndex = CopyOperationIndex;
|
|
|
|
RWCopyVPLFlux[DestIndex] = VPLFlux[SourceIndex];
|
|
}
|
|
}
|
|
|
|
// In float's, must match FConvertToUniformMeshVertex and ComputeUniformVertexStride()
|
|
#define TRIANGLE_VERTEX_DATA_STRIDE 24
|
|
|
|
uint NumTriangles;
|
|
Buffer<float> TriangleVertexData;
|
|
|
|
float LoadVertexAttribute(uint TriangleIndex, uint VertexIndex, uint AttributeIndex)
|
|
{
|
|
return TriangleVertexData[(TriangleIndex * 3 + VertexIndex) * TRIANGLE_VERTEX_DATA_STRIDE + AttributeIndex];
|
|
}
|
|
|
|
RWBuffer<float> RWTriangleAreas;
|
|
|
|
[numthreads(THREADGROUP_TOTALSIZE, 1, 1)]
|
|
void ComputeTriangleAreasCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint TriangleIndex = DispatchThreadId.x;
|
|
|
|
if (TriangleIndex < NumTriangles)
|
|
{
|
|
float3 Position0 = float3(LoadVertexAttribute(TriangleIndex, 0, 0), LoadVertexAttribute(TriangleIndex, 0, 1), LoadVertexAttribute(TriangleIndex, 0, 2));
|
|
float3 Position1 = float3(LoadVertexAttribute(TriangleIndex, 1, 0), LoadVertexAttribute(TriangleIndex, 1, 1), LoadVertexAttribute(TriangleIndex, 1, 2));
|
|
float3 Position2 = float3(LoadVertexAttribute(TriangleIndex, 2, 0), LoadVertexAttribute(TriangleIndex, 2, 1), LoadVertexAttribute(TriangleIndex, 2, 2));
|
|
|
|
float3 TriangleNormal = cross(Position2 - Position0, Position1 - Position0);
|
|
float TriangleArea = .5f * length(TriangleNormal);
|
|
RWTriangleAreas[TriangleIndex] = TriangleArea;
|
|
}
|
|
}
|
|
|
|
Buffer<float> TriangleAreas;
|
|
RWBuffer<float> RWTriangleCDFs;
|
|
|
|
[numthreads(THREADGROUP_TOTALSIZE, 1, 1)]
|
|
void ComputeTriangleCDFsCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint TriangleIndex = DispatchThreadId.x;
|
|
|
|
if (TriangleIndex < NumTriangles)
|
|
{
|
|
float Integral = 0;
|
|
|
|
for (int i = 0; i <= TriangleIndex; i++)
|
|
{
|
|
Integral += TriangleAreas[i];
|
|
}
|
|
|
|
RWTriangleCDFs[TriangleIndex] = Integral;
|
|
}
|
|
}
|
|
|
|
float InterpolateAttribute(uint TriangleIndex, float3 BarycentricCoordinates, uint AttributeIndex)
|
|
{
|
|
float Attribute = BarycentricCoordinates.x * LoadVertexAttribute(TriangleIndex, 0, AttributeIndex)
|
|
+ BarycentricCoordinates.y * LoadVertexAttribute(TriangleIndex, 1, AttributeIndex)
|
|
+ BarycentricCoordinates.z * LoadVertexAttribute(TriangleIndex, 2, AttributeIndex);
|
|
|
|
return Attribute;
|
|
}
|
|
|
|
float4 InterpolateFloat4Attribute(uint TriangleIndex, float3 BarycentricCoordinates, uint StartAttributeIndex)
|
|
{
|
|
float4 SampleValues;
|
|
SampleValues.x = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 0);
|
|
SampleValues.y = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 1);
|
|
SampleValues.z = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 2);
|
|
SampleValues.w = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 3);
|
|
return SampleValues;
|
|
}
|
|
|
|
float3 InterpolateFloat3Attribute(uint TriangleIndex, float3 BarycentricCoordinates, uint StartAttributeIndex)
|
|
{
|
|
float3 SampleValues;
|
|
SampleValues.x = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 0);
|
|
SampleValues.y = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 1);
|
|
SampleValues.z = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 2);
|
|
return SampleValues;
|
|
}
|
|
|
|
float2 InterpolateFloat2Attribute(uint TriangleIndex, float3 BarycentricCoordinates, uint StartAttributeIndex)
|
|
{
|
|
float2 SampleValues;
|
|
SampleValues.x = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 0);
|
|
SampleValues.y = InterpolateAttribute(TriangleIndex, BarycentricCoordinates, StartAttributeIndex + 1);
|
|
return SampleValues;
|
|
}
|
|
|
|
Buffer<float> TriangleCDFs;
|
|
|
|
float SampleTrianglesProportionalToArea(float RandomFraction, float TotalArea)
|
|
{
|
|
float Sample = .999f;
|
|
int ElementIndex = -1;
|
|
|
|
// Find the index of where the step function becomes greater or equal to the generated number
|
|
//@todo - CDFArray is monotonically increasing so we can do better than a linear time search
|
|
for (int i = 0; i < NumTriangles; i++)
|
|
{
|
|
if (RandomFraction * TotalArea <= TriangleCDFs[i])
|
|
{
|
|
ElementIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (ElementIndex >= 0)
|
|
{
|
|
Sample = ElementIndex / (float)NumTriangles;
|
|
}
|
|
|
|
return Sample;
|
|
}
|
|
|
|
uint SurfelStartIndex;
|
|
uint NumSurfelsToGenerate;
|
|
RWBuffer<float4> RWInterpolatedVertexData;
|
|
|
|
[numthreads(THREADGROUP_TOTALSIZE, 1, 1)]
|
|
void SampleTrianglesCS(
|
|
uint3 GroupId : SV_GroupID,
|
|
uint3 DispatchThreadId : SV_DispatchThreadID,
|
|
uint3 GroupThreadId : SV_GroupThreadID)
|
|
{
|
|
uint SurfelIndex = DispatchThreadId.x;
|
|
|
|
if (SurfelIndex < NumSurfelsToGenerate)
|
|
{
|
|
//@todo - 1d uniform
|
|
float Uniform = SurfelIndex / (float)NumSurfelsToGenerate;
|
|
float TotalArea = TriangleCDFs[NumTriangles - 1];
|
|
|
|
//uint TriangleIndex = (uint)(Uniform * NumTriangles);
|
|
uint TriangleIndex = (uint)(SampleTrianglesProportionalToArea(Uniform, TotalArea) * NumTriangles);
|
|
|
|
float2 Uniforms = frac(Square((SurfelIndex + 15) / (float)NumSurfelsToGenerate + 10) * float2(1361.456345, 2333.578));
|
|
//float2 Uniforms = Hammersley(SurfelIndex, NumSurfelsToGenerate, uint2(0, 0));
|
|
|
|
float SqrtUniform0 = sqrt(Uniforms.x);
|
|
float3 BarycentricCoordinates = float3(1 - SqrtUniform0, SqrtUniform0 * Uniforms.y, SqrtUniform0 * (1 - Uniforms.y));
|
|
//BarycentricCoordinates = float3(1, 0, 0);
|
|
|
|
float DiskArea = TotalArea / NumSurfelsToGenerate;
|
|
float DiskRadius = sqrt(DiskArea / PI);
|
|
//float DiskRadius = 30;
|
|
float4 PositionAndRadius = float4(InterpolateFloat3Attribute(TriangleIndex, BarycentricCoordinates, 0), DiskRadius);
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 0] = PositionAndRadius;
|
|
|
|
float3 Tangent0 = InterpolateFloat3Attribute(TriangleIndex, BarycentricCoordinates, 4);
|
|
float3 Tangent1 = InterpolateFloat3Attribute(TriangleIndex, BarycentricCoordinates, 7);
|
|
float3 Tangent2 = InterpolateFloat3Attribute(TriangleIndex, BarycentricCoordinates, 10);
|
|
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 1] = float4(Tangent0, 0);
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 2] = float4(Tangent1, 0);
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 3] = float4(Tangent2, 0);
|
|
|
|
float2 UV0 = InterpolateFloat2Attribute(TriangleIndex, BarycentricCoordinates, 13);
|
|
float2 UV1 = InterpolateFloat2Attribute(TriangleIndex, BarycentricCoordinates, 15);
|
|
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 4] = float4(UV0, UV1);
|
|
|
|
float4 VertexColor = InterpolateFloat4Attribute(TriangleIndex, BarycentricCoordinates, 17);
|
|
|
|
RWInterpolatedVertexData[(SurfelStartIndex + SurfelIndex) * INTERPOLATED_VERTEX_DATA_STRIDE + 5] = VertexColor;
|
|
}
|
|
} |