diff --git a/external/reshade/shaders/OSD.fx b/external/reshade/shaders/OSD.fx new file mode 100644 index 0000000..07f8204 --- /dev/null +++ b/external/reshade/shaders/OSD.fx @@ -0,0 +1,254 @@ +#include "ReShade.fxh" + +texture FontTexture < source = "font.png"; > +{ + Width = 512; + Height = 512; + Format = RGBA8; +}; +sampler FontSampler { Texture = FontTexture; }; +// Time dilation +uniform bool OSD_ShowTD = false; +uniform bool TD_Enabled = false; +uniform float TD_World = 1.0; +uniform float TD_AI = 1.0; +// God mode +uniform bool OSD_ShowGodMode = false; +uniform bool GodMode_Enabled = false; +// Invulnerability +uniform bool OSD_ShowInvuln = false; +uniform bool Invulnerability_Enabled = false; +// --- Character arrays for labels --- +static const int ON_LENGTH = 2; +static float ON_CHARS[32] = { + 79-32, 78-32, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; // "ON" + +static const int OFF_LENGTH = 3; +static float OFF_CHARS[32] = { + 79-32, 70-32, 70-32, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; // "OFF" + +static const int TD_LABEL_LEN = 14; +static float TD_LABEL[32] = { + 84-32, 105-32, 109-32, 101-32, 32-32, 100-32, 105-32, 108-32, // Time dilation : + 97-32, 116-32, 105-32, 111-32, 110-32, 32-32,0,0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const int WORLD_LEN = 8; +static float WORLD_CHARS[32] = { + 32-32, 87-32, 111-32, 114-32, 108-32, 100-32, 58-32, 32-32, // World : + 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,32-32,0,0,0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// New labels +static const int GOD_LEN = 9; +static float GOD_CHARS[32] = { + 71-32, 111-32, 100-32, 32-32, 77-32, 111-32, 100-32, 101-32, // God Mode + 32 -32, 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 INV_LEN = 12; +static float INV_CHARS[32] = { // 73 103 110 111 114 101 32 104 105 116 115 32 + 73-32, 103-32, 110-32, 111-32, 114-32, 101-32, 32-32, 104-32, // "Ignore hits" + 105-32, 116-32, 115-32, 32-32, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// --- SDF Rectangle --- +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 text 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); + 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]); + col.rgb = lerp(col.rgb,glyph.rgb,glyph.a); + col.a = max(col.a,glyph.a); + } + } + return col; +} + +// --- Draw float number as text --- +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; + //float chars[4] = { i0 + 16, 14, i1 + 16, 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; +} + +// --- Alpha blend --- +void AlphaBlend(inout float4 dst, float4 src) { + dst.rgb = lerp(dst.rgb, src.rgb, src.a); + dst.a = max(dst.a, src.a); +} + +// --- Draw ON/OFF flag dynamically --- +float4 DrawFlag(float2 uv, inout float2 pen, float2 charSize, const float label[32], int labelLen, bool enabled) { + float4 combined = DrawText(uv, pen, charSize, label, labelLen); + pen.x += labelLen*charSize.x; + + float4 state = enabled ? DrawText(uv, pen, charSize, ON_CHARS, ON_LENGTH) + : DrawText(uv, pen, charSize, OFF_CHARS, OFF_LENGTH); + pen.x += (enabled ? ON_LENGTH : OFF_LENGTH)*charSize.x; + + AlphaBlend(combined, state); + return combined; +} + +// --- Pixel Shader --- +float4 PS_OSD(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_Target { + float4 col = tex2D(ReShade::BackBuffer, uv); + + if (!OSD_ShowTD && !OSD_ShowGodMode && !OSD_ShowInvuln) + return col; + + float margin_top = 20.0; + float2 screen_size = float2(BUFFER_WIDTH, BUFFER_HEIGHT); + float aspect = screen_size.x/screen_size.y; + float2 center_uv = float2(0.5, margin_top/screen_size.y+0.01); + float2 p = uv - center_uv; p.x *= aspect; + + // --- Frame rect --- + float charAdvance = 0.003; + float2 charSize = float2(0.003, 0.02); // widht * height + float totalLen = 0; + float3 color; + if (TD_Enabled && OSD_ShowTD) { + totalLen = TD_LABEL_LEN + ON_LENGTH + WORLD_LEN + 4 + AI_LEN + 4; + color = float3(0.3, 1.0, 0.3); // Green + } + if (!TD_Enabled && OSD_ShowTD) { + totalLen = TD_LABEL_LEN + OFF_LENGTH; + color = float3(1.0, 0.3, 0.3); // Red + } + if (GodMode_Enabled && OSD_ShowGodMode) { + totalLen = GOD_LEN + ON_LENGTH; + color = float3(0.3, 1.0, 0.3); + } + if (!GodMode_Enabled && OSD_ShowGodMode) { + totalLen = GOD_LEN + OFF_LENGTH; + color = float3(1.0, 0.3, 0.3); + } + if (Invulnerability_Enabled && OSD_ShowInvuln) { + totalLen = INV_LEN + ON_LENGTH; + color = float3(0.3, 1.0, 0.3); + } + if (!Invulnerability_Enabled && OSD_ShowInvuln) { + totalLen = INV_LEN + OFF_LENGTH; + color = float3(1.0, 0.3, 0.3); + } + + float2 size_uv = float2((totalLen* charAdvance * 0.5 + charAdvance * 1.0) * aspect, 20.0/screen_size.y); + 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); + if (abs(d)