Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





Me Va A Volver Loco El Id3dxsprite

Iniciado por KACHORRO, 23 de Octubre de 2005, 12:39:33 PM

« anterior - próximo »

KACHORRO

 Pues eso, he implementado el ejemplo más tonto posible con ID3DXSprite y me peta en tiempo de ejecución diciendo que le programa ha realizado una operacion no valida.

Citar
#include
#include

ID3DXSprite *sp;
IDirect3DTexture9* tex;

.... INICIALIZO DIRECT3D ....

D3DXCreateSprite(g_pd3dDevice,&sp);
D3DXCreateTextureFromFile(g_pd3dDevice,"prueba.bmp",&tex);

g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0, 0 );

  g_pd3dDevice->BeginScene();

      sp->Begin(NULL);   
      sp->Draw(tex,NULL ,NULL, NULL,0xffffffff);
     sp->End();

   g_pd3dDevice->EndScene();

g_pd3dDevice->Present(NULL,NULL,NULL,NULL);   

Pues bien, he comprobado que cargue la textura, he comprobado que cree el sprite, he probado el sp->Begin() y el sp->End() sin el sp->Draw, y tambien peta (en el sp->End())

Estoy en modo a pantalla completa, a 1024x768.

Hay algo especifico que poner en la inicialización de Direct3D para que esto funcione ? o puede ser que la tarjeta grafica no soporte algo ?

Ayuda !!!

BeRSeRKeR

 Hola.

Hace un tiempo un usuario hizo la misma pregunta que tú. Los sprites también le fallaban al hacer la llamada al método End. Lo primero que se me ocurrió es que la textura no se estaba cargando bien porque la ruta no estaba bien especificada. El decía que no, que no le daba ningún error al cargar la textura, pero finalmente ese era el problema.

Aquí tienes el ejemplo que hice y aquí está el hilo del que te hablo.

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

KACHORRO

 Te puedo asegurar que no es problema de la textura.
De hecho he usado la de tu ejemplo y en la misma ruta y forma en que la cargas tú.

Creo que el problema viene de arriba, de la forma que inicializo Direct3D.

Yo lo pongo a pantalla completa (una diferencia con tu ejemplo)

y la otra es el formato que tu especificas como unknown, y yo no puedo, porque si no no me inicializa la pantalla.

   d3dpp.Windowed = TRUE;   (yo pongo FALSE)
   d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; (yo uso D3DFMT_X8R8G8B8)

Por lo demás, no veo diferencias entre mi codigo y el tuyo.

Voy a investigar la inicialización a ver si es algo de eso.

Un saludo y muchas gracias !!! Me va a ser muy util tu ejemplo.



AK47

 Tambien puedes usar el debug runtime de Direct3D, que se accede mediante panel de control -> directX. Esto hace que Direct3D haga log de  sus cosas en el output del Visual Studio. Te informa de cosas como memory leaks, indices no validos, etc. Quizas te de alguna pista (a mi me ayuda muchisimo :))

zupervaca

 esto me suena a que la textura no es potencia de 2, me paso a mi con mi test de velocidad para tarjetas graficas con shaders 2.0, tenia una textura de 384x384 si mal no recuerdo y a mucha gente no le funcionaba, mira que la textura sea potencia de 2, por lo demas decirte en ese codigo que pones no veo ningun fallo, lo unico recomendarte usar el A8... en vez del X8...

editado: ber pone el formato D3DFMT_UNKNOWN para coger la propia del escritorio de windows ya que esta en modo ventana, es una forma mas rapida que andar teniendo que coger el adaptador actual

Ray

 Si la textura no es potencia de 2 hay que usar D3DXCreateTextureFromFileEx y pasar como parámetros de ancho y alto la constante D3DX_DEFAULT_NONPOW2.

Tiene que estar soportado por el dispositivo pero yo creo que todas las tarjetas actuales pueden hacerlo.

zupervaca

 tambien pense yo que en los tiempos que corren no importaba y no es asi, muchos probaron el test con directx y no les funciono en cambio a otros si, el de opengl directamente no funciono por este motivo, cuando puse potencia de dos el test directx y opengl funciono correctamente, excepto con tarjetas graficas ATI que esto ya es debido a otro motivo por culpa de los shaders, yo probaria, si sigue fallando pues a otra cosa

KACHORRO

 mmmm... dada mi desesperación ayer por la mañana, acabé tan harto que programé mi propia clase Sprite usando texturas sobre quads y mandé al id3dxsprite a freir espárragos.

Por cierto que el rendimiento es mucho menor que el que me daba directdraw, al menos en las mismas condiciones y con la implementación que hice:

put_sprite de 4000 sprites simultaneos repartidos  sobre el mapa en directdraw frente a 200 de direct3d

A partir de esos numeros la velocidad comienza a resentirse.

Los sprites no están todos en las coordenadas de pantalla.

(uso una geforce4 mx 440 creo)

Alguna idea para optimizar direct3d?



AK47

 Como pintas los sprites? Pintas cada quad con una llamada a DrawPrimitive? Creo que en estos casos es mejor usar un vertex buffer dinamico y calcular los vertices de los quads a mano y pintarlos todos de una tacada (bueno, se tendria que agrupar los quads por textura etc etc).

zupervaca

 
CitarPor cierto que el rendimiento es mucho menor que el que me daba directdraw
miralo bien que algo estas haciendo mal, hace tiempo puse con otro usuario unos test de direct3d, directdraw y opengl y el resultado es que opengl y direct3d eran muchisimo mas rapido que directdraw, siendo opengl y direct3d pares en velocidad

BeRSeRKeR

 También ten en cuenta que siendo sprites, podrías ordenarlos tú mismo por Z y desactivar el depth test y el depth write. Supongo que eso hará que ganes en rendimiento.

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

Lord Trancos 2

Cita de: "BeRSeRKeR"También ten en cuenta que siendo sprites, podrías ordenarlos tú mismo por Z y desactivar el depth test y el depth write. Supongo que eso hará que ganes en rendimiento.
Creo q si ordena él ganaria rendimiento, pero si desactiva el z-buffer eso podria provocar que aumentará el overdraw, ¿no?  
on los años y mucho esfuerzo he llegado a atesorar una ignorancia total sobre casi todas las cosas.
Gate to Avalon (mi Blog)

Ray

 Te pongo algunos consejillos para acelerar, quizás te sirven.

- Crear las texturas en la memoria de video (D3DPOOL_DEFAULT)

- Desactivar z-buffer cuando no sea necesario

lpDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);

- seleccionar como operacion de color solo textura

  lpDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
  lpDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);

- usar vertices trasformados con coordenada de textura para la mayoría de objetos, luego para otros objetos mas complejos crear otros tipos de vertices y activar los estados correspondientes.


struct MIVERTICE {
  float x,y,z, rhw;
  float tu, tv;
  };

MIVERTICE MisVertices[4x1000]; // 1000 sprites con 4 vertices cada uno que deberan ser establecidos al principio y actualizados cuando sea necesario.

- Establecer todos los vertices antes de dibujar
 

 lpDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1);
 lpDevice->SetStreamSource( 0, MisVertices, 0, sizeof(MIVERTICE));

- activar la textura y dibujar para cada sprite (solo los sprites que sean necesarios)


lpDevice->BeginScene();

for (int n=0;n<1000;n++) {  
  if (bDibujarSprite[n]==TRUE) {
       lpDevice->SetTexture(0, TexturaSprite[n]);
       lpDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, n*4, 4);
       }
  }

lpDevice->EndScene();

Para acelerarlo más quizás tendrías que usar buffers de vertices o indexarlos, además de otras historias como hacer grupos que usen la misma textura o estados, pero si dices que ya dibujas 200 sprites rápidamente me parece una cantidad suficiente para cualquier juego, no caben tantos en la pantalla y si son muy pequeños lo mejor es meterlos todos en una misma textura, ya que los cambios de estado y de textura consumen bastante.

Prueba también a usar UpdateSurface y StretchRect para dibujar el fondo o para texturas sin efectos, son similares al Blt de DDraw aunque sorprendentemente con más restricciones.

Para entretenerte tienes desde luego.

[EX3]

 Tuve la misma impresion cuando salte de DDraw a D3D en el desarrollo de la dx_lib32 (y en VB6 que de por si es mas lento que C++), y es cierto, no es lo mismo "blitear" con DDraw que "poligonar, transformar y texturizar" en D3D (3 pasos aprox. en D3D frente a 1 en DDraw), pero al caso, opino lo mismo, no es preciso muchos sprites para hacer algo mas que decente, a la larga acabas utilizando menos sprites de los que un principio crees que necesitaras.

Mi experiencia personal, yo la verdad que me sorprendi mucho cuando desarrolle el nuevo modulo grafico de la dx_lib32, el de la version 2.0 que esta por ver la luz. Reescribi casi todo el codigo del modulo de la version actual, la 1.03, que era muy lento para ciertas operaciones, entre ellas dibujar un numero decente de sprites en pantalla, y en esta version utilizaba la interfaz D3DXSprite por facilitarme un monton de operaciones como rotacion y alguna otra. En la nueva version implemente un sistema de renderizado que permite ordenacion para el dibujado, se dibujan los sprites y demas llamadas graficas como primitvas o texto segun su coordenada Z sin utilizar el Z-Buffer, todo a pelo. Ahora en vez de dibujar los sprites con D3DXSprite los monto sobre un poligono y calculo la rotacion y espejados a pelo, despues cada sprite es dibujado realizando una llamada a DrawPrimitiveUP() por sprite a dibujar, a lo bruto, vamos.

En teoria y siendo en VB6, programar todas esas acciones a pelo deberia ser mas lento que utilizando la interfaz D3DXSprite. Pues no, el nuevo modulo grafico ha ganado notoria velocidad frente a la version actual, no llegando hasta el punto de las burradas que se pueden hacer en DDraw pero permitiendo mucho mas que lo que llegaba hacer antes con lo que tenia implementado, sin utilizar Buffers de Vertices y demas, que de seguro iria mucho mas rapido pero seria mucho mas complejo de desarrollar, y mas tal y como tengo implementado el sistema de renderizado actual.

No sabria darte algun consejo en especial para que optimices tu motor de render, la idea esta en que trates de realizar las mismas acciones con el menor numero de llamadas posibles, por ejemplo, en los render states, create flags para verificar si el renderstate que quieres aplicar ya esta aplicado o no, y cosas asi por el estilo. Si puedes, trata de aplicar los buffers de vertices como te recomiendan, seguro que logras mejorar considerablemente el sistema de renderizado.

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

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

KACHORRO

 Joer...muchas gracias a todos

Soy novatísimo con Direct3D así que seguramente no tengo hecho nada como me comentais. Voy a implementar las optimizaciones y ya os cuento que tal ...

Muchas gracias de nuevo !!