4.2 Ray casting x rasterização
Ray casting e rasterização são duas abordagens distintas de se renderizar uma cena, e resultam em pipelines também distintos. Ray casting consiste em lançar raios que saem do centro de projeção, atravessam os pixels da tela e intersectam os objetos da cena. A rasterização faz o caminho inverso: os objetos da cena são projetados na tela na direção do centro de projeção, e são então convertidos em pixels.
Neste curso usaremos apenas a rasterização, que é a forma de renderização utilizada na maioria das aplicações gráficas interativas. É também a única abordagem de renderização suportada atualmente no pipeline gráfico do OpenGL. Entretanto, é importante observar que novos pipelines baseados em traçado de raios (uma forma de ray casting) têm sido incorporados às APIs gráficas e tendem a conquistar cada vez mais espaço em síntese de imagens em tempo real.
Ray casting
Na sua forma mais simples, o algoritmo de ray casting (Roth 1982) consiste nos seguintes passos (figura 4.4):
- Para cada pixel do framebuffer:
- Calcule o raio \(R\) que sai do centro de projeção e passa pelo pixel.
- Seja \(P\) a interseção mais próxima (se houver) de \(R\) com um objeto da cena.
- Faça com que a cor do pixel seja a cor calculada em \(P\).
Em ray casting, cada pixel é visitado apenas uma vez. Entretanto, para cada pixel visitado, potencialmente todos os objetos da cena podem ser consultados para calcular a interseção mais próxima. Assim, o principal custo da geração de imagem usando ray casting está relacionado ao cálculo das interseções.
Estruturas de dados de subdivisão espacial como k-d tree (Bentley 1975) e octree (Meagher 1980) podem ser utilizadas para que seja possível descartar rapidamente a geometria não intersectada pelo raio e com isso diminuir o número de testes de interseção.
Embora o ray casting seja conceitualmente simples, é pouco adequado para implementação em hardware, pois cada iteração do laço principal exige a manutenção de toda a cena na memória do renderizador, além da estrutura de subdivisão espacial. Essa limitação tem sido cada vez menos significativa nas GPUs mais recentes, mas ray casting ainda é pouco utilizado em síntese de imagens em tempo real.
Para produzir imagens fotorrealistas, a cor em \(P\) deve ser calculada através da integração da energia luminosa que incide sobre o ponto vindo de todas as direções da cena, e da determinação da quantidade dessa energia que é refletida na direção do pixel na tela. Isso pode ser feito de diferentes formas e em diferentes níveis de aproximação.
Uma aproximação pouco acurada, mas muito eficiente, é avaliar a equação de um modelo de iluminação local como o modelo de reflexão de Phong (Phong 1973) ou Blinn-Phong (Blinn 1977) que considera que a cor em uma superfície é determinada unicamente pela luz que incide diretamente sobre a superfície, e não pela luz indireta refletida por outros objetos.
Outra aproximação, mais acurada porém bem menos eficiente, é a técnica de traçado de raios recursivo (Whitted 1979) que consiste em lançar novos raios a partir de \(P\) (figura 4.5). Esses raios são:
- Um raio de sombra (shadow ray) em direção a cada fonte de luz, para saber se \(P\) encontra-se na sombra em relação à fonte de luz correspondente;
- Um raio de reflexão (reflection ray) na direção espelhada em relação ao vetor normal à superfície em \(P\);
- Um raio de refração (refraction ray) que atravessa a superfície do objeto, caso o objeto seja transparente.
Os raios de reflexão e refração podem intersectar outros objetos, e novos raios podem ser gerados a partir desses pontos de interseção, recursivamente, de tal modo que a cor final refletida em \(P\) é formada por uma combinação da energia luminosa representada por todos os raios.
Rasterização
Em oposição ao ray casting, a rasterização é centrada no processamento de primitivas em vez de pixels. Cada primitiva é projetada no plano de imagem e rasterizada em seguida (figura 4.6):
- Para cada primitiva da cena:
- Projete a primitiva no plano de imagem.
- Rasterize a primitiva projetada.
- Modifique o framebuffer com a cor calculada em cada pixel da primitiva, exceto se o pixel do framebuffer já tiver sido preenchido anteriormente com uma primitiva mais próxima do plano de imagem.
Na etapa 3, a cor do pixel é geralmente avaliada através de um modelo de iluminação local como o modelo de Blinn-Phong. Outras técnicas podem ser utilizadas para melhorar a aproximação da luz refletida no ponto amostrado, mas não há lançamento de raios ou testes de interseção como no ray casting.
A rasterização é mais adequada para implementação em hardware, pois cada iteração do laço principal só precisa armazenar a primitiva que está sendo processada, juntamente com o conteúdo do framebuffer. Como resultado, o processamento de transformação geométrica de vértices e a conversão matricial podem ser paralelizados de forma massiva, como de fato ocorre nas GPUs.