frame method

Future<void> frame()

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;
  }
}