Core - Keep small LEDs addressable at reduced render scales

Sample each LED from its unsnapped absolute boundary instead of the
render-grid-aligned AbsoluteRectangle, ensuring at least one pixel and
clamping to the texture. Also apply the saved render scale at startup.
This commit is contained in:
RobertBeekman committed 2026-10-17 20:38:30 +02:00
1 parent df9ab302ca
commit e1357f1bf0
2 files changed
+28 -9

No files matched your search

+21 -8
View File
@@ -29,19 +29,32 @@ public sealed class SKTexture : ITexture, IDisposable
foreach (ArtemisDevice artemisDevice in devices) foreach (ArtemisDevice artemisDevice in devices)
{ {
foreach (ArtemisLed artemisLed in artemisDevice.Leds) foreach (ArtemisLed artemisLed in artemisDevice.Leds)
{ _ledRects[artemisLed.RgbLed] = CreateSampleRect(artemisLed.RgbLed.AbsoluteBoundary, scale, width, height);
_ledRects[artemisLed.RgbLed] = SKRectI.Create(
(int)(artemisLed.AbsoluteRectangle.Left * RenderScale),
(int)(artemisLed.AbsoluteRectangle.Top * RenderScale),
(int)(artemisLed.AbsoluteRectangle.Width * RenderScale),
(int)(artemisLed.AbsoluteRectangle.Height * RenderScale)
);
}
} }
} }
#endregion #endregion
private static SKRectI CreateSampleRect(Rectangle boundary, float scale, int width, int height)
{
(int left, int right) = ScaleSpan(boundary.Location.X, boundary.Size.Width, scale, width);
(int top, int bottom) = ScaleSpan(boundary.Location.Y, boundary.Size.Height, scale, height);
return new SKRectI(left, top, right, bottom);
}
private static (int Start, int End) ScaleSpan(float location, float size, float scale, int max)
{
float start = location * scale;
float end = (location + size) * scale;
if (end <= 0 || start >= max)
return (0, 0);
// Always sample at least one pixel
int startPixel = Math.Clamp(start.RoundToInt(), 0, max - 1);
int endPixel = Math.Clamp(end.RoundToInt(), startPixel + 1, max);
return (startPixel, endPixel);
}
internal Color GetColorAtRenderTarget(in RenderTarget renderTarget) internal Color GetColorAtRenderTarget(in RenderTarget renderTarget)
{ {
if (_image == null) return Color.Transparent; if (_image == null) return Color.Transparent;
+7 -1
View File
@@ -47,6 +47,7 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
_preferredGraphicsContext.SettingChanged += PreferredGraphicsContextOnSettingChanged; _preferredGraphicsContext.SettingChanged += PreferredGraphicsContextOnSettingChanged;
Utilities.ShutdownRequested += UtilitiesOnShutdownRequested; Utilities.ShutdownRequested += UtilitiesOnShutdownRequested;
ApplyRenderScaleMultiplier();
_surfaceManager = new SurfaceManager(this, GraphicsContext, _targetFrameRateSetting.Value, (float) _renderScaleSetting.Value); _surfaceManager = new SurfaceManager(this, GraphicsContext, _targetFrameRateSetting.Value, (float) _renderScaleSetting.Value);
} }
@@ -189,9 +190,14 @@ internal class RenderService : IRenderService, IRenderer, IDisposable
_surfaceManager.UpdateTargetFrameRate(_targetFrameRateSetting.Value); _surfaceManager.UpdateTargetFrameRate(_targetFrameRateSetting.Value);
} }
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e) private void ApplyRenderScaleMultiplier()
{ {
RenderScale.SetRenderScaleMultiplier((int) (1 / _renderScaleSetting.Value)); RenderScale.SetRenderScaleMultiplier((int) (1 / _renderScaleSetting.Value));
}
private void RenderScaleSettingOnSettingChanged(object? sender, EventArgs e)
{
ApplyRenderScaleMultiplier();
_surfaceManager.UpdateRenderScale((float) _renderScaleSetting.Value); _surfaceManager.UpdateRenderScale((float) _renderScaleSetting.Value);
} }