Stratos: Punto de Encuentro de Desarrolladores

¡Bienvenido a Stratos!

Acceder

Foros





¿Triángulos por segundo normales?

Iniciado por tewe76, 13 de Enero de 2009, 04:10:17 PM

« anterior - próximo »

tewe76

Hola :)
Estoy haciendo pruebas de rendimiento con el engine irrlicht sobre C++ y me han sorprendido negativamente >:( . Pero como soy novato en 3D (más o menos), en el motor irrlicht y en C++ (estoy aprendiendo sobre la marcha), quería compartir los resultados a ver si son normales o es que estoy haciendo algo mal.

Tened en cuenta que las pruebas las hago en un PC con XP, que el ordenador es bueno, FarCry2 y semejantes me van perfectamente con calidad alta. Para las pruebas uso DX8 (aunque con DX9 sale semejante, con OGL un poco menos).

Prueba 1: cargo un archivo "aaa.3ds", que es básicamente un cubo modificado, con un total de 20 triángulos. Sin textura.
Número de Copias que dibujo -> Frames Por Segundo
1->7500
10->6800
10x10->2000
100x10->250
100x100->25
1000x100->3

Nota 1: irrlicht permite "invisibilizar" los meshes. Así, dibujando 1000x100 copias, pero con todas invisibles menos:
100x100 -> 17 FPS
100x10 -> 45 FPS
1 -> 50 FPS

Es decir, si "dibujo" 100.000 copias, aunque sólo haya una visible, lo máximo que consigo son 50 FPS (vamos, que afecta claramente, aunque sean invisibles).
Nota 2: estos resultados son independientes de si en pantalla estoy viendo todo (lejos) o sólo unos pocos cubos (cerca)(hasta aquí Barrio Sésamo :) ).

Prueba 2: cargo un archivo "bbb.3ds", que es básicamente un grid, con un total aprox. de 20.000 triángulos. Sin textura.
Número de Copias que dibujo -> Frames Por Segundo
1->750
5 ->220
10 ->110
10x10 -> 12

Las Notas 1 y 2 anteriores son válidas aquí también.

Conclusión:
Usando objetos de 20 tris a partir de 1000 objetos ya tiene FPS normalillos (250). Es decir: 20x1000=20.000 tris
Usando objetos de 20.000 tris puedo poner 5 objetos para conseguir aprox lo mismo (220FPS). Es decir: 20000x5=100.000 tris

Preguntas:
¿Véis normales estos resultados? ¿Es normal que un buen ordenador no pueda mover más de 3000 o 4000 cubos con fluidez?
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

tamat

Creo que cuando se trata de hacer benchmarking tienes que tener en cuenta todos los factores:
- Numero de meshes renderizados
- Numero de poligonos de cada mesh
- Pixeles que ocupa en pantalla el objeto (importante si trabajas con pixel shaders complejos)
- Ordenacion en Z (importante si tienes pixel shaders complejos)
- Complejidad de los shaders
- Pases de rendering

Como ves, no todo es "numero de poligonos"
Por un stratos menos tenso

Ruben

Hi,
Irrlicht usa la funcion DrawIndexedPrimitiveUP en no me acuerdo que casos, mira que no la este llamando. Si mal no recuerdo, la familia de funciones Draw*UP lo que hace es que para cada llamada crea y destruye internamente los buffers necesarios para poder pintar los vertices que les pasas. Tiene pinta de ser eso. :)

Un saludo,
Ruben

senior wapo

#3
Lo que estás experimentando se llama "draw call overhead" y en este caso la culpa es de Irrlicht y de Direct3D a partes iguales.

La simplicidad de Irrlicht se paga, y es que la última vez que miré (hace ya tiempo), abusaba mucho de buffers intermedios para todo (no solo por los datos para DrawPrimitiveUP sino incluso para conversiones,listas de objetos visibles y demás).

Soluciones:
- Por la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable. A ésto se le llama "batching".
- Por la parte de Irrlicht, supongo que será mejor mantener en tu grafo de escena solamente lo que sea visible e ir añadiendo y quitando nodos en cada frame en lugar de mantenerlo siempre todo dentro y ocultarlo/mostrarlo.

EDITO: Aunque visto lo visto, miedo me da pensar en como gestiona la lista de hijos de cada nodo del scenegraph.

Prompt

Cita de: senior wapo en 13 de Enero de 2009, 05:18:49 PM
- Por la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable. A ésto se le llama "batching".

Realmente solo deberia existir 1 solo buffer, demostrado! :) es menos costoso modificar el buffer en CPU, gestionarlo en cada frame (bueno cuando tenga que cambiar, depende del frustum culling q cada uno implemente). Realmente habria que tener quizas un buffer por material no?

Mmm...bueno no, porque puedes decidir desde que "punto hasta que punto" pintar y lo metes dentro de un begin / end de un shader y listo. Si! un solo buffer vamos!

tewe76

No respondo porque estoy haciendo algunas pruebecillas  :)
Vuelvo pronto...
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

tewe76

Aquí estoy :)

Primero, rectificar lo que dije de "Nota 2: estos resultados son independientes de si en pantalla estoy viendo todo (lejos) o sólo unos pocos cubos (cerca)". Creí que era así, pero ahora no lo es: si me acerco y sólo veo unos pocos meshes suben los FPS, aunque no mucho.

Y ahora vuestros comentarios:
CitarCreo que cuando se trata de hacer benchmarking tienes que tener en cuenta todos los factores:
Sí, lo tengo en cuenta. Son unas primeras pruebas caseras, intentando simular el uso que pretendía darle para mi juego.

CitarIrrlicht usa la funcion DrawIndexedPrimitiveUP en no me acuerdo que casos, mira que no la este llamando.
Sí, podría ser éso. Pero no tengo ni idea de cómo comprobarlo. Con "DrawIndexedPrimitiveUP" te refieres a una función de DX, ¿no? El irrlicht no tiene nada que se llame así, creo.

CitarPor la parte de Direct3D, no uses muchos objetos de poco tamaño, sino pocos buffers con mucha geometría, si es que te es viable.
¿Tus "buffers" son los "Node" de irrlicht o no tiene nada que ver? Porque he probado dos cosas: meter todas las copias del mesh en un solo Node y crear un montón de Nodes cada uno con un solo mesh. El resultado es idéntico.
Ah, veo que habláis bastante de D3D. Tened en cuenta que con OGL va igual (incluso peor).
CitarPor la parte de Irrlicht, supongo que será mejor mantener en tu grafo de escena solamente lo que sea visible e ir añadiendo y quitando nodos en cada frame en lugar de mantenerlo siempre todo dentro y ocultarlo/mostrarlo.
Eso me ha parecido una buena idea, aunque no he probado si lo de crear/destruir en runtime irá a una velocidad aceptable... De todas maneras, el minimo número de "cubos" que necesito a la vez en pantalla (tienen que estar creados, por narices) ya me baja los FPS demasiado, así que aún así no sería solución.

A Prompt: tu mensaje es demasiado avanzado para mí, me temo ;). Entiendo lo que dices, pero no sabría aplicarlo.

Bueno, os dejo el código de mi prueba, es corto. A ver si véis algo que no os cuadra:
Código (cpp) [Seleccionar]
//Inicializo el irrlicht (segun los tutoriales)
#include <irrlicht.h>
using namespace irr;using namespace core;using namespace scene;
using namespace video;using namespace io;using namespace gui;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "Irrlicht.lib")
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif

int main(){
//800x600x32 Windowed
IrrlichtDevice *device = createDevice( EDT_DIRECT3D8, dimension2d<s32>(800, 600), 32,false, false, false, 0);
if (device == 0)   return 1;
//Cosillas del irrlicht...
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();

//tamanyo del array de meshes (para hacer pruebas rapidas)
const long CantX =100;const long CantZ=100;
//cargamos mesh (aaa.3ds tiene 20 tris, sin textura)
IAnimatedMesh*  mesh = smgr->getMesh("aaa.3ds");
//creamos un array de Nodes
IAnimatedMeshSceneNode* node[CantX][CantZ];

//anyadimos el Mesh a cada Node del array:
for (int a=0;a<CantX;a++){
for (int b=0;b<CantZ;b++){
//anyadimos el mesh
node[a][b] = smgr->addAnimatedMeshSceneNode( mesh,0,-1,vector3df(0,0,0));
//autoiluminado, al no usar luz externa en esta prueba
node[a][b]->setMaterialFlag(EMF_LIGHTING, false);
//ponemos cada node en su sitio, formando un "cuadrado"
node[a][b]->setPosition (vector3df(a*(2.2)-CantX/2*2,0,b*(2.2)-CantZ/2*2+1));
}
}
//anyadimos una camara (que se puede mover con las flechas y el raton, tipo FPS)
smgr->addCameraSceneNodeFPS();
//para medir los Frames Por Segundo
int lastFPS = -1;

//comienza el loop eterno
while(device->run()){
//funciones propias de irrlicht para dibujar la escena
driver->beginScene(true, true, SColor(255,100,101,140));
smgr->drawAll();
driver->endScene();
//calcula FPS y los pone en el caption
int fps = driver->getFPS();
if (lastFPS != fps) {core::stringw str = L"["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; }
}
//descargamos el engine
device->drop();
return 0;
}
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

Ruben

Hi,
CitarSí, podría ser éso. Pero no tengo ni idea de cómo comprobarlo. Con "DrawIndexedPrimitiveUP" te refieres a una función de DX, ¿no? El irrlicht no tiene nada que se llame así, creo.
busca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa.  :)

Un saludo,
Ruben

mi-go

tewe, ¿pero no dijiste que querías usar Irrlicht porque ibas a hacer un juego gráficamente sencillo?
¿vas a cargar 100.000 cubos en pantalla?

Igual estás pensando en hacer un juego de romper miles de cubos, y entonces no me hagas caso, pero te lo digo por romperte un poco la idea de lo que estás haciendo; no vayas a estar perdiendo el tiempo en prubas.

Web personal: www.javiermairena.net
The Game Kitchen: www.thegamekitchen.com
AccessAble Games: www.accessablegames.com
Blog Videojuegos Accesibles: www.videojuegosaccesibles.es

tewe76

Citarbusca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa
Debo parecer tonto, pero sólo soy un novato en C++ (y en Visual C++) ::) La cuestión, que no consigo hacer éso que dices. Por un lado, cuando cargo el proyecto sólo "veo" el archivo cpp, no sé cómo llegar a los includes para ponerles los BP (dentro de VC++, me refiero). Y he probado a poner un BP en mi cpp e ir debugando paso por paso, pero, no entiendo por qué, pero la llamada "smgr->drawAll();", que es donde sospecho que hará las llamadas a DrawIndexedPrimitiveUP, no me deja entrar, pasa directamente a la siguiente línea ???

Citartewe, ¿pero no dijiste que querías usar Irrlicht porque ibas a hacer un juego gráficamente sencillo?
¿vas a cargar 100.000 cubos en pantalla?
:D
Sí, es que pensaba que era sencillo ::) .
Cuando digo sencillo me refiero a que no voy a usar normalmaps, ni shaders, ni cosas así. Pero sí, era mi idea, necesito cargar muchos objetos.

Explicaré un poco lo que quiero, seguramente me entenderéis mejor:
Mi idea es hacer un juego con lógica 2D pero con gráficos 3D. Mi primera idea era hacerlo todo 2D, pero pensé que los gráficos en 3D no deberían complicar la lógica, que seguiría siendo la misma, pero me permitirían hacer efectos de luces, zooms, "vuelos" por la escena, cinemáticas, gráficos más animados, etc.
Para entendernos, digamos que quiero coger un zelda clásico (2D), pero en vez de mostrarlo dibujando tiles 2D, hacerlo con "tiles 3D". Así, un tile de suelo no es una imagen, sino un cubo, una piedra no es una imagen, sino un mesh, los personajes no son sprites, sino md2, etc.
Y, claro, un simple mapa de 100x100 tiles, bastante pequeño, ya se te pone en 10.000 cubos, y éso sólo para dibujar el suelo Oo

¿Ahora me entendéis? :P ¿Alguna sugerencia?
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos

Ruben

Cita de: tewe76 en 15 de Enero de 2009, 07:30:44 PM
Citarbusca en el codigo fuente de Irrlicht las funciones DrawIndexedPrimitiveUP y pon breakpoints. Compila en debug y mira a ver que es lo que pasa
Debo parecer tonto, pero sólo soy un novato en C++ (y en Visual C++) ::) La cuestión, que no consigo hacer éso que dices. Por un lado, cuando cargo el proyecto sólo "veo" el archivo cpp, no sé cómo llegar a los includes para ponerles los BP (dentro de VC++, me refiero). Y he probado a poner un BP en mi cpp e ir debugando paso por paso, pero, no entiendo por qué, pero la llamada "smgr->drawAll();", que es donde sospecho que hará las llamadas a DrawIndexedPrimitiveUP, no me deja entrar, pasa directamente a la siguiente línea ???
No joer, ¿porque vas a parecer tonto? Si no lo sabes, no eres tonto es que no lo sabes. Parece obvio pero hay un monton de gente que lo piensa. Me cabrea un huevo que se confunda desconocimiento con inteligencia!  :grrr: :grrr: :grrr: si no lo has hecho en tu vida, porque coj**** tienes que parecer tonto?  >.< >.<

Aclarado que no pareces tonto..... se me ocurre que te este pasando dos cosas:
a) Tienes incluido el proyecto del irrlicht en la solucion y le estes dando al F10 y para entrar en las funciones en visual se usa la tecla F11.
b) No tienes el proyecto del irrlicht incluido en tu solucion. Para debugear una libreria que usas (supongo que tienes el codigo fuente como es el caso del irrlicht), lo mas sencillo es incluirla en tu solucion, hacer que el proyecto que la use depende de ella y poco mas. Una vez que ejecutes en modo debug (F5), te aconsejo que hayas compilado en Debug aunque tambien podrias hacerlo en Release, puedes meterte en las funciones que usen irrlicht. Yo te aconsejaria que intentases hacer esta solucion, asi aprendes como manejarte con varios proyectos en una misma solucion, con dependencias entre ellos (que no es trivial).

Con cualquier duda, a postear! :D

Un saludo,
Ruben

Zaelsius

#11
La última versión de Irrlicht permite el uso de VBOs:

CitarHardware accelerated Vertex and Index Buffer support finally integrated into Irrlicht. Thanks to a resource handling idea by Klasker and the almost immediate implementation by Luke, Irrlicht now supports VBOs under OpenGL and D3D.
   Hardware buffers make rendering the same vertices much faster. To use this feature with a mesh, simply set a usage type via MeshBuffer->setHardwareMappingHint(scene::EHM_STATIC). The driver will upload the vertices and indices on the next draw and reuse this information without the need to upload it each frame.
   Vertex and Index buffers can also be updated separately, which is e.g. useful for the terrain node's LOD.

De esa manera Irrlicht dejaría de usar DrawIndexedPrimitiveUP (D3D) internamente para mandar los triángulos a la tarjeta.

@Tewe: para poder depurar una librería en C++, la librería debe estar compilada en "modo debug", de otra manera no es depurar código dentro de ella. Aunque con los VBO probablemente ya ganes velocidad, si aun así quieres depurar código de Irrlicht lo más sencillo en tu caso sería bajarte el código fuente del motor y:

1. Compilar la solución de VS que viene con él con la configuración "debug".
2. Enlazar con el .lib (o es una dll?) generado desde la configuración "debug" de la solución de tu juego y listo.

Hace bastante tiempo que no trasteo con VS pero más o menos sería eso. También podrías meter tanto tu juego como Irrlicht dentro de la misma solución, como apunta Rubén.

tewe76

CitarNo joer, ¿porque vas a parecer tonto? Si no lo sabes, no eres tonto es que no lo sabes.
Tranquilo, que lo decía de cachondeo :) . Sólo me considero tonto cuando intento atravesar una puerta de cristal o situaciones semejantes :P .

Citarb) No tienes el proyecto del irrlicht incluido en tu solucion.
No, no lo tengo (creo ::)). Lo he intentado, pero no me aclaro. ¿Podrías explicarme qué hay que hacer?

CitarLa última versión de Irrlicht permite el uso de VBOs:
Pues sí, éso parecía una buena solución. Pero lo he puesto siguiendo cosas que he encontrado en los foros y, o no lo hago bien, o no tiene utilidad en mi caso, porque no me da ningún error pero los FPS no cambian ??? .
En cualquier caso, tengo una duda: ¿los VBO los soportan todas las tarjetas gráficas o sólo las modernas?
Tewe
www.TAPAZAPA.com : Funny and easy to play games for all ages! - Fairy Match - Brain Crash
www.LaRebelionDelBiberon.com : Experiencias de unos padres primerizos






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.