Pourquoi les GPU divisent-ils l'espace de clip Z par W, pour la position?

8

Contexte:
J'ai trouvé qu'il est très facile d'utiliser un tampon de profondeur linéaire, en n'utilisant qu'une légère modification de la transformation canonique du sommet. La méthode la plus simple se trouve au bas de https://www.mvps.org/directx/articles/linear_z/linearz.htm .

Cependant, la mise en garde est que cela ne fonctionne que pour les triangles qui n'ont pas besoin d'être clipsés contre les plans proche ou éloigné. (Et une autre solution, consistant à effectuer la division en perspective dans le vertex shader, produira un problème similaire pour les quatre autres plans tronconiques.)

Étant donné que l'écrêtage nécessite une interpolation linéaire pour fonctionner sur les quatre coordonnées d'espace de clip, je pense qu'il est impossible de travailler avec une profondeur linéaire, en utilisant uniquement un vertex shader. Mais la raison en est que Z est divisé par W.

Pourquoi est-ce fait? X et Y doivent être divisés par la distance de la caméra, mais pas la coordonnée Z, pour s'intégrer parfaitement dans la boîte NDC.

Jessy
la source

Réponses:

13

Si vous faites une image en perspective et que votre modèle a des intersections implicites, si vous utilisez "Z linéaire", ces intersections apparaîtront aux mauvais endroits.

Par exemple, considérons un simple plan de masse avec une ligne de poteaux téléphoniques, s'éloignant au loin, qui transpercent le sol (et continuent ci-dessous). Les intersections implicites seront déterminées par les valeurs de profondeur interpolées. Si ceux-ci ne sont pas interpolés avec 1/Z, alors lorsque les sommets projetés ont été calculés avec la perspective, l'image sera incorrecte.

Je m'excuse pour la qualité non esthétique des illustrations suivantes mais je les ai faites en 1997.

La première image montre l'effet de rendu requis. (Notez que les "pylônes" bleus vont assez loin sous le plan du sol et sont donc coupés au bas des images)

entrez la description de l'image ici

Cette deuxième image montre le résultat de l'utilisation d'un tampon de profondeur non réciproque: (Excuses pour le changement d'échelle - celles-ci ont été copiées à partir d'un ancien document MS Word et je n'ai aucune idée de ce qui s'est passé avec la mise à l'échelle.)

entrez la description de l'image ici

Comme vous pouvez le voir, les résultats sont incorrects.

Sur une autre note, êtes-vous sûr de vouloir vraiment une représentation Z linéaire? Si vous effectuez un rendu en perspective, on veut sûrement plus de précision plus près de la caméra qu'à distance?

Re votre commentaire ultérieur:

"Si ceux-ci ne sont pas interpolés avec 1 / Z" que je ne comprends pas. Quelle interpolation est-ce?

La première chose à noter est qu'avec une projection en perspective standard, les lignes droites dans l'espace mondial restent des lignes droites dans l'espace en perspective. Les distances / longueurs ne sont cependant pas conservées.

Pour simplifier, supposons qu'une transformation de perspective triviale est utilisée pour projeter les sommets, c'est-à-dire Nous devons également calculer une profondeur d'espace d'écran réciproque, par exemple mais le Z linéaire dans le tampon de profondeur nécessiterait, selon moi, quelque chose comme: (On peut supposer ici que scale = 1)

XScreen=XWorldZWorld
YScreen=YWorldZWorld
ZScreen=1ZWorld
ZScreen=scaleZWorld

Supposons que nous ayons une ligne avec les points d'extrémité de l'espace mondial Avec la mise en perspective de ces cartes sur les coordonnées de l'espace d'écran

[001]and[200010]
[001]and[2000.1]

Le système / matériel de rendu interpolera linéairement l'espace d'écran z, donc au point 1/2 de la ligne, tel qu'il apparaît à l'écran, c'est-à-dire au pixel (10, 0), nous obtiendrions un Z inverse (projeté) 0,55, ce qui correspond à une valeur Z de l'espace mondial de ~ 1,818. Étant donné les valeurs Z de début et de fin, cela représente environ 20% le long de la ligne.

Si à la place, nous essayions d'interpoler en utilisant les valeurs Z d'origine, nous nous retrouverions avec Z correspondant à une valeur d'espace mondial de 5,5. Tant que rien ne se croise, vous pouvez être d'accord (je n'y ai pas trop réfléchi) mais tout ce qui a des intersections implicites sera incorrect.

Ce que je n'ai pas mentionné, c'est qu'une fois que vous avez introduit une texturation correcte en perspective (ou même un ombrage correct en perspective), vous devez effectuer une interpolation par pixel de 1 / w et, en outre, calculer également, par pixel, l'inverse de cette valeur interpolée.

Simon F
la source
Je ne pense pas que je serai en mesure de comprendre cette réponse sans plus de mathématiques / diagrammes. Et oui, plus de précision, plus près, a probablement du sens, mais une mise à l'échelle de linéaire par far / z, qui est standard, n'a pas de sens. Il produit un tampon de profondeur qui devient plus linéaire plus les deux plans de clip sont proches l'un de l'autre. Cela ressemble à une fusion de deux concepts: un écran espace linéaire Z et un mappage de tampon de profondeur non constant pour un hack de performance.
Jessy
Plus précisément, c'est le «si ceux-ci ne sont pas interpolés avec 1 / Z» que je ne comprends pas. Quelle interpolation est-ce?
Jessy
1
J'ajouterai du texte supplémentaire pour, je l'espère, expliquer
Simon F
Merci! Je pense que le problème se résume à "Le système / matériel de rendu interpolera linéairement l'espace d'écran z". J'avais l'impression que la position NDC serait calculée en tant que (x, y, z) / wfragment, mais apparemment, à la place, nous devons traiter avec une version interpolée linéairement de (x/w, y/w, z/w)? Cela ne me semble pas raisonnable en 2018, mais ce serait bien de savoir si c'est le hack avec lequel nous devons vivre pour l'instant de toute façon!
Jessy
Pour effectuer une texturation / ombrage / perspective correcte, vous devez interpoler linéairement les valeurs (Val / w), puis, par fragment, faire une division par le 1 / w interpolé linéairement. C'est un peu difficile à expliquer juste dans un commentaire, mais il y a un peu d'explication dans computergraphics.stackexchange.com/a/4799/209 . Sinon, faites une recherche pour l'article de Jim Blinn "Interpolation hyperbolique"
Simon F
6

L'utilisation de Z / W pour le tampon de profondeur va plus loin que le simple écrêtage contre les plans proche et éloigné. Comme Simon l'a fait allusion, cela a à voir avec l'interpolation entre les sommets d'un triangle, pendant la pixellisation.

Z / W est l'option unique qui permet de calculer correctement les valeurs de profondeur NDC pour les points à l'intérieur du triangle, en interpolant simplement les valeurs de profondeur NDC à partir des sommets, dans l'espace d'écran . En principe, nous pourrions utiliser n'importe quelle fonction que nous aimons pour mapper l'espace de la caméra Z à la valeur du tampon de profondeur, mais tout autre choix que Z / W nécessiterait des calculs plus compliqués par pixel, ce qui serait plus lent et plus difficile à construire du matériel.

Notez que si vous utilisez un tampon de profondeur linéaire, alors bien sûr, les valeurs de profondeur à interpolation linéaire seront correctes dans l' espace monde ... mais pas, en général, dans l'espace écran! Et c'est l'espace d'écran qui importe pour la pixellisation, car nous devons être en mesure de générer des valeurs de profondeur correctes en perspective (et d'autres valeurs d'attribut, comme les UV) pour chaque centre de pixel ou autre point d'échantillonnage, dans les limites de l'espace d'écran d'un triangle en cours de tramage.

Nathan Reed
la source
Je ne sais pas comment concevoir un GPU, mais il me semble qu'il suffit d'interpoler Z au lieu de Z / W, pour une profondeur linéaire, et une interpolation Z / W pourrait encore se produire par la suite pour tout ce qui est visible. Je ne peux toujours pas dire si c'est une question de bon raisonnement ou de «personne ne s'en soucie donc nous ne prenons pas la peine de mettre à jour».
Jessy
L'interpolation de Z au lieu de Z / W ne donne pas de résultats corrects dans l'espace d'écran. Z / W le fait.
Nathan Reed
Droite. Mais si le tampon de profondeur est quantifié avec une précision inférieure à la position, alors, en plus d'être performant quand il fonctionne, ce n'est pas une bonne idée de stocker un morceau à l'échelle de l'espace d'écran Z. Si l'interpolation linéaire est tout ce que nous obtenons, alors le découpage a besoin se produire dans l'espace de vue. Et Z doit être interpolé avant la division par W, pour le tampon de profondeur, et après, pour ce que vous avez dépassé. La réponse à ma question est-elle donc "parce que les GPU n'ont toujours été interpolés que dans l'espace clip parce que c'était la seule solution pratique sur les premiers GPU, et cela a assez bien fonctionné depuis"?
Jessy
Je ne suis pas en train de suivre ce que vous entendez par "quantifié avec une précision inférieure à la position" ou "stocker un morceau à l'échelle de l'espace d'écran Z".
Nathan Reed
1
De plus, "Z doit être interpolé avant la division par W, pour le tampon de profondeur" —non. C'est ce que j'ai essayé d'expliquer. Vous obtenez les mauvaises réponses si vous interpolez Z (ou toute autre chose) dans l'espace d'écran sans le diviser par W d'abord. Vous semblez être coincé sur cette idée qu'un tampon Z linéaire fonctionnerait juste si nous ne divisions pas par W. Mais cela ne fonctionnera pas - il ne s'interpolera pas correctement dans l'espace d'écran.
Nathan Reed