frame method
Drives a single frame. Call from a Ticker
/ SchedulerBinding
.
Implementation
Future<void> frame() async {
// Bail during resize/context swap
if (_isResizing || _inFrame) return;
// Guard readiness up front
if (_camera == null) return;
_inFrame = true;
try {
_perf?.beginFrame();
// Always sort immediately when rendering
if (_splatBuffer != null && _splatCount > 0) {
final vp = _projectionMatrix.multiplied(_viewMatrix);
_depthSorter.runSort(vp, _splatBuffer!, _splatCount);
}
_perf?.markGpuBegin(_gl);
_gl
..viewport(0, 0, _camera!.width, _camera!.height)
..clearColor(0, 0, 0, 0)
..clear(WebGL.COLOR_BUFFER_BIT | WebGL.DEPTH_BUFFER_BIT)
..disable(WebGL.DEPTH_TEST)
..disable(WebGL.BLEND); // no blend for skydome
if (_bg?.isReady ?? false) {
_bg!.execute(_gl, _camera!); // your Skydome pass
}
// Only draw splats if we have data
if (_splatBuffer != null && _splatCount > 0) {
_splatPass.execute(
_gl,
_camera!,
projectionMatrix: _projectionMatrix,
viewMatrix: _viewMatrix,
);
}
_gl.flush();
_perf?.markGpuEnd(_gl);
_lastPerfStats = _perf?.endFrame(_gl);
} catch (_) {
// Recovery path on GL/Program invalidation
await _recoverFromContextLoss();
} finally {
_inFrame = false;
}
}