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

Hola a todos,

Ya sé que este es un tema ya muy trillado, pero por más que busco aquí y por Internet no consigo encontrar una solución.

He implementado unas funciónes para renderizado de sprites 2D con DirectX9, y mi problema es que con algunas tarjetas gráficas los quads se ven mal. Es decir, los 4 vértices que forman el quad se desalinean o desplazan 1 pixel y hacen que la imagen se estire o se distorsione, lo cual me da a entender que es un problema de perspectiva, pero no sé por que funciona de forma diferente en cada tarjeta.

Utilizo una proyección ortogonal, la matriz de proyección la creo con D3DXMatrixOrthoLH, que exactamente hace esto:

  D3DXMATRIX matriz;
   float zn=0.0, zf=100000.0;
   w=800; //El ancho de la ventana
   h=600; //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;


La matriz de objeto y de camara son la matriz identidad, y luego creo un rectangulo formado por dos triangulos delante de la camara, y con Z=1.0. Las coordenadas X e Y del quad tienen las mismas proporciones que las dimensiones de la imagen que quiero colocar en la pantalla 1:1.

Antes usaba para la matriz de proyección los valores zn=1.0 y zf=10000.0 y según donde estuviera el quad tambien con mi tarjeta se estiraba un pixel. Con los valores actuales (los del código anterior) no tengo problemas.
He probado la opcion D3DRS_LASTPIXEL del device, pero no es eso.

El problema es que con mi Radeon X1600 lo veo todo perfecto y no puedo debugear, pero este es el resultado que se obtiene en algunas tarjetas:

(Aquí la barra de arriba son 9 botones como se deberian ver)


(En medio de esta imagen se puede ver como se estira el quad, por lo que el texto se ve mal)


Si quereis ver la imagen anterior en vivo y en directo, podeis instalar la version BETA de mi visor aquí http://www.devalvr.com/install/beta (Es un plugin para el navegador, esto es una instalador de 280K) y luego acceder a esta pagina http://www.lesarcs.com/visite_360/anglais/visites_HIGH/index.html?visite=visite11 (Ojo, es una beta, cerrad todos los programas antes de probar)

¿Alguien se ha encontrado con este problema? ¿Como puedo solucionarlo?

Gracias!
www.videopanoramas.com Videopanoramas 3D player

Topper

prueba a activar el modo CLAMP en la textura para que se ajuste a toda su extensión.

Saludos.

marcode

Eso pasa porque no coincide el tamaño del quad con el del número de pixels que ocupa. A diferentes resoluciones o tamaños de ventana es difícil que coincida siempre.

A mí me ha pasado y la única solución era establecer el viewport de tamaño exactamente igual al "client rect". Pero si no lo quieres o puedes hacer prueba a activar el filtrado de textura bilineal a ver cómo queda.
size=9]afortunadamente siempre ha habido alguien dispuesto a reinventar la rueda, de lo contrario seguiríamos usando un disco de piedra con un agujero.[/size]

fiero

Hola, gracias por las respuestas!

Topper, el modo CLAMP es el que tengo por defecto, pero en este caso creo que el problema es más de posicionamiento de vertices.

marmocle, ¿a que te refieres con "client rect"? ¿al tamaño de la ventana de renderización? Si es eso, es lo que tengo ahora, el tamaño del viewport es el mismo que el de la ventana de render. Lo del filtrado bilinear queda un poco "sucio" para este tipo de imagenes, ya que por ejemplo, las lineas de un pixel se difuminan y casi desaparecen, dando una sensación de desenfoque o de falta de nitidez.

Lo que no entiendo es porqué si para una imagen de 50x50 pixels, creo un quad de 50x50 y en algunas tarjetas gráficas se vé de 51x51 pixels. Es cierto que este fallo depende mucho de la posicion del quad dentro de del viewport, y de las dimensiones del viewport, pero con la configuración actual, en mi ATI se ve perfecto en cualquier tamaño de ventana (mi visor tiene una pestaña para cambiar el tamaño rapidamente). Sin embargo en otras tarjetas se ve mal a cualquier tamaño de ventana  :?
www.videopanoramas.com Videopanoramas 3D player

[EX3]

Podrian venir los tiros por usar texturas no potencia de 2? Yo he tenido problemas con mi libreria cuando he usado texturas de tamaño irregular, como luego estas en memoria se escalan a un tamaño de potencia de 2 al tratar de dibujarlas a la escala real de la textura originaria es como dibujaramos con un escalado inferior, de ahi que a veces de esos defectos en la imagen. A veces el usar filtros de suavizado como te mencionan suele hacer que esos defectos se disfracen dando un resultado algo mas decente.

Un apunte, lo que no entiendo es por que dibujas 2D usando una proyeccion con matriz para 3D. Yo al menos no trabajo proyecciones en dx_lib32 para dibujar mis quads, lo que no se si afectara para bien o para mal, pero en principio y quizas por desconocimiento diria que no es necesario o imprescindible para trabajar en 2D.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

fiero

Para almacenar la imagen utilizo el tamaño potencia de 2 más cercano (por encima) al tamaño real de la imagen. Después al crear el quad, las coordenadas U y V las calculo en función al trozo de la textura que compone la imagen. Por ejemplo, si mi imagen mide 50 pixeles de ancho, la meto en una textura de 64, pero le pongo U=0.78125 en los vertices del quad.

¿Qué función utilizas para renderizar los quads? ¿Vertices transformados?
www.videopanoramas.com Videopanoramas 3D player

[EX3]

Utilizo DrawPrimitiveUP(), no es de las mejoras formas dado dibujo quad por quad en vez de todo de una tajada que seria lo mas optimo, pero es con lo que aprendi en los tutoriales de antaño :)

Pues si no es por el tema de la escala de la textura ya no sabria orientarte bien ya que el resto de jugar con las coordenadas UV y demas lo tengo implementado en la libreria para temas de espejado y poco mas, pero no es que lo domine como tal (fue una implementacion mas a prueba/error que otra cosa) a parte que hace un par de años que no lidio en profundidad con DirectGraphics (lo poco que toco para mantenimiento de la libreria).

Lo que si estaba pensando es, por que no pruebas a implementar el asunto mediante la interfaz ID3DXSprite? Quizas esta a parte de facilitarte el asunto pueda corregir fallos de coordenadas en las texturas.

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

fiero

Yo utilizo tambien uso indistintamente DrawIndexedPrimitive o DrawIndexedPrimitiveUP y dibujo cada quad por separado. Seguramente utilizarás vertices ya transformados, por eso te da igual que matriz de proyección haya. Creo que voy a pelearme con esto de los vertices transformados, quizás sea la solución, ya que si las coordenadas de pantalla las creo yo, estoy seguro de que son las mismas en todas las tarjetas. Me refiero a usar D3DFVF_XYZRHW en el FVF.

Lo de utilizar ID3DXSprite no me gusta, ya que tendria que meter la librería de DX9 "d3dx9.lib" y eso aumenta 100 o 200 KB el tamaño total del plugin. Además, prefiero tener el control de todo lo que pasa, es decir, yo ahora mismo divido las imagenes en trozos de 256x256, que cargo en memoria de sistema, a memoria de video solo subo los cachos que realmente se ven y en cuanto dejan de verse los descargo, etc. Creo que controlar todo esto a mi gusto con ID3DXSprite me llevaría mas tiempo.

gracias!
www.videopanoramas.com Videopanoramas 3D player

marcode

Cita de: "fiero"marmocle, ¿a que te refieres con "client rect"? ¿al tamaño de la ventana de renderización? Si es eso, es lo que tengo ahora, el tamaño del viewport es el mismo que el de la ventana de render.

No, me lié con otra cosa. Lo que creo que debe ser es el volumen de visualización igual al del viewport. Si tienes una función que cree una matriz de proyección ortogonal deberías pasarle los mismos valores que el viewport para el ancho y alto ....creo  :?
size=9]afortunadamente siempre ha habido alguien dispuesto a reinventar la rueda, de lo contrario seguiríamos usando un disco de piedra con un agujero.[/size]

[EX3]

Cita de: "fiero"Yo utilizo tambien uso indistintamente DrawIndexedPrimitive o DrawIndexedPrimitiveUP y dibujo cada quad por separado. Seguramente utilizarás vertices ya transformados, por eso te da igual que matriz de proyección haya. Creo que voy a pelearme con esto de los vertices transformados, quizás sea la solución, ya que si las coordenadas de pantalla las creo yo, estoy seguro de que son las mismas en todas las tarjetas. Me refiero a usar D3DFVF_XYZRHW en el FVF.
Asi es como trabaja dx_lib32 y de momento no he tenido problemas en las distintas maquinas donde se ha ejecutado :)

Cita de: "fiero"Además, prefiero tener el control de todo lo que pasa, es decir, yo ahora mismo divido las imagenes en trozos de 256x256, que cargo en memoria de sistema, a memoria de video solo subo los cachos que realmente se ven y en cuanto dejan de verse los descargo, etc. Creo que controlar todo esto a mi gusto con ID3DXSprite me llevaría mas tiempo.
Al reves, te ahorra todo la historia de montar los quads y demas implementaciones, tan solo una llamada para dibujar una textura en coordenada y escala que quieras con el color que le indiques e incluso seccion de la textura a dibujar ademas de rotaciones con centro variable. Para dibujo 2D esta muy comodo y rapido de usar. Prueba y echa un vistazo, la razon de los 200kb de mas por la libreria extra a añadir al plugin hoy dia no le veo mucho sentido ;)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

fiero

Cita de: "[EX3"] Prueba y echa un vistazo, la razon de los 200kb de mas por la libreria extra a añadir al plugin hoy dia no le veo mucho sentido ;)

Ahora mismo se descargan el plugin 75000 personas al mes, y el plugin son unos 280KB, esto hacen un total de 21GB de transferencia mensual. Ahora mismo las descargas aumentan a razón de unas 5000 al mes, pero creo que puede llegar un momento que se produzca una repentina subida, (sobre todo si páginas con muchos usuarios se deciden a usarlo). Los últimos años de desarrollo me he cuidado mucho de hacer todo por mi cuenta y no meter librerías, quizás me hubiera ahorrado unos meses de trabajo, pero el plugin tendría ahora más de 1 ó 2 MB seguramente.Mi idea es que el plugin se extienda cada vez más, y los 250KB de tamaño son un buen reclamo.

Quizás me he vuelto demasiado quisquilloso con los años, pero creo que en este caso, el tamaño importa ;)

Acerca de los fallos de los sprites creo que he encontrado el problema, luego lo explico, tengo que ver si me hacen unas pruebas más.

un saludo
www.videopanoramas.com Videopanoramas 3D player

[EX3]

Cita de: "fiero"Ahora mismo se descargan el plugin 75000 personas al mes, y el plugin son unos 280KB, esto hacen un total de 21GB de transferencia mensual. Ahora mismo las descargas aumentan a razón de unas 5000 al mes, pero creo que puede llegar un momento que se produzca una repentina subida, (sobre todo si páginas con muchos usuarios se deciden a usarlo). Los últimos años de desarrollo me he cuidado mucho de hacer todo por mi cuenta y no meter librerías, quizás me hubiera ahorrado unos meses de trabajo, pero el plugin tendría ahora más de 1 ó 2 MB seguramente.Mi idea es que el plugin se extienda cada vez más, y los 250KB de tamaño son un buen reclamo.
Hombre, visto asi... aceptamos barco :)

Salu2...
José Miguel Sánchez Fernández
.NET Developer | Game Programmer | Unity Developer

Blog | Game Portfolio | LinkedIn | Twitter | Itch.io | Gamejolt

XÑA

Bueno, tu problem está bien documentando en el SDK de DX. todo es debido a que en DX el centro del pixel no está situado en la esquina superior izquierda como nos pensamos, y por tanto la asignación de texturas a pixels no es perfecta. Para ello hay que hacer una corrección en el shader. Pero como veo que no usas shaders, deberás hacerlo en tu propia matriz de transformación.

Precisamente ahora voy a hacer una clase de sprites y tengo que resolver este problema. Si lo consigo te digo cómo lo he hecho.

Si quieres, mírate el ejemplo de PostProcessing del SDk, verás que suma 0.5 en el Quad.

fiero

Hi all,

Cita de: "[EX3"]Hombre, visto asi... aceptamos barco :)

Es que estoy mu extresao y parece que respondo siempre defendiendome ;), (menudo rollo he soltao como para no aceptarme barco como animal marino...)

Si XÑA, eso era. Lo que yo hacia para desplazar todo a la esquina superior izquierda era:

matProjectionOrto._31=-1;
matProjectionOrto._32=1;

Con esto se consigue que el 0,0 sea la esquina superior izquierda, pero si el viewport tiene un numero impar de pixels, el 0,0 cae justo en medio de un pixel. Por lo visto no todas las tarjetas funcionan igual al asignar ese medio pixel a uno o a otro, sobre todo hay diferencias entre ATI y nVidia (como no).

Ahora lo que hago es restarle al quad un offset que es el numero de pixels del viewport/2 (+ 1 si el tamaño del viewpor es impar) y parece que funciona bien.

un saludo
www.videopanoramas.com Videopanoramas 3D player

XÑA

¿Entonces al final como te queda tu matriz?






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.