Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Sky Dome. Un Shader Interesante

Iniciado por Haddd, 06 de Enero de 2004, 08:46:11 PM

« anterior - próximo »

Haddd

 Estoy preparando algo del espacio, y me asaltó una duda.

Imaginaos el espacio formado por las estrellas y los planetas. Pues los planetas son esferas texturizadas y el espacio es una gran esfera texturizada con estrellas. Hasta aquí todo lógico y sencillo.

Bien, pues para hacer un render óptimo, se me ocurre que primero se dibujen los planetas y después se dibuje el espacio. De esta forma si el espacio no se tiene que dibujar porque estamos mirando de frente un planeta, pues el ZBuffer lo descartará rápidamente.

Pues se me ocurre hacer un shader que la Z siempre sea =1 en clip space. De esta forma, da igual el tamaño que tenga la esfera que hace el espacio, porque siempre se dibujará como si su Z fuera la más grande y por tanto no tapará nada que no deba taparse.

Algunos pensareis, que tontería, haz la bola enorme y listo. Pues no, porque eso me obliga a que el far plane sea tambien enorme, y por tanto perdería precicisón cuando en realidad no hay motivos para hacerlo.

Por otro lado, me parece que si puedo resolverlo en un shader, mejor que mejor.

Bien, pues este es mi shader y ...¡no funciona!

"vs_2_0               // version instruction\n"\
"dcl_position v0      // declare position register\n"\
"dcl_texcoord v8      // declare texture coordinate register\n"\
"def c12, 1, 1, 1, 1   // initialize a constant\n"\
"def c13, 1, 1, 1, 1   // initialize a constant\n"\
"m4x4 oPos, v0, c0    // transform vertices by view/projection matrix\n"\
"mov oPos.z, c13.x          // move diffuse color to output color register\n"\
"mov oD0, c12          // move diffuse color to output color register\n"\
"mov oT0, v8          // move texture color to output texture register\n"\

Lo que hago es decirle que el valor de Z en clip space es 1, pero no lo hace bien. Estoy seguro que me falta leerme cosas sobre el clip space para entenderlo bien, pero aquí está el foro para echarme una mano, y de paso, comparto la idea de este shader, que me parece muy buena.

Venga, ánimo!

BeRSeRKeR

 La verdad es que no sé si con lo que quieres hacer obtendrás los resultados esperados pero bueno, ahí va lo que yo haría.

He hecho una prueba rápida con el RenderMonkey. Ha consistido en hacer que el modelo del elefante siempre estuviera por delante del modelo ScreenAlignedQuad. Aunque éste último en realidad está justo en medio del elefante, es decir, viendo frontalmente el quad (lateralmente el elefante), el quad parte en dos al elefante.

Este es el vertex shader del elefante (no tiene misterio, es como siempre):

Citarstruct VS_OUTPUT
{
     float4 Pos: POSITION;
};

VS_OUTPUT vs_main( float4 inPos: POSITION )
{
     VS_OUTPUT Out;

     // Object space -> clip-space.
     Out.Pos = mul(view_proj_matrix, inPos);

     return Out;
}

Este es el vertex shader del quad. Aquí es donde las cosas cambian:

Citarstruct VS_OUTPUT
{
     float4 Pos: POSITION;
};

VS_OUTPUT vs_main( float4 inPos: POSITION )
{
     VS_OUTPUT Out;

     // Escalamos un poco el quad.
     inPos.xy = inPos.xy * 50.0f;

     // Object space -> clip-space.
     Out.Pos = mul(view_proj_matrix, inPos);

     // Coordenadas homogéneas (comentar estas dos líneas
     // si se quiere que el quad se vea normal, es decir,
     // para que parta en dos al elefante).

     Out.Pos.xyw = Out.Pos.xyw / Out.Pos.w;
     Out.Pos.z = Out.Pos.w;   // si se quiere que el quad siempre
                                       // esté delante del elefante, poner a 0.

     return Out;
}

Por ahora no se me ocurre otra cosa...

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 ¿para qué haces esto?

Out.Pos.xyw = Out.Pos.xyw / Out.Pos.w;
Out.Pos.z = Out.Pos.w

El Clip Space es un cubo que en X,Y va de -1 a 1 y en Z de 0 a 1. Lo lógico sería que le pusiéramos un 1 en la z y en la w, ¿no es así?

BeRSeRKeR

 
Cita de: "Haddd"¿para qué haces esto?

Out.Pos.xyw = Out.Pos.xyw / Out.Pos.w;
Out.Pos.z = Out.Pos.w

El Clip Space es un cubo que en X,Y va de -1 a 1 y en Z de 0 a 1. Lo lógico sería que le pusiéramos un 1 en la z y en la w, ¿no es así?
En realidad, el clip-space no se define de la forma:

-1 <= x <= 1
-1 <= y <= 1
0 <= z <= 1

sino que Direct3D utiliza la siguiente regla:

-w <= x <= w
-w <= y <= w
0 <= z <= w

En OpenGL, la regla es un poco diferente:

-w <= x <= w
-w <= y <= w
-w <= z <= w

Para que esa regla se cumpla, las coordenadas del vértice tienen que ser homogéneas y para ello tienes que hacer lo que he hecho en las dos líneas estas:

Out.Pos.xyw = Out.Pos.xyw / Out.Pos.w;
Out.Pos.z = Out.Pos.w

Lo que se puede ver con esto es que las coordenadas homogéneas tienen la forma:

(x/w, y/w, z/w, 1/w)

Lo que pasa es que debido a que tú quieres que la Z siempre esté en el far plane, debes cumplir la regla número 3, es decir:

0 <= z <= w

De ahí que en el código del vertex shader pusiera:

Out.Pos.z = Out.Pos.w

La verdad, no soy un "teórico" de las 3D así que puede que no me haya explicado con precisión e incluso puede que haya utilizado algún término incorrectamente. Lo que sí te puedo asegurar es que:

-w <= x <= w
-w <= y <= w
0 <= z <= w

:)

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

BeRSeRKeR

 Por si te aclara un poco las cosas, w siempre se suele poner a 1 pero cuando tú aplicas la matriz de proyección a la coordenada de un vértice, w suele dejar de valer 1.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

fiero

Haddd ¿no es más rápido desactivar el ZBuffer a la hora de dibujar la esfera del espacio y dibujarla la primera?

Perdonad por el off-shader....
www.videopanoramas.com Videopanoramas 3D player

BeRSeRKeR

 
Cita de: "fiero"Haddd ¿no es más rápido desactivar el ZBuffer a la hora de dibujar la esfera del espacio y dibujarla la primera?

Perdonad por el off-shader....
En realidad así es como se suele hacer todo el tema este de skyboxes, skydomes, etc...

En el caso este, la esfera se hace de una unidad de radio, siempre posicionada en el mismo lugar que la cámara y como ha dicho fiero, se renderiza primero, desactivando el depth buffer.

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Yo creo que es más óptimo lo que yo digo. si renderizo primero el cielo, SIEMPRE se dibujará todo, aunque luego no se vea nada de nada. En cambio si lo dibujo al final, SOLO se dibujará lo que se vea.  

Haddd

 Bien ya está, gracias a Berserker.

Sin embargo es necesaria una modificación

//vout.position.xyw = vout.position.xyw / vout.position.w;

 vout.position.z = vout.position.w;

No debemos dividir por w puesto que ya se divide después del clip space.

En el libro ShaderX2 hay un artículo sobre Advanced Sky Dome Rendering, que también utiliza esta técnica, pero de una forma diferente:

dp4 oPos.x,v0,c0
dp4 oPos.y,v0,c1
dp4 oPos.zw,v0,c3   ; forzamos z a 1 haciendo que sea igual a w

Sin embargo NO me funciona utilizando shaders con c3 y sí me funciona con c2. Esto es extraño y me dice que debo analizar muuucho mejor el Clip Space en D3D y las matrices finales.

BeRSeRKeR

Cita de: "Haddd"Sin embargo es necesaria una modificación

//vout.position.xyw = vout.position.xyw / vout.position.w;

 vout.position.z = vout.position.w;

No debemos dividir por w puesto que ya se divide después del clip space.
Muy cierto. :)

Por cierto, ¿tienes el libro de ShaderX2?. ¿Qué tal está?. ¿Lleva ya cosas sobre el HLSL o sigue con los shaders en ensamblador?.

Supongo que sabrás que está en camino el ShaderX3. Este supongo que sí utilizará el HLSL :)

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Kriller

 Retomando el tema, ¿realmente merece la pena hacerlo con un shader? Se podría hacer como dice fiero pero con una ligera modificación. Se podría desactivar la escritura en Z-buffer pero dejar los tests activados, y entonces dibujar el sky dome al final del todo. De esta manera se aprovecha la optimización que dices tú, Haddd, que si no se ve nada del cielo el Z-buffer lo descarta rápidamente (por eso lo de dejar los tests activados). Además tenemos la escritura en Z-buffer desactivada, por lo tanto una optimización más.

Vuelvo a sacar el tema porque en breves voy a implementar esto en mi motor y no quiero pelearme todavía con los shaders, aunque si me convencéis de que merece la pena pues habrá que hacerlo...  ;)

Saludos.

BeRSeRKeR

 
Cita de: "Kriller"Retomando el tema, ¿realmente merece la pena hacerlo con un shader?

Es que Haddd está orientando su motor 100% a los shaders. Concretamente shaders 2.0 que, en mi opinión, es como debería hacer cualquier motor que empieza su desarrollo ahora. ¡Evidentemente también dependerá del producto que se vaya a desarrollar con ese motor! :)


Cita de: "Kriller"Se podría desactivar la escritura en Z-buffer pero dejar los tests activados, y entonces dibujar el sky dome al final del todo. De esta manera se aprovecha la optimización que dices tú, Haddd, que si no se ve nada del cielo el Z-buffer lo descarta rápidamente (por eso lo de dejar los tests activados). Además tenemos la escritura en Z-buffer desactivada, por lo tanto una optimización más.

Pero en ese caso, ¿cómo especificas que la Z = W?. Porque si Z < W entonces, cuando se realice el depth test, el skydome se dibujará, probablemente, sobre todos los objetos ya que, supuestamente, el skydome sería de 1 unidad de radio. Supongo que la forma equivalente de hacer lo mismo que el shader pero en la fixed pipeline sería transformar los vértices manualmente con la matriz WorldViewProj, pero dejando la Z igual a W y evidentemente no activar ninguna matriz cuando fuéramos a dibujar el skydome. Pero ya sabemos que eso no es óptimo.

Cita de: "Kriller"Vuelvo a sacar el tema porque en breves voy a implementar esto en mi motor y no quiero pelearme todavía con los shaders, aunque si me convencéis de que merece la pena pues habrá que hacerlo...  ;)

Yo creo que sí es bastante recomendable. Realmente no sé cuál va a ser el cometido de tu motor pero si, sea lo que sea, va a tardar más de 6 meses en ver la luz, ¿por qué no utilizar única y exclusivamente shaders?. De aquí a entonces, quien no tenga una aceleradora compatible con pixel shaders 1.1 es porque no quiere. Y es más, me atrevería a ir más allá y decir que cualquier motor que empiece ahora, debería orientarse exclusivamente para vertex & pixel shaders 2.0. Vamos, ¡que una Radeon 9600 Pro está ahora mismo por 120€! :)

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!

Haddd

 Pensamiento de BerserKer=Pensamiento Haddd

Shaders 2.0 al poder.

Sin embargo, te diré que...¡shaders 3.0 al poder! Porque ahora mismo echo de menos la función noise en mi radeon. Los 3.0 espero que sean un estandard, y obligen a todos a tener al menor 4 MRT. Creo que NVidia no posee MRT(Multiple Render Target) lo cual es una...para poder hacer deferred lighning y esas cosas.

Grugnorr

 En alternate.es veo las veo por los 160€ IVA incluido ^_^

PD: Sips, lo suyo es hacer las cosas con lo más moderno posible, al cabo de 2 años que lo acabes ya tendrá todo el mundo la tarjeta ;)
hat the hells!

BeRSeRKeR

 Yo me compré la Radeon 9600 (no la Pro) por ~120€ en PCBox y un amigo se compró la Pro hace unos días por el mismo precio más o menos. Evidentemente no es de marca pero bueno, funciona perfectamente :D

Saludos.
¡Si te buscan en nombre de la ley, huye en nombre de la libertad!!






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.