TD5 - BRDF de Ward

L'objectif de ce TD est d'ajouter la BRDF anisotrope de Ward au lanceur de rayon et de l'évaluer efficacement de façon physiquement réaliste. Afin de commencer dans de bonnes conditions, téléchargez l'archive sia_td5.zip qui contient une correction du TD précédent.

1. Éclairage direct

Commencez par implémenter la méthode Ward::brdf en vous aidant de la description détaillée fournie dans ce document, en particulier l'équation 4. Étant anisotrope, la BRDF de Ward a besoin d'être orientée sur le maillage à l'aide d'un repère $(\vec{x},\vec{y},\vec{n})$ où $\vec{n}$ est la normale à la surface et $\vec{x}, \vec{y}$ sont deux vecteurs orthogonaux dans le plan tangent. Dans le cadre de ce TD, vous utiliserez un champ de direction vertical, c'est à dire que vous prendrez pour vecteur tangent $\vec{x}$, la projection du vecteur $(0,1,0)$ sur le plan tangent défini par la normale $\vec{n}$. Le vecteur $\vec{y}$ sera alors obtenu à partir de $\vec{x}$ et $\vec{n}$ par produit vectoriel.

Dans un premier temps, utiliserez l'intégrateur Direct pour tester votre code avec la scène "sphereWard.scn" en faisant varier les paramètres $\alpha_x$ et $\alpha_y$.

ward ward ward ward
$\alpha_x = \alpha_y = 0.01$ $\alpha_x = \alpha_y = 0.1$ $\alpha_x = \alpha_y = 0.25$ $\alpha_x = \alpha_y = 0.5$
Ward isotrope (éclairage direct)
ward ward ward ward
$\alpha_x = 0.2 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.5 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.2$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.5$
Ward anisotrope (éclairage direct)

2. Échantillonnage uniforme de la BRDF

Pour simuler fidèlement un matériau glossy, vous allez intégrer – au sens de Monte-Carlo – le modèle d'éclairement sur tout l’hémisphère supérieur. Implémentez un nouvel intégrateur DirectMats s'inspirant de ao et Whitted mais où la réflexion miroir sera remplacée par l'échantillonnage uniforme de la BRDF (ignorez la réfraction). Cet échantillonnage correspond à la moyenne de la contribution de chaque direction aléatoire pondérée par la BRDF, le cosinus de son angle par rapport à la normale et l'inverse de sa fonction de densité de probabilité (pdf). Cette dernière vaut $pdf=\cos\theta/\pi$ pour un échantillonnage pondéré par le cosinus de l'hémisphère. D'où l'estimateur final, avec $N$ le nombre d'échantillons : $$\langle L_o \rangle = \frac{1}{N} \sum_{1}^{N} L_i \mathbf{p} \cdot \mathbf{n} \frac{1}{pdf} = \frac{\pi}{N} \sum_{1}^{N} L_i$$

Chargez les deux paramètres suivants dans le constructeur de la classe DirectMats :

  <integrator type="direct_mats">
    <integer name="samples" value="100"/>  <!-- nombre d’échantillons -->
    <boolean name="IS" value="false"/>     <!-- utilisation de l’échantillonnage préférentiel -->
  </integrator>

Afin d'obtenir un rendu plus réaliste nous utiliserons une carte d’environnement. Lorsqu'un rayon (primaire comme réfléchi) n'intersecte aucun objet, au lieu de lui donner la couleur de fond de la scène, on va chercher sa couleur dans une image représentant l'environnement. La classe LightProbe permet de charger des light probes OpenEXR au format panoramique latitude-longitude, comme celles fournis par l'USC. Si une carte d’environnement est spécifiée dans le fichier de scène, celle-ci sera automatiquement chargée et la méthode Scene::backgroundColor renverra la radiance correspondant à la direction passée en paramètre (en appelant la fonction LightProbe::intensity).

Testez avec le fichier de scène "sphereWardEnvMap.scn" (qui utilise l'envmap "ennis.exr" à télécharger séparément) dont la composante diffuse est nulle :

ward ward
$\alpha_x = \alpha_y = 0.01$ $\alpha_x = \alpha_y = 0.1$
ward ward
$\alpha_x = 0.5 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.5$
Échantillonnage uniforme (100 échantillons)

3. Échantillonnage préférentiel

Les images obtenues souffrent d'une forte variance se traduisant par un bruit important, même avec de nombreux échantillons, en particulier lorsque le lobe spéculaire est très fin. La technique d'importance sampling a pour objectif de réduire la variance en concentrant l’échantillonnage dans les directions contribuant majoritairement au résultat final (dans le lobe spéculaire, par exemple). Avec une BRDF analytique comme celle de Ward, il est possible de calculer exactement la distribution de probabilité idéale pour effectuer cet échantillonnage.

Les équations 6 à 8 du même document vous permettront de générer les directions d'échantillonnage. Ajouter une méthode d'importance sampling à la classe Material qui retournera une nouvelle direction d'échantillonnage à chaque appel.

Dans Viewer::drawContents, lorsque un rayon lancé par un clic utilisateur intersecte un objet, tirez et affichez avec Line::draw une centaine de directions d'échantillonnage. Assurez-vous que la distribution de ces directions varie en accord avec les paramètres de la BRDF (taille et anisotropie du lobe).

ward ward ward ward
$\alpha_x = \alpha_y = 0.01$ $\alpha_x = \alpha_y = 0.1$ $\alpha_x = 0.5 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.5$
Directions préférentielles (100 échantillons)

N'oubliez pas que vous devez également diviser la radiance obtenue dans la direction d'échantillonnage par la probabilité associée ($pdf$ décrite par l'équation 9). Pour une plus grande stabilité numérique (et pour réduire le coût de calcul), il est conseillé de pré-diviser la BRDF par cette probabilité. Dans le cas de Ward, implémentez l'équation 10 dans une méthode Ward::premultBrdf. Notez que le $\cos(\theta)$ est désormais inclus dans le calcul de la BRDF ; ne le re-multipliez pas dans l'intégrateur. Conservez bien la fonction Ward::brdf qui sera appelée lors du calcul de l'éclairage directe.

ward ward
$\alpha_x = \alpha_y = 0.01$ $\alpha_x = \alpha_y = 0.1$
ward ward
$\alpha_x = 0.5 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.5$
Échantillonnage préférentiel (100 échantillons)

Nous n'avons considéré dans les exemples précédents que des matériaux de Ward purement métalliques. La BRDF de Ward comporte néanmoins une composante diffuse qu'il vous faut également intégrer. Vous pouvez à nouveau utiliser l'échantillonnage pondéré par le cosinus.

Modifiez votre fonction d'importance sampling de la classe Ward pour tirer aléatoirement une direction spéculaire ou diffus. La probabilité de choisir la première par rapport à la seconde devra être proportionnelle au rapport des réflectivités moyennes (moyenne des 3 canaux de couleur) : Avg(m_specularColor) / (Avg(m_specularColor) + Avg(m_diffuseColor)).

Notez à quel point la contribution diffuse ré-introduit du bruit dans l'image.

ward ward
$\alpha_x = \alpha_y = 0.01$ $\alpha_x = \alpha_y = 0.1$
ward ward
$\alpha_x = 0.5 ~~~ \alpha_y = 0.1$ $\alpha_x = 0.1 ~~~ \alpha_y = 0.5$
Échantillonnage préférentiel (100 échantillons)