// Copyright Epic Games, Inc. All Rights Reserved. // Mirrors PCGNormalToDensityMode #define NORMAL_TO_DENSITY_MODE_Set 0 #define NORMAL_TO_DENSITY_MODE_Minimum 1 #define NORMAL_TO_DENSITY_MODE_Maximum 2 #define NORMAL_TO_DENSITY_MODE_Add 3 #define NORMAL_TO_DENSITY_MODE_Subtract 4 #define NORMAL_TO_DENSITY_MODE_Multiply 5 #define NORMAL_TO_DENSITY_MODE_Divide 6 [numthreads(64, 1, 1)] void PCGNormalToDensityCS(uint3 GroupId : SV_GroupID, uint GroupIndex : SV_GroupIndex) { // Mark the kernel as having executed. Must run before we early out via thread index, because the kernel is still 'executed' even if the number of // threads to iterate on is zero. Even if GetNumThreads() returns 0, the kernel will still have been dispatched on a single thread to set this flag. if (all(GroupId == 0) && GroupIndex == 0) { Out_SetAsExecutedInternal(); } const uint ThreadIndex = GetUnWrappedDispatchThreadId(GroupId, GroupIndex, 64); if (ThreadIndex >= GetNumThreads().x) return; uint InDataIndex, InElemIndex; if (!In_GetThreadData(ThreadIndex, InDataIndex, InElemIndex)) { return; } uint OutDataIndex, OutElemIndex; if (!Out_GetThreadData(ThreadIndex, OutDataIndex, OutElemIndex)) { return; } // Propagate the 'Removed' status to the output point. Otherwise, this point will not be culled. if (In_IsPointRemoved(InDataIndex, InElemIndex)) { Out_RemovePoint(OutDataIndex, OutElemIndex); return; } // Do the actual 'work' of this node. const float3 Normal = normalize(NormalToDensity_GetNormal()); const float Offset = NormalToDensity_GetOffset(); const float Strength = max(NormalToDensity_GetStrength(), 0.0001); const uint DensityMode = NormalToDensity_GetDensityMode(); const float InDensity = In_GetDensity(InDataIndex, InElemIndex); const float4 InRotation = In_GetRotation(InDataIndex, InElemIndex); const float3 PointUp = QuatRotateVector(InRotation, float3(0, 0, 1)); float NormalDensity = pow(clamp(dot(PointUp, Normal) + Offset, 0.0, 1.0), 1 / Strength); float OutDensity = 0; if (DensityMode == NORMAL_TO_DENSITY_MODE_Set) { OutDensity = NormalDensity; } if (DensityMode == NORMAL_TO_DENSITY_MODE_Minimum) { OutDensity = min(InDensity, NormalDensity); } else if (DensityMode == NORMAL_TO_DENSITY_MODE_Maximum) { OutDensity = max(InDensity, NormalDensity); } else if (DensityMode == NORMAL_TO_DENSITY_MODE_Add) { OutDensity = InDensity + NormalDensity; } else if (DensityMode == NORMAL_TO_DENSITY_MODE_Subtract) { OutDensity = InDensity - NormalDensity; } else if (DensityMode == NORMAL_TO_DENSITY_MODE_Multiply) { OutDensity = InDensity * NormalDensity; } else if (DensityMode == NORMAL_TO_DENSITY_MODE_Divide) { OutDensity = (NormalDensity != 0) ? InDensity / NormalDensity : 0.0f; } // Copy all attributes PCG_COPY_ALL_ATTRIBUTES_TO_OUTPUT(Out, In, OutDataIndex, OutElemIndex, InDataIndex, InElemIndex); // Write output density. Out_SetDensity(OutDataIndex, OutElemIndex, OutDensity); }