Skip to content

La perry-camera

Quest’oggi parliamo della distorsione prospettica nelle camere reali :). Come sicuramente quelle 2/3 persone che leggeranno questo post sapranno, diverso tempo fà ho lavorato in un videogioco di pallavolo, quando questo sport viene trasmesso in tv accade, come in tutti gli altri sport, che venga ri-trasmessa l’ultima azione, come riempitivo di un momento morto o perché particolarmente spettacolare (nella pallavolo il primo caso è il più comune). Nella pallavolo alcune volte il replay fa uso di una telecamera grandangolare piazzata altezza rete… ed ovviamente la trasposizione videoludica non si poteva esimere dall’avere lo stesso effetto distorto e incomprensibile. Dopo un po’ di esperimenti cercando di riprodurre questo effetto, notai che mentre solitamente si proietta la scena 3D su un piano davanti alla telecamera, dove ogni punto è su un piano come se fosse parallelo allo schermo, per ottenere un’effetto distorto dovevo trattare la proiezione come fosse su una sfera, quindi se solitamente abbiamo sx=\frac{x}{z} e sy=\frac{y}{z}  , dove x,y e z sono le coordinate 3d da proiettare e sx e sy i punti proiettati, per la visione a “occhio di pesce” avevo d=\sqrt{x^2+y^2+z^2}  e quindi sx=\frac{x}{d}  e sy=\frac{y}{d}  .

Anche se non ho mai trovato altre applicazioni di questa formula nei videogiochi, ho trovato che la proiezione su una sfera sia più veritiera, infatti si trovano programmi per eliminarla dalle foto, io invece volevo crearla nel 3D. Purtroppo la rasterizzazione dei triangoli si sposa male con rette curve a causa della distorsione della lente e quindi ho cercato una usa possibile applicazione nel raytracing dove per ogni pixel viene sparato un raggio e questi possono essere calcolato in qualunque modo.

Nel raytracing però la formula è invertita, abbiamo le coordinate schermo e vogliamo il raggio che rappresenta il dato pixel. Supponendo per semplicità di spiegazione di avere una camera piazzata all’origine degli assi e rivolta verso z in un sistema sinistrorso, abbiamo come punto di partenza la camera e la direzione che si calcola con la solita formula come x=sx * tan(\frac{fov}{2})  ,  y=sy * tan(\frac{fov}{2}) e z=1 dove sx e sy sono le coordinate del pixel normalizzato, cioé con sx compreso tra -1,333 e 1,333 e sy tra -1 e 1 (o combinazioni varie per rispettare l’aspect-ratio), e fov è la focale di camera, cioè l’angolo di visione. Per riuscire ad applicare la mia formula invece ho dovuto passare le coordinate schermo da un sistema cartesiamo ad uno sferico, quindi da sx e sy a theta = atan(\frac{sy}{sx}) e phi = \sqrt{sx^2+sy^2} * \frac{fov}{2} così la nuova direzione ha x=cos(theta)*sin(phi), y=sin(theta)*sin(phi) e z=cos(phi).

Qua potete vedere risultati comparativi di un programmino che ho scritto per provare questa formula, in alto la mia proiezione in basso quella classica, ai fov di 45, 90 e 179°. Ovviamente la mia può proiettare a più di 179°.

Sul perché queste immagini sono antialiasate ne parlerò in un prossimo post dove metterò anche il codice di questo flat  raytracing (forse).

Be First to Comment

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.

*