拆分逻辑帧和渲染帧

This commit is contained in:
ww-rm
2025-11-08 17:17:25 +08:00
parent d6ca3cca92
commit 763d2e295e

View File

@@ -50,7 +50,7 @@ namespace SpineViewer.ViewModels.MainWindow
/// <summary> /// <summary>
/// 坐标轴顶点缓冲区 /// 坐标轴顶点缓冲区
/// </summary> /// </summary>
private readonly SFML.Graphics.VertexArray _axisVertices = new(SFML.Graphics.PrimitiveType.Lines, 2); // XXX: 暂时未使用 Dispose 释放 private readonly SFML.Graphics.VertexArray _axisVertices = new(SFML.Graphics.PrimitiveType.Lines, 4); // XXX: 暂时未使用 Dispose 释放
/// <summary> /// <summary>
/// 帧间隔计时器 /// 帧间隔计时器
@@ -87,6 +87,12 @@ namespace SpineViewer.ViewModels.MainWindow
_models = _vmMain.SpineObjects; _models = _vmMain.SpineObjects;
_renderer = _vmMain.SFMLRenderer; _renderer = _vmMain.SFMLRenderer;
_wallpaperRenderer = _vmMain.WallpaperRenderer; _wallpaperRenderer = _vmMain.WallpaperRenderer;
// 画一个很长的坐标轴, 用 1e9 比较合适
_axisVertices[0] = new(new(-1e9f, 0), _axisColor);
_axisVertices[1] = new(new(1e9f, 0), _axisColor);
_axisVertices[2] = new(new(0, -1e9f), _axisColor);
_axisVertices[3] = new(new(0, 1e9f), _axisColor);
} }
/// <summary> /// <summary>
@@ -194,7 +200,7 @@ namespace SpineViewer.ViewModels.MainWindow
/// </summary> /// </summary>
private SFML.Graphics.Color _axisColor = SFML.Graphics.Color.White; private SFML.Graphics.Color _axisColor = SFML.Graphics.Color.White;
public string BackgroundImagePath public string? BackgroundImagePath
{ {
get => _backgroundImagePath; get => _backgroundImagePath;
set => SetProperty(_backgroundImagePath, value, v => set => SetProperty(_backgroundImagePath, value, v =>
@@ -243,7 +249,7 @@ namespace SpineViewer.ViewModels.MainWindow
} }
}); });
} }
private string _backgroundImagePath; private string? _backgroundImagePath;
public Stretch BackgroundImageMode public Stretch BackgroundImageMode
{ {
@@ -475,16 +481,34 @@ namespace SpineViewer.ViewModels.MainWindow
_wallpaperRenderer.SetActive(true); _wallpaperRenderer.SetActive(true);
_renderer.SetActive(true); _renderer.SetActive(true);
float frameDelta; float delta;
float updateDelta;
while (!_cancelToken?.IsCancellationRequested ?? false) while (!_cancelToken?.IsCancellationRequested ?? false)
{ {
updateDelta = frameDelta = _clock.ElapsedTime.AsSeconds(); delta = _clock.ElapsedTime.AsSeconds();
_clock.Restart(); _clock.Restart();
UpdateLogicFrame(delta);
UpdateRenderFrame();
}
}
catch (Exception ex)
{
_logger.Debug(ex.ToString());
_logger.Fatal("Render task stopped, {0}", ex.Message);
MessagePopupService.Error(ex.ToString());
}
finally
{
_renderer.SetActive(false);
_wallpaperRenderer.SetActive(false);
}
}
private void UpdateLogicFrame(float delta)
{
// 计算实时帧率, 1 秒刷新一次 // 计算实时帧率, 1 秒刷新一次
_accumFpsCount++; _accumFpsCount++;
_accumFpsTime += frameDelta; _accumFpsTime += delta;
if (_accumFpsTime > 1f) if (_accumFpsTime > 1f)
{ {
_realTimeFps = _accumFpsCount / _accumFpsTime; _realTimeFps = _accumFpsCount / _accumFpsTime;
@@ -494,26 +518,43 @@ namespace SpineViewer.ViewModels.MainWindow
} }
// 停止更新的时候只是时间不前进, 但是坐标变换还是要更新, 否则无法移动对象 // 停止更新的时候只是时间不前进, 但是坐标变换还是要更新, 否则无法移动对象
if (!_isUpdating) updateDelta = 0; if (!_isUpdating) delta = 0;
// 加上要快进的量 // 加上要快进的量
lock (_forwardDeltaLock) lock (_forwardDeltaLock)
{ {
updateDelta += _forwardDelta; delta += _forwardDelta;
_forwardDelta = 0; _forwardDelta = 0;
} }
// 更新模型对象时间
lock (_models.Lock)
{
foreach (var sp in _models.Where(sp => sp.IsShown && (!_renderSelectedOnly || sp.IsSelected)).Reverse())
{
if (_cancelToken?.IsCancellationRequested ?? true) break; // 提前中止
sp.Update(0); // 避免物理效果出现问题
sp.Update(delta * _speed);
}
}
}
private void UpdateRenderFrame()
{
// 同步视图
if (_wallpaperView)
{
using var view = _renderer.GetView(); using var view = _renderer.GetView();
_wallpaperRenderer.SetView(view); _wallpaperRenderer.SetView(view);
}
if (_vmMain.IsVisible) _renderer.Clear(_backgroundColor); // 更新背景图位置和缩放
if (_wallpaperView) _wallpaperRenderer.Clear(_backgroundColor);
// 渲染背景
lock (_bgLock) lock (_bgLock)
{ {
if (_backgroundImageSprite is not null) if (_backgroundImageSprite is not null)
{ {
using var view = _renderer.GetView();
var bg = _backgroundImageSprite; var bg = _backgroundImageSprite;
var viewSize = view.Size; var viewSize = view.Size;
var bgSize = bg.Texture.Size; var bgSize = bg.Texture.Size;
@@ -536,20 +577,26 @@ namespace SpineViewer.ViewModels.MainWindow
bg.Scale = new(signX * scaleX, signY * scaleY); bg.Scale = new(signX * scaleX, signY * scaleY);
bg.Position = view.Center; bg.Position = view.Center;
bg.Rotation = view.Rotation; bg.Rotation = view.Rotation;
if (_vmMain.IsVisible) _renderer.Draw(bg);
if (_wallpaperView) _wallpaperRenderer.Draw(bg);
} }
} }
// 清除背景
if (_vmMain.IsVisible) _renderer.Clear(_backgroundColor);
if (_wallpaperView) _wallpaperRenderer.Clear(_backgroundColor);
// 渲染背景
lock (_bgLock)
{
if (_backgroundImageSprite is not null)
{
if (_vmMain.IsVisible) _renderer.Draw(_backgroundImageSprite);
if (_wallpaperView) _wallpaperRenderer.Draw(_backgroundImageSprite);
}
}
// 渲染坐标轴
if (_showAxis && _vmMain.IsVisible) if (_showAxis && _vmMain.IsVisible)
{ {
// 画一个很长的坐标轴, 用 1e9 比较合适
_axisVertices[0] = new(new(-1e9f, 0), _axisColor);
_axisVertices[1] = new(new(1e9f, 0), _axisColor);
_renderer.Draw(_axisVertices);
_axisVertices[0] = new(new(0, -1e9f), _axisColor);
_axisVertices[1] = new(new(0, 1e9f), _axisColor);
_renderer.Draw(_axisVertices); _renderer.Draw(_axisVertices);
} }
@@ -560,9 +607,6 @@ namespace SpineViewer.ViewModels.MainWindow
{ {
if (_cancelToken?.IsCancellationRequested ?? true) break; // 提前中止 if (_cancelToken?.IsCancellationRequested ?? true) break; // 提前中止
sp.Update(0); // 避免物理效果出现问题
sp.Update(updateDelta * _speed);
if (_vmMain.IsVisible) if (_vmMain.IsVisible)
{ {
// 为选中对象绘制一个半透明背景 // 为选中对象绘制一个半透明背景
@@ -585,22 +629,10 @@ namespace SpineViewer.ViewModels.MainWindow
} }
} }
// 显示内容
if (_vmMain.IsVisible) _renderer.Display(); if (_vmMain.IsVisible) _renderer.Display();
if (_wallpaperView) _wallpaperRenderer.Display(); if (_wallpaperView) _wallpaperRenderer.Display();
} }
}
catch (Exception ex)
{
_logger.Debug(ex.ToString());
_logger.Fatal("Render task stopped, {0}", ex.Message);
MessagePopupService.Error(ex.ToString());
}
finally
{
_renderer.SetActive(false);
_wallpaperRenderer.SetActive(false);
}
}
public RendererWorkspaceConfigModel WorkspaceConfig public RendererWorkspaceConfigModel WorkspaceConfig
{ {