226 lines
6.8 KiB
HLSL
226 lines
6.8 KiB
HLSL
|
|
#include "ReShade.fxh"
|
||
|
|
|
||
|
|
texture FontTexture < source = "font.png"; >
|
||
|
|
{
|
||
|
|
Width = 512;
|
||
|
|
Height = 512;
|
||
|
|
Format = RGBA8;
|
||
|
|
};
|
||
|
|
sampler FontSampler {
|
||
|
|
Texture = FontTexture;
|
||
|
|
};
|
||
|
|
|
||
|
|
uniform bool TD_Show = false;
|
||
|
|
uniform bool TD_Enabled = false;
|
||
|
|
uniform float TD_World = 1.0;
|
||
|
|
uniform float TD_AI = 1.0;
|
||
|
|
|
||
|
|
|
||
|
|
// Define caracters for "Time Dilation ON" (size 32)
|
||
|
|
static const int ON_LENGTH = 17;
|
||
|
|
static float ON_CHARS[32] = {
|
||
|
|
84 - 32, 105 - 32, 109 - 32, 101 - 32, // T, i, m, e
|
||
|
|
32 - 32, 100 - 32, 105 - 32, 108 - 32, // , d, i, l
|
||
|
|
97 - 32, 116 - 32, 105 - 32, 111 - 32, // a, t, i, o
|
||
|
|
110 - 32, 32 - 32, 79 - 32, 78 - 32, // n, , O, N
|
||
|
|
32 - 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // ' ' + filling
|
||
|
|
};
|
||
|
|
|
||
|
|
// Define caracters for "Time Dilation OFF" (size 32)
|
||
|
|
static const int OFF_LENGTH = 17;
|
||
|
|
static float OFF_CHARS[32] = {
|
||
|
|
84 - 32, 105 - 32, 109 - 32, 101 - 32, // T, i, m, e
|
||
|
|
32 - 32, 100 - 32, 105 - 32, 108 - 32, // , d, i, l
|
||
|
|
97 - 32, 116 - 32, 105 - 32, 111 - 32, // a, t, i, o
|
||
|
|
110 - 32, 32 - 32, 79 - 32, 70 - 32, // n, , O, F
|
||
|
|
70 - 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F + filling
|
||
|
|
};
|
||
|
|
|
||
|
|
static const int WORLD_LEN = 7;
|
||
|
|
static float WORLD_CHARS[32] = {
|
||
|
|
87 - 32,111 - 32,114 - 32, 108 - 32, // W, o, r, l
|
||
|
|
100 - 32, 58 - 32, 32 - 32, 0, // d, :, ,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
||
|
|
};
|
||
|
|
|
||
|
|
static const int AI_LEN = 5;
|
||
|
|
static float AI_CHARS[32] = {
|
||
|
|
32 - 32, 65 - 32, 73 - 32, 58 - 32, // ' ', A, I, :
|
||
|
|
32 - 32, 0, 0, 0, // ' ' + filling
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
||
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
||
|
|
};
|
||
|
|
|
||
|
|
// Fonction SDF pour le rectangle (inchangée)
|
||
|
|
float sdRoundRect(float2 p, float2 b, float r) {
|
||
|
|
float2 q = abs(p) - b + r;
|
||
|
|
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Draw a character
|
||
|
|
float4 DrawChar(float2 uv, float2 pos, float2 charSize, float charIndex) {
|
||
|
|
float2 texSize = float2(14.0, 7.0);
|
||
|
|
float2 fontUV = float2(charIndex % texSize.x, floor(charIndex / texSize.x)) / texSize;
|
||
|
|
float2 fontUVSize = 1.0 / texSize;
|
||
|
|
float2 localUV = (uv - pos) / charSize;
|
||
|
|
float2 finalFontUV = fontUV + fontUVSize * localUV;
|
||
|
|
return tex2D(FontSampler, finalFontUV);
|
||
|
|
}
|
||
|
|
|
||
|
|
// Draw a characters array
|
||
|
|
float4 DrawText(float2 uv, float2 startPos, float2 charSize, float chars[32], int length) {
|
||
|
|
float4 col = float4(0, 0, 0, 0);
|
||
|
|
|
||
|
|
[unroll]
|
||
|
|
for (int i = 0; i < 32; i++)
|
||
|
|
{
|
||
|
|
if (i >= length) break;
|
||
|
|
|
||
|
|
float2 charPos = startPos + float2(i * charSize.x, 0.0);
|
||
|
|
|
||
|
|
// test si le pixel est dans le quad du caractère
|
||
|
|
if (uv.x >= charPos.x && uv.x < charPos.x + charSize.x &&
|
||
|
|
uv.y >= charPos.y && uv.y < charPos.y + charSize.y) {
|
||
|
|
float4 glyph = DrawChar(uv, charPos, charSize, chars[i]);
|
||
|
|
|
||
|
|
// proper alpha-over
|
||
|
|
col.rgb = lerp(col.rgb, glyph.rgb, glyph.a);
|
||
|
|
col.a = max(col.a, glyph.a);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return col;
|
||
|
|
}
|
||
|
|
|
||
|
|
float4 DrawFloat(float2 uv, float2 startPos, float2 charSize, float value) {
|
||
|
|
float4 col = float4(0,0,0,0);
|
||
|
|
|
||
|
|
float v = abs(value);
|
||
|
|
int iv = (int)(v * 100.0 + 0.5);
|
||
|
|
int i0 = iv / 100;
|
||
|
|
int i1 = (iv / 10) % 10;
|
||
|
|
int i2 = iv % 10;
|
||
|
|
|
||
|
|
float chars[4];
|
||
|
|
chars[0] = i0 + 16; // '0'
|
||
|
|
chars[1] = 14; // '.'
|
||
|
|
chars[2] = i1 + 16;
|
||
|
|
chars[3] = i2 + 16;
|
||
|
|
|
||
|
|
[unroll]
|
||
|
|
for (int i = 0; i < 4; i++)
|
||
|
|
{
|
||
|
|
float2 pos = startPos + float2(i * charSize.x, 0);
|
||
|
|
if (uv.x >= pos.x && uv.x < pos.x + charSize.x && uv.y >= pos.y && uv.y < pos.y + charSize.y) {
|
||
|
|
float4 g = DrawChar(uv, pos, charSize, chars[i]);
|
||
|
|
col.rgb = lerp(col.rgb, g.rgb, g.a);
|
||
|
|
col.a = max(col.a, g.a);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return col;
|
||
|
|
}
|
||
|
|
|
||
|
|
void AlphaBlend(inout float4 dst, float4 src) {
|
||
|
|
dst.rgb = lerp(dst.rgb, src.rgb, src.a);
|
||
|
|
dst.a = max(dst.a, src.a);
|
||
|
|
}
|
||
|
|
|
||
|
|
float4 PS_OSD(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target {
|
||
|
|
float4 col = tex2D(ReShade::BackBuffer, uv);
|
||
|
|
|
||
|
|
if (TD_Show) {
|
||
|
|
// ---- Size & position of the frame ----
|
||
|
|
float margin_top = 20.0;
|
||
|
|
|
||
|
|
// ---- aspect ratio correction for SDF ----
|
||
|
|
float2 screen_size = float2(BUFFER_WIDTH, BUFFER_HEIGHT);
|
||
|
|
float aspect = screen_size.x / screen_size.y;
|
||
|
|
|
||
|
|
// Pure UV Center (for text)
|
||
|
|
float2 center_uv = float2(0.5, margin_top / screen_size.y + 0.01);
|
||
|
|
float2 p = uv - center_uv;
|
||
|
|
p.x *= aspect;
|
||
|
|
|
||
|
|
// Compute total text length to center it horizontally
|
||
|
|
float totalLen = (TD_Enabled ? ON_LENGTH + WORLD_LEN + 4 + AI_LEN + 4 : OFF_LENGTH) ; // 4 = 3 chiffres + '.'
|
||
|
|
float2 charSize = float2(0.003, 0.02); // width, height
|
||
|
|
float charAdvance = charSize.x;
|
||
|
|
|
||
|
|
// SDF center (for the frame)
|
||
|
|
float textWidthUV = totalLen * charAdvance;
|
||
|
|
float padding = charAdvance * 1.0;
|
||
|
|
float2 size_uv = float2((textWidthUV * 0.5 + padding) * aspect, 20.0 / screen_size.y);
|
||
|
|
|
||
|
|
// ---- Thickness and radius in pixels ----
|
||
|
|
float thickness_px = 1.0;
|
||
|
|
float thickness = thickness_px * ReShade::PixelSize.y;
|
||
|
|
float radius_px = 2.0;
|
||
|
|
float radius = radius_px * ReShade::PixelSize.y;
|
||
|
|
|
||
|
|
float d = sdRoundRect(p, size_uv, radius);
|
||
|
|
|
||
|
|
// ---- Border drawing ----
|
||
|
|
if (abs(d) < thickness) {
|
||
|
|
float3 border = TD_Enabled ? float3(0.3, 1.0, 0.3) : float3(1.0, 0.3, 0.3); // green ON , red OFF
|
||
|
|
col.rgb = lerp(col.rgb, border, 0.85);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---- Draw the text (ON/OFF + World + AI) ----
|
||
|
|
|
||
|
|
float2 pen = center_uv;
|
||
|
|
pen.x -= totalLen * charAdvance * 0.5; // horizontal centering
|
||
|
|
pen.y -= charSize.y * 0.5; // vertical centering
|
||
|
|
|
||
|
|
float4 t0, t1, wv, t2, av;
|
||
|
|
float4 textCol = float4(0,0,0,0);
|
||
|
|
|
||
|
|
if (TD_Enabled) { // "Time Dilation ON"
|
||
|
|
t0 = DrawText(uv, pen, charSize, ON_CHARS, ON_LENGTH);
|
||
|
|
pen.x += charAdvance * ON_LENGTH;
|
||
|
|
|
||
|
|
// "World: "
|
||
|
|
t1 = DrawText(uv, pen, charSize, WORLD_CHARS, WORLD_LEN);
|
||
|
|
pen.x += charAdvance * WORLD_LEN;
|
||
|
|
|
||
|
|
// World value
|
||
|
|
wv = DrawFloat(uv, pen, charSize, TD_World);
|
||
|
|
pen.x += charAdvance * 4;
|
||
|
|
|
||
|
|
// "AI: "
|
||
|
|
t2 = DrawText(uv, pen, charSize, AI_CHARS, AI_LEN);
|
||
|
|
pen.x += charAdvance * AI_LEN;
|
||
|
|
|
||
|
|
// AI value
|
||
|
|
av = DrawFloat(uv, pen, charSize, TD_AI);
|
||
|
|
}
|
||
|
|
else // "Time Dilation OFF"
|
||
|
|
t0 = DrawText(uv, pen, charSize, OFF_CHARS, OFF_LENGTH);
|
||
|
|
|
||
|
|
// ---- Combine all glyphs ----
|
||
|
|
float4 combined = t0;
|
||
|
|
AlphaBlend(combined, t1);
|
||
|
|
AlphaBlend(combined, wv);
|
||
|
|
AlphaBlend(combined, t2);
|
||
|
|
AlphaBlend(combined, av);
|
||
|
|
|
||
|
|
float3 textColor = TD_Enabled ? float3(0.3,1.0,0.3) : float3(1.0,0.3,0.3);
|
||
|
|
combined.rgb *= textColor;
|
||
|
|
|
||
|
|
// ---- final blend ----
|
||
|
|
col.rgb = lerp(col.rgb, combined.rgb, combined.a);
|
||
|
|
}
|
||
|
|
|
||
|
|
return col;
|
||
|
|
}
|
||
|
|
|
||
|
|
technique TimeDilationOSD {
|
||
|
|
pass {
|
||
|
|
VertexShader = PostProcessVS;
|
||
|
|
PixelShader = PS_OSD;
|
||
|
|
}
|
||
|
|
}
|