ssi-patterns / ssi-pattern-connections-visualization / src / rendering / webgl / programs / common / program.ts
program.ts
Raw
/**
 * Sigma.js WebGL Renderer Program
 * ================================
 *
 * Class representing a single WebGL program used by sigma's WebGL renderer.
 * @module
 */
import { loadVertexShader, loadFragmentShader, loadProgram } from "../../shaders/utils";

export interface RenderParams {
  width: number;
  height: number;
  ratio: number;
  matrix: Float32Array;
  scalingRatio: number;
  correctionRatio: number;
}

export interface IProgram {
  bufferData(): void;
  allocate(capacity: number): void;
  bind(): void;
  render(params: RenderParams): void;
}

/**
 * Abstract Program class.
 *
 * @constructor
 */
export abstract class AbstractProgram implements IProgram {
  points: number;
  attributes: number;
  gl: WebGLRenderingContext;
  array: Float32Array = new Float32Array();
  buffer: WebGLBuffer;
  vertexShaderSource: string;
  vertexShader: WebGLShader;
  fragmentShaderSource: string;
  fragmentShader: WebGLShader;
  program: WebGLProgram;

  constructor(
    gl: WebGLRenderingContext,
    vertexShaderSource: string,
    fragmentShaderSource: string,
    points: number,
    attributes: number,
  ) {
    this.points = points;
    this.attributes = attributes;
    this.gl = gl;
    this.vertexShaderSource = vertexShaderSource;
    this.fragmentShaderSource = fragmentShaderSource;
    const buffer = gl.createBuffer();
    if (buffer === null) throw new Error("AbstractProgram: error while creating the buffer");
    this.buffer = buffer;
    gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);

    this.vertexShader = loadVertexShader(gl, this.vertexShaderSource);
    this.fragmentShader = loadFragmentShader(gl, this.fragmentShaderSource);
    this.program = loadProgram(gl, [this.vertexShader, this.fragmentShader]);
  }

  bufferData(): void {
    const gl = this.gl;
    gl.bufferData(gl.ARRAY_BUFFER, this.array, gl.DYNAMIC_DRAW);
  }

  allocate(capacity: number): void {
    this.array = new Float32Array(this.points * this.attributes * capacity);
  }

  hasNothingToRender(): boolean {
    return this.array.length === 0;
  }

  abstract bind(): void;
  abstract render(params: RenderParams): void;
}