Skip to content

webGL: esperimento 2

Ciao a tutti,

come prima cosa, ecco il risultato: aperricone.altervista.org/wegl2/

ultimamente mi è venuta la pazza idea di convertire un mio esperimento openGL in WebGL,  l’esperimento è visionabile qua: https://www.youtube.com/watch?v=qhwlZcrYKFc, in esso utilizzo una sorgente luminosa sferica: ha una  posizione è un raggio. La ragione per cui l’ho fatto è che ho sempre trovato l’illuminazione da area light più realistica delle altre, e una sfera è una buona approssimazione da applicare al real time.

Il rendering è un forward con prepass, nella versione OpenGL, gli step sono:

  • rendering della scena su una cube map di formato depth centrata nella luce, utilizzando geometry shader per farlo in single pass.
  • z-prepass della scena nel frame buffer principale
  • rendering della scena, esso ha:
    • una illuminazione adattata per utilizzare il raggio della luce
    • un’ombra PCSS (percentage closed soft shadow)
    • un ambient SSAO utilizzando il deph buffer copiato in una texture.
  • post process

Per la conversione in WebGL, la prima cosa è stato che non c’è il geometry shader, questo me l’aspettavo, quindi invece di un singolo pass  bisogna farne sei.

La seconda cosa, che non mi aspettavo, è che non possibile creare un cube map di tipo depth, c’è proprio un test di conformità che specifica che bisogna tornare operazione invalida se ci si prova… Soluzione: la cubemap è di tipo colore, ed invece di fare un rendering solo Z, uno uno shader che codifica lo z buffer nel colore, in questo modo:

vec3 rgbVal = vec3(fract(zVal*vec3(1.0,256.0,256.0*256.0)));
rgbVal -= rgbVal.yzz * vec3(1.0/256.0,1.0/(256.0*256.0),0.0);

quindi in fase di lettura, da un semplice sampling si passa a:

float zVal =  dot(rgbVal,vec3(1.0,1.0/256.0,1.0/(256.0*256.0)));

Questo problema è stato facile da risolvere… 🙂 anche se la trovo una limitazione inutile…

il terzo problema si può vedere anche nella descrizione sopra, ho scritto: “utilizzando il deph buffer copiato in una texture” in OpenGL questo si fà chiamando glCopyTexImage2D che copia il frame buffer su una texture, se è di tipo depth allora copia il depth buffer, come spiegato qua: depth_texture. Questo va bene anche in OpenGL ES: OES_depth_texture. invece su WebGL WEBGL_depth_texture si può solo usare una depth associato ad un frame buffer…

SSAO in post

prima soluzione, spostare l’SSAO in post process, quindi l’ambient del disegno è nero e  nel post processing aggiungo un ambient con SSAO… questa soluzione funziona, è veloce, è facile.

Piccolo problema in fase di post non conosco il colore del materiale quindi ho fatto tutto l’ambient grigio… funziona ma è proprio bruttino.

seconda soluzione, usare OES_depth_texture, quindi creo un’altro frame buffer con un’altra texture di tipo depth e a metà rendering attivo questo depth e ci scrivo sopra così:

gl_FragDepthEXT = texture2D(depthBuffer,texCoord).x;

Che giro malato, ma il risultato è quello sperato.

Oltre alle peripezie con WebGL, sono soddisfatto di questo esperimento per altre cose:

  • l’uso di ammo.js per la fisica, passando per un WebWorker così da rendere la pagina multithread 😎 .
  • Il sonoro, anche se il risultato è una mezza schifezza, mi sono divertito a farlo… 🙂
  • La minimizzazione: Ho fatto un programma che prende l’html, e minimizza tutto il javascript presente, parsa il javascript e minimizza tutti gli shader. Davvero fico.

Tanti saluti e belle cose

Be First to Comment

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.


*