1 pontos por GN⁺ 2024-11-21 | 1 comentários | Compartilhar no WhatsApp
  • Os jaggies e o pixel crawling gerados pela rasterização ficam mais visíveis em movimento do que em imagens estáticas, e o texto compara vários métodos de anti-aliasing com uma demo de círculo em WebGL
  • SSAA, MSAA e FXAA têm limitações diferentes: custo de downsampling, dependência de hardware e distorção de forma por pós-processamento
  • O Analytical Anti-Aliasing, quando conhece a borda matemática da forma, usa um signed distance field para calcular a distância até a borda e aplica um alpha fade de 1 pixel ao redor da aresta
  • O tamanho do pixel pode ser calculado diretamente a partir do objeto e do tamanho de renderização em 2D; com perspectiva 3D, são necessárias Screen Space derivatives como dFdx, dFdy e fwidth
  • Pode ser implementado até em WebGL 1.0/OpenGLES 2.0 sem buffers adicionais nem hardware especial, mas exige o SDF da forma inteira e tem limitações com formas de alta frequência menores que 1 pixel

Anti-aliasing visto com uma demo de círculo em WebGL

  • O objetivo do texto é examinar várias técnicas de Anti-Aliasing para reduzir os jaggies da rasterização e, ao final, apresentar uma implementação de Analytical Anti-Aliasing
  • A comparação cobre SSAA, MSAA, FXAA, a família MLAA/SMAA e AAA
  • A demo desenha um círculo em movimento em um canvas WebGL e parte da premissa de que anti-aliasing deve ser entendido no movimento, não em imagens estáticas
  • O canvas de exemplo renderiza na resolução nativa do dispositivo, e a caixa vermelha mostra uma visualização ampliada em 4x
  • Para telas de alta resolução em que o aliasing é difícil de ver, há alternância entre resoluções de renderização Native, 1/2, 1/4 e 1/8, usando integer scaling

O problema criado pela renderização básica de um círculo

  • A forma mais simples de renderizar um círculo é fazer o fragment shader emitir cor quando length(uv) < 1.0 e, caso contrário, usar discard
  • O círculo não depende da resolução da geometria em si: o shader decide o que está dentro e fora do círculo sobre um quad feito com 4 vértices
  • varying vec2 uv é interpolado para cada fragment e fornece coordenadas centradas em 0, no intervalo de -1 a +1
  • Esse método corresponde a Alpha testing, e o valor de length(uv) se conecta depois ao signed distance field usado no AAA
  • Em baixa resolução, o círculo fica blocky, e ao se mover aparecem com força o pixel crawling e o wobble, em que fileiras de pixels surgem e desaparecem
  • As resoluções 1/4 e 1/8 não servem apenas para ampliação simples, mas também como exemplo de elementos pequenos ou distantes em 3D

SSAA: simples, mas caro por causa do downsampling

  • SSAA é a sigla de Super Sampling Anti-Aliasing e consiste em renderizar em uma resolução maior e depois fazer downsample para uma menor
  • Na implementação de exemplo, o círculo é desenhado em uma texture de tamanho (canvas.width / resDiv) * 2, (canvas.height / resDiv) * 2, depois sofre downsampling para o framebuffer em resolução padrão e por fim é enviado à tela com blit
  • Renderizar em 2x de resolução usa 4 pixels de entrada para cada pixel de saída, então memória e carga computacional aumentam 4x
  • No exemplo real, o anti-aliasing acontece, mas parece mais fraco do que o esperado
    • Deveriam existir 4 níveis de transparência, mas na prática há trechos em que só 2 níveis aparecem
    • Em baixa resolução, os 4 níveis de transparência surgem principalmente perto de diagonais de 45 graus
    • Nas partes inferiores alinhadas aos eixos, aparecem apenas totalmente opaco e 50% transparente, sem os níveis de 25% e 75%
  • O motivo é que a própria forma do círculo não é amostrada em 2x de resolução; o que é reamostrado é um resultado do círculo já quantizado
  • Como a implementação do exemplo usa uma texture em 2x de resolução com interpolação linear, na prática ela consome 5x mais VRAM
  • Um SSAA de verdade funciona amostrando a cena várias vezes e combinando os resultados sem buffer intermediário, o que exige integração profunda com o pipeline de renderização

MSAA: prós e contras da amostragem baseada em hardware

  • MSAA é uma forma de supersampling, mas em geral se aplica ao contorno dos modelos, à geometria sobreposta e às bordas de texturas com Alpha to Coverage ativado
  • A implementação depende do hardware da GPU e do fornecedor gráfico, e o nível de suporte varia conforme hardware e driver
  • Como o WebGL 1 não oferece suporte a MSAA, o exemplo usa um contexto WebGL 2
  • A interface da demo compara No MSAA, 2x, 4x, 8x, 16x, 32x e 64x, além das resoluções de renderização Native, 1/2, 1/4 e 1/8
  • O número máximo de amostras suportadas é lido com gl.MAX_SAMPLES, e só as opções disponíveis ficam ativadas
  • Em GPUs móveis, a chamada renderbufferStorageMultisample() pode na prática ser forçada para 4x MSAA
    • No Android, mesmo que a interface permita selecionar 2x, o driver força 4x
    • Em iPhone e iPad, selecionar 2x vira 4x, e a transparência é arredondada para valores próximos de múltiplos de 50%, criando bordas duplas no exemplo
  • Como o MSAA fica a cargo do hardware, o dispositivo do usuário pode não oferecer o recurso necessário
  • O padrão de amostragem pode produzir resultados diferentes do esperado e, dependendo do hardware, os níveis de transparência na borda do círculo podem parecer em “ordem errada”
  • Ainda assim, ele continua poderoso em certas condições
    • forward rendering
    • geometry não muito densa
    • GPUs com arquitetura de tile-based rendering
  • Rahul Prasad explica que, no mobile, o MSAA não é tão caro quanto no desktop e que, em algumas GPUs móveis, 4x MSAA pode sair de graça
  • Como material extra, é citado o MSAA color resolve deep-dive do KhronosGroup Vulkan-Samples

O fluxo de pós-processamento que leva a MLAA, SMAA e FXAA

  • Um artigo de 2009 de Alexander Reshetov propôs uma abordagem que encontra bordas em imagens com aliasing blocky e reduz arestas em bloco com regras de filtragem para cada formato de pixel
  • Essa abordagem baseada em morfologia levou ao MLAA e depois foi aprimorada no SMAA, com foco maior na remoção de artefatos sub-pixel
  • Alguns usuários consideravam a família MLAA/SMAA borrada demais, o que levou à expressão “vaseline on the screen”
  • O anti-aliasing por pós-processamento mostra a mudança do AA para uma base em shader, afastando-se do suporte de hardware instável

FXAA 3.11: estrutura e limites de um AA de pós-processamento rápido

  • FXAA é o algoritmo Fast approximate anti-aliasing de Timothy Lottes, inspirado em MLAA
  • A última versão pública é o FXAA 3.11, e a demo se baseia na versão lançada em 12 de agosto de 2011
  • A demo compara a cena do círculo nas resoluções Native, 1/2, 1/4 e 1/8
  • A configuração padrão usa FXAA_PC 1, FXAA_QUALITY_PRESET 12, fxaaQualitySubpix 0.75, fxaaQualityEdgeThreshold 0.166 e fxaaQualityEdgeThresholdMin 0.0833
  • O FXAA primeiro amostra a luminância do pixel central e dos pixels acima, abaixo, à esquerda e à direita; se o contraste local estiver abaixo do limite, retorna o pixel original
  • Se não houver early exit, ele amostra também a luminância diagonal, calcula a direção da borda horizontal ou vertical e então busca nas duas direções para encontrar as extremidades da borda
  • No fim, desloca a coordenada do pixel e faz amostragem com texture2D; segundo o whitepaper oficial, não se trata simplesmente de borrar a borda
  • Na demo do círculo, as bordas parecem suaves em estado estático, mas a forma se distorce quando o círculo se move
    • Pequenas saliências aparecem e desaparecem nas partes superior e inferior alinhadas aos eixos
    • Em baixa resolução, o círculo perde a forma arredondada e treme como gráficos de PlayStation 1
  • Como ele considera apenas a vizinhança 3x3 de cada pixel, não consegue saber que aquela região faz parte de um círculo maior
  • O FXAA foi criado para aplicar anti-aliasing em cenas mais complexas e oferece várias configurações e presets
  • A full demo com a cena de NeoTokyo° calcula o canal de luminância a partir da saída com aliasing, aplica FXAA e permite ajustar todos os presets e settings

Entradas do FXAA e condições de parâmetros

  • Ao definir FXAA_GREEN_AS_LUMA como 1, o canal verde é usado no lugar de luma; nesse caso, a entrada RGB deve estar em um espaço de cor não linear
  • A entrada RGB do FXAA deve ser LDR; mais especificamente, o FXAA deve ser aplicado após o tonemapping
  • Se FXAA_GREEN_AS_LUMA não for usado, é preciso armazenar no canal alpha, antes da execução do FXAA, o luma no espaço perceptual
  • O luma precisa ser calculado corretamente para que o FXAA funcione como deve
  • FXAA_QUALITY_PRESET é uma configuração que troca desempenho por qualidade
    • 12 é o padrão
    • 15 e 29 são a qualidade mais alta
    • 39 é EXTREME QUALITY
  • fxaaQualitySubpix ajusta a quantidade de remoção de aliasing subpixel
    • O valor padrão é 0.75
    • 1.00 é mais suave, e 0.50 é mais nítido, mas remove menos aliasing subpixel
    • 0.00 é o estado desligado
  • fxaaQualityEdgeThreshold define o contraste local mínimo necessário para aplicar o algoritmo
  • fxaaQualityEdgeThresholdMin corta áreas escuras do conjunto processado
  • O FXAA pode ter baixo custo de desempenho quando já existe um pipeline de pós-processamento ou quando se usa deferred shading
  • Em gráficos para mobile, o acesso à memória é caro; por isso, se for preciso criar uma nova configuração de render-to-texture para usar FXAA, a vantagem de custo diminui

O núcleo do Analytical Anti-Aliasing

  • Analytical Anti-Aliasing é uma forma de desenhar os pixels já com anti-aliasing, sabendo de antemão qual forma precisa ser desenhada
  • Ao desenhar formas 2D ou 3D, faz o fade exato de 1 pixel na borda da forma
  • O exemplo compara um círculo em resolução nativa, 1/2, 1/4 e 1/8, mostrando suavização de borda e preservação da forma mesmo em baixa resolução
  • circle-analytical.fs calcula o signed distance field do círculo com dist = length(uv)
  • Para aplicar fade com largura de 1 pixel aos pixels próximos da borda do círculo, usa alpha = (1.0 - dist) / pixelSizeAdjusted
  • Esse método é suave e sem artifacts, permite ajustar a quantidade de filtering e não exige buffers extras nem requisitos adicionais de hardware
  • Funciona até mesmo no WebGL 1.0 básico ou no OpenGLES 2.0, sem extensões
  • O smoothing de 1 pixel é nítido, mas, dependendo da combinação entre resolução da tela, tamanho e posição do círculo, os lados alinhados ao eixo em 90 graus ainda podem ser percebidos como flat
  • Filtrar com base no tamanho diagonal do pixel, √2 px = 1.4142..., pode reduzir essa sensação de flat, mas deixa a forma muito ligeiramente mais borrada

O significado de “Analytical” e a implementação baseada em SDF

  • Em programação gráfica, “Analytical” significa um efeito produzido por cálculo a partir da definição matemática da shape desejada, sabendo previamente como ela é composta
  • Esse termo é usado de forma solta em computer graphics e pode ter vários significados dependendo do contexto
  • A implementação é baseada em signed distance field e assume que, em cada point amostrado, a distância até a shape desejada é conhecida
  • Essa informação pode ser baked em uma texture, como no SDF text rendering, ou, em shapes simples, derivada por pixel com fórmulas matemáticas
  • A borda da shape é submetida a fade out de acordo com a signed distance, e, se a distância de fade for definida como 1 pixel, obtém-se uma borda suave
  • A principal questão de implementação é como o shader sabe o tamanho do pixel e como faz o blend com base na distance
  • Essa abordagem oferece pixel-perfection estável em movimento, mas não combina com a rasterização tradicional e exige um signed distance field da shape inteira

Cálculo do tamanho do pixel: pré-cálculo, dFdx/dFdy, fwidth

  • Se a largura do fade na borda for um valor fixo, como 95% do raio do círculo, isso pode parecer bom em um certo tamanho e resolução, mas, se o tamanho mudar, o resultado pode ficar suave demais ou gerar aliasing
  • O tamanho do pixel é um dos problemas resolvidos por Screen Space derivatives
  • dFdx, dFdy e fwidth permitem descobrir quanto um determinado valor varia em unidades de pixel na tela
  • No exemplo, a variação da distância é obtida com pixelSize = fwidth(dist) ou pixelSize = length(vec2(dFdx(dist), dFdy(dist)))
  • Screen Space derivatives refletem corretamente transformações, incluindo perspectiva 3D, mas não fazem parte do padrão WebGL 1; por isso, exigem a extensão GL_OES_standard_derivatives ou WebGL 2
  • A abordagem com length() calcula o comprimento do vetor formado por dFdx e dFdy, enquanto fwidth() usa a aproximação abs(dFdx()) + abs(dFdy())
  • A aproximação de fwidth() escala demais na direção diagonal, então o fade pode ser aplicado com mais intensidade nas diagonais
  • A extensão Shapes para Unity chama o AAA baseado em fwidth() de “Fast Local Anti-Aliasing” e a abordagem baseada em length() de “Corrected Local Anti-Aliasing”
  • Em 2D, como o tamanho de renderização do contexto e o tamanho do quad são conhecidos, é possível calcular diretamente o tamanho do pixel para cada objeto
  • O exemplo passa o tamanho do pixel com base na altura, como em gl.uniform1f(pixelSizeCircle, (2.0 / (canvas.height / resDiv))); esse método funciona até em hardware antigo, sem WebGL 2 nem extensões

alpha blending e escolha da função step

  • Depois de calcular a largura do fade, é preciso ajustar a opacidade
  • Em 2D, Alpha blending é uma escolha simples
  • Outra opção é usar MSAA junto com Alpha to Coverage, o que pode ser útil em cenas 3D quando é necessário escrever no depth buffer para obter o blending correto
  • O alpha deve receber fade com base na distance, e normalmente usa-se uma função step que interpola entre o início e o fim
  • Em implementações de anti-aliasing em GLSL, smoothstep() é usado com frequência, mas, neste contexto, como a função atua em apenas 1 a 2 pixels, quase não há curva perceptível para observar
  • Se a interpolação de Hermite for removida de smoothstep(), obtém-se linearstep(), que é uma interpolação linear com clamp
  • Quando há apenas uma shape por quad, o clamp também pode ser removido
  • O alpha final pode ser calculado com uma divisão simples, como float alpha = (1.0 - dist) / (pixelSize * smoothingAmount);
  • Em termos de desempenho, a parte cara continua sendo a divisão feita por pixel, e GPUs modernas podem otimizar as multiplicações e somas da interpolação de Hermite com Fused Multiply-Add

Bordas do quad, MSAA e correção de 0,5 pixel

  • Existe uma interação entre MSAA + Alpha to Coverage e o rasterizer que aparece apenas em parte do hardware
  • Ao usar MSAA + Alpha to Coverage, pode acontecer de exatamente 0,5 pixel desaparecer em um lado do quad, independentemente do número de samples
  • Para lidar com isso, o exemplo adiciona uma folga de 0,5 pixel ao SDF na forma dist += pixelSizeAdjusted * 0.5
  • Em 2D, é possível implementar manualmente um tratamento parecido com NV_conservative_raster_dilate
    • No vertex shader, aumenta-se o quad em 0,5 pixel
    • No fragment shader, reduz-se o signed distance field em 0,5 pixel
  • Os demos 2D da página funcionam dessa forma, e vertex *= size + pixelSize cumpre esse papel
  • Questões de gamma e premultiplied alpha também são importantes em todas as formas de AA, mas não são tratadas aqui para manter o foco em AAA

Várias formas e expansão para 3D

  • É possível desenhar várias formas dentro de um único quad e aplicar anti-aliasing em cada uma delas
  • Quando há várias formas, é preciso avaliar ambas por pixel e então aplicar clamp·weight·sum aos resultados para manter o anti-aliasing mesmo nos pontos de interseção
  • Colorir de uma vez na saída da forma necessária tem custo menor do que desenhar um overlay de cor em um pass separado
  • O exemplo em 3D usa uma câmera em movimento e um rounded square 2D colocado em perspectiva
  • O fragment shader 3D calcula o SDF da rounded box com roundedBoxSDF e obtém o tamanho do pixel com length(vec2(dFdx(dist), dFdy(dist)))
  • Quando há multiplicação pela matriz da câmera e de perspectiva, usar Screen Space derivatives para obter o tamanho do pixel é confiável
  • Em teoria, seria possível multiplicar as coordenadas do fragment pela matriz de perspectiva inversa em cada pixel sem usar derivatives, mas o custo de desempenho é alto
  • Colocar o fade no centro da borda pode reduzir a deformação da forma em tamanhos pequenos ou com perspectiva forte, mas as bordas podem sair para fora do quad e causar hard edge ou clipping
  • A NVIDIA introduziu a extensão NV_conservative_raster_dilate, que fornece pixels adicionais na borda, mas ela não pode ser usada no WebGL e é limitada a hardware NVIDIA

Casos reais de implementação

  • A extensão para Unity Shapes, de Freya Holmér, é considerada a implementação funcionalmente mais completa dessa abordagem
    • Faz anti-aliasing de SDF com MSAA ou blending no estilo AAA
    • Inclui motion blur, gradientes de cor que respeitam a forma e um recurso para fazer opacity fade em linhas com menos de 1 pixel
    • A técnica para linhas com menos de 1 pixel é chamada de Line Thinness Fading
  • A Valve Software adotou amplamente signed distance field rendering no Source engine durante o desenvolvimento de Orange Box
    • Foi usado com destaque no HUD de Team Fortress 2 para criar elementos de UI suaves, mas nítidos
    • A empresa desenvolveu um line art shader system que mantém silhuetas suaves mesmo quando imagens de resolução fixa são ampliadas para alta resolução
    • Também lida com outline e drop shadow, e pode ser aplicado a elementos do mundo como placas no espaço 3D
  • A Valve divulgou a implementação em um artigo da SIGGRAPH 2007, que também inclui casos no mundo 3D de jogos
  • “Shape Decomposition for Multi-channel Distance Fields”, de Viktor Chlumský, é um exemplo de evolução da técnica citada em uma nota de rodapé do artigo da Valve
    • Trabalhos relacionados incluem msdfgen e msdf-atlas-gen
  • A abordagem de multi-channel distance field usa RGB e um termo de mediana para produzir texto nítido, enquanto o alpha channel contém um SDF clássico para lidar com efeitos como glow e drop shadow
  • Caracteres CJK exigem texturas maiores por causa dos detalhes finos, e reduzir texturas grandes pode gerar seus próprios artefatos
  • Um usuário do Hacker News, aappleby, mencionou que o Google Maps usa AAA baseado em capsule shape para segmentos de estrada
    • aappleby disse que escreveu isso há cerca de 10 anos
    • Ele explicou que, ao verificar com o depurador WebGL Spector.js, o código de shader do draw call das ruas parece indicar alpha com blending dependente da forma

Limitações da abordagem com SDF e discussão sobre TAA

  • Yakov Galka aponta que a abordagem com SDF pode gerar aliasing quando o SDF tem componentes de alta frequência, já que ela amostra o SDF em um ponto específico
  • Ao rasterizar um círculo menor que 1 pixel, a abordagem deste texto pode não conseguir eliminar completamente o aliasing
  • Como um método verdadeiramente analítico para rasterizar formas poligonais e bezier com anti-aliasing, Yakov Galka cita Wavelet Rasterization, de J. Manson e S. Schaefer
  • Após a publicação do texto, nos comentários houve feedback de que a crítica ao TAA foi forte demais, e o autor reconheceu que não tratou suficientemente dos problemas que o TAA tenta resolver e dos problemas difíceis de resolver com outras técnicas
  • Timothy Lottes diz que vê o TAA como uma evolução técnica clara, embora com limitações na clareza do movimento
  • FXAA 4 era um blender de 2 frames e é fundamentalmente diferente do TXAA, enquanto o TXAA não usa MLAA e é baseado em MSAA
  • Como material recomendado para entender melhor o TAA, foi indicada a apresentação da GDC Temporal Reprojection Anti-Aliasing in INSIDE, do desenvolvedor de Inside Lasse Jon Fuglsang Pedersen
  • O AAA é avaliado como uma técnica capaz de desenhar formas de vários tamanhos em resolução nativa de modo suave, nítido e estável em movimento

1 comentários

 
GN⁺ 2024-11-21
Comentários do Hacker News
  • Sou o autor; se tiverem perguntas, eu respondo

    • O Google Maps usa AAA em formato de cápsula para todos os trechos de estrada. Escrevi isso há cerca de 10 anos :D
    • Excelente artigo. Ao tentar entender o antialiasing de fontes MSDF, vi algumas afirmações
      Há a afirmação de que o antialiasing deve ser feito no espaço RGB linear, não no espaço sRGB [1] [2], mas também há a afirmação de que, como isso não foi feito assim por décadas, as fontes foram sendo ajustadas, e às vezes sRGB é melhor [3] [4]. Fiquei curioso se você tem algum conselho sobre antialiasing em espaço linear vs sRGB
      [1] https://www.puredevsoftware.com/blog/2019/01/22/sub-pixel-ga...
      [2] http://hikogui.org/2022/10/24/the-trouble-with-anti-aliasing...
      [3] https://news.ycombinator.com/item?id=12023985
      [4] http://hikogui.org/2022/10/24/the-trouble-with-anti-aliasing...
    • Uma pequena correção: WebGL dá suporte a MSAA desde o WebGL1. Só que, no WebGL1, isso só é possível no canvas, não dá para controlar a contagem de amostras, e basicamente só é possível ativar ou desativar o antialiasing
      O WebGL2 ainda não tem objetos de textura MSAA e só oferece suporte a render buffers MSAA, então não dá para ler diretamente amostras individuais no shader. É um recurso útil para passes de renderização de resolução (resolve) personalizados, mas isso só é possível no WebGPU
    • Concordo que a tendência recente de depender de upscalers foi longe demais, e muitos jogos AAA acabam produzindo resultados borrados e cheios de artefatos. Mas, depois de ver esta análise aprofundada da Digital Foundry [1], achei bastante convincente o argumento de que só tecnologias como DLSS conseguem atingir uma estabilidade de movimento e nitidez que podem até ser melhores que SSAA
      Então agora minha visão mudou de “TAA == borrão” para “TAA + machine learning bem usado é o melhor antialiasing possível nos jogos 3D atuais”; fiquei curioso para saber como você vê isso
      [1] https://youtu.be/WG8w9Yg5B3g
    • Fiquei curioso para saber quanto tempo levou para escrever este artigo
      Eu também já escrevi alguns posts de blog baseados em visualização em tempo real, e levou um tempo enorme. Ainda assim, acho que esse é o caminho certo. Numa era de excesso de conteúdo, acredito que seja melhor para todos produzir menos conteúdo, mas de maior qualidade, mesmo que leve mais tempo
  • O problema em volta do antialiasing é maior do que o antialiasing em si. Nas configurações dos jogos, há várias siglas para escolher, mas quase não explicam qual é a diferença entre elas, e metade delas eu nem conheço
    Claro que dá para pesquisar, mas seria bom se houvesse um pouco mais de preocupação com usabilidade. Este artigo parece que vai ajudar como referência daqui em diante

    • Jogos/gráficos são, sem dúvida, uma área com muito jargão técnico. Se você não quer virar um mago, basta ir alterando as opções e observar o resultado. Gosto da abordagem do Dolphin, que coloca tooltips detalhados nas configurações, mas sempre vai sobrar um certo grau de conhecimento tácito
      Num nível mais meta, tenho a impressão de que ultimamente tenho visto com frequência um clima contra siglas. Acho que nunca foi tão fácil pesquisar quanto agora. Certamente existem siglas em um nível que atrapalha o aprendizado ou funciona como uma espécie de barreira de entrada, mas é preciso dar nomes úteis aos conceitos para conseguir trabalhar; então acho que as siglas das configurações gráficas dos jogos são bastante razoáveis
  • A forma de analisar programação gráfica com exemplos em WebGL é genial. É hipertexto que realmente aproveita as vantagens do meio. Lembra textos que eu esperaria ver em https://pudding.cool/, mas vai muito mais fundo
    Usei MSAAx4 por um bom tempo no mecanismo de renderização e recentemente estava pensando em mudar para uma implementação de FXAA/TAA, mas agora não tenho tanta certeza se vou mesmo trocar. Aprendi muito aqui, e acho que vou experimentar uma abordagem analítica para elementos de UI. Artigos sobre programação gráfica não aparecem com tanta frequência no HN; para quem tiver mais interesse, recomendo este recurso, uma coletânea de artigos de análise de frames:
    https://www.adriancourreges.com/blog/

    • Steve Wittens também escreve muitos artigos desse tipo, com ilustrações matemáticas misturadas com WebGL, em https://acko.net/
      Um artigo de que gosto especialmente é https://acko.net/blog/how-to-fold-a-julia-fractal/. Nunca vi um material que ajudasse tanto a entender a relação entre funções trigonométricas e números complexos
    • Eu realmente detesto TAA. Especialmente em taxas de quadros baixas, o ghosting é forte demais. Muitas vezes acabo mudando de propósito para um algoritmo mais lento para evitar ghosting
  • Os frames com os círculos e as partes ampliadas transmitem a mensagem muito bem. O artigo inteiro é muito agradável de ler

  • SDF ou mSDF não são o futuro, mas sim clássicos bons o suficiente
    A parte de que “é preciso resolver todos os segmentos de curvas de Bézier para cada pixel, então o desempenho cai muito” é que eu vejo mais como futuro, ou como presente. Slug e DirectWrite já são usados com bom desempenho
    https://sluglibrary.com/
    https://learn.microsoft.com/en-us/windows/win32/directwrite/...

    • Também não dá para esquecer a renderização de curvas implícitas [0]. A patente deve expirar em breve [1]
      [0]: https://www.microsoft.com/en-us/research/wp-content/uploads/...
      [1]: https://patents.google.com/patent/US20070097123A1/en
    • Cerca de 20 anos atrás, escrevi uma implementação do artigo Loop/Blinn para a Microsoft Game Studios, e fico curioso se ela ainda é usada
      Deu realmente muito trabalho para deixá-la em nível de produção. A tesselação baseada em Voronoi daquele artigo se comportava de forma patologicamente ruim em muitos caracteres asiáticos
    • Minha memória pode estar totalmente errada, mas o algoritmo usado no Slug não é coberto por patente?
  • Enquanto rolava o texto, a captura de tela de NeoTokyo saltou imediatamente aos meus olhos. Corri por aquele corredor milhares de vezes. Mantive servidores daquele mod por anos e me diverti muito com uma comunidade pequena, mas habilidosa e bacana

    • O mais impressionante é que ele ainda é jogado ativamente. Toda sexta à noite um servidor fica lotado, e às vezes também aos sábados/domingos. Há uma base de fãs bastante dedicada, e nunca vi esse tipo de dedicação em um jogo multiplayer tão antigo
  • Como alguém que já escreveu tanto engines de renderização 2D quanto 3D, deixo uma pequena observação: as duas são realmente diferentes. Não é só uma questão de acrescentar uma dimensão; os objetivos, casos de uso e expectativas são completamente diferentes
    Então, em vez de dizer que “tudo que foi discutido aqui se estende ao 3D”, eu diria que este texto inteiro é, em grande parte, sobre renderização 3D, não renderização 2D. Um bom texto que trata desse assunto pela perspectiva da renderização 2D é https://ciechanow.ski/alpha-compositing/
    Critérios de antialiasing com os quais ninguém se importa em 3D, mas que são muito importantes em 2D, são precisão e viés. Por exemplo, AAA tem muito viés e é impreciso. Se você desenhar a mesma forma várias vezes na mesma posição, ela fica mais opaca ou mais escura. Com MSAA isso não acontece; o erro é limitado e não há viés

    • Eu estava pensando em um renderizador vetorial 3D baseado em WebGPU em JS/TS e vi ontem o seu projeto [0]
      O desenho de linhas grossas é especialmente interessante, porque é difícil [1]. Recentemente também vi isto [2] e fiquei me perguntando se seria possível converter todas as formas em segmentos de curvas de Bézier quadráticas e usar essa técnica. Gostaria de saber se você vê isso como um caminho que vale a pena seguir
      [0] https://github.com/Lichtso/contrast_renderer
      [1] https://mattdesl.svbtle.com/drawing-lines-is-hard
      [2] https://scribe.rip/@evanwallace/easy-scalable-text-rendering...
    • É difícil dizer que este texto se generaliza diretamente para 3D
      A solução apresentada depende de campos de distância assinada, mas passa meio por cima da parte crucial: “distância até o quê?”. Em 2D isso é claro, pois basta medir a distância até a fronteira entre o objeto e o fundo, isto é, até a silhueta
      Em 3D, a coisa fica complicada porque o objeto pode girar e gerar auto-oclusão. Em relação a que se mediria o SDF? A silhueta da projeção 2D de um objeto 3D muda o tempo todo e não pode ser simplesmente pré-computada
  • Gostei de ver o link para Captain Disillusion. Eu não o conhecia, mas o trabalho dele é incrível. Link direto para quem se interessa por efeitos de vídeo: https://www.youtube.com/@CaptainDisillusion

  • O texto é bem estruturado, mas acho que a parte que ataca o TAA pode causar confusão. Antialiasing por SDF não é, de forma alguma, uma alternativa ao TAA
    TAA lida com todos os tipos de aliasing, enquanto aqui se trata apenas de aliasing de borda. Muitos jogos modernos usam abordagens baseadas em Monte Carlo para iluminação indireta e outros efeitos, e isso basicamente exige TAA

  • A parte que diz que “chips móveis dão suporte exatamente a MSAAx4 e a situação é estranha. No Android é possível escolher 2x, mas o driver força 4x de qualquer jeito” me parece um pouco curiosa
    No meu celular Android, a diferença entre 2x e 4x é claramente visível, mas não parece “arredondada” como no iPhone