Anticrénelage / filtrage dans le lancer de rayons

20

Dans le lancer de rayons / tracé, l'un des moyens les plus simples d'anti-aliaser l'image est de suréchantillonner les valeurs des pixels et de faire la moyenne des résultats. C'EST À DIRE. au lieu de prendre chaque échantillon au centre du pixel, vous décalez les échantillons d'une certaine quantité.

En recherchant sur Internet, j'ai trouvé deux méthodes quelque peu différentes pour ce faire:

  1. Générez des échantillons comme vous le souhaitez et pesez le résultat avec un filtre
    • Un exemple est PBRT
  2. Générez les échantillons avec une distribution égale à la forme d'un filtre


Générer et peser

Le processus de base est le suivant:

  1. Créez des échantillons comme vous le souhaitez (au hasard, stratifiés, séquences à faible écart, etc.)
  2. Décalage du rayon de la caméra à l'aide de deux échantillons (x et y)
  3. Rendre la scène avec le rayon
  4. Calculez un poids en utilisant une fonction de filtre et la distance de l'échantillon par rapport au centre du pixel. Par exemple, Box Filter, Tent Filter, Gaussian Filter, etc.) Formes de filtre
  5. Appliquer le poids à la couleur du rendu


Générer sous la forme d'un filtre

Le principe de base est d'utiliser l' échantillonnage par transformation inverse pour créer des échantillons qui sont distribués en fonction de la forme d'un filtre. Par exemple, un histogramme d'un échantillon distribué sous la forme d'un gaussien serait:
Histogramme gaussien

Cela peut être fait exactement, ou en regroupant la fonction dans un pdf / cdf discret. smallpt utilise le cdf inverse exact d'un filtre de tente. Des exemples de méthodes de binning peuvent être trouvés ici


Des questions

Quels sont les avantages et les inconvénients de chaque méthode? Et pourquoi voudriez-vous utiliser l'un sur l'autre? Je peux penser à quelques choses:

Générer et peser semble être le plus robuste, permettant toute combinaison de n'importe quelle méthode d'échantillonnage avec n'importe quel filtre. Cependant, cela vous oblige à suivre les poids dans ImageBuffer puis à effectuer une résolution finale.

Générer sous la forme d'un filtre ne peut prendre en charge que des formes de filtre positives (c.-à-d. Pas de Mitchell, Catmull Rom ou Lanczos), car vous ne pouvez pas avoir un pdf négatif. Mais, comme mentionné ci-dessus, il est plus facile à mettre en œuvre, car vous n'avez pas besoin de suivre les poids.

Cependant, à la fin, je suppose que vous pouvez considérer la méthode 2 comme une simplification de la méthode 1, car elle utilise essentiellement un poids de filtre de boîte implicite.

RichieSams
la source
Penser à voix haute ... Pourriez-vous modéliser la partie négative d'un filtre séparément pour générer deux ensembles d'échantillons, l'un à traiter comme positif et l'autre comme négatif? Cela permettrait-il des filtres arbitraires pour votre seconde approche (générer sous la forme d'un filtre)?
trichoplax
Peut être? Lemme joue avec ça un peu
RichieSams
1
Ok, si vous suivez les zéros de la fonction, vous pouvez abs () la sortie dans le pdf. Ensuite, lors de l'échantillonnage, vous pouvez vérifier si vous êtes négatif. Exemple de code ici: gist.github.com/RichieSams/aa7e71a0fb4720c8cb41
RichieSams

Réponses:

9

Il existe un excellent article de 2006 sur ce sujet, Filter Importance Sampling . Ils proposent votre méthode 2, étudient les propriétés et se prononcent généralement en sa faveur. Ils affirment que cette méthode donne des résultats de rendu plus fluides car elle pondère tous les échantillons qui contribuent à un pixel de manière égale, réduisant ainsi la variance dans les valeurs finales des pixels. Cela a du sens, car c'est une maxime générale dans le rendu Monte Carlo que l'échantillonnage d'importance donnera une variance plus faible que les échantillons pondérés.

La méthode 2 a également l'avantage d'être légèrement plus facile à paralléliser car les calculs de chaque pixel sont indépendants de tous les autres pixels, tandis que dans la méthode 1, les résultats des échantillons sont partagés entre les pixels voisins (et doivent donc être synchronisés / communiqués d'une manière ou d'une autre lorsque les pixels sont parallélisés entre eux plusieurs processeurs). Pour la même raison, il est plus facile de faire un échantillonnage adaptatif (plus d'échantillons dans les zones à forte variance de l'image) avec la méthode 2 que la méthode 1.

Dans l'article, ils ont également expérimenté avec un filtre Mitchell, échantillonnant à partir des abs () du filtre, puis pondérant chaque échantillon avec +1 ou -1, comme l'a suggéré @trichoplax. Mais cela a fini par augmenter la variance et être pire que la méthode 1, ils concluent donc que la méthode 2 n'est utilisable que pour les filtres positifs.

Cela étant dit, les résultats de cet article peuvent ne pas être universellement applicables, et il peut être quelque peu dépendant de la scène quelle méthode d'échantillonnage est la meilleure. J'ai écrit un article de blog sur cette questionindépendamment en 2014, en utilisant une «fonction d'image» synthétique plutôt que le rendu complet, et a trouvé la méthode 1 pour donner des résultats plus visuellement agréables en raison du lissage plus agréable des bords à contraste élevé. Benedikt Bitterli a également commenté ce message signalant un problème similaire avec son moteur de rendu (bruit haute fréquence excessif autour des sources de lumière lors de l'utilisation de la méthode 2). Au-delà de cela, j'ai trouvé que la principale différence entre les méthodes était la fréquence du bruit résultant: la méthode 2 donne un bruit de fréquence plus élevée, "de taille pixel", tandis que la méthode 1 donne des "grains" de bruit de 2 à 3 pixels, mais l'amplitude du bruit était similaire pour les deux, donc quel type de bruit semble moins mauvais est probablement une question de préférence personnelle.

Nathan Reed
la source
Merci! Ce sont d'excellentes ressources. Donc, au final, il y a 3 méthodes? 1. Générer et peser avec éclaboussures 2. Générer et peser sans éclaboussures 3. Générer sous la forme d'un filtre
RichieSams
Connaissez-vous des articles, blogs, etc. qui explorent comment paralléliser Générer et pondérer avec l' éclaboussure? Du haut de ma tête, vous pourriez avoir un mutex par tuile, ou rendre chaque pixel atomique.
RichieSams
2
@RichieSams Je ne sais pas pourquoi vous utiliseriez "générer et peser sans éclabousser", en fait - cela semble être en tout cas pire que l'échantillonnage de l'importance du filtre. Je supposais que «générer et peser» implique des éclaboussures. En ce qui concerne la parallélisation des éclaboussures, du haut de ma tête, une façon serait de diviser l'image en tuiles, mais donnez à chaque tuile une bordure de 2 à 3 pixels pour attraper les éclaboussures qui traversent le bord de la tuile. Ensuite, dans un dernier passage, composez additivement les carreaux bordés ensemble dans l'image finale.
Nathan Reed