Anti-aliasing / Filtragem em Ray Tracing


20

No traçado de raios / traçado, uma das maneiras mais simples de suavizar o alias da imagem é sobresaminar os valores de pixel e calcular a média dos resultados. IE. em vez de fotografar todas as amostras pelo centro do pixel, você as compara em alguma quantidade.

Ao pesquisar na Internet, encontrei dois métodos um tanto diferentes para fazer isso:

  1. Gere amostras da maneira que desejar e pese o resultado com um filtro
    • Um exemplo é o PBRT
  2. Gere as amostras com uma distribuição igual à forma de um filtro


Gerar e pesar

O processo básico é:

  1. Crie amostras da maneira que desejar (sequências aleatórias, estratificadas, de baixa discrepância etc.)
  2. Desloque o raio da câmera usando duas amostras (x e y)
  3. Renderize a cena com o raio
  4. Calcule um peso usando uma função de filtro e a distância da amostra em referência ao centro de pixels. Por exemplo, filtro de caixa, filtro de barraca, filtro gaussiano etc.) Formas de filtro
  5. Aplique o peso à cor da renderização


Gerar na forma de um filtro

A premissa básica é usar a Amostragem de transformação inversa para criar amostras que são distribuídas de acordo com a forma de um filtro. Por exemplo, um histograma de uma amostra distribuída na forma de um gaussiano seria:
Histograma gaussiano

Isso pode ser feito exatamente ou dividindo a função em um discreto pdf / cdf. smallpt usa o cdf inverso exato de um filtro de barraca. Exemplos do método de binning podem ser encontrados aqui


Questões

Quais são os prós e os contras de cada método? E por que você usaria um sobre o outro? Eu posso pensar em algumas coisas:

Gerar e pesar parece ser o mais robusto, permitindo qualquer combinação de qualquer método de amostragem com qualquer filtro. No entanto, requer que você rastreie os pesos no ImageBuffer e faça uma resolução final.

A geração na forma de um filtro pode suportar apenas formas positivas de filtro (ou seja, sem Mitchell, Catmull Rom ou Lanczos), pois você não pode ter um pdf negativo. Mas, como mencionado acima, é mais fácil de implementar, pois você não precisa rastrear nenhum peso.

Embora, no final, eu acho que você possa pensar no método 2 como uma simplificação do método 1, já que ele usa essencialmente um peso implícito do filtro de caixa.


Apenas pensando em voz alta ... Você poderia modelar a parte negativa de um filtro separadamente para gerar dois conjuntos de amostras, uma para ser tratada como positiva e a outra como negativa? Isso permitiria filtros arbitrários para sua segunda abordagem (gerada na forma de um filtro)?
Trichoplax

Talvez? Deixe-me mexer um pouco com ele um pouco #
RichieSams 2/16

11
Ok, se você rastrear os zeros da função, poderá abs () a saída no pdf. Então, ao fazer a amostragem, você pode verificar se é negativo. Exemplo de código aqui: gist.github.com/RichieSams/aa7e71a0fb4720c8cb41
RichieSams

Respostas:


9

Há um excelente artigo de 2006 sobre esse tópico, Amostragem de importância de filtro . Eles propõem o seu método 2, estudam as propriedades e geralmente são favoráveis ​​a ele. Eles afirmam que esse método fornece resultados de renderização mais suaves porque pesa todas as amostras que contribuem para um pixel igualmente, reduzindo assim a variação nos valores finais do pixel. Isso faz algum sentido, pois é uma máxima geral na interpretação de Monte Carlo que a amostragem por importância fornecerá uma variação menor do que as amostras ponderadas.

O método 2 também tem a vantagem de ser um pouco mais fácil de paralelizar porque os cálculos de cada pixel são independentes de todos os outros pixels, enquanto no método 1, os resultados da amostra são compartilhados entre os pixels vizinhos (e, portanto, precisam ser sincronizados / comunicados de alguma forma quando os pixels são paralelos entre múltiplos processadores). Pelo mesmo motivo, é mais fácil fazer amostragem adaptativa (mais amostras em áreas de alta variação da imagem) com o método 2 do que com o método 1.

No artigo, eles também experimentaram um filtro Mitchell, amostrando a partir de abs () do filtro e depois ponderando cada amostra com +1 ou -1, como sugeriu @trichoplax. Mas isso acabou aumentando a variação e sendo pior que o método 1, então eles concluem que o método 2 é utilizável apenas para filtros positivos.

Dito isto, os resultados deste artigo podem não ser universalmente aplicáveis, e pode ser um pouco dependente da cena qual método de amostragem é melhor. Eu escrevi uma postagem no blog investigando esta questãoindependentemente em 2014, usando uma "função de imagem" sintética em vez de renderização completa, encontrou o método 1 para fornecer resultados visualmente mais agradáveis ​​devido a suavizar as bordas de alto contraste mais bem. Benedikt Bitterli também comentou sobre esse post relatando um problema semelhante com o seu renderizador (excesso de ruído de alta frequência em torno de fontes de luz ao usar o método 2). Além disso, descobri que a principal diferença entre os métodos era a frequência do ruído resultante: o método 2 gera um ruído "com tamanho de pixel" de frequência mais alta, enquanto o método 1 fornece "grãos" de ruído com 2-3 pixels de diâmetro, mas a amplitude do ruído foi semelhante para ambos, portanto, que tipo de ruído parece menos ruim provavelmente é uma questão de preferência pessoal.


Obrigado! Estes são ótimos recursos. Então, no final, existem 3 métodos? 1. Gerar e pesar, com splatting 2. Gerar e Pesar sem splatting 3. Gerar na forma de um filtro
RichieSams

Você conhece algum artigo, blog etc. que explora como paralelizar Gerar e Ponderar com respingos? Em cima da minha cabeça, você pode ter um mutex por bloco ou tornar cada pixel atômico.
precisa saber é o seguinte

2
@ RichieSams Eu não sei por que você usaria "gerar e pesar sem respingar", na verdade - isso parece ser pior em qualquer caso do que a amostragem por importância do filtro. Eu estava assumindo que "gerar e pesar" implica splatting. Quanto à paralelização de splatting, em cima da minha cabeça, uma maneira seria dividir a imagem em blocos, mas dê a cada bloco uma borda de 2‒3 pixels para capturar splats que cruzam a borda do bloco. Em uma passagem final, componha os azulejos com bordas na imagem final.
Nathan Reed
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.