Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Per Pixel Lighting

Iniciado por Helius, 10 de Julio de 2004, 05:20:28 PM

« anterior - próximo »

Helius

 Tengo esta estructura par los vértices usando iluminación Blinn-Phong:

struct MIVERTICE
{
float x, y, z;  // posición de un vértice
float u,v;   // coord de  textura
float nx, ny, nz;  // normal
float Ux, Uy, Uz;  // tangente
float Vx, Vy, Vz;  // binormal
};


Y esta declaración del vértice:

D3DVERTEXELEMENT9 MyDecl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{ 0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
{ 0, 20, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{ 0, 32, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0},
{ 0, 44, D3DDECLTYPE_FLOAT3 ,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL, 0},
D3DDECL_END()
};


En todos los ejemplos que he visto para implementar esto usan Meshes de DirectX pero yo uso mi propia geometría por lo que también uso mis propios Buffers de vértices con lo cual necesito otra declaración de FVF. Este es mi problema, que no se si la estoy declarando bien. Actualmente lo hago así:


#define D3DFVF_MIVERTICE (D3DFVF_XYZ|D3DFVF_TEX0|D3DFVF_NORMAL|D3DFVF_XYZ|D3DFVF_XYZ)

La posición, las coord de textura, la normal y los dos últimos para la binormal y la tangente. ¿Está bien así?

Otra cosa, alguién sabría ponerme una función fácil de entender para calcular la tangente y la binormal de un triángulo? Estoy intentando descifrar la que viene en "Real-time Rendering Tricks and Techniques" pero no hay manera, no entiendo porque usa otra normal para el tangent space aparte de la del propio vértice. Para cada vértice usa un vector posición, una coord de textura, una normal, y tres vectores para el tangent space  :blink:

Estoy confuso...
Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.

Lord Trancos 2

 prueba con :

#define D3DFVF_MIVERTICE (D3DFVF_XYZ|D3DFVF_TEX0|D3DFVF_NORMAL|D3DFVF_XYZB1|D3DFVF_XYZB2)
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

BeRSeRKeR

 Para calcular el tangent-space te puede servir el archivo TangentSpace.pas que viene con esta demo de Tom Nuydens.

También tienes el NVMeshMender en la web de nVidia. En mis tiempos de programador lo probé y funcionaba. :)

Y por supuesto, en la web de ATI seguro que también encuentras código para calcular el tangent-space.

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

Helius

  :( A ver, tengo un problema:

Al hacer más de una pasada para pintar más de una luz en un polígono se me está sumando también el ambiente (como cabía esperar). El caso es que sólo se me ocurre una solución: Hacer una pasada para el ambiente y luego todas las necesarias por cada luz, pero esto me parece una locura porque entonces por cada luz ya serían mínimo 2 pasadas...  

Alguna solución?

Este es el pixel shader que uso:


float4 pSize;
float3 ambient;
float3 diffuse;
float3 specular;
float Kd;
float Ks;
float Ka;
float specular_power;
float atten_power;

//////////////////////////////////////////////////////////////////////

sampler base_map;
sampler bump_map;
sampler gloss_map;

//////////////////////////////////////////////////////////////////////

struct PS_INPUT_STRUCT
{
float2 bump_map:     TEXCOORD0;
float3 light_vector: TEXCOORD1;
float3 view_vector:  TEXCOORD2;
};

struct PS_OUTPUT_STRUCT
{
float4 color0:       COLOR0;
};

//////////////////////////////////////////////////////////////////////

PS_OUTPUT_STRUCT Main(PS_INPUT_STRUCT psInStruct)
{
PS_OUTPUT_STRUCT psOutStruct;

float atten = saturate(1 - dot(psInStruct.light_vector, psInStruct.light_vector));

float3 normalized_light_vector = normalize(psInStruct.light_vector);
float3 normalized_view_vector = normalize(psInStruct.view_vector);

float height = tex2D(bump_map, psInStruct.bump_map).a;
float2 newTexCoord = psInStruct.bump_map + normalized_view_vector.xy * (height * pSize.x + pSize.y);

float4 base = tex2D(base_map, newTexCoord);
float3 bump = tex2D(bump_map, newTexCoord) * 2 - 1;
float3 gloss = tex2D(gloss_map, newTexCoord);

bump = normalize(bump);

float4 n_dot_l = dot(bump, normalized_light_vector);

float3 final_ambient = (base * ambient * Ka);
float3 final_diffuse = (base * diffuse * Kd * saturate(n_dot_l));
float3 final_specular = (gloss * specular * Ks * pow(saturate(dot(reflect(-normalized_view_vector, bump), normalized_light_vector)), specular_power));

psOutStruct.color0.rgb = final_ambient + ((final_specular + final_diffuse) * (atten * atten_power));
     
psOutStruct.color0.a = base.a;

return psOutStruct;
}
Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.

BeRSeRKeR

 Lo que se suele hacer (creo que por ejemplo Doom3 lo hace) es dar una primera pasada en la que sólo se procesa el ambient. En esta pasada evidentemente la información de profundidad se almacena en el depth buffer por lo que ya no tienes que volver a actualizarlo para las siguientes pasadas.

Así que, una vez hecha la pasada para el ambient, desactivas la escritura en el depth buffer y activas el depth test en modo equal (aunque creo que en algunas aceleradoras no funcionará y tendrás que poner lequal) y finalmente das una pasada para cada luz.

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

BeRSeRKeR

 
Cita de: "Helius"Hacer una pasada para el ambiente y luego todas las necesarias por cada luz, pero esto me parece una locura porque entonces por cada luz ya serían mínimo 2 pasadas...
Bueno, básicamente es lo que he dicho salvo que debes tener en cuenta que sólo en la primera pasada escribes en el depth buffer. De todas formas no entiendo lo de dos pasadas por luz. Sólo sería una por luz...

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

Haddd

 He ledio que se considera mucho más óptimo hacerlo así. De esta forma, el pixel shader sólo ejecuta el código pesado cuando ya sabemos que ese punto pasa el Depth Test.

Lo del igual en el test, es por culpa de la compresión. ATI te dice que no uses igual, porque a veces, no funcionará.

Helius

Cita de: "BeRSeRKeR"De todas formas no entiendo lo de dos pasadas por luz. Sólo sería una por luz...
Me refiero a que por cada polígono que este afectado por al menos una luz (que serán casi todos, al menos en mis niveles) será dibujado mínimo 2 veces, una para el ambient y otra para esa luz, y claro si le afectan más pues más.

Ahora que lo dice Haddd, todo tiene más lógica, los pixel shaders de las luces sólo se ejecutaran si pasan el depht test... Lo de la compresión también tiene su lógica.

Pues me pongo a ello  ;)

Muchas gracias
Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.

Helius

 Tengo un problema al hacer varias pasadas de luces, es decir, al sumarlas. Se supone que para sumar la siguiente pasada hay que activar el alpha blend con "SrcBlend = One" y "DestBlend = One" no? pues si lo hago el modelo me sale transparente  :blink: . Aquí os pongo una foto.

Si no activo el alpha blend lógicamente las luces no se suman y sólo se pinta la última.
Os enseño mi pixel shader:


float3 light_color;
float atten_power;

//////////////////////////////////////////////////////////////////////

sampler base_map;

//////////////////////////////////////////////////////////////////////

struct PS_INPUT_STRUCT
{
float2 tex_coord:    TEXCOORD0;
float3 light_vector: TEXCOORD1;
float3 normal_vector: TEXCOORD2;
};

struct PS_OUTPUT_STRUCT
{
float4 color0:       COLOR0;
};

//////////////////////////////////////////////////////////////////////

PS_OUTPUT_STRUCT Main(PS_INPUT_STRUCT psInStruct)
{
PS_OUTPUT_STRUCT psOutStruct;

float atten = saturate(1 - dot(psInStruct.light_vector, psInStruct.light_vector));

float3 normalized_light_vector = normalize(psInStruct.light_vector);

float4 base = tex2D(base_map, psInStruct.tex_coord);

float3 final_diffuse = base * light_color * saturate(dot(psInStruct.normal_vector, normalized_light_vector));

psOutStruct.color0.rgb = final_diffuse * atten * atten_power;
     
psOutStruct.color0.a = base.a;

return psOutStruct;
}

Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.

Haddd

 No entiendo porque te hace esto. Yo lo hacía y no tenía problemas...
Volveré a probarlo estos días, ahora que he hecho unos cuantos cambios, y té diré si veo algo raro.

Helius

 Vale ya está, era un error tonto, la primera de las pasadas también la estaba haciendo con el alpha activado.  :D  
Geardome Devlog
Tutoriales sobre DirectX 9, Nintendo DS y PSP.






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.