Files
UnrealEngine/Engine/Plugins/PCG/Shaders/Private/PCGShaderUtils.ush
2025-05-18 13:04:45 +08:00

128 lines
2.6 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
// These follow the corresponding C++ functions in PCGHelpers.
uint ComputeSeed(uint A, uint B)
{
return ((A * 196314165U) + 907633515U) ^ ((B * 73148459U) + 453816763U);
}
uint ComputeSeed(uint A, uint B, uint C)
{
return ((A * 196314165U) + 907633515U) ^ ((B * 73148459U) + 453816763U) ^ ((C * 34731343U) + 453816743U);
}
uint ComputeSeedFromPosition(float3 InPosition)
{
const int3 PosInt = (int3)InPosition;
const int Seed = ((PosInt.x * 196314165U) + 907633515U) ^ ((PosInt.y * 73148459U) + 453816763U) ^ ((PosInt.z * 34731343U) + 453816743U);
return (uint)Seed;
}
// This follows the implementation in FRandomStream.
float FRand(inout uint InOutSeed)
{
InOutSeed = (InOutSeed * 196314165U) + 907633515U;
const float Result = asfloat(0x3F800000U | (InOutSeed >> 9));
return Result - 1.0f;
}
float3 CreateGrid2D(uint ElementIndex, uint NumPoints, uint NumRows, float3 Min, float3 Max)
{
if (NumRows == 0)
{
return Min;
}
const uint NumCols = ceil((0.f + NumPoints) / NumRows);
if (NumCols == 0)
{
return Min;
}
const uint IndexX = ElementIndex / NumRows;
const uint IndexY = ElementIndex - NumRows * IndexX;
float3 Spacing = (Max - Min);
if (NumCols > 1)
{
Spacing.x /= (NumCols - 1);
}
if (NumRows > 1)
{
Spacing.y /= (NumRows - 1);
}
float3 Position = Min;
Position.x += IndexX * Spacing.x;
Position.y += IndexY * Spacing.y;
return Position;
}
float3 CreateGrid2D(uint ElementIndex, uint NumPoints, float3 Min, float3 Max)
{
if (NumPoints == 0)
{
return Min;
}
const uint NumRows = ceil(sqrt(NumPoints));
return CreateGrid2D(ElementIndex, NumPoints, NumRows, Min, Max);
}
float3 CreateGrid3D(uint ElementIndex, uint NumPoints, uint NumRows, uint NumCols, float3 Min, float3 Max)
{
if (NumRows == 0 || NumCols == 0)
{
return Min;
}
const uint NumLayers = ceil((0.f + NumPoints) / (NumRows * NumCols));
if (NumLayers == 0)
{
return Min;
}
uint3 Index;
Index.x = ElementIndex % NumCols;
Index.y = (ElementIndex / NumCols) % NumRows;
Index.z = ElementIndex / (NumRows * NumCols);
float3 Spacing = Max - Min;
if (NumCols > 1)
{
Spacing.x /= (NumCols - 1);
}
if (NumRows > 1)
{
Spacing.y /= (NumRows - 1);
}
if (NumLayers > 1)
{
Spacing.z /= (NumLayers - 1);
}
return Min + Index * Spacing;
}
float3 CreateGrid3D(uint ElementIndex, uint NumPoints, float3 Min, float3 Max)
{
if (NumPoints == 0)
{
return Min;
}
const uint NumRows = round(pow(NumPoints, 1.f / 3.f));
const uint NumCols = NumRows;
return CreateGrid3D(ElementIndex, NumPoints, NumRows, NumCols, Min, Max);
}