Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





SSAO Webgl

Iniciado por KneDa, 24 de Abril de 2012, 05:53:49 PM

« anterior - próximo »

KneDa

Saludos señores, estaba intentando hacer algún efecto de postprocesado en webgl, pero el caso es que no tengo muy claro como llegar a usar el depth buffer...

Si alguien fuese tan amable me podría explicar que alternativas hay con webgl? He estado googleando bastante y todavía no he conseguido dar con una buena solución.

Gracias por adelantado.

XÑA

Que yo sepa acceder al Depth buffer en WebGL es imposible. De hecho hasta la revisión DX10 y OGL 3.1 ( creo) no se podía acceder.

Lo que tienes que hacer es una pasada adicional usando un RenderTarget y guardando la Z.

KneDa

Claro, es como tu dices, por eso pregunto de alguna forma de hacerlo.

Mmm, podrías detallarme más esto último que comentas del rendertarget y guardar la Z, hace poco que he empezado a usar webgl y ando bastante perdido.

Gracias.

Gallo

al depht buffer ya se podia acceder en dx9 y OGL 2.1, pero las técnicas de postprocesado se han vuelto una práctica mas común estando presentes las APIs de dx10 y 3.1, pero muchos de motores lo implementan para las versiones antiguas por conservar la compatibilidad con windows XP.

Si la spec de webgl no  permite acceder directamente a la info del depht buffer, que así parece ser, puedes crear una textura y "volcar" los valores de profundiad en ella, es decir, renderizar la escena en una textura pero en el gl_FragColor, el color que guardas es un gris entre 0 y 1 que indica la profundiad (la z del fragment), esta textura luego la puedes la pasar a los shaders y volver a renderizar la escena usando la textura como ZBuffer para por ejemplo hacer blur, o SSAO, eso si.. el rendimiento debe ser penoso, pero por experimentar que no quede!!

KneDa

Ok Gallo, intentaré ese método que has comentado usando la extensión OES-texture-float... aunque creo haber leído en algún sitio que solo está soportada en chrome.

Gracias :)

Gallo

A ver, he estado indagando y en si solo tienes que atachar un renderbuffer o texture2d al framebuffer donde pintas, con el flag gl.DEPTH_ATTACHMENT

En este tutorial de "render to texture" tienes un ejemplo de como atachan una textura para guardar el color y un renderbuffer para guardar la infromación de profundiad. Si usas una textura puedes pasarla luego como parámetro para el shader que hace el efecto de postprocesado:

http://learningwebgl.com/blog/?p=1786

Este es el trozo de código para crear y atachar un renderbuffer, es muy similar para la textura, también esta enne l tuto :

var renderbuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rttFramebuffer.width, rttFramebuffer.height);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer);

KneDa

Ummm, gracias Gallo. Ok, actualmente ya no tengo ningún problema con el tema de los FBO y el multipass rendering... ahora bien, una dudilla concreta del efecto en si.

Cuales son las posibilidades a la hora de calcular el depth buffer, quiero decir, supongo que no hay la forma definitiva (o igual si :D ), quisiera saber cómo lo calculan ustedes o algún buen tutorial. Aquí la forma sencilla:

commonDepth_fs
-------------------------
precision mediump float;

uniform float time;
varying vec4 posGL;

void main(void) {
   float zDepth=posGL.z/posGL.w;
   gl_FragColor = vec4(zDepth,zDepth,zDepth,1.0);
};

commonDepth_vs
--------------------------
attribute vec3 position;
uniform mat4 mvp_transform;
varying vec4 posGL;

void main(void) {
   gl_Position = mvp_transform * vec4(position, 1.0);
   posGL=gl_Position;
}

El problema de este cálculo es que tengo que andar ajustar los valores zNear y zFar de la cámara para conseguir un resultado más o menos bueno dependiendo de la escena. Entonces, cómo se haría el cálculo correcto? Gracias por adelantado :)

KneDa

Ánimo, algún valiente que se atreva a exponerme la teoría del Z y el W buffer ?  He leído información en varios sitios y todavía no lo acabo de tener claro... actualmente tengo el SSAO corriendo pero sigo con el problema de tener que meter valores muy altos del ZNear plane con proyección en perspectiva. Me gustaría averiguar la solución para valores menores entre (0,1] ... Gracias por adelantado.

KneDa

Ok, al final acabé tirando de lápiz y papel y comprendí las mates detrás d todo esto. El Z y el W buffer ya no tienen misterio y el SSAO está tirando bastante bien :D

KneDa

Ummm, hasta ahora había estado guardando las coordenadas del espacio de cámara en texturas para luego usarlas en el shader SSAO, lo cual funciona bien.

Pero estos días he estado intentando evitar dicho paso y quería calcular dichas coordenadas a partir del depth buffer, método el cual está más que documentado en cientos de artículos de internet, pero he tenido varios problemas.

Antes de explicar el método usado, pongamos algo de nomenclatura:

M=World matrix transformation
V=View matrix transformation IV=Inverse View matrix transformation
P=Projection matrix transformation   IP=Inverse Projection Matrix transformation

v_m=model space coordinates
v_w=world space coordinates=M*v_m               
v_e=eye space coordinates=V*v_w                     
v_c=clip space coordinates=P*v_e                     
v_n=normalized device coordinates=(v_c.x/v_c.w,v_c.y/v_c.w,v_c.z/v_c.w) = v_c.xyz/v_c.w

* = Producto matricial

Ok, ahora bien, lo que interesa aquí es recuperar v_e a partir de v_n. La primera forma lógica de proceder sería algo tal que así:

v_c=(v_n.x*v_c.w,v_n.y*v_c.w,v_n.x*v_c.w,v_c.w)
v_e=IP*v_c

pero con el depth buffer desconocemos a priori v_c.w , ya que estamos almacenando v_c.z/v_c.w . Lo que algunas páginas proponen sería utilizar el siguiente método:

v_e'=IP*v_n
v_e.xyz=(v_e'.x/v_e'.w,v_e'.y/v_e'.w,v_e'.z/v_e'.w)

la verdad, no he conseguido demostrar esta igualdad, así que he hecho un programa que generando coordenadas aleatorias use este método y si que es verdad que funciona.

Pero a pesar de que el cálculo es a correcto no estoy consiguiendo los resultados correctos en mi shader utilizando este método y todavía no he averiguado porqué, ya que mi matriz de proyección inversa es correcta y los valores de mi v_n están en el rango [-1,1] ... Mi única sospecha es que cuando corrijo el rango del valor del depth buffer estoy haciendo (depth-0.5)*2.0 y quizás tendría que hacer ((1.0-depth)-0.5)*2.0 , lo probaré el lunes en el trabajo.

Entonces, algún valiente sería capaz de explicarme o demostrarme matemáticamente este método de obtener v_e a partir del depth?

Guau, vaya chorizo he largado :P






Stratos es un servicio gratuito, cuyos costes se cubren en parte con la publicidad.
Por favor, desactiva el bloqueador de anuncios en esta web para ayudar a que siga adelante.
Muchísimas gracias.