Baixar PDF - PUC-Rio

Propaganda
Trabalho de
Fundamentos da Computação Gráfica
Melhorias para o Ray Tracing
1. Níveis de pré-visualização
2. Paralelização com Buckets (na CPU)
3. Anti-aliasing (Supersampling)
4. Passes
a. Mapa de Profundidade
b. Oclusão de Ambiente
c. Composição dos passes
5. Conclusão
6. Referências
Aarão Marins
1021747
1. Níveis de pré-visualização
Uma vez que o passe de oclusão de ambiente está sendo calculado junto com o ray
tracing, o tempo de render é maior, portanto foi ajustou-se o algoritmo de exibição para
permitir ao usuário pré-visualizar como a cena está ficando, simplesmente fazendo o
cálculos de pixels intercalados, de acordo com uma variável de resolução, que vai
convergendo para a resolução final da imagem.
Figura 1 - Dois níveis de pré-visualização e o resultado final
É importante ressaltar que a cada vez que a resolução converge, os pixels já calculados são
reaproveitados para a nova exibição, logo, não aumentam o tempo de cálculos da respectiva
resolução.
Se o usuário escolher ver dois níveis de resolução, na primeira imagem exibida ele verá um
pixel a cada conjunto de 4x4 pixels, já na segunda imagem verá um pixel a cada conjunto de 2x2
pixels, e enfim verá a terceira com todos os pixels.
2. Paralelização com Buckets (na CPU)
Como os raios no ray tracing utilizado são independentes entre si, utilizou-se o OpenMP
para fazer a paralelização dos mesmo na CPU. A fim de trabalhar com espaços determinados na
memória e obter uma visualização mais "reveladora" para o usuário, foi implementada uma
estrutura de buckets, que neste caso, são conjuntos quadrados de pixels com tamanho pré-definidos.
Figura 2 - Representação gráfica de uma execução do programa com buckets de 60x60 pixels
Uma vez que todo o espaço de pixels está mapeado nos n buckets, uma lista que contém
esses n buckets é distribuída por todas as threads disponíveis para o programa: t. Logo cada
processador começa o processor de ray tracing com n/t buckets que lhe foram atribuídos.
Para não perder o controle do programa durante a execução, antes de iniciar o raytracing,
uma thread é criada para executar esse código em paralelo, enquanto a thread principal (que é a
única que se comunica com o OpenGL) continua na iteração da glutIdle(), graças a isso é possível
visualizar os buckets na medida em que terminam de ser processados.
3. Anti-aliasing (Supersampling)
Pensando na melhoria da qualidade da imagem final, implementou-se uma forma simples
(e cara) de fazer o anti-aliasing chamada Supersampling. Basicamente é uma média onde ao invés de
apenas um, vários raios são mandados para o cálculo de um pixel.
Existem várias formas de escolher quais serão estes raios, a forma escolhida para esse
trabalho foi o Jittered, onde um pixel é divido em sub-pixels, e dentro de cada sub-pixel é lançado
um raio aleatório. O resultado final é obtido então, a partir da média entre todos os resultados
obtidos, como pode ser visto na Figura 3.
Figura 3 - Exemplo de como funciona o refinamento das bordas usando 4 raios por pixel
4. Passes
Este trabalho aproveita o mesmo algoritmo de traçado de raios para calcular além
das informações de cor (com reflexão) do algoritmo base, um passe que guarda o mapa de
profundidade e um para guardar o mapa de oclusão de ambiente. No algoritmo base
retirou-se o cálculo de sombras para melhor visualização da oclusão de ambiente.
Figura 4 - Ray tracing inicial (sem as sombras)
a. Mapa de Profundidade
O mapa de profundidade é obtido simplesmente com uma proporção entre a
distância do olho até o ponto aonde o raio atirado bate em relação à distância de alcance
máxima do olho.
Figura 5 - Resultado do passe do mapa de profundidade
b. Oclusão de Ambiente
O mapa de oclusão de ambiente é um passe que ajuda a adicionar à imagem um
toque de realismo, considerando a atenuação da luz nos objetos devido a oclusão.
Figura 6 - Resultado do passe de oclusão de ambiente
Para cada ponto da superfície encontrado no algoritmo do traçados de raios, são
gerados diversos raios aleatórios na semi-esfera orientada na direção da normal desse ponto.
A atenuação da oclusão se dá em função do raio escolhido para essa esfera. A oclusão é
obtida calculando-se a soma da divisão todas as distâncias onde houve oclusão (cada
distância é dividida pelo raio da semi-esfera). Essa soma então é dividida pelo número total
de raios traçados, obtendo-se o valor da oclusão para o determinado ponto.
c. Composição dos Passes
A imagem final é uma composição do passe inicial (ray tracing sem sombra), sendo formada
pela multiplicação do mesmo com o mapa de profundidade, e este resultado então é multiplicado
pelo mapa de oclusão de ambiente, obtendo a imagem final do algoritmo. Um exemplo de
composição final pode ser visto na figura 7.
Figura 7 - Composição final das imagens
5.
Conclusão
Foi possível notar que o tempo de render aumenta consideravelmente quando a
oclusão de ambiente está ativa. Uma vez que para que os resultados ficassem satisfatórios,
era necessário traçar cem novos raios aleatórios para calcular a oclusão, e isto para cada
ponto de superfície encontrado no ray tracing.
Em contrapartida a paralelização usando buckets garantiu uma aceleração bem
significante para o algoritmo, e, principalmente, se tornando uma forma do usuário já ter
uma idéia de como está ficando a imagem final antes do término de todo o processamento.
6.
Referências
- Supersampling
http://en.wikipedia.org/wiki/Supersampling
http://www.everything2.com/index.pl?node_id=1028947
- GPU Gems - Chapter 17. Ambient Occlusion
http://http.developer.nvidia.com/GPUGems/gpugems_ch17.html
- Assorted Notes about Ambient Occlusion by Greg Coombe
http://www.cs.unc.edu/~coombe/research/ao/
Download