Transformation de coordonnées de 3D à 2D | WebGPU

La grande finale de notre histoire de transformations. Nous verrons comment transformer un sommet 3D de NDC en coordonnées d'écran 2D, qui seront utilisées pour créer une image qui nous rend fiers.

Keywords: WebGPU, le pipeline de rendu, le rendu en temps réel, les transformations

By Carmen Cincotti  

Je voudrais terminer cette histoire de transformations subies par un sommet pendant son parcours à travers le pipeline de rendu. Notre dernier arrêt est l’espace 2D. Alors - on y va !

La transformation du viewport

Nous reprenons notre discussion à partir de NDC. Pour l’instant, on est encore dans l’espace 3D.

Comment allons-nous à l’espace 2D ?

Il faut transformer notre sommet de NDC en coordonnées de l’écran.

Lors de l’initialisation du Canvas, on est chargé de configurer sa taille. Cette taille est utilisée pour convertir nos coordonnées NDC en coordonnées de l’écran. Voici l’illustration :

NDC to Screen Coordinates

Faites attention à la position de l’origine de chaque espace dans l’illustration ci-dessus :

  • NDC - L’origine est au centre. Nos coordonnées NDC sont normalisées entre les valeurs (-1, 1) dans les axes x et y. La valeur de l’axe z est entre (0, 1).
  • Les coordonnées de l’écran - l’origine est en haut à gauche. Le point qui se trouve en bas à droit est la taille définie de notre écran (w largeur, h hauteur).

Le framebuffer

Pour dessiner notre image à l’écran, le WebGPU doit écrire des informations sur chaque pixel dans un tampon de couleur (color buffer).

Le tampon de couleur, combiné avec d’autres tampons qui peuvent être utilisés pour rendre une image finale tels que le tampon de profondeur (depth buffer) et le tampon de stencil (stencil buffer), sont stockés dans la mémoire GPU. Cette combinaison s’appelle un framebuffer.

Si l’on considère que notre framebuffer contient un tampon de couleur qui stocke les informations de couleur d’une aire de pixels de la taille de notre écran (ou d’une taille de Canvas arbitrairement définie par nous), il faudrait donc transformer ces coordonnées normalisées dans celles qui correspondent aux coordonnées de notre cible de rendu (l’écran / Canvas).

Les mathématiques de la transformation

Les axes x et y correspondent à la taille définie de l’image finale. Heureusement, les docs de WebGPU nous fournissent ce calcul :

fbCoords(n).x=vp.x+0.5(n.x+1)vp.wfbCoords(n).y=vp.y+0.5(n.y+1)vp.h\textbf{fbCoords(n).x} = vp.x + 0.5 * (n.x + 1) * vp.w\\ \textbf{fbCoords(n).y} = vp.y + 0.5 * (n.y + 1) * vp.h\\

La hauteur (vp.h) et la largeur (vp.w) sont la largeur et la hauteur définies de notre viewport. Les positions vp.x et vp.y sont des décalages de position. Supposons que nous les définissions comme 0.

En ce moment, le calcul pour convertir l’axe z n’est pas défini dans les docs. Cependant, Songho nous indique que pour OpenGL, le calcul est comme suit :

fbCoords(n).z=0.5(fn)z.y+0.5(f+n)\textbf{fbCoords(n).z} = 0.5*(f-n)* z.y + 0.5*(f+n)

f est la valeur de la position du plan lointain, et n est la valeur de la position du plan proche. Voyez l’article de la semaine dernière pour en savoir plus.

Avec ces calculs, nous pouvons voir que le mapping entre NDC et les coordonnées de l’écran est une relation linéaire :

x:1x,1x+wy:1y,1y+hz:0n,1f \textbf{x}: -1 \rightarrow x, 1 \rightarrow x + w \\ \textbf{y}: -1 \rightarrow y, 1 \rightarrow y + h \\ \textbf{z}: 0 \rightarrow n, 1 \rightarrow f \\

💡 Que devient-elle, la coordonnée z ?

Lors de la rastérisation, la couleur d’un pixel qui sera rendu sur l’écran est provisionnée dans le tampon de couleur.

Cependant, si l’on configure un test de profondeur (depth test), la coordonnée z pourrait être utilisée pour résoudre la visibilité, avec l’utilisation du tampon de profondeur pendant le processus qui s’appelle merging.

Bref, le test de profondeur assure que les sommets / primitives les plus proches de la caméra sont provisionnés dans le tampon de couleur (rendu sur l’image finale) et les autres sont rejetés.

Nous reviendrons sur ce sujet quand nous abordons la rastérisation.

Le code dans WebGPU

Il y a quelques semaines, nous avons vu du code afin de créer un triangle avec WebGPU. Rappelons qu’il y a une étape pour configurer à la fois notre CanvasContext et swap chain :

const configureContext = (presentationFormat) => { const devicePixelRatio = window.devicePixelRatio || 1; const presentationSize = [ this._context.canvas.clientWidth * devicePixelRatio, this._context.canvas.clientHeight * devicePixelRatio, ]; this._context.configure({ device: this._device, format: presentationFormat, size: presentationSize, }); } const presentationFormat = this._context.getPreferredFormat(this._adapter); configureContext(presentationFormat)

C’est notre travail de fournir la taille de l’image finale. Cette taille est utilisée pendant la transformation de NDC en coordonnées de l’écran.

C’est à nous de redéfinir cette valeur au cas où nous changerions la taille de la fenêtre.

La suite

Je pense qu’il est temps de continuer l’aventure de la simulation de tissu. Étant équipés de ces nouvelles connaissances, on est prêt à implémenter un moyen de charger un fichier .obj dans notre scène.

Des ressources (en français et anglais)


Comments for Transformation de coordonnées de 3D à 2D | WebGPU



Written by Carmen Cincotti, computer graphics enthusiast, language learner, and improv actor currently living in San Francisco, CA.  Follow @CarmenCincotti

Contribute

Interested in contributing to Carmen's Graphics Blog? Click here for details!