Files
ReshadePluginsAddon/external/reshade/shaders/TimeDilationOSD.fx

226 lines
6.8 KiB
HLSL
Raw Normal View History

2025-12-31 14:29:36 +01:00
#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;
}
}