Graphics constructor

Graphics(
  1. HTMLCanvasElement _canvas, {
  2. int batchCapacityInBytes = 65536,
})

Initializes the graphics system with the given HTML canvas element.

  • _canvas: The HTMLCanvasElement to render to.
  • batchCapacityInBytes: The initial capacity of the vertex buffer for batched rendering, in bytes. Larger values can improve performance by reducing draw calls but will consume more memory. Defaults to 65536 bytes (64KB).

Typically, you don't instantiate this class yourself. Instead, you use the app.gfx member provided by the App class.

Implementation

Graphics(this._canvas, {int batchCapacityInBytes = 65536}) {
  _batchCapacityInBytes = batchCapacityInBytes;
  _initialBatchCapacityQuads = _batchCapacityInBytes ~/ (_vertexSizeInBytes * 4);
  _currentBatchCapacityVertices = _initialBatchCapacityQuads * 4;
  _batchedInterleavedData = Float32List(_initialBatchCapacityQuads * 4 * _floatsPerVertex);

  _canvas
    ..onWebGlContextLost.listen((Event event) {
      event.preventDefault();
      warn("[webgl] :: context lost");
    })
    ..onWebGlContextRestored.listen((_) {
      warn("[webgl] :: context restored");
    });

  var glContext = _canvas.getContext("webgl2", {"alpha": false} as dynamic);
  if (glContext == null) throw Exception("Can't create WEBGL!");
  gl = glContext as WebGL2RenderingContext;

  _byteDataView = _batchedInterleavedData.buffer.asByteData();
  resetMatrix();

  _program = _createProgramFromSources(gl, vertexShaderSource, fragmentShaderSource)!;

  _positionAttributeLocation = gl.getAttribLocation(_program, 'a_position');
  _texcoordAttributeLocation = gl.getAttribLocation(_program, 'a_texcoord');
  _colorAttributeLocation = gl.getAttribLocation(_program, 'a_color');

  if (_positionAttributeLocation < 0 || _texcoordAttributeLocation < 0 || _colorAttributeLocation < 0) {
    die('One or more attributes not found in the _program.');
  }

  _projectionMatrixLocation = gl.getUniformLocation(_program, 'u_projectionMatrix')!;
  _textureLocation = gl.getUniformLocation(_program, 'u_texture')!;

  _vao = gl.createVertexArray()!;
  gl.bindVertexArray(_vao);

  _interleavedBuffer = gl.createBuffer()!;
  gl.bindBuffer(GL.ARRAY_BUFFER, _interleavedBuffer);

  gl.bufferData(GL.ARRAY_BUFFER, (_batchedInterleavedData.lengthInBytes).toJS, GL.STREAM_DRAW);

  _quadIndexBuffer = gl.createBuffer()!;
  gl.bindBuffer(GL.ELEMENT_ARRAY_BUFFER, _quadIndexBuffer);

  final int maxQuads = _currentBatchCapacityVertices ~/ 4;
  final int maxIndices = maxQuads * 6;
  final Uint16List quadIndices = Uint16List(maxIndices);
  for (int i = 0; i < maxQuads; ++i) {
    final int vIndex = i * 4;

    quadIndices
      ..[i * 6 + 0] = (vIndex + 0)
      ..[i * 6 + 1] = (vIndex + 1)
      ..[i * 6 + 2] = (vIndex + 2)
      ..[i * 6 + 3] = (vIndex + 2)
      ..[i * 6 + 4] = (vIndex + 1)
      ..[i * 6 + 5] = (vIndex + 3);
  }

  gl
    ..bufferData(GL.ELEMENT_ARRAY_BUFFER, quadIndices.buffer.asUint8List().toJS, GL.STATIC_DRAW)
    ..enableVertexAttribArray(_positionAttributeLocation)
    ..vertexAttribPointer(_positionAttributeLocation, 2, GL.FLOAT, false, _vertexSizeInBytes, 0)
    ..enableVertexAttribArray(_texcoordAttributeLocation)
    ..vertexAttribPointer(
      _texcoordAttributeLocation,
      2,
      GL.FLOAT,
      false,
      _vertexSizeInBytes,
      2 * Float32List.bytesPerElement,
    )
    ..enableVertexAttribArray(_colorAttributeLocation)
    ..vertexAttribPointer(
      _colorAttributeLocation,
      4,
      GL.UNSIGNED_BYTE,
      true,
      _vertexSizeInBytes,
      4 * Float32List.bytesPerElement,
    )
    ..useProgram(_program)
    ..disable(GL.SCISSOR_TEST)
    ..lineWidth(_renderState.lineWidth);

  final JSAny? param = gl.getParameter(GL.ALIASED_LINE_WIDTH_RANGE);
  final Float32List lineWidthRange =
      param.isA<JSFloat32Array>() ? (param as JSFloat32Array).toDart : Float32List.fromList([1.0, 1.0]);

  _lineWidthMin = lineWidthRange[0];
  _lineWidthMax = lineWidthRange[1];

  set2DProjection(width: _canvas.clientWidth.toDouble(), height: _canvas.clientHeight.toDouble());

  _renderState
    ..isScissorEnabled = false
    ..blendMode.apply(gl);
  Texture.white = Texture.createWhite(gl);
}