Traçado de raios em tempo real
Paulo Ivson
20-10-2008
Sumário




Algoritmo convencional
Problemas
Grade Regular
Kd-tree
Algoritmo convencional

Para cada raio da imagem

Para cada objeto na cena



Calcular interseção raio x objeto
Guardar interseção mais próxima
Se houve interseção, calcular iluminação
Problemas

Para cada raio da imagem

Para cada objeto na cena




Calcular interseção raio x objeto
Guardar interseção mais próxima
Se houve interseção, calcular iluminação
Processamento custoso



Divisões de ponto flutuante
Cálculo de raiz quadrada
etc
Problemas

Para cada raio da imagem

Para cada objeto na cena




Calcular interseção raio x objeto
Guardar interseção mais próxima
Se houve interseção, calcular iluminação
Complexidade O(rn)

“Busca” em força bruta pela interseção mais
próxima
Problemas

Para cada raio da imagem

Para cada objeto na cena




Calcular interseção raio x objeto
Guardar interseção mais próxima
Se houve interseção, calcular iluminação
Cerca de 90% do tempo é gasto no cálculo de
interseções

Sem chance de ser tempo real
Solução

Otimizar cálculo de interseções



Pré-calcular divisões
Evitar raiz quadrada
Reduzir complexidade do algoritmo

O(rn) → O(r lg n)
Estrutura de Aceleração

Índice espacial



Encontrar geometria mais próxima ao longo de um
raio
Da forma mais eficiente possível
Objetivo

Trocar custo de interseção pelo custo de percurso
na estrutura
Estuturas mais bem-sucedidas

Grade regular
Kd-tree
BVH*

Queremos





Boa adaptação (teapot in a stadium)
Percurso de raios eficiente
Construção eficiente*
Mas antes, volumes envolventes
AABB (revisão)

Construção O(n)

Para cada vértice



Armazenar mín. e máx. para coordenadas x, y e z
Ajuste nem sempre bom
Mas suficiente para o traçado de raios
Estruturas de aceleração
Grade Regular

Subdivisão espacial



Regular
Não-adaptativa
Células de tamanho uniforme

Largura, altura e profundidade



Não precisam ser iguais entre si
São iguais para todas as células
Aplicações principais


Busca por vizinhos próximos
Traçado de raios
Representação

vec3 boxMin
vec3 boxMax
vec3 cellSize
vec3 numCells
int** data

vec3 invCellSize




Construção
Encontrar AABB da cena
Determinar número de células
1.
2.
kN
Nx  dx
V
3
kN
Nz  dz
V
Para cada geometria
3.


kN
Ny  dy
V
3
Determinar quais células ela ocupa
Complexidade O(n)
3
Determinar células ocupadas

Dado ponto no espaço, qual célula ele ocupa?
1.
Obter AABB da geometria
Determinar cellStart, cellEnd
Calcular interseção exata de cada célula com
a geometria
2.
3.
Percurso de raios



Similar à rasterização
3D-DDA
Amanatides, J., Woo, A. A Fast Voxel Traversal Algorithm for Ray Tracing. In Eurographics ’87.
Eurographics Association, 3–10.
Percurso de raios

Intervalos regulares em cada dimensão
Percurso de raios
Percurso de Raios
Inicialização
1.
•
•
Determinar célula inicial
Calcular limites para percurso do raio
Percurso
2.
•
•
•
•
•
Determinar qual próxima célula a ser visitada
Calcular interseção com triângulos
Se encontrou interseção, retorna
Senão, atualizar limites em cada dimensão
Loop
kd-Tree


Estritamente binária
Um plano de corte por nó



Distribuição irregular de geometrias


Alinhado com um dos eixos coordenados
Posicionado arbitrariamente
Adapta-se melhor do que Octree
Aplicações principais


Busca por vizinhos próximos
Traçado de raios
Construção
1.
2.
Testar critério de parada
Encontrar “melhor” plano de corte


Eixo: alternado, maior extensão da caixa do nó
Posição: mediana espacial, heurística
4.
Classificar geometrias em cada lado do plano
Chamadas recursivas para cada nó filho

Complexidade O(n lg n)
3.

Depende da heurística para encontrar plano de
corte
Como encontrar plano de corte

Eixo


Posição


Alternado, ao longo da maior dimensão
Mediana espacial, mediana das geometrias, média
das geometrias
Término

Mín. primitivas em uma folha, limite no tamanho da
altura
Como encontrar plano de corte

Eixo


Posição


Mediana espacial, mediana das geometrias, média
das geometrias
Término


Alternado, ao longo da maior dimensão
Mín. primitivas em uma folha, limite no tamanho da
altura
Não são recomendadas (usem como plano B)
Como encontrar plano de corte

Melhor algoritmo atualmente


Surface Area Heuristic
Qual plano escolher?



Aquele que for melhor para o traçado de raios
Escreva função de custo e minimize ela
Algoritmo guloso (solução ótima local)
Função de custo

Qual custo de traçar um raio por um nó?

Probabilidade de um raio qualquer atingir o nó


Proporcional à área de superfície do nó
Custo de interseção das primitivas contidas pelo nó

Proporcional à quantidade de primitivas (aproximação)
Cost(node) = c_trav + Prob(hit L) * Cost(L) + Prob(hit R) * Cost(R)
= c_trav + c_intr * ( SA(L) * nPrim(L) + SA(R) * nPrim(R) )
Levando em conta o custo
Levando em conta o custo


Probabilidades de L & R iguais
Não considera custos de L & R
Levando em conta o custo


Custos de L & R iguais
Não considera probabilidades de L & R
Partição otimizando custo


Automaticamente isola complexidade
Produz grandes regiões de espaço vazio
Onde avaliar função de custo



Onde estão os pontos críticos?
Variar áreas → variação linear (contínuo)
Variar nPrim → degrau (discreto)



Mínimo quando número de triângulos muda
Utilizar limites das AABBs ou interseção exata
Para cada dimensão x, y, z


Avaliar custo de plano nos pontos críticos
Guardar plano de menor custo
Critério de parada

Quando terminar subdivisão?


Considerar nó atual uma folha
Vale a pena subdividir?
CostLeaf(node) = c_trav + c_intr * nPrim(node)
If CostLeaf(node) <= Cost(node)
stop recursion
Representação

Node

É folha? + Eixo do plano de corte (0=x, 1=y, 2=z)


Posição do plano de corte


32 bit float
Sempre dois filhos, colocar lado-a-lado na memória


2 bits
Um ponteiro de 32-bits
Conseguimos 8 bytes?
Representação

Node

É folha? + Eixo do plano de corte (0=x, 1=y, 2=z)


Posição do plano de corte


32 bit float
Sempre dois filhos, colocar lado-a-lado na memória


2 bits
Um ponteiro de 32-bits
Conseguimos 8 bytes?

Usar 2 bits menos significativos do ponteiro
kD-Tree Traversal Step
t_split
t_min
split
t_max
kD-Tree Traversal Step
t_max
t_split
split
t_min
kD-Tree Traversal Step
t_max
t_split
t_min
split
Passo do percurso
Dado: ray P & iV (1/V), t_min, t_max, split_location, split_axis
t_at_split = ( split_location - ray->P[split_axis] ) * ray_iV[split_axis]
if t_at_split > t_min
need to test against near child
If t_at_split < t_max
need to test against far child
Percurso de raios
while ( not a leaf )
t_at_split = (split_location - ray->P[split_axis]) * ray_iV[split_axis]
if t_split < t_min
continue with far child
if t_split > t_max
continue with near child
// hit either far child or none
// hit near child only
// hit both children
push (far child, t_split, t_max) onto stack
continue with (near child, t_min, t_split)
Considerações finais


Usar float ao invés de double
Pré-calcular valores




Utilizar early exits
Otimizar raios de sombra



Evitar divisões
Evitar raiz quadrada
Interseção com alguma primitiva?
Não precisam de informação de hit
Muitas outras otimizações



Pacotes de raios (SIMD)
Representações paramétricas
etc
Download

PPT - PUC-Rio