Files
UnrealEngine/Engine/Shaders/Private/VectorFieldCompositeShaders.usf
2025-05-18 13:04:45 +08:00

104 lines
3.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*==============================================================================
GlobalVectorFieldShaders.usf: Shaders for building global vector fields.
==============================================================================*/
/*------------------------------------------------------------------------------
Composite an animated vector field.
------------------------------------------------------------------------------*/
#if COMPOSITE_ANIMATED
#include "Common.ush"
Texture2D AtlasTexture;
SamplerState AtlasTextureSampler;
Texture3D NoiseVolumeTexture;
SamplerState NoiseVolumeTextureSampler;
RWTexture3D<float4> OutVolumeTexture;
void Extrude_X(float3 VolumeUV, out float2 ImageUV, out float3 AxisX, out float3 AxisY, out float3 AxisZ)
{
ImageUV.x = VolumeUV.y;
ImageUV.y = 1.0f - VolumeUV.z;
AxisX = float3(0,1,0);
AxisY = float3(0,0,1);
AxisZ = float3(1,0,0);
}
void Extrude_Y(float3 VolumeUV, out float2 ImageUV, out float3 AxisX, out float3 AxisY)
{
ImageUV.x = VolumeUV.x;
ImageUV.y = 1.0f - VolumeUV.z;
AxisX = float3(1,0,0);
AxisY = float3(0,0,1);
}
void Extrude_Z(float3 VolumeUV, out float2 ImageUV, out float3 AxisX, out float3 AxisY)
{
ImageUV.x = VolumeUV.x;
ImageUV.y = 1.0f - VolumeUV.y;
AxisX = float3(1,0,0);
AxisY = float3(0,1,0);
}
void Revolve_HalfZ(float3 VolumeUV, out float2 ImageUV, out float3 AxisX, out float3 AxisY, out float3 AxisZ)
{
const float2 PlaneDir = VolumeUV.xy * 2 - 1;
//ImageUV.x = 0.5f * saturate(length(PlaneDir)) + 0.5f;
ImageUV.x = saturate(length(PlaneDir));
ImageUV.y = 1.0f - VolumeUV.z;
AxisX = float3(normalize(PlaneDir),0);
AxisY = float3(0,0,1);
AxisZ = cross(AxisX,AxisY);
}
[numthreads(THREADS_X,THREADS_Y,THREADS_Z)]
void CompositeAnimatedVectorField(
uint3 DispatchThreadId : SV_DispatchThreadID,
uint3 GroupId : SV_GroupID,
uint3 GroupThreadId : SV_GroupThreadID,
uint ThreadId : SV_GroupIndex )
{
float3 AxisX = float3(1,0,0);
float3 AxisY = float3(0,1,0);
float3 AxisZ = float3(0,0,1);
float2 ImageUV = float2(0,0);
// Compute the UV coordinate for this voxel within the volume.
const float3 VolumeUV = DispatchThreadId * CVF.VoxelSize.xyz + CVF.VoxelSize.xyz * 0.5f;
// Sample the noise texture.
const float3 NoiseSample = Texture3DSampleLevel(NoiseVolumeTexture, NoiseVolumeTextureSampler, VolumeUV, 0).xyz;
const float NoiseMagnitude = length(NoiseSample);
const float3 NormalizedNoise = NoiseSample / (NoiseMagnitude + 0.001f);
const float3 Noise = NormalizedNoise * min(NoiseMagnitude * CVF.NoiseScale, CVF.NoiseMax);
// Determine the 2-D projection for this voxel based on the desired operation.
if (CVF.Op == 0) // VFCO_Extrude
{
Extrude_X(VolumeUV, ImageUV, AxisX, AxisY, AxisZ);
}
else // VFCO_Revolve
{
Revolve_HalfZ(VolumeUV, ImageUV, AxisX, AxisY, AxisZ);
}
// Sample the two subimages and interpolate.
float2 FrameA_UV = ImageUV.xy * CVF.FrameA.xy + CVF.FrameA.zw;
float2 FrameB_UV = ImageUV.xy * CVF.FrameB.xy + CVF.FrameB.zw;
float4 FrameA_Sample = Texture2DSampleLevel(AtlasTexture, AtlasTextureSampler, FrameA_UV, 0);
float4 FrameB_Sample = Texture2DSampleLevel(AtlasTexture, AtlasTextureSampler, FrameB_UV, 0);
float4 LerpedValue = lerp(FrameA_Sample, FrameB_Sample, CVF.FrameLerp);
// Determine the direction and project back to the volume.
float3 Direction = (LerpedValue.xyz * 2 - 1) * LerpedValue.w;
float3 ProjectedDirection = Direction.x * AxisX + Direction.y * AxisY + Direction.z * AxisZ;
// Write out this voxel's result.
OutVolumeTexture[DispatchThreadId] = float4(Noise + ProjectedDirection, 0.0f);
}
#endif // #if COMPOSITE_ANIMATED