2.4.9 L'artefact du triangle adouci

2.4.9.1 Quel est le problème ?

Il y a un problème avec les triangles adoucis qui apparaît parfois comme un artefact lumineux. Cela peut arriver avec des triangles adoucis individuels, des maillages de triangles adoucis et des champs de niveaux adoucis. Ce problème se manifeste aussi lors de l'utilisation de modèles de pentes dans la même situation. Cette image montre les deux cas :

Artefacts d'illumination et de modèles de pentes sur un triangle adouci
Artefacts d'illumination et de modèles de pentes sur un triangle adouci

Le code source de cette image est :

camera {right x*4 location <0, 1,-5> look_at 0 angle 35}
light_source {y*100, 1}
light_source {-y*100, x}

smooth_triangle {
	<-.5, 0,-1>, <-1, 1,-1>, <.5, 0,-1>, <1, 1,-1>, <0, 0, 1>, <0, 1, 1>
	pigment {rgb 1}
	translate -x*.6
}
smooth_triangle {
	<-.5, 0,-1>, <-1, 1,-1>, <.5, 0,-1>, <1, 1,-1>, <0, 0, 1>, <0, 1, 1>
	pigment {slope y color_map {[0 rgb z][1 rgb x+y]}}
	finish {ambient 1}
	translate x*.6
}

Le triangle sur la gauche est un triangle adouci normal qui est illuminé par une source de lumière blanche au-dessus. Il y a aussi une source de lumière rouge par dessous. Comme vous pouvez le voir, la partie éloignée du triangle est faussement illuminée en rouge. Aucune partie du triangle ne devrait être éclairée par la lumière rouge parce que la partie supérieure du triangle ne fait jamais face vers le bas.

Le triangle à droite est le même triangle adouci avec un motif de pentes appliqué, qui va du bleu (dans la direction -y) au jaune (dans la direction +y). L'éclairage a été éliminé par spécification d'une haute ambiance. Comme toutes les parties du côté supérieur pointent vers le haut, la totalité devrait être colorée avec des nuances de jaune, mais comme vous pouvez le voir, la même portion éloignée est faussement éclairée en bleu.

(si vous estimez que le problème arrive quand le vecteur de normale du triangle pointe en s'éloignant de la caméra, vous devinez juste.)

2.4.9.2 Qu'est-ce qui cause le problème ?

Le problème est causé par l'algorithme de rendu utilisé par POV-Ray. Le texte suivant est quelque peu technique, aussi si vous ne cherchez que des solutions possibles au problème, vous pouvez sauter cette section.

Le problème est que le moteur de rendu assume que l'obet renvoie un vecteur de normale vrai pour un point donné de la surface. Pour qu'un objet soit correctement rendu, il doit donner le vecteur de normale exact (c.a.d. un vecteur qui est exactement perpendiculaire à la surface en ce point).

Les maillages adoucis et les champs de niveaux adoucis ne font pas ça. Ils retournent des vecteurs de normale qui ne sont pas perpendiculaires à la surface. Cela provoque des erreurs de rendu.

Ce qui arrive est que le moteur de rendu lance un rayon et touche la surface d'un objet, le moteur demande à l'objet "quel est le vecteur de normale à ce point de ta surface ?". Maintenant, si l'angle entre le vecteur de normale et le vecteur du rayon est plus petit que 90 degrés (donc, le vecteur de normale pointe en s'éloignant du point de vue du départ du rayon), alors le moteur inverse le vecteur de normale renvoyé. Cela est essentiel pour que l'illumination fonctionne normalement (si la normale n'est pas inversée, vous auriez une sorte d'erreur d'illumination, ex. des surfaces qui seraient illuminées depuis l'arrière alors qu'elles ne le devraient pas, ou une surface qui ne serait pas illuminée même en faisant face à une source de lumière).

Cela assume que le vecteur de normale renvoyé par l'objet est un vrai vecteur de normale, et cela fonctionne parfaitement quand c'est le cas.

Toutefois, si l'objet renvoie un vecteur de normale érroné, ex. un vecteur qui n'est pas perpendiculaire à la surface, des erreurs de rendu peuvent apparaître.

Les triangles adoucis et les champs de niveaux adoucis font cela, et le prix à payer est les artefacts d'illumination dans certaines situations.

L'artefact est produit quand le vecteur de normale vrai devrait avoir un angle de plus de 90 degrés avec le rayon, mais le vecteur renvoyé par l'objet a un angle plus petit que 90 degrés avec le rayon. Dans ce cas, le moteur de rendu inverse le vecteur de normale même s'il ne le devrait pas. Cela parcequ'il assume que c'est un vecteur de normale vrai.

Ce problème peut être résolu en rendant la décision d'inversion du vecteur de normale dépendante du vecteur de normale vrai, et pas du vecteur renvoyé. Toutefois, à cause de l'implementaton interne du moteur de rendu de la version actuelle de POV-Ray, cela n'est pas facile à faire. Il peut être corrigé dans POV-Ray 4.0, où le moteur de rendu sera reécrit, et cette sorte de chose peut être prise en compte au tout début.

2.4.9.3 Ce problème peut-il être résolu ?

Vous pouvez échapper à l'artefact de l'illumination en appliquant double_illuminate à l'objet en question. Quand une surface est doublement illuminée, la façon dont pointe la normale n'est plus importante - il sera toujours illuminé en prenant en compte la position de la source de lumière. Bien sûr, cela n'a pas d'importance si l'objet est illuminé des deux côtés. Si cela est un problème, ce n'est pas facilement résolvable.

Notez que dans l'exemple donné au début de cette section, cette solution ne fonctionne pas : il illuminera le triangle avec les deux sources de lumière ! Toutefois, cette solution fonctionne bien avec les maillages de triangles fermés, où le côté interne du maillage est ombré par le maillage lui-même. Mais, si vous utilisez no_shadow dans l'objet (par exemple pour résoudre les artefacts de ligne d'ombre), de nouveaux problèmes peuvent survenir dans l'éclairage (comme des parties brillantes quand il ne devrait pas y en avoir; cela est provoqué par le même problème).

Le modèle de pentes est plus problématique et il n'y a pas de solution générique qui fonctionnera dans tous les cas. Heureusement, l'utilisation la plus courante de ces modèles est dans les champs de niveaux, et là une solution est possible :

Si vous avez ce problème dans un champ de niveaux, la solution est de dédoubler le spectre de couleur (ou tout autre modèle utilisé) aux alentours de 0.5. Alors l'inversion de la normale n'est plus importante. Ainsi, si vous avez quelque chose comme ceci dans une champ de niveaux :

slope y color_map {
	[0.50 rgb <.5, .5, .5>]	// rocher
	[0.75 rgb <.8, .4, .1>]	// sol
	[1.00 rgb <.4, 1, .4>]	// herbe
}

Vous avez seulement à répéter le spectre autour de 0.5, c.a.d. ajouter les valeurs de 0 à 0.5 mais dans l'ordre inverse :

slope y color_map {
	[0.00 rgb <.4, 1, .4>]	// herbe
	[0.25 rgb <.8, .4, .1>]	// sol
	[0.50 rgb <.5, .5, .5>]	// rocher
	[0.75 rgb <.8, .4, .1>]	// sol
	[1.00 rgb <.4, 1, .4>]	// herbe
}

A côté de cela, vous pouvez bien sûr appliquer double_illuminate au champ de niveaux pour obtenir la bonne illumination.

2.4.8 L'artefact en ligne d'ombre 2.4.8 L'artefact en ligne d'ombre 2.5 Annexes 2.5 Annexes