122 lines
5.0 KiB
HLSL
122 lines
5.0 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
// Simple numeric print functions.
|
|
// Text size and placement is entirely determined by the scale and origin of the coordinates passed in
|
|
// Numbers appear vertically y=0 and y=1 with the baseline at y=0
|
|
// Numbers appear horizontally right-justified at x=0 (so only at *negative* values of x)
|
|
//
|
|
// Basic usage:
|
|
// OutColor = lerp(OutColor, TextColor, PrintFixed(coord, 3, value));
|
|
// OutColor = lerp(OutColor, TextColor, PrintScientific(coord, 3, value));
|
|
//
|
|
// Typical usage for a single number centered in the middle of the screen
|
|
// OutColor = lerp(OutColor, TextColor, PrintFixed(50 * (SVPosition.xy * View.BufferSizeAndInvSize.zw - 0.5), 2, value)
|
|
//
|
|
// Typical usage for a grid of numbers, this one is every two lines in Y and every 10 characters in X
|
|
// OutColor = lerp(OutColor, PrintFixed(float2(
|
|
// 10 * frac(6 * SVPos.x * View.BufferSizeAndInvSize.z) - 9,
|
|
// 2 * frac(30 * SVPos.y * View.BufferSizeAndInvSize.w)),
|
|
// 2, value));
|
|
//
|
|
// position can also be texture coordinates, shadow coordinates, etc.
|
|
|
|
|
|
// fixed-point print adapted from P_Malin https://www.shadertoy.com/view/4sBSWW
|
|
// converted to HLSL, font glyphs flipped vertically, use integer types, less compact style
|
|
// @param StringCoords position and scale of text. Numbers are 1x1 units in size, right-justified at 0,0
|
|
// @param Value float value to print
|
|
// @return 0 for non-text, 1 for text values.
|
|
float PrintFixed(float2 StringCoords, int DecimalPlaces, float Value)
|
|
{
|
|
if ((StringCoords.y < 0.0) || (StringCoords.y >= 1.0)) return 0.0;
|
|
int iCoord = -int(floor(StringCoords.x));
|
|
|
|
int NegativeValue = Value < 0.0 ? 1 : 0;
|
|
Value = abs(Value);
|
|
int Digits = max(int(log2(Value) / log2(10.0)), 0) + 1;
|
|
int Decimal = DecimalPlaces > 0 ? 1 : 0;
|
|
int iValue = int(floor(Value * pow(10., DecimalPlaces)));
|
|
|
|
int CharBin = 0, DigitIndex = 0;
|
|
if (iCoord < 0)
|
|
return 0.; // right of number
|
|
else if (iCoord < DecimalPlaces)
|
|
DigitIndex = iCoord; // fractional digit
|
|
else if (iCoord == DecimalPlaces && DecimalPlaces)
|
|
CharBin = 131072; // decimal point
|
|
else if (iCoord < Digits + Decimal + DecimalPlaces)
|
|
DigitIndex = iCoord - Decimal; // integer digit
|
|
else if (iCoord < NegativeValue + Digits + Decimal + DecimalPlaces)
|
|
CharBin = 1792; // minus sign
|
|
else
|
|
return 0.; // left of number
|
|
|
|
// has to be a digit
|
|
if (CharBin == 0)
|
|
{
|
|
const int digits[] = { 480599, 139810, 464711, 476999, 280405, 476951, 481047, 279623, 481111, 477015 };
|
|
int Digit = int(iValue / pow(10, DigitIndex)) % 10;
|
|
CharBin = digits[Digit];
|
|
}
|
|
|
|
// convert binary to 4x5 array of points
|
|
int2 DigitCoord = int2(frac(StringCoords.x) * 4., StringCoords.y * 5.);
|
|
return float((CharBin >> (DigitCoord.x + DigitCoord.y * 4)) & 1);
|
|
}
|
|
|
|
// Print value in scientific notation
|
|
// @param StringCoords position and scale of text. Numbers are 1x1 units in size, right-justified at 0,0
|
|
// @param DecimalPlaces number of decimal places to print in mantissa
|
|
// @param Value float value to print
|
|
// @return 0 for non-text, 1 for text values.
|
|
// Typical usage: OutColor = lerp(OutColor, TextColor, PrintValue(coord, 3, value));
|
|
float PrintScientific(float2 StringCoords, int DecimalPlaces, float Value)
|
|
{
|
|
if ((StringCoords.y < 0.0) || (StringCoords.y >= 1.0)) return 0.0;
|
|
int iCoord = -int(floor(StringCoords.x));
|
|
|
|
int NegativeValue = Value < 0.0 ? 1 : 0;
|
|
Value = abs(Value);
|
|
|
|
int Exponent = int(floor(log2(Value) / log2(10.)));
|
|
int NegativeExponent = Exponent < 0 ? 1 : 0;
|
|
Exponent = abs(Exponent);
|
|
int ExponentDigits = max(0, int(floor(log2(float(Exponent)) / log2(10.)))) + 1;
|
|
|
|
int iValue = int(floor(Value * pow(10., DecimalPlaces - Exponent)));
|
|
|
|
int CharBin = 0, DigitIndex = 0;
|
|
if (iCoord < 0)
|
|
return 0.; // right of number
|
|
else if (iCoord < ExponentDigits)
|
|
{
|
|
iValue = Exponent; // set up to print exponent
|
|
DigitIndex = iCoord;
|
|
}
|
|
else if (iCoord == ExponentDigits)
|
|
CharBin = (NegativeExponent == 0) ? 10016 : 1792; // +/- sign for exponent
|
|
else if (iCoord == ExponentDigits + 1)
|
|
CharBin = 464663; // E for exponent
|
|
else if (iCoord < ExponentDigits + DecimalPlaces + 2)
|
|
DigitIndex = iCoord - ExponentDigits - 1; // fractional digit
|
|
else if (iCoord == ExponentDigits + DecimalPlaces + 2)
|
|
CharBin = 131072; // decimal point
|
|
else if (iCoord == ExponentDigits + DecimalPlaces + 3)
|
|
DigitIndex = DecimalPlaces; // integer digit
|
|
else if (iCoord == ExponentDigits + DecimalPlaces + 3 + NegativeValue)
|
|
CharBin = 1792; // minus sign for value
|
|
else
|
|
return 0.; // left of number
|
|
|
|
if (CharBin == 0) // has to be a digit
|
|
{
|
|
const int digits[] = { 480599, 139810, 464711, 476999, 280405, 476951, 481047, 279623, 481111, 477015 };
|
|
int Digit = iValue * pow(10, -DigitIndex) % 10;
|
|
CharBin = digits[Digit];
|
|
}
|
|
|
|
// convert binary to 4x5 array of points
|
|
int2 DigitCoord = int2(frac(StringCoords.x) * 4., StringCoords.y * 5.);
|
|
return float((CharBin >> (DigitCoord.x + DigitCoord.y * 4)) & 1);
|
|
}
|