* Copyright (c), Huawei Technologies Co., Ltd. 2025-2025. All rights reserved.
*/
import type { default as GlyphAtlas } from '../GlyphAtlas';
import shaders from '../shaders';
import { Program } from './Program';
export class TextProgram extends Program {
private maxVertices: number = 500000;
atlas: GlyphAtlas;
#uniformLoc: Record<string, WebGLUniformLocation | null> = {};
constructor(gl: WebGL2RenderingContext, atlas: GlyphAtlas) {
super(gl);
this.atlas = atlas;
}
initialize(): void {
const { vertexShader, fragmentShader } = this.getShaderCode();
this.program = this.createProgram(vertexShader, fragmentShader);
const gl = this.gl;
this.#uniformLoc.uScale = gl.getUniformLocation(this.program, 'uScale');
this.#uniformLoc.uTranslate = gl.getUniformLocation(this.program, 'uTranslate');
this.#uniformLoc.uResolution = gl.getUniformLocation(this.program, 'uResolution');
this.#uniformLoc.uAtlasSampler = gl.getUniformLocation(this.program, 'uAtlasSampler');
this.instanceBuffer = this.createBuffer(this.maxVertices * 12 * 4);
this.vao = gl.createVertexArray()!;
gl.bindVertexArray(this.vao);
gl.bindBuffer(gl.ARRAY_BUFFER, this.instanceBuffer);
const stride = 12 * 4;
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, stride, 0);
gl.vertexAttribDivisor(0, 1);
gl.enableVertexAttribArray(1);
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, stride, 8);
gl.vertexAttribDivisor(1, 1);
gl.enableVertexAttribArray(2);
gl.vertexAttribPointer(2, 4, gl.FLOAT, false, stride, 16);
gl.vertexAttribDivisor(2, 1);
gl.enableVertexAttribArray(3);
gl.vertexAttribPointer(3, 4, gl.FLOAT, false, stride, 32);
gl.vertexAttribDivisor(3, 1);
gl.bindVertexArray(null);
}
draw(params: { instanceCount: number, uniformData: Float32Array }): void {
const gl = this.gl;
const { instanceCount, uniformData } = params;
gl.useProgram(this.program);
gl.uniform2f(this.#uniformLoc.uScale, uniformData[0], uniformData[1]);
gl.uniform2f(this.#uniformLoc.uTranslate, uniformData[8], uniformData[9]);
gl.uniform2f(this.#uniformLoc.uResolution, uniformData[12], uniformData[13]);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this.atlas.texture);
gl.uniform1i(this.#uniformLoc.uAtlasSampler, 0);
gl.bindVertexArray(this.vao);
gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, instanceCount);
gl.bindVertexArray(null);
}
private getShaderCode(): { vertexShader: string; fragmentShader: string } {
return shaders.text;
}
}