Esta é uma demonstração de renderizar texto diretamente na GPU usando os contornos do vetor definidos pela fonte.
Os contornos de um glifo são convertidos em uma lista de curvas bezier quadráticas individuais (definidas por seus pontos de controle), que são carregados na GPU.
Um quad é gerado para cada glifo e o shader do pixel determina se cada pixel está dentro ou fora do glifo. Para fazer isso, o número de enrolamento do pixel é calculado cruzando um raio com as curvas bezier. Em todo cruzamento, o raio entra ou sai da área preenchida, conforme determinado pela direção da curva bezier em relação ao raio. A cada saída, o número de enrolamento é aumentado em um e a cada entrada o número de enrolamento diminui em um. Depois de considerar todos os cruzamentos, o número de enrolamento será diferente de zero se o pixel estiver dentro do contorno.
A direção dos raios não importa para esse cálculo do número de enrolamento, mas a matemática pode ser bastante simplificada usando raios paralelos ao eixo x. Ao subtrair a posição da amostra dos pontos de controle das curvas bezier, o sistema de coordenadas é deslocado para que a origem do raio esteja em
Para encontrar as interseções entre um raio e uma única curva bezier, lembre -se de que uma curva quadrática de Bezier é descrita pela seguinte fórmula (para o fundo sobre curvas bezier, veja a beleza e o primer):
Pegando apenas o componente y e aplicando a condição
Que pode ser reorganizado em:
Para que possa ser resolvido usando a fórmula quadrática:
Substituindo
A equação quadrática pode ter zero, uma ou duas soluções. Além disso, uma solução
Nesse ponto, as interseções entre o raio e a curva bezier foram identificadas, mas elas ainda precisam ser classificadas como entrada ou saída. A demonstração fornecida por Dobbie calcula explicitamente a derivada da curva bezier para cada
Portanto, a curva bezier cruza o eixo x em uma direção fixa em cada solução e, combinada com a convenção para a orientação do contorno,
Uma abordagem diferente para entender esse relacionamento é perceber que, devido aos diferentes sinais usados nas soluções e na raiz quadrada sendo não negativa,
Se o parâmetro
O anti-aliasing ao longo da direção do raio é implementado considerando uma janela do tamanho de um pixel em torno da origem do raio. Se uma interseção cair nessa janela, o número de enrolamento será alterado apenas fracionalmente para calcular a cobertura do pixel. O peso fracionário é determinado pela distância da borda esquerda do pixel (isso é consistente com os raios apontando para a direita). Ao considerar as seções individuais, pode-se ver que isso calcula exatamente a cobertura unidimensional.
Observe que também temos que considerar as interseções um pouco atrás da origem dos raios, mas a implementação primeiro calcula qualquer interseção com o eixo x e verifica a posição X, para que não mude muito. Uma maneira diferente de pensar sobre isso é que a condição
Para anti-aliasing completo, podemos usar vários raios ao longo de diferentes direções (por exemplo, uma ao longo do eixo x e uma ao longo do eixo y).
Esse tipo de técnica está sujeito a artefatos da precisão numérica limitada dos números de pontos flutuantes. A imagem abaixo mostra uma instância desses artefatos quando ampliada totalmente (e sabendo para onde procurar). No entanto, achei que essa implementação já está numericamente estável. Quaisquer artefatos restantes podem ser eliminados usando o algoritmo SLUG, que não é implementado aqui devido à patente associada.
Essa demonstração também não implementa nenhuma otimização de desempenho (como o Banding) e pode ter alto uso de GPU em alguns cenários e ao usar fontes muito complexas.

Clone o projeto recursivamente para inicializar os submódulos para as dependências (ou executar git submodule update --init se você já clonou o repositório):
git clone --recursive https://github.com/GreenLightning/gpu-font-rendering.git
cd gpu-font-rendering
# Note: CMake will create the build directory.
cmake -S . -B build
make -j8 --directory build
No Windows, você pode querer usar o CMake GUI e/ou o Visual Studio.
No Linux, você pode precisar instalar pacotes adicionais para o OpenGL Development (por exemplo, sudo apt-get install xorg-dev libgl1-mesa-dev para ubuntu).
./build/main
O programa exige que os diretórios de fonts e shaders estejam no diretório atual para carregar seus recursos. Se você conseguir uma janela preta , esse é provavelmente o problema. Verifique seu diretório de trabalho e verifique o console para erros.
Testado no Windows 10, MacOS Monterey e Ubuntu 22.04.