- Um renderer de software é implementado do zero, sem bibliotecas gráficas externas, para entender como OpenGL, Vulkan, Metal e DirectX funcionam por dentro
- Ele converte um modelo 3D em imagem a partir de uma malha de triângulos e texturas, sem abordar implementação de GUI ou aplicações para GPU
- O código final tem cerca de 500 linhas, e os alunos normalmente começam a criar um renderer funcional em 10 a 20 horas
- São fornecidos apenas uma classe para manipulação de TGA com suporte a RGB, RGBA e tons de cinza, além da função de definir um único pixel; o desenho de linhas e triângulos deve ser implementado manualmente
- Em vez de copiar o código pronto, é preciso escrevê-lo por conta própria para entender os conceitos de renderização e também o funcionamento interno de bibliotecas 3D
O processo de criar o pipeline de renderização por conta própria
- Aprende-se o funcionamento do pipeline de renderização seguindo de forma solta a estrutura das bibliotecas modernas de gráficos 3D
- Em vez de ensinar a escrever aplicações para GPU, o funcionamento interno é reproduzido com um renderer de software
- A entrada é um modelo 3D composto por malha de triângulos e texturas, e a saída é uma imagem renderizada
- O programa gera um arquivo de imagem sem interface gráfica
- Para reduzir dependências externas, usa-se o formato de imagem simples TGA
- As únicas funções fornecidas no início são carregar e salvar imagens, além de definir a cor de um único pixel
- Como não há função embutida para desenhar linhas ou triângulos, tudo precisa ser escrito manualmente
- O exemplo inicial cria um framebuffer RGB
64x64, define como brancos os pixels de três coordenadas e depois salva em framebuffer.tga
- Os valores de cor são especificados na ordem BGRA
Build e execução do código
git clone https://github.com/ssloy/tinyrenderer.git &&
cd tinyrenderer &&
cmake -Bbuild &&
cmake --build build -j &&
build/tinyrenderer obj/diablo3_pose/diablo3_pose.obj obj/floor.obj
- O resultado da execução é salvo em
framebuffer.tga
- Embora o código final tenha cerca de 500 linhas, não é recomendado usar o código fornecido como está, porque o processo de implementar por conta própria é essencial para compreender os conceitos
1 comentários
Opiniões no Hacker News
https://github.com/kshitijl/tinyrenderer-rs
O repositório tem muitas capturas de tela do processo de desenvolvimento e de bugs visuais engraçados. Aprendi bastante não só sobre os princípios de renderização, mas também que CPUs modernas são muito rápidas e que mesmo um renderizador de CPU single-thread consegue rodar um jogo 3D interativo com efeitos especiais chamativos
Foi antes das LLMs, então levou pelo menos dois meses, e passei a maior parte do tempo entendendo a matemática de computação gráfica e rastreando erros de segmentação em C
Estas notas de aula no GitHub foram melhores para revisar os conceitos. Não gosto do estilo de código do repositório, e o rasterizador antigo também é simples e ineficiente demais, mas ainda assim acho mais agradável de ler do que o livro de Foley
Com as mudanças de edição, a linguagem usada também evoluiu de Pascal para C, depois C e C++, e a edição mais recente inclui um pouco de C#. Vários conceitos novos ficaram de fora, mas acho que ainda há muito conteúdo valioso
O clipping contra o frustum pode ser tratado pela seleção de pontos em tiles locais, e a síntese de primitivas é mais fácil quando se trabalha com o retângulo de clipping transformado inversamente no sistema de coordenadas baricêntricas. É possível controlar erros de arredondamento com dupla precisão ou ponto fixo, e a principal dificuldade é regenerar os valores de Z e 1/Z dos novos vértices. Em um rasterizador com síntese tardia de atributos, o restante passa naturalmente pelo pipeline, e há exemplos na implementação open source do OpenSWR.org
A maior barreira psicológica é a estranheza do espaço projetivo e das coordenadas homogêneas. Os seis planos do espaço de clipping são simples:
x = ±w,y = ±w,z = ±w; basta percorrer cada aresta do polígono, determinar se seus dois extremos estão dentro ou fora, e interpolar linearmente a posição da interseção com a borda e os atributos dos vértices. Aplicando esse processo a todos os planos em sequência, o triângulo vira um polígono convexo de até 9 vértices e pode ser facilmente triangulado de novo. Se você pré-calcular o outcode, pode pular o clipping de triângulos que estejam completamente dentro ou completamente foraArtigo: https://dl.acm.org/doi/10.1145/360767.360802
Mantendo uma forma de pipeline fixo, dá para processar uma quantidade surpreendente de triângulos com funções de desenho bem simples