Éviter les combats z avec des surfaces coïncidentes

26

Lors du rendu de deux surfaces coplanaires superposées, un problème courant est le «combat z», où le rendu ne peut pas décider laquelle des deux surfaces est la plus proche de la caméra, ce qui donne des artefacts visuels dans la zone de chevauchement.

La solution standard est de donner aux surfaces un léger décalage lors de la conception du modèle. N 'y a-t-il pas une autre solution?

marque
la source
2
Vous pouvez extraire les tampons de profondeur logarithmique. Il y a un article sur gamasutra
Soapy
1
Quand vous dites «coplanaire», voulez-vous dire «presque» ou «exactement» coplanaire et, dans ce dernier cas, ces surfaces sont-elles toujours des surfaces / triangles identiques? Le matériel de rendu doit être déterministe (en supposant que vous ne soumettez pas dans un ordre aléatoire) pour le dernier cas et ne pas avoir de combat. S'il s'agit de surfaces non identiques mais exactement coplanaires, pourriez-vous mettre à jour le modèle pour diviser les surfaces en portions superposées et non superposées?
Simon F
@SimonF, par "coplanaire", je veux dire "exactement coplanaire". La solution de Soapy ne fonctionne que dans le cas "presque coplanaire".
Mark
Pourriez-vous donner un exemple de vos surfaces? La seule chose à laquelle je peux penser du haut de ma tête est les triangles en double comme l'a mentionné @SimonF.
RichieSams
@RichieSams le cas le plus courant auquel je peux penser est celui des décalcomanies, où vous n'avez pas besoin de triangles exactement en double.
rys

Réponses:

10

Si les surfaces sont exactement co-planantes, votre sort dépend des dieux du FPU; vous aurez plus que probablement des combats Z. Si les triangles sont identiques et vous faites le exacte même mathématiques à chacun, vous allez retrouver avec les mêmes valeurs Z pour les deux. Mais encore une fois, cela ne se produira que si vos opérations mathématiques sont identiques pour les deux. (Puisque, en général, les opérations FPU ne sont pas commutatives)

Une solution possible consiste à ne pas utiliser du tout le tampon Z. Vous pouvez plutôt utiliser l' algorithme du peintre . Certes, cela vient aussi avec tous les problèmes de l'algorithme des peintres. Mais cela résoudrait les combats en Z.

Dans votre cas d'exemple de Screen Space Decals (SSD), la solution courante consiste à utiliser un décalage, alias un simple cube mince. Voir la présentation de Warhammer 40k sur les SSD pour référence. Ou Bart Wronski poste qui traite d'autres questions avec des autocollants, mais aussi des liens vers quelques autres présentations sur disques SSD

RichieSams
la source
5
Un nouveau rendu de la même géométrie avec les mêmes transformations génère de manière fiable les mêmes valeurs de profondeur à chaque fois. (C'est-à-dire que ce n'est pas une puissance , c'est une volonté ). C'est pourquoi l'éclairage avant à plusieurs passes fonctionne, par exemple.
Nathan Reed
@NathanReed corrigé. Merci pour la clarification
RichieSams
1
Pour obtenir cette fonctionnalité, vous devez utiliser le qualificatif invariant dans glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu
Notez que des expressions de shader identiques (et des entrées, évidemment) lors de l'évaluation des positions des sommets peuvent ne pas être suffisantes pour obtenir des résultats identiques car certaines optimisations peuvent dépendre du reste du shader. GLSL a le mot-clé "invariant" pour déclarer les sorties de shader qui doivent être évaluées de manière identique dans différents shaders.
Firadeoclus
2

Voici comment j'ai résolu cela dans le passé:

  1. Dessinez le premier objet (celui qui devrait apparaître derrière l'autre objet) par un test de profondeur mais pas par une écriture de profondeur
  2. Dessinez le deuxième objet par des tests de profondeur et une écriture en profondeur. Cela ne causera pas de z-combats car nous n'avons pas écrit de profondeur à l'étape 1.
  3. Dessinez le premier objet en écrivant uniquement dans le tampon de profondeur et non dans le tampon de couleur. Cela garantit que le tampon de profondeur est à jour pour tous les pixels couverts par l'objet 1 mais pas par l'objet 2.

Notez que les objets doivent être dessinés consécutivement pour que cela fonctionne.

défaut
la source
0

Selon votre moteur de rendu, vous pouvez rendre les surfaces plus "floues" en appliquant un décalage minuscule dans une profondeur de multi-échantillonnage en utilisant un algorithme de type bruit. Cela devrait se traduire par une sorte d'effet de fusion pour les surfaces à proximité de profondeur proche. Pour ce que je sais, la définition de la profondeur par échantillon dans le fragment shader est assez récente dans OpenGL, puis uniquement en tant qu'extension.

OpenGL a le PolygonOffset mais nécessite de savoir à l'avance que vous êtes sur le point de rendre quelque chose de coplanaire. Bien que cela ne soit pas possible pour les surfaces d'un modèle unique, cela pourrait bien fonctionner, par exemple lors du rendu d'une route superposée sur un terrain.

Andreas
la source