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…

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