Měsíc WebGL. Den 30. Vykreslování textu ve WebGL

Toto je série blogových příspěvků souvisejících s WebGL. Nový příspěvek bude k dispozici každý den


Připojte se do seznamu adresátů a získejte nové příspěvky přímo do vaší doručené pošty

Zdrojový kód je k dispozici zde

Postaveno s

Ahoj 👋

Vítejte v měsíci WebGL.

V předchozích tutoriálech jsme se zaměřovali na vykreslování 2D a 3D tvarů, ale nikdy jsme nevykreslili text, což je důležitá součást každé aplikace.

V tomto článku se podíváme na možné způsoby vykreslování textu.

Překryvná vrstva HTML

Nejjasnějším a nejjednodušším řešením by bylo vykreslit text pomocí HTML a umístit jej nad plátno webgl, ale to bude fungovat pouze pro 2D scény, 3D věci budou vyžadovat určité výpočty pro výpočet polohy textu a transformací css

Plátno jako textura

V širším spektru případů lze použít jinou techniku. Vyžaduje to několik kroků

  1. vytvořit další plátno
  2. získejte 2D kontext (canvas.getContext('2d') )
  3. vykreslit text pomocí fillText nebo strokeText
  4. použijte toto plátno jako webgl texturu se správnými souřadnicemi textury

Vzhledem k tomu, že textura je rastrovaný obrázek, ztratí kvalitu, když se "přiblížíte" k objektu

Textura glyfů

Každý font je ve skutečnosti sada „glyfů“ – každý symbol je vykreslen v signle obrázku

A | B | C | D | E | F | G |
---------------------------
H | I | J | K | L | M | N |
...

Každé písmeno bude mít své vlastní "vlastnosti", jako je šířka (i je tenčí než W ), výška (o vs L ) atd.
Tyto vlastnosti ovlivní způsob vytváření obdélníků obsahujících každé písmeno

Obvykle kromě textury budete potřebovat objekt javascript popisující všechny tyto vlastnosti a souřadnice v původním obrázku textury

const font = {
    textureSize: {
        width: 512,
        height: 512,
    },
    height: 32,
    glyphs: {
        a: { x: 0, y: 0, height: 32, width: 16 },
        b: { x: 16, y: 0, height: 32, width: 14 },
    },
    // ...
};

a k vykreslení nějakého textu budete potřebovat něco takového

function getRects(text, sizeMultiplier) {
    let prevLetterX = 0;

    const rects = text.split('').map((symbol) => {
        const glyph = font.glyphs[symbol];

        return {
            x: prevLetterX,
            y: font.height - glyph.height,
            width: glyph.width * sizeMultiplier,
            height: glyph.height * sizeMultiplier,
            texCoords: glyph,
        };
    });
}

Později budou tyto "obdélníky" použity pro generování dat atributů

import { createRect } from './gl-helpers';

function generateBuffers(rects) {
    const attributeBuffers = {
        position: [],
        texCoords: [],
    };

    rects.forEach((rect, index) => {
        attributeBuffers.position.push(...createRect(rect.x, rect.y, rect.width, rect.height)),
            attributeBuffers.texCoords.push(
                ...createRect(rect.texCoords.x, rect.texCoords.y, rect.texCoords.width, rect.texCoords.height)
            );
    });

    return attributeBuffers;
}

Existuje balíček gl-render-text, který dokáže vykreslit fonty založené na texturách

Triangulace písma

Protože webgl je schopen kreslit trojúhelníky, dalším zjevným řešením by bylo rozdělit každé písmeno na trojúhelníky
Zdá se, že jde o velmi složitý úkol 😢

Naštěstí – existuje balíček fontpath-gl, který přesně tohle dělá

Písmo pole vzdálenosti se znaménkem

Další technika vykreslování textu v OpenGL/WebGL

Více informací naleznete zde


Připojte se do seznamu adresátů a získejte nové příspěvky přímo do vaší doručené pošty

Zdrojový kód je k dispozici zde

Postaveno s