184 lines
9.8 KiB
HLSL
184 lines
9.8 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
// LWCNormalizeTile will convert a LWC value to have an integral tile value, and an offset value within (-TileSize, TileSize)
|
|
// This is important if we want to compare LWC values, or to ensure that fractional part is fully contained within the offset
|
|
FLWCType LWCNormalizeTile(FLWCType V)
|
|
{
|
|
FFloatType IntTile = floor(V.Tile + (V.Offset * UE_LWC_RENDER_TILE_SIZE_RCP + 0.5f));
|
|
return LWCConstructor(IntTile, (V.Tile - IntTile) * UE_LWC_RENDER_TILE_SIZE + V.Offset);
|
|
}
|
|
|
|
// Forces the tile to be an integral value, but doesn't adjust range of offset
|
|
FLWCType LWCMakeIntTile(FLWCType V)
|
|
{
|
|
FFloatType IntTile = floor(V.Tile);
|
|
return LWCConstructor(IntTile, (V.Tile - IntTile) * UE_LWC_RENDER_TILE_SIZE + V.Offset);
|
|
}
|
|
|
|
FFloatType LWCSqrtUnscaled(FLWCType V) { return sqrt(V.Offset * UE_LWC_RENDER_TILE_SIZE_RCP + LWCGetTile(V)); }
|
|
FFloatType LWCRsqrtUnscaled(FLWCType V) { return rsqrt(V.Offset * UE_LWC_RENDER_TILE_SIZE_RCP + LWCGetTile(V)); }
|
|
FFloatType LWCRcpUnscaled(FLWCType V) { return rcp(V.Offset * UE_LWC_RENDER_TILE_SIZE_RCP + LWCGetTile(V)); }
|
|
FFloatType LWCSqrtScaled(FLWCType V, float Scale) { return LWCSqrtUnscaled(V) * Scale; }
|
|
FFloatType LWCRsqrtScaled(FLWCType V, float Scale) { return LWCRsqrtUnscaled(V) * Scale; }
|
|
FFloatType LWCRcpScaled(FLWCType V, float Scale) { return LWCRcpUnscaled(V) * Scale; }
|
|
FFloatType LWCSqrt(FLWCType V) { return LWCSqrtScaled(V, UE_LWC_RENDER_TILE_SIZE_SQRT); }
|
|
FFloatType LWCRsqrt(FLWCType V) { return LWCRsqrtScaled(V, UE_LWC_RENDER_TILE_SIZE_RSQRT); }
|
|
FFloatType LWCRcp(FLWCType V) { return LWCRcpScaled(V, UE_LWC_RENDER_TILE_SIZE_RCP); }
|
|
|
|
#define LWC_COMPARE_OP(Name, Op, FLWCType, FFloatType, FBoolType) \
|
|
FBoolType Name(FLWCType Lhs, FLWCType Rhs) { \
|
|
return (LWCGetTile(Lhs) - LWCGetTile(Rhs)) * UE_LWC_RENDER_TILE_SIZE Op Rhs.Offset - Lhs.Offset; } \
|
|
FBoolType Name(FFloatType Lhs, FLWCType Rhs) { \
|
|
return -LWCGetTile(Rhs) * UE_LWC_RENDER_TILE_SIZE Op Rhs.Offset - Lhs; } \
|
|
FBoolType Name(FLWCType Lhs, FFloatType Rhs) { \
|
|
return LWCGetTile(Lhs) * UE_LWC_RENDER_TILE_SIZE Op Rhs - Lhs.Offset; }
|
|
|
|
LWC_COMPARE_OP(LWCGreater, >, FLWCType, FFloatType, FBoolType)
|
|
LWC_COMPARE_OP(LWCGreaterEqual, >=, FLWCType, FFloatType, FBoolType)
|
|
LWC_COMPARE_OP(LWCLess, <, FLWCType, FFloatType, FBoolType)
|
|
LWC_COMPARE_OP(LWCLessEqual, <=, FLWCType, FFloatType, FBoolType)
|
|
|
|
#undef LWC_COMPARE_OP
|
|
|
|
// No ddxy inside ray tracing shaders
|
|
#if RAYHITGROUPSHADER || RAYMISSHADER || RAYCALLABLESHADER || USE_FORCE_TEXTURE_MIP
|
|
FFloatType LWCDdx(FLWCType V) { return (FFloatType)0; }
|
|
FFloatType LWCDdy(FLWCType V) { return (FFloatType)0; }
|
|
#else
|
|
FFloatType LWCDdx(FLWCType V) { return ddx(LWCGetTile(V)) * UE_LWC_RENDER_TILE_SIZE + ddx(V.Offset); }
|
|
FFloatType LWCDdy(FLWCType V) { return ddy(LWCGetTile(V)) * UE_LWC_RENDER_TILE_SIZE + ddy(V.Offset); }
|
|
#endif
|
|
|
|
FLWCType LWCAdd(FLWCType Lhs, FLWCType Rhs) { return LWCConstructor(LWCGetTile(Lhs) + LWCGetTile(Rhs), Lhs.Offset + Rhs.Offset); }
|
|
FLWCType LWCAdd(FFloatType Lhs, FLWCType Rhs) { return LWCConstructor(LWCGetTile(Rhs), Lhs + Rhs.Offset); }
|
|
FLWCType LWCAdd(FLWCType Lhs, FFloatType Rhs) { return LWCConstructor(LWCGetTile(Lhs), Lhs.Offset + Rhs); }
|
|
|
|
FLWCType LWCSubtract(FLWCType Lhs, FLWCType Rhs) { return LWCConstructor(LWCGetTile(Lhs) - LWCGetTile(Rhs), Lhs.Offset - Rhs.Offset); }
|
|
FLWCType LWCSubtract(FFloatType Lhs, FLWCType Rhs) { return LWCConstructor(-LWCGetTile(Rhs), Lhs - Rhs.Offset); }
|
|
FLWCType LWCSubtract(FLWCType Lhs, FFloatType Rhs) { return LWCConstructor(LWCGetTile(Lhs), Lhs.Offset - Rhs); }
|
|
|
|
FBoolType LWCEquals(FLWCType Lhs, FLWCType Rhs)
|
|
{
|
|
return (LWCGetTile(Lhs) - LWCGetTile(Rhs)) * UE_LWC_RENDER_TILE_SIZE == Rhs.Offset - Lhs.Offset;
|
|
}
|
|
FBoolType LWCEquals(FFloatType Lhs, FLWCType Rhs)
|
|
{
|
|
return -LWCGetTile(Rhs) * UE_LWC_RENDER_TILE_SIZE == Rhs.Offset - Lhs;
|
|
}
|
|
FBoolType LWCEquals(FLWCType Lhs, FFloatType Rhs)
|
|
{
|
|
return LWCGetTile(Lhs) * UE_LWC_RENDER_TILE_SIZE == Rhs - Lhs.Offset;
|
|
}
|
|
FBoolType LWCEqualsApprox(FLWCType Lhs, FLWCType Rhs, float Threshold)
|
|
{
|
|
return abs((LWCGetTile(Lhs) - LWCGetTile(Rhs)) * UE_LWC_RENDER_TILE_SIZE + (Lhs.Offset - Rhs.Offset)) < (FFloatType)Threshold;
|
|
}
|
|
FBoolType LWCEqualsApprox(FFloatType Lhs, FLWCType Rhs, float Threshold)
|
|
{
|
|
return abs(-LWCGetTile(Rhs) * UE_LWC_RENDER_TILE_SIZE + (Lhs - Rhs.Offset)) < (FFloatType)Threshold;
|
|
}
|
|
FBoolType LWCEqualsApprox(FLWCType Lhs, FFloatType Rhs, float Threshold)
|
|
{
|
|
return abs(LWCGetTile(Lhs) * UE_LWC_RENDER_TILE_SIZE + (Lhs.Offset - Rhs)) < (FFloatType)Threshold;
|
|
}
|
|
|
|
FLWCType LWCSelect(FBoolType S, FLWCType Lhs, FLWCType Rhs) { return LWCConstructor(select(S, LWCGetTile(Lhs), LWCGetTile(Rhs)), select(S, Lhs.Offset, Rhs.Offset)); }
|
|
FLWCType LWCSelect(FBoolType S, FFloatType Lhs, FLWCType Rhs) { return LWCConstructor(select(S, (FFloatType)0, LWCGetTile(Rhs)), select(S, Lhs, Rhs.Offset)); }
|
|
FLWCType LWCSelect(FBoolType S, FLWCType Lhs, FFloatType Rhs) { return LWCConstructor(select(S, LWCGetTile(Lhs), (FFloatType)0), select(S, Lhs.Offset, Rhs)); }
|
|
|
|
FLWCType LWCNegate(FLWCType V) { return LWCConstructor(-LWCGetTile(V), -V.Offset); }
|
|
|
|
FFloatType LWCFrac(FLWCType V)
|
|
{
|
|
FFloatType FracTile = frac(LWCGetTile(V) * UE_LWC_RENDER_TILE_SIZE);
|
|
return frac(FracTile + V.Offset);
|
|
}
|
|
|
|
FLWCType LWCFloor(FLWCType V) { FLWCType VN = LWCMakeIntTile(V); return LWCConstructor(LWCGetTile(VN), floor(VN.Offset)); }
|
|
FLWCType LWCCeil(FLWCType V) { FLWCType VN = LWCMakeIntTile(V); return LWCConstructor(LWCGetTile(VN), ceil(VN.Offset)); }
|
|
FLWCType LWCRound(FLWCType V) { FLWCType VN = LWCMakeIntTile(V); return LWCConstructor(LWCGetTile(VN), round(VN.Offset)); }
|
|
FLWCType LWCTrunc(FLWCType V) { FLWCType VN = LWCMakeIntTile(V); return LWCConstructor(LWCGetTile(VN), trunc(VN.Offset)); }
|
|
|
|
// These rely on +/-inf being handled properly by various min/max operations
|
|
FFloatType LWCSign(FLWCType V) { return FFloatType(sign(LWCToFloat(V))); }
|
|
FFloatType LWCSaturate(FLWCType V) { return saturate(LWCToFloat(V)); }
|
|
FFloatType LWCClampScalar(FLWCType V, float Low, float High) { return clamp(LWCToFloat(V), Low, High); }
|
|
|
|
FLWCType LWCMultiply(FLWCType Lhs, FLWCType Rhs)
|
|
{
|
|
return LWCConstructor(LWCGetTile(Lhs) * (LWCGetTile(Rhs) * UE_LWC_RENDER_TILE_SIZE + Rhs.Offset) + LWCGetTile(Rhs) * Lhs.Offset, Lhs.Offset * Rhs.Offset);
|
|
}
|
|
FLWCType LWCMultiply(FFloatType Lhs, FLWCType Rhs) { return LWCConstructor(LWCGetTile(Rhs) * Lhs, Lhs * Rhs.Offset); }
|
|
FLWCType LWCMultiply(FLWCType Lhs, FFloatType Rhs) { return LWCConstructor(LWCGetTile(Lhs) * Rhs, Lhs.Offset * Rhs); }
|
|
|
|
FLWCType LWCDivide(FLWCType Lhs, FLWCType Rhs) { return LWCMultiply(Lhs, LWCRcp(Rhs)); }
|
|
FLWCType LWCDivide(FLWCType Lhs, FFloatType Rhs) { return LWCMultiply(Lhs, rcp(Rhs)); }
|
|
FLWCType LWCDivide(FFloatType Lhs, FLWCType Rhs) { return LWCConstructor((FFloatType)0, Lhs * LWCRcp(Rhs)); }
|
|
|
|
//FLWCType LWCLerp(FLWCType Lhs, FLWCType Rhs, FFloatType S) { return LWCAdd(Lhs, LWCMultiply(S, LWCSubtract(Rhs, Lhs))); }
|
|
FLWCType LWCLerp(FLWCType Lhs, FLWCType Rhs, FFloatType S)
|
|
{
|
|
return LWCConstructor(lerp(LWCGetTile(Lhs), LWCGetTile(Rhs), S), lerp(Lhs.Offset, Rhs.Offset, S));
|
|
}
|
|
|
|
FFloatType LWCModulo(FLWCType Lhs, FFloatType Rhs)
|
|
{
|
|
return LWCToFloat(LWCSubtract(Lhs, LWCMultiply(LWCTrunc(LWCDivide(Lhs, Rhs)), Rhs)));
|
|
}
|
|
|
|
FFloatType LWCFmod(FLWCType Lhs, FFloatType Rhs)
|
|
{
|
|
return LWCToFloat(LWCSubtract(Lhs, LWCMultiply(LWCTrunc(LWCDivide(Lhs, Rhs)), Rhs)));
|
|
//FFloatType ModTileSize = fmod(UE_LWC_RENDER_TILE_SIZE, Rhs);
|
|
//return fmod(ModTileSize * LWCGetTile(Lhs) + Lhs.Offset, Rhs);
|
|
}
|
|
FFloatType LWCFmodFloor(FLWCType Lhs, FFloatType Rhs)
|
|
{
|
|
return LWCToFloat(LWCSubtract(Lhs, LWCMultiply(LWCFloor(LWCDivide(Lhs, Rhs)), Rhs)));
|
|
//FFloatType ModTileSize = FmodFloor(UE_LWC_RENDER_TILE_SIZE, Rhs);
|
|
//return FmodFloor(LWCGetTile(Lhs) * ModTileSize + Lhs.Offset, Rhs);
|
|
}
|
|
FFloatType LWCFmodFloorPI(FLWCType V)
|
|
{
|
|
return LWCFmodFloor(V, PI);
|
|
//return LWCGetTile(V) * UE_LWC_RENDER_TILE_SIZE_FMOD_PI + V.Offset;
|
|
}
|
|
FFloatType LWCFmodFloor2PI(FLWCType V)
|
|
{
|
|
return LWCFmodFloor(V, 2.0f * PI);
|
|
//return LWCGetTile(V) * UE_LWC_RENDER_TILE_SIZE_FMOD_2PI + V.Offset;
|
|
}
|
|
|
|
FFloatType LWCSin(FLWCType V) { return sin(LWCFmodFloor2PI(V)); }
|
|
FFloatType LWCCos(FLWCType V) { return cos(LWCFmodFloor2PI(V)); }
|
|
FFloatType LWCTan(FLWCType V) { return tan(LWCFmodFloorPI(V)); }
|
|
FFloatType LWCASin(FLWCType V) { return asin(LWCClampScalar(V, -1.0f, 1.0f)); }
|
|
FFloatType LWCACos(FLWCType V) { return acos(LWCClampScalar(V, -1.0f, 1.0f)); }
|
|
FFloatType LWCATan(FLWCType V) { return atan(LWCClampScalar(V, -0.5f*PI, 0.5f*PI)); }
|
|
|
|
FFloatType LWCSmoothStep(FLWCType Lhs, FLWCType Rhs, FLWCType S)
|
|
{
|
|
FFloatType t = LWCSaturate(LWCDivide(LWCSubtract(S, Lhs), LWCSubtract(Rhs, Lhs)));
|
|
return t*t*(3.0f - (2.0f*t));
|
|
}
|
|
|
|
FLWCType LWCMin(FLWCType Lhs, FLWCType Rhs) { return LWCSelect(LWCLess(Lhs, Rhs), Lhs, Rhs); }
|
|
FLWCType LWCMin(FFloatType Lhs, FLWCType Rhs) { return LWCSelect(LWCLess(Lhs, Rhs), Lhs, Rhs); }
|
|
FLWCType LWCMin(FLWCType Lhs, FFloatType Rhs) { return LWCSelect(LWCLess(Lhs, Rhs), Lhs, Rhs); }
|
|
FLWCType LWCMax(FLWCType Lhs, FLWCType Rhs) { return LWCSelect(LWCGreater(Lhs, Rhs), Lhs, Rhs); }
|
|
FLWCType LWCMax(FFloatType Lhs, FLWCType Rhs) { return LWCSelect(LWCGreater(Lhs, Rhs), Lhs, Rhs); }
|
|
FLWCType LWCMax(FLWCType Lhs, FFloatType Rhs) { return LWCSelect(LWCGreater(Lhs, Rhs), Lhs, Rhs); }
|
|
|
|
FLWCType LWCAbs(FLWCType V) { return LWCSelect(LWCLess(V, (FFloatType)0), LWCNegate(V), V); }
|
|
|
|
FFloatType LWCStep(FLWCType Lhs, FLWCType Rhs) { return select(LWCGreaterEqual(Rhs, Lhs), (FFloatType)1.0f, (FFloatType)0.0f); }
|
|
FFloatType LWCStep(FLWCType Lhs, FFloatType Rhs) { return select(LWCGreaterEqual(Rhs, Lhs), (FFloatType)1.0f, (FFloatType)0.0f); }
|
|
FFloatType LWCStep(FFloatType Lhs, FLWCType Rhs) { return select(LWCGreaterEqual(Rhs, Lhs), (FFloatType)1.0f, (FFloatType)0.0f); }
|
|
|
|
// LWCSquareScaled returns the value squared, scaled by the LWC tile size
|
|
FLWCType LWCSquareScaled(FLWCType V)
|
|
{
|
|
FFloatType OffsetScaled = V.Offset * UE_LWC_RENDER_TILE_SIZE_RCP;
|
|
return LWCConstructor(LWCGetTile(V) * (LWCGetTile(V) + OffsetScaled * 2.0f), V.Offset * OffsetScaled);
|
|
}
|