You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Sparse Volume Texture asset from imported OpenVDB (only a single float channel for now). Static or animated sequence. It will be possible to generate SVT at runtime from GPU later. Using FEditorBulkData for handling raw source without loading everything when not caching or cooking. BulkData used at runtime for loading. No streaming yet. Importer with dependency on OpenVDB is in a SparseVolumeTexture module only loaded when in editor Sparse volume texture can be sampled from any materials (sample, sample parameter) and overridden on material instance and material instance dynamic. Added support for uint in compiler (fetch from page table, see SparseVolumeTextureGetVoxelCoord) Volume texture with u8 VirtualTextureLayerIndex!=255 (INDEX_NONE) are sparse texture. The layer index then represent what texture/attribute to sample. #preflight https://horde.devtools.epicgames.com/job/6346a466f93be0f6345af86c #rb Patrick.Kelly, Charles.deRousiers [CL 22551963 by sebastien hillaire in ue5-main branch]
193 lines
5.3 KiB
Plaintext
193 lines
5.3 KiB
Plaintext
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
VisualizeSparseVolumeTexture.usf: Used to visualize and debug a sparse texture asset.
|
|
=============================================================================*/
|
|
|
|
#include "/Engine/Private/Common.ush"
|
|
|
|
|
|
#ifdef VERTEX_SHADER
|
|
|
|
float DepthAsDeviceZ;
|
|
|
|
void VisualizeSparseVolumeTextureVS(
|
|
in uint VertexId : SV_VertexID,
|
|
out float4 Position : SV_POSITION)
|
|
{
|
|
float2 UV = -1.0f;
|
|
UV = VertexId == 1 ? float2(-1.0f, 3.0f) : UV;
|
|
UV = VertexId == 2 ? float2(3.0f, -1.0f) : UV;
|
|
|
|
Position = float4(UV, DepthAsDeviceZ, 1.0f);
|
|
}
|
|
|
|
#endif // VERTEX_SHADER
|
|
|
|
|
|
#ifdef PIXEL_SHADER
|
|
|
|
// Updated from http://jcgt.org/published/0007/03/04/
|
|
bool Slabs(float3 p0, float3 p1, float3 rayOrigin, float3 invRaydir, out float outTMin, out float outTMax)
|
|
{
|
|
float3 t0 = (p0 - rayOrigin) * invRaydir;
|
|
float3 t1 = (p1 - rayOrigin) * invRaydir;
|
|
float3 tmin = min(t0, t1), tmax = max(t0, t1);
|
|
float maxtmin = max(max(tmin.x, tmin.y), tmin.z);
|
|
float mintmax = min(min(tmax.x, tmax.y), tmax.z);
|
|
outTMin = maxtmin;
|
|
outTMax = mintmax;
|
|
return maxtmin <= mintmax;
|
|
}
|
|
|
|
float3 VolumeBoundMinWorld;
|
|
float3 VolumeBoundMaxWorld;
|
|
|
|
|
|
Texture3D<float4> SparseVolumeTexture;
|
|
float3 SparseVolumeTextureResolution;
|
|
|
|
Texture3D<uint> SparseVolumeTexturePageTable;
|
|
float3 SparseVolumeTexturePageTableResolution;
|
|
|
|
#define SPARSE_VOLUME_TILE_RES 16
|
|
|
|
void VisualizeSparseVolumeTexturePS(
|
|
in float4 SVPos : SV_POSITION,
|
|
out float4 OutLuminanceAlpha : SV_Target0
|
|
)
|
|
{
|
|
ResolvedView = ResolveView();
|
|
const uint2 PixelCoord = uint2(SVPos.xy);
|
|
float2 UvBuffer = PixelCoord * View.BufferSizeAndInvSize.zw; // Uv for depth buffer read (size can be larger than viewport)
|
|
|
|
float2 ScreenPosition = SvPositionToScreenPosition(SVPos).xy;
|
|
const float Depth = 10000.0f;
|
|
float4 TranslatedWorldPos = mul(float4(ScreenPosition * Depth, Depth, 1), View.ScreenToTranslatedWorld);
|
|
|
|
const float3 RayDir = normalize(TranslatedWorldPos.xyz - View.TranslatedWorldCameraOrigin);
|
|
const float3 RayOrig = LWCHackToFloat(ResolvedView.WorldCameraOrigin);
|
|
|
|
OutLuminanceAlpha = float4(0.0, 0.0, 0.0, 1.0);
|
|
|
|
float TMin = 0.0f;
|
|
float TMax = 0.0f;
|
|
float Transmittance = 1.0f;
|
|
if (Slabs(VolumeBoundMinWorld, VolumeBoundMaxWorld, RayOrig, 1.0 / RayDir, TMin, TMax) && TMax > 0.0f)
|
|
{
|
|
Transmittance = 0.5; // show the bounding box
|
|
|
|
// Amanatides 3D DDA marching implementation - Paper: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.42.3443&rep=rep1&type=pdf
|
|
// See https://www.shadertoy.com/view/3sKXDK
|
|
|
|
float3 StartPos = RayOrig + RayDir * max(0.0, TMin);
|
|
|
|
float3 VolumeResolution = SparseVolumeTexturePageTableResolution * SPARSE_VOLUME_TILE_RES;
|
|
|
|
const float3 StartUVs = (StartPos - VolumeBoundMinWorld) / (VolumeBoundMaxWorld - VolumeBoundMinWorld);
|
|
float3 P = StartUVs * VolumeResolution;
|
|
|
|
// Force round to volume
|
|
if (P.x < 0) P.x = 0;
|
|
if (P.y < 0) P.y = 0;
|
|
if (P.z < 0) P.z = 0;
|
|
if (P.x > (VolumeResolution.x)) P.x = (VolumeResolution.x);
|
|
if (P.y > (VolumeResolution.y)) P.y = (VolumeResolution.y);
|
|
if (P.z > (VolumeResolution.z)) P.z = (VolumeResolution.z);
|
|
|
|
// Amanatides 3D-DDA data preparation
|
|
float3 stepSign = sign(RayDir);
|
|
float3 tDelta = abs(1.0 / RayDir);
|
|
float3 tMax = float3(0.0, 0.0, 0.0);
|
|
float3 refPoint = floor(P);
|
|
tMax.x = stepSign.x > 0.0 ? refPoint.x + 1.0 - P.x : P.x - refPoint.x;
|
|
tMax.y = stepSign.y > 0.0 ? refPoint.y + 1.0 - P.y : P.y - refPoint.y;
|
|
tMax.z = stepSign.z > 0.0 ? refPoint.z + 1.0 - P.z : P.z - refPoint.z;
|
|
tMax.x *= tDelta.x;
|
|
tMax.y *= tDelta.y;
|
|
tMax.z *= tDelta.z;
|
|
|
|
LOOP
|
|
while (P.x >= 0 && P.y >= 0 && P.z >= 0 && P.x <= VolumeResolution.x && P.y <= VolumeResolution.y && P.z <= VolumeResolution.z)
|
|
{
|
|
float StepLength = 0.0;
|
|
#if 0
|
|
// Slow reference
|
|
P += RayDir * 0.005;
|
|
StepLength = 0.005;
|
|
#else
|
|
// Amanatides 3D-DDA
|
|
if (tMax.x < tMax.y)
|
|
{
|
|
if (tMax.x < tMax.z)
|
|
{
|
|
P.x += stepSign.x;
|
|
tMax.x += tDelta.x;
|
|
|
|
StepLength += 1;
|
|
}
|
|
else
|
|
{
|
|
P.z += stepSign.z;
|
|
tMax.z += tDelta.z;
|
|
|
|
StepLength += 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (tMax.y < tMax.z)
|
|
{
|
|
P.y += stepSign.y;
|
|
tMax.y += tDelta.y;
|
|
|
|
StepLength += 1;
|
|
}
|
|
else
|
|
{
|
|
P.z += stepSign.z;
|
|
tMax.z += tDelta.z;
|
|
|
|
StepLength += 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
float3 PageCoordF = floor(P * (1.0 / SPARSE_VOLUME_TILE_RES));
|
|
const uint EncodedPage = SparseVolumeTexturePageTable.Load(int4(int3(PageCoordF), 0));
|
|
if (EncodedPage)
|
|
{
|
|
const int3 TileCoord = int3(
|
|
EncodedPage & 0x7FF,
|
|
(EncodedPage >> 11 ) & 0x7FF,
|
|
(EncodedPage >> 22 ) & 0x3FF);
|
|
|
|
int3 VoxelCoord = TileCoord * SPARSE_VOLUME_TILE_RES + int3(P - PageCoordF * SPARSE_VOLUME_TILE_RES);
|
|
|
|
const float4 VoxelData = SparseVolumeTexture.Load(int4(VoxelCoord, 0));
|
|
|
|
const float Density = VoxelData.x;
|
|
if (Density > 0.0f)
|
|
|
|
{
|
|
#if 0
|
|
//OutLuminanceAlpha = float4(Rand3DPCG16(PageCoordF).x / 65535.0f, Rand3DPCG16(VoxelCoord).y / 65535.0f, 0.0, 0.0);
|
|
//OutLuminanceAlpha = float4(Rand3DPCG16(PageCoordF) / 65535.0f, 0.0);
|
|
OutLuminanceAlpha = float4(Rand3DPCG16(VoxelCoord) / 65535.0f, 0.0);
|
|
break;
|
|
#else
|
|
Transmittance *= exp(-StepLength * Density * 0.025);
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
OutLuminanceAlpha.a = Transmittance;
|
|
}
|
|
|
|
|
|
#endif // PIXEL_SHADER
|
|
|
|
|