Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Sprites 2D con DX9

Iniciado por fiero, 20 de Julio de 2007, 02:08:14 AM

« anterior - próximo »

fiero

Cita de: "XÑA"¿Entonces al final como te queda tu matriz?

Como puse al principio. Las dos lineas anteriores no formaban parte de mi función D3DXMatrixOrthoLH, así que no me dí cuenta de ponerlas cuando inicié el post. Mi matriz queda así:

   D3DXMATRIX matriz;
   float zn=0.0, zf=100000.0;
   int w;   //El ancho de la ventana
   int h;   //El alto de la ventana

   ZeroMemory(&matriz,sizeof(D3DXMATRIX));
   matriz._11=2.0/w;
   matriz._22=2.0/h;
   matriz._33=1.0/(zf-zn);
   matriz._34=zn/(zn-zf);
   matriz._44=1.0;


Despues en la función de imprimir el sprite, creo el primer vertice del quad (superior izquierdo) en:

   int posx;           //Posixion del sprite en la pantalla
   int posy;
   int tx;               //Tamaño de la imagen 2D
   int ty;

   offx= w /2 + (w&1);
   offy= h /2 + (h&1);
   vertice.x= posx + (tx/2) - offx;
   vertice.y= -posy - (ty/2) + offy;
   vertice.z= 1.0;


un saludo
www.videopanoramas.com Videopanoramas 3D player

XÑA

¿y el vértice inferior derecho?

El Vertex Shader lo que hace es devolver una posicion en Clip Space. Clip Space es como un cubo que pasa por el monitor, y el vértice en clip space coincide con la pantalla cuando se dividen todos sus componentes por w. Así que DX una vez calculada la posición del vértice, la divide por w, y luego aplica la matriz del ViewPort.

Lo importante aquí es que Clip Space es un cubo que tiene el 0,0 en el centro de la pantalla, y los lados son -1,1. Por tanto lo que haces con la matriz de perspectiva y con los valores que transformas es pasar de Screen Space a Clip Space. Te podrías ahorrar sin problemas la matriz de Projección, y hacer los cálculos en el vértice, si quisieras.

Sin embargo, si utilizas D3DFVF_XYZRHW, le estás diciendo a D3D que se salte el proceso de Vertex Shader y ya le das los valores en Screen Space. El problema de utilizar este sistema es que el Vertex Shader NO se ejecuta.

De todas formas, todavía no he empezado con la clase sprite, y estoy convencido de que el problemita del pixel me tocará las narices. Cuando lo tenga, te mando el código!!!

fiero

No, yo uso D3DFVF_XYZ, pero no uso vertex shaders. Habia hablado de D3DFVF_XYZRHW, pero solo en el caso de que no consiguiera hacerlo funcionar.

El vertice inferior derecho sería:

   vertice_inferior_derecho.x= vertice.x + tx;
   vertice_inferior_derecho.y= vertice.y + ty;
   vertice_inferior_derecho.z= 1.0;

Si utilizas coordenadas en clipspace tendrás que jugar sumando o restando ese medio pixel creo yo. Contando con que
medio pixel en coordenadas de clip space = (2.0 / widthPixelsViewport) *0.5

Ya nos contarás!
www.videopanoramas.com Videopanoramas 3D player

Loover

Buenas, yo también tenía ese problema. Ahora mismo no sé muy bien decirte en que fallas pero te voy a poner la función que uso en LooverLib para crear un viewport (la región donde voy a dibujar). Funciona perfectamente, puedo dibujar imágenes de incluso 1x26 pixeles por ponerte un ejemplo que se dibujan exactamente como son sin ningún tipo de artifact.

Seguramente lo que se te ha olvidado es esto:
D3DXMatrixTranslation (&mTrans, -(pWidth/2) -0.5f, -(pHeight/2) -0.5f, 0);   

Trasladar 0.5f para ajustar con el texel.

Una vez llames a esta función no tendrás que hacer nada raro para dibujar en una posición cualquiera de pantalla un sprite. Tan solo haciendo la traslación pertienente en x, y en píxeles.

/*
==================
Configura el ViewPort 2d
==================
*/

//! Configura el ViewPort 2d

/*!
\b Parámetros:

\arg \b pX              Coordenada x de la esquina superior izquierda del ViewPort
\arg \b pY              Coordenada y de la esquina superior izquierda del ViewPort
\arg \b pWidth          Anchura del ViewPort
\arg \b pHeight         Altura del ViewPort

\b Funcionamiento:  

Esta función devuelve 1 (cierto) si se crea un ViewPort (marco) en la posición y
tamaño especificados como parámetros.

El ViewPort es la región de dibujo. Por defecto LooverLib se inicializa con un
ViewPort que ocupa toda la ventana, pero utilizando este método puede definirse
uno distinto.

Una vez utilizado el método, todos los gráficos que se dibujen a continuación se
dibujaran en dicho ViewPort y si está activado el descarte de bloques (ver el
parámetro pBlockCull en SetTransform2d()) se aplicará dicho descarte a todos los
bloques que queden fuera del ViewPort.

Para usar varios marcos, basta cor ir definiendo cada uno de ellos y después
dibujar los gráficos que contengan.

Este método devuelve 0 (falso) si el ViewPort que se intenta crear queda fuera de
la ventana.
*/
inline bool LOV_Render::SetViewPort2d (int pX,
int pY,
int pWidth,
int pHeight)
{
// ----- Si la región de vista queda fuera del frame buffer devolvemos error -----

if (pX +  pWidth > mInfo.mFBWidth) return 0;
if (pX < 0) return 0;
if (pY + pHeight > mInfo.mFBHeight) return 0;
if (pY < 0) return 0;

// ----- Almacenamos las características del ViewPort -----

mInfo.mViewPortX  = pX;
mInfo.mViewPortY  = pY;
mInfo.mViewPortWidth  = pWidth;
mInfo.mViewPortHeight = pHeight;

// ----- Matriz de mundo -----

D3DXMATRIX mMatWorld;
mInfo.mDevice->SetTransform (D3DTS_WORLD, D3DXMatrixIdentity (&mMatWorld));

// ----- Matriz de vista -----

D3DXMATRIX mMatView, mTrans;
D3DXVECTOR3 mEyePt (0.0f, 0.0f, -5.0f);
D3DXVECTOR3 mLookatPt (0.0f, 0.0f, 0.0f);
D3DXVECTOR3 mUpVec (0.0f, 1.0f, 0.0f);
D3DXMatrixLookAtRH (&mMatView, &mEyePt, &mLookatPt, &mUpVec);
D3DXMatrixRotationZ (&mTrans, (float) PI);
D3DXMatrixMultiply (&mMatView, &mTrans, &mMatView);
// 0.5 => Para ajustar con el texel
D3DXMatrixTranslation (&mTrans, -(pWidth/2) -0.5f, -(pHeight/2) -0.5f, 0);
D3DXMatrixMultiply (&mMatView, &mTrans, &mMatView);
mInfo.mDevice->SetTransform (D3DTS_VIEW, &mMatView);

// ----- Matriz de proyección -----

D3DXMATRIX mMatProj;
D3DXMatrixOrthoRH (&mMatProj, (float) pWidth, (float) pHeight, -2048.0f, 2048.0f);
mInfo.mDevice->SetTransform (D3DTS_PROJECTION, &mMatProj);

// ----- Región de vista  -----

D3DVIEWPORT9 mViewData = { pX, pY, pWidth, pHeight, -2048.0f, 2048.0f };
mInfo.mDevice->SetViewport (&mViewData);


// Inicializamos algunos parámetros de D3D
mInfo.mDevice->SetRenderState(D3DRS_NORMALIZENORMALS, FALSE);
mInfo.mDevice->SetRenderState (D3DRS_ZENABLE, D3DZB_FALSE);
mInfo.mDevice->SetRenderState (D3DRS_ZWRITEENABLE, 0);
mInfo.mDevice->SetRenderState (D3DRS_LIGHTING, FALSE);

mInfo.mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mInfo.mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);

return 1;
}


¡Espero que te ayude!
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

fiero

Hola Loover,

Me ha llamado la atención ese "near Z" que pones para crear la matriz ortogonal, con -2048. ¿El 0 no está en la cámara? ¿Entonces el Z cercano lo pones detras de la camara?

un saludo y gracias!
www.videopanoramas.com Videopanoramas 3D player

Loover

Sí, supongo que es para que nunca te desaparezca un sprite por cercano que esté a la cámara... supongo. La verdad no me acuerdo muy bien.

¿Se ha solucionado tu problema?
IndieLib Libreria 2.5d utilizando aceleración por hardware para la programación de juegos 2d.
Indie Rover The monkeys are reading!

fiero

Sí, al final he solucionado el problema restando y sumando unos offsets al quad. Con la matriz ortogonal que utilizo no le desplazo siempre ese -0.5 (solo cuando el tamaño del viewpor es impar), aunque tengo que probar en más tarjetas a ver que pasa, hasta ahora parece que se ve perfecto.

Gracias! un saludo
www.videopanoramas.com Videopanoramas 3D player

XÑA

Aquí está el codigo a nivel de shader....


// Transform a ScreenSpace position To ClipSpace (z=0;w=1)
float4 FromScreenSpaceToClipSpace(float4 position)
{
   float4 clipCoord;
   
clipCoord.x = ( ((position.x/ ENV_RenderTargetWidth) * 2.0f) - 1.0f );
clipCoord.y = ( 1.0f-((position.y / ENV_RenderTargetHeight)* 2.0f) );
clipCoord.z = 0;
clipCoord.w = 1;

// DX texture correction
clipCoord.x -= (0.5f / ENV_RenderTargetWidth);
clipCoord.y -= (0.5f / ENV_RenderTargetHeight);

return clipCoord;
}






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.