Foros - Stratos

Programadores => Programación gráfica => Mensaje iniciado por: Loover en 19 de Marzo de 2008, 10:54:13 AM

Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 10:54:13 AM
Buenas,

No sé si habreis jugado al Aquaria. Para aquellos que sí, lo que me gustaría hacer es un efecto como el que tienen las algas de dicho juego. En él, las algas, aún sin cambiar el sprite (no tienen animación por sprites) ondulan. Parece ser que lo que hace es modificar los vértices del quad en el que están modificadas, para propiciar dicho efecto.

Me gustaría saber cuál es la mejor forma de hacer esto en Direct3d. Lo primero que se me ocurre es lockear el buffer de vértices y modificar a pelo los vértices... pero lockear un buffer constantemente dentro de un loop es muy costoso.

Tampoco creo que en el juego usen vertex shaders para eso, aunque quizás sí, no estoy seguro.

Sea cómo sea, ¿cómo lo haríais vosotros?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 10:58:02 AM
Una opción sería hacerlo en plan sistema de particulas: calcular las mallas (que serán muy simples) de todas las algas visiblesen la CPU y hacer un sólo lock/unlock del vertex buffer. No creo que tenga ningún impacto sensible sobre el rendimiento :)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 11:04:46 AM
Sí, eso es lo que me refería. Un solo unlock, modificar vértices, lock.

¿No influiría eso hacerlo para cada bicho de la escena? Imaginemos 100 bichos.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 11:30:11 AM
Hey, puedo usar DrawPrimitiveUp, en vez de DrawPrimitive. Así no tendré que hacer ningún lock / unlock.

¿Qué os parece eso?

El problema es que DrawPrimitiveUp es más lenta. Por lo que igual tendré que separar en dos tipos:

- LOV_STATIC_SURFACE     => Uso DrawPrimitive y no se pueden moficicar los vértices
- LOV_DYNAMIC_SURFACE   => Uso DrawPrimitiveUp y sí se pueden modificar los vértices.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 11:34:25 AM
Puedes hacer un sólo lock/unlock que agrupe a todos los bichos?

Y DrawPrimitiveUp hace un lock/unlock interno, vamos que no se gana nada
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 11:44:34 AM
No creo que me sea posible dicho lock / unlock de todos los bichos. Además que en muchos casos, algunos no cambiarian, solo algunos de ellos...

No sé, tengo que hacer pruebas de rendimiento.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 12:02:28 PM
Yo hace tiempo me estuve fumando un tutorial del SDK de DirectX para C++ (en el sdk de VB nos marginan en cuestion de tutos "interesantes") donde se implementaban efectos como ondas marinas o efectos "lupa" y recuerdo que tocaban algo a nivel de vertices (vertex shaders quiza...) y bumpmapping si mal no recuerdo (si recuerdo lo enrevesado que son los codigos de los tutos y ejemplos del SDK en ambos lenguajes :P)

Cita de: LooverHey, puedo usar DrawPrimitiveUp, en vez de DrawPrimitive. Así no tendré que hacer ningún lock / unlock.
Interesante, dx_lib32 se apoya en esta funcion para todas las operaciones graficas excepto las de texto y no sabia que se podian hacer efectos de ondas y similares alterando los vertices con dicha funcion.

No estoy muy puesto en el tema y si me iluminarais un poco el asunto seria mucho de agradecer por que hasta ahora daba por sentado que tendria que tirar de pixel shaders para hacer efectos similares al que comenta Loover :)

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 12:48:29 PM
Yo hasta ahora, cuando cargaba una imagen, la recortaba en trozos (del tamaño especificado por el usuario o el tamaño óptimo que consideraba LooverLib) para poder cargar imágenes de cualquier tamaño, (no solo potencia de 2). Creaba un vertexbuffer y en cada frame y para cada sprite, hacia un DrawPrimitive (creía que era más rápido que DrawPrimitiveUp, el cuál solo uso para dibujar las primitivas: líneas, círculos, etc).

Por ejemplo, puedo cargar una imagen de 124x1232 y decirle que me la corte en bloques de 64x64 (está claro que en los bordes ajusto las coordenadas de mapeado porque habrá sobrante).

Ahora bien, si quiero dar la posibilidad de mover los vértices de esos "grids" que creo (cosa que no hacía hasta el momento, pero que es muy interesante para efectos tipo burbuja, etc), tengo varias opciones:

- DrawPrimitive + Unlock / Lock
- DrawPrimitiveUp (con un array propio en el que modifico cuando quiero)
- Vertex Shader

Descartando directamente el Vertex Shader (por que quiero que el engine vaya en tarjetas que no tengan vertex shaders). Me he centrado en leer sobre los dos primeros:

- http://www.gamedev.net/community/forums/topic.asp?topic_id=83590
- http://www.gamedev.net/community/forums/topic.asp?topic_id=314310&whichpage=1&#2016017
- http://www.gamedev.net/community/forums/showfaq.asp?forum_id=10#q28

Pego lo más importante que he deducido:
CitarDan Baker (on the Microsoft Direct3D team) says: "Using DrawPrimUP for very small loads isn't any different then creating a Dynamic Vertex Buffer And filling it yourself - except an extra memcopy (that is negligible since the loads are small). If you are just using it to do UI quads or sprites, then its fine. "

Así que parece ser que si comienzo a usar DrawPrimitiveUp en vez de DrawPrimitive para renderizar mis grids, no voy a notar mucho la diferencia. Otra cosa que me ha dado buena espina, es que tras hablar con un programador del Harvest - Massive Encounter (http://www.oxeyegames.com/harvest/) me han dicho que han usado DrawPrimitiveUp para los sprites. Y ahí tienen MILES de sprites al mismo tiempo.

Como soy un tanto desconfiado, creo que voy a permitir ambos métodos, y hacer unos tests de rendimiento. O quizás no, luego lo decido, conforme vea lo que vais opinando.

También he hablado con Alec, programador del Aquaria, lo que el usa es directamente llamadas a GlQuad(), etc, llamadas directas al Api... cosa que no permite Direct3d.


Un saludo.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Prompt en 19 de Marzo de 2008, 12:56:44 PM
En el caso de que uses vertex shaders, como yo uso en mi motor, es comodisimo hacerse un efecto de tipo ondas, o viento ( para una supercie con plantas ). Está tirao y no hace falta hacer lock / unlock con lo que provoca... en rendimiento. Si tienes el BUS petado de datos por cada frame lo vas a notar.

¿Por qué no puedes hacer lock / unlock de todas las instancias? no las agrupas? no haces "instancing" para renderizar todo lo común a la vez?

Saludos.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 01:09:01 PM
Bueno, antes de renderizar cada sprite, aplico una serie de transformaciones para calcular su rotación, posición, escalado, etc... que son independientes para cada sprite. Y también una transformación del color (puedes hacer entintados, fades, transparencias, etc).

Por lo tanto, si aplico una trasnformación antes de cada sprite, no puedo meterlos dentro de un mismo vertexbuffer. ¿O sí se puede?

Umm, pensandolo bien, debe poderse aplicar la transformación y luego hacer el SetTexture y el DrawPrimitiveUp... pero cada vez que creara un nuevo sprite tendría que agrandar el VertexBuffer "gigante" con todos los sprites y cada ver que borrara un sprite se quedaría un hueco y tendría que copiar zonas del array y ponerlas más atrás... ¿ganaría algo con todo ese tinglado en vez de tener un VertexBuffer por sprite como tengo ahora?

¿Cómo lo haces tú [Ex3]?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 01:24:22 PM
Por los vertex shader no te preocupes, si la tarjeta no los acelera lo hace la CPU y con un rendimiento que, obviamente no tan alto como la tarjeta, si suficientemente bueno para usarlo sin problemas.

Y no hagas un DrawPrimitive por cada sprite, agrupalos tanto como puedas, asi la tarjeta tiene mucho mas material para trabajar en vez de estar esperando a la CPU. Es mas rapido calcular todos los vertices de los sprites en la CPU, hacer el lock/unlock y dibujarlos todos a la vez que no hacer ningun lock/unlock y tener que dibujarlos uno a uno
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 01:27:58 PM
¿Se ganaría mucho?, porque tal como lo tengo me va muy bien de rendimiento para un gran número de sprites en pantalla.

Estais todos de acuerdo en que ese VertexBuffer gigante con todos los sprites... en el que cada vez que quiero añadir un sprite tendré que redimensionarlo (para añadir el nuevo sprite) y cada vez que quiera borrar uno tendré que copiar todo el array desde la posición en adelante y pegar todo el bloque en la posición donde estaba el sprite... ¿es mejor?

¿Es esto lo que haceis normalmente? ¿Tú también [Ex3] para tus sprites?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 01:44:22 PM
* duplicado *
me voy a cagar en el dichoso "Network error" y su santo padre... dame paciencia para soportar los duplicados, señor ¬¬u
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 01:45:39 PM
Cita de: Loover- DrawPrimitiveUp (con un array propio en el que modifico cuando quiero)
Parece que no iba tan verde en el asunto como pensaba. Asi es como implemento las trasnformaciones de simulacion de perspectivas 3D en dx_lib32 en la funcion de dibujo en isometrica y caballera, modificando los valores de los vertices del array a pelo :)

Lo que no me queda claro del todo es, yo mis sprites son solo dos triangulos formando un quad, no n quads como usas en looverlib por lo de diseccionar la imagen, quiere eso decir que hace falta varios poligonos para poder simular el efecto de ondas o el numero da igual y con dos puedo meter mano al asunto? (desde mi ignorancia me huele que necesitare mas de dos triangulos :))

Cita de: LooverDescartando directamente el Vertex Shader (por que quiero que el engine vaya en tarjetas que no tengan vertex shaders).
A no ser que tengas de target minimo, como yo con la dx_lib32, una GeForce 2 no vas a tener problemas de soporte de Vertex Shader ya que estan presentes desde la GeForce 3 por lo que he leido aqui (http://es.wikipedia.org/wiki/GeForce).

Cita de: Loover¿Cómo lo haces tú [Ex3]?
Pues segun se mire... o muy chapuceramente o adaptado al objetivo del render. Me explico. Mi render grafico define un array de profundidad Z para facilitar al programador la ordenacion de dibujado (similara a lo que ofrecia Div Games Studio). Dicho array de profundidad no es mas que una coleccion de arrays, un array por nivel (de 8 a -8 tomando 0 por el nivel intermedio) que almacena los parametros calculados de las operaciones de dibujo que se llaman antes de generar la escena: sprites, primitivas, texto... y poco mas. Este metodo me obliga a individualizar si o si cada objeto sprite/primitiva/texto por separado y no poder agruparlo "facilmente" en un vertexBuffer o similar (tampoco meto la mano en el fuego por no estar muy puesto en el tema de vetexBuffers & cia.). El asunto es que yo genero un quad que luego sera dibujado uno a uno llamando a DrawPrimitiveUp() y dichos quad's se almacenan en un array propio que le paso como parametro a DrawPrimitiveUp(). Mis sprites, como no aplico ningun algorritmo para partir imagenes en fragmentos de potencia de 2 para respetar el aspecto original de una imagen de tamaño irregular (en mi caso se suavizan los pixeles por el autoreescalado de la grafica) solo represento mis sprites como un simple quad de 2 triangulos. Este bajo numero de vertices es lo que me hace dudar que pueda aplicar o no efectos de los mencionados ya.

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 01:53:13 PM
Yo lo que haria sería calcular en cada frame los vertices de todos los sprites, y hacer un lock/unlock de toda esta informacion en un unico vertex buffer. Luego controlas las texturas que tienes que activar y el offset del VB para dibujar cada grupo de sprites. Si es un juego 2D todos estos vertices no seran mucho mas que un par de modelos del quake 3, digo yo, e ira a toda leche. Creo que es asi como se hacen los sistemas de particulas sin recurrir a calculos masivos paralelos con la GPU (cosa que implica pixel shaders y un shader model del 2 parriba creo).

Y repito, los vertex shaders por CPU van mu bien :D
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 02:03:16 PM
Pero yo creo que lo que ganaría por usar un solo VertexBuffer, lo perdería al tener que, en cada frame, meter los vértices de todos los sprites en dicho buffer. Que algunos sprites, como ya he dicho, pueden estar taselados en más de dos triángulos.

Aparte, que para poder aplicar las transformaciones, tendría que seguir usando distintos DrawPrimitive, intercalados con los métodos de transformación. Vamos, que no podría hacer un solo "DrawPrimitive", sino varios, intercalados con las transformaciones. ¿No es así?

Y eso, lo veo igual que tener distintos vertexbuffer y hacer DrawPrimitive de cada uno de ellos. ¿No?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 02:03:39 PM
Cita de: AK47Y repito, los vertex shaders por CPU van mu bien :D
Tomo nota :) El asunto que aun no me habeis aclarado, para aplicar un efecto tipo ondas, bien sea con VertexShader o a pelo, se requiere una cantidad "minima" de vertices para hacer el efecto minimamente decente o hay algun mecanimso "esoterico" que con dos triangulos lo permita? :)

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 02:18:30 PM
Con dos triangulos, [EX3], la forma esoterica seria usar displacement mapping o alguna movida de estas. Resumiendo: pixel shaders y no cualquier shader model. Para hacer lo de la ondulacion hay que meter mas vertices, no hay mas ;)

En cuanto a lo de tener que llamar a DrawPrimitive por cada sprites es cierto si... Si no usas la tecnica de "shader instancing" con vertex shaders, que puedes usarlos porque en CPU van bien (TM) XD

Ahora que menciono el shader instancing, me doy cuenta que con esta tecnica no necesitas hacer lock/unlock en absoluto, como dijo antes Prompt.

La idea del shader instancing es la siguiente: tienes el quad (formado por 2 triangulos) unitario que es el que usas para dibujar sprites, es decir, el ancho y alto del quad miden 1 unidad. Yo lo pondria en el plano ZY con la X = 0, con el centro del quad en (0, 0, 0).

Bien, tenemos este quad, pues en el vertex buffer al cargar el juego lo copiamos N veces. Si, en ese vertex buffer hay un porron de quads, todos iguales, ocupando el mismo espacio.

Ahora biene lo bueno: por cada sprite, calculas su matriz de transformacion, que contiene toda la informacion necesaria (translacion, rotacion y escalado). Lo que se hace es agrupar estas matrices en un array y pasarselo al vertex shader, que se lo aplica a cada quad. Asi puedes posicionar, rotar o escalar los sprites como quieras, con una unica llamada. No es del todo cierto, ya que estas limitado por el numero de constantes del vertex shader (96 en 1.1).

Como sabe el vertex shader que matriz coger para aplicarselo al vertice? Muy facil: cada vertice lleva un indice, indicando que matriz debe usarse para transformarlo. Por lo tanto, los 4 vertices de un quad compartiran este indice (o no, quizas puedas hacer efectorros).

Se puede sofisticar esto para añadir matrices de transformacion para las coordenadas de texturas y demas cosas, pero creo que ya pillas la idea (espero, no se si me he explicado mu bien XD).

Ala, a ver si le vale a alguien :)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 02:33:34 PM
Buff, creo que me retiro, se me queda grande el asunto de los vertexBuffer y vertexShaders y de los pixelShaders ni hablemos :lol: Creo que me conformare con usar alphas para simular efectos "discretos" :P

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 02:42:04 PM
No es dificil comprenderlo. La idea clave es que en el vertex shader, se procesa un vertice cada vez, y que no puedes acceder a ningun otro vertice de la malla. Solo tienes los datos del vertice y los datos que le has pasado (como se chorizo de matrices)  8)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 03:47:36 PM
Creo que de momento voy a dejar los shaders de lado. Porque seguro surgirán diferentes complicaciones con otros aspectos del engine, o limitaciones como la que has citado. Aparte que no los veo necesarios, porque no creo que un juego vaya a necesitar más sprites en pantalla que los que usa el Harvest, que es una salvajada, y les va de perlas con el DrawPrimitiveUp (pero lo que si hacen es agrupar por textura).

En cuanto a lo de un solo buffer, tiene su gracia si vas a hacer un solo DrawPrimitive, pero si antes de cada sprite tengo que hacer las transformaciones, al final voy a hacer tantos DrawPrimitive como si hubiera distintos buffers, por lo que no gano nada. Al revés, pierdo en complejidad y en el tiempo en crear ese buffer gigante.

Otra forma de ganar velocidad que me han comentado es agrupar los sprites por textura. Pero eso no me libra de las transformaciones...

[Ex3], lo de los efectos tipo ondulación y tal, consiste en esto:
- Cargas un sprite y lo divides en bloques (tantos como quieras). Vamos, un grid.
- Permites, mediante una función, mover cada vértice del grid.

Ahora, recorriendo dichos vértices, puedes hacer todo tipo de animaciones. Desde una cortina (uniendo dichos vértices a un engine de física), hasta un efecto de ondas (moviéndo vértices usando alguna función sin, etc).

Desde la primera versión de LooverLib, tengo el método que carga las imágenes trocéandolas en cuantos trozos quiero. Ahora lo interesante es dar unos métodos para mover los vértices de dicho grid. Y luego, si acaso, hacer una clase de efectos, que moviendo dichos vértices, cree distintos efectos animados.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 04:12:06 PM
*duplicado*
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 19 de Marzo de 2008, 04:12:32 PM
Cita de: AK47No es dificil comprenderlo.
No, si lo dificil es adaptarlo al codigo del render de la dx_lib32 :lol: El buffer de profundidad que implemente y la forma de trabajar con el ha hecho que me limite mucho el implementar cosas complejas como vertexBuffers o incluso PixelShaders (que solo podria aplicar shaders a texturas independientes y no en conjunto).

Cita de: Loover[Ex3], lo de los efectos tipo ondulación y tal, consiste en esto:
- Cargas un sprite y lo divides en bloques (tantos como quieras). Vamos, un grid.
- Permites, mediante una función, mover cada vértice del grid.
Esto puedo hacerlo sin modificar nada del codigo actual ya que puedo dibujar una misma textura pero seleccionando regiones o frames, lo que me da como resultado varios sprites en pantalla, lo que es lo mismo, varios quads. El unico engorro seria el tener calcular la rotacion o transformacion correcta de cada frame del grupo de sprites (he ahi lo malo de tenerlos independientes) y que tendria que calcular a pelo sin vertexShaders las alteraciones de los sprites, en el engine del juego (hablo de implementar todo esto fuera de la dx_lib32).

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Prompt en 19 de Marzo de 2008, 04:58:18 PM
Cita de: LooverBueno, antes de renderizar cada sprite, aplico una serie de transformaciones para calcular su rotación, posición, escalado, etc... que son independientes para cada sprite. Y también una transformación del color (puedes hacer entintados, fades, transparencias, etc).

Por lo tanto, si aplico una trasnformación antes de cada sprite, no puedo meterlos dentro de un mismo vertexbuffer. ¿O sí se puede?

Umm, pensandolo bien, debe poderse aplicar la transformación y luego hacer el SetTexture y el DrawPrimitiveUp... pero cada vez que creara un nuevo sprite tendría que agrandar el VertexBuffer "gigante" con todos los sprites y cada ver que borrara un sprite se quedaría un hueco y tendría que copiar zonas del array y ponerlas más atrás... ¿ganaría algo con todo ese tinglado en vez de tener un VertexBuffer por sprite como tengo ahora?

¿Cómo lo haces tú [Ex3]?

Es mucho mejor:
- Destruir un buffer.
- Crear uno nuevo.
- Agrupar todo.
- Evidarlo a la tarjeta.

Que ir mandandolo poco a poco. El coste de esto es minimo y la agrupación antes de mandarla por el BUS a la tarjeta grafica la hace la CPU.

El rendimiento es buenisimo. Intenta que esto no ocurra mucho, reservando bloques de memoria lo suficientemente grandes, es decir, si en tu vertexBuffer borras elementos, agrupas y resulta que sobra un buen cacho no te preocupes. Redimensionalo solo si necesitas más y hazlo pensando en que no se vuelva hacer al menos en unos pocos de frames o segundos.

Normalmente todo lo precargas antes de una escena, y esto debería ocurrir muy poco.

PD: no se si lo he explicado muy bien, me voy a casita!! Esto se explica todo en el "instancing" para D3D. En OpenGL se llama pseudo instancing porque esta gestion según los datos que maneja la gente de nVidia dicen que glDrawElements ( creo que era ) el == a DrawPrimitives, va muchisimo mejor que en DX y la perdida es mínima.

No obstante... estoy seguro que haciendo lo mismo va mejor. Yo aun no lo tengo hecho, pero tengo pendiente crear un único VBO para todo.

No me extiendo más... adioooooooooo !! A ver si luego en casa miro los demás post!
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Prompt en 19 de Marzo de 2008, 05:11:29 PM
Post repetido...  :?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 06:22:21 PM
Pero no puedo agruparlo y mandarlo todo si tengo que hacer transformaciones por sprite. Antes de cada DrawPrimitive, tengo que hacer una transformación. Para posicionar el sprite en coordenadas de mundo (rotaciones, escalados, traslaciones). Y también efectos de entintado, fade, etc.

Vamos, no puedo "mandarlo todo" y ale.

Tengo que:

- Aplicar transformaciones del sprite en cuestión
- Hacer un DrawPrimitive del sprite

¿O hay alguna forma de hacer eso en un solo buffer?

¿Cómo lo tienes tu [Ex3]?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 19 de Marzo de 2008, 06:49:46 PM
Puedes agrupar los sprites por texturas y calcular sus matrices. Luego, por cada conjunto de sprites que comparten textura, coges sus matrices y los envias en trozos que puedan entrar en las constantes del vertex shader. De esta forma en mi juego puedo dibujar 90 arboles de golpe (con sus limitaciones, claro).

Aun asi igual no merece la pena, yo agruparia los sprites en texturas y los dibujaria de golpe todos a la vez (N llamadas de DrawprimitiveUp, por ejemplo, donde N = numero texturas diferentes en pantalla). No hace falta enviar matrices a la tarjeta, los vertices que le envias ya estan transformados por la CPU. Si, asi no se aprovecha la tarjeta, pero creo que es mas rapido en vez de enviarlos uno por uno.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Prompt en 19 de Marzo de 2008, 07:03:56 PM
Lo puedes hacer por grupo Loover machote.

Ordenas por material.
Lo que tenga transparencia.
etc...

Aplicas las transformaciones a todos los vertices del "grupo" y subes!

Busca en la ayuda de DX o en nVidia sobre el Instancing, seguro que al leerlo un poco lo ves más claro.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 19 de Marzo de 2008, 10:00:09 PM
CitarAplicas las transformaciones a todos los vertices del "grupo" y subes!

Pero es que no hay grupos que coincidan... cada sprite tiene posiciones, rotaciones y escalados distintos. Aparte de fades, entintados y niveles de transparencia también distintos...

Citar
No hace falta enviar matrices a la tarjeta, los vertices que le envias ya estan transformados por la CPU. Si, asi no se aprovecha la tarjeta, pero creo que es mas rapido en vez de enviarlos uno por uno.

¿Me recomiendas que aplique las transformaciones y genere un vertexbuffer con todos los vértices transformados y entonces lo dibuje agrupando por textura? ¿En vez de hacer el típico "Set" de la matriz de mundo con las rotaciones, escalados, etc del sprite y entonces dibujarlo (y que se encargue de las transformaciones la tarjeta)? Pues no lo veo claro, porque hago pruebas con burradas de sprites en pantalla y va de perlas.

Sin embargo, el tener que generar dicho buffer, y en cada frame copiar toda la info de los sprites (pq puede que alguno no haya que dibujarlo porque el usuario lo haya desactivado o borrado) me da repelús (no solo por el memcopy al vertexbuffer) sino aparte por que tendría que usar la CPU para transformar los vértices de cada sprite.

Aunque por otro lado no he hecho pruebas, por lo que quizás si que ganaría algunos fps en situaciones con más de 1000 sprites en pantalla. No lo sé...

[Ex3], pronunciate, ¿como lo haces tú en la dx_lib32?
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 20 de Marzo de 2008, 01:40:11 AM
Cita de: Loover[Ex3], pronunciate, ¿como lo haces tú en la dx_lib32?
Invocado me has :P

Me supongo que ahora preguntaras por lo de las transformaciones. Recapitualndo un poco para que se entienda esto, mi render funciona en un modo "virtual" por llamarlo asi, esto es, cada llamada que hago a mis funciones graficas de dibujo solo generan parametros de salida que voy agrupando en colecciones de arrays que almacenarian las llamadas reales, un orden que se define como coordenada Z. En el caso de la funcion de dibujo de sprites, todo el grueso de calculos y transformaciones las hago en la llamada virtual, DRAW_MapEx(). En esta funcion calculo la posicion de los vertices, la region de la textura si se ha definido, la configuracion UV de la textura para aplicar el espejado indicado y la transformacion por matrices para escalar y/o rotar los vertices. Despues simplemente agrego la llamada a la coleccion en el array correspondiente a la Z indicada. El render como tal seria un metodo interno que ejecutaria por orden los 17 niveles de la coleccion o "buffer de profundidad" (de -8 el mas lejano a la camara, pasando por 0 que es el nivel intermedio hasta 8 el mas cercano a la camara) llamada tras llamada, en el caso de los sprites/tiles o cualquier grafico textura lo que hace en este metodo seria configurar los renderstates y rendertextures que definen dos parametros de la llamada a DRAW_MapEx(), el modo de alphablending y el filtro de textura (solo modifica renderstates y rendertextures si los valores no son los mismos que los ya activados), por ultimo activo la textura a dibujar y llamo a DrawPrimitiveUP().

Si no ha quedado muy claro, por que reconozco que es un poco lioso de explicar, aqui un pequeño croquis:
zBuffer o tambien RenderBuffer:

zBuffer[-8][2] {e, f}
zBuffer[-3][1] {c}
zBuffer[0][4] {a,b,d,g}
zBuffer[6][1] {h}

Las letras definen el orden en que fueron agregados al buffer pero no su orden de dibujado, que lo define el array segun su posicion en el zBuffer, lo que en este caso seria dibujar en el siguiente orden: e, f, c, a, b, d, g, h.

// La funcion de dibujo de sprites con opciones de transformacion:
DRAW_MapEx()
{
   Defino el quad inicial con las dimensiones indicadas
   Asigno los colores a los vertices y el specular si se indico
   Configuro el UV de la textura en los vertices del quad segun el espejado indicado
   Aplico transformaciones con matrices para escalar y rotar si fuese necesario
   Agrego lista de parametros calculados al nivel correcto definido por la coordenada Z al zBuffer
}

Frame() // Seria el Flip() o Render() de dx_lib32, es la llamada que ejecutaria el envio de datos a la grafica:
{
   Control de recuperacion de device
   Limpiamos escena (D3DDevice.Clear())
   ExecuteRenderBuffer() <-- El render de llamadas
   D3DDevice.Present()
   Calculo de FPS
}

// El render por excelencia:
ExecuteRenderBuffer()
{
   D3DDevice.BeginScene()

   Recorremos cada nivel del zBuffer (desde -8 hasta 8)
   {
       Leemos cada elemento del array (desde 0 hasta n)
       {
           Configuramos renderstates (modo de alphablending o efecto de color (invertir colores por ejemplo))
           Configuramos rendertextures (filtro textura)

           swich (tipo operacion)
           {
               texturas y/o primitivas:
               {
                   Llamamos a DrawPrimitiveUP()
               }
               textos:
               {
                   ...
               }
           }
       }
   }
   D3DDevice.EndSecene()
   Vaciamos el zBuffer
}

He de decir que este sistema funciona mejor de lo que me esperaba en su momento, teniendo en cuenta que son llamadas totalmente aisladas (de ahi que me sea problematico hacer agrupaciones con vertexBuffers y similares) y que es codigo compilado en Visual Basic 6.0 (no quiero saber como iria esto en C++).

De implementar yo efectos, si son filtros para invertir colores o aplicar combinaciones de blendings para el alpha, esto seria en el espacio donde configuro los renderstates en ExecuteRenderBuffer(), mientras que si se tratase de un efecto a nivel de vertices, como los de simulacion de perspectivas 3D de DRAW_AdvMap(), esto se haria en la propia funcion de llamada "virtual", DRAW_loquesea().

No sera la implementacion mas optima pero si resulta comoda para organizar llamadas por grupos sin importar el orden de ejecucion del codigo :) (realmente una mania adquirida en mis años de programacion con Div Games Studio, dichosa coordenada Z de los procesos xD)

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 20 de Marzo de 2008, 11:33:37 AM
Bastaba con un: "uso un DrawPrimitiveUP() por sprite", jajaja. Que es como lo hago yo tb.

Lo que tengo yo es una clase "entidad" a la que le puedo asignar una superficie (un sprite que he taselado (o no), no confundir con superficies de direct3d).

Luego esa entidad tiene numerosos métodos: SetPos, SetRotation, SetFade, SetTint, SetBoundingAreas, etc, etc.

Luego ordendo las entidades por su valor z, en el manager de entidades. A la hora de dibujar (con un método al que el usuario llama cuando él quiere), recorro dicho manager, para cada entidad:

- Función de transformación (rotaciones, escalados, traslaciónes, mirroring, etc)
- Función de atributos de color (fades a un color, tintes a un color, transparencias, filtros, etc).
- DrawPrimitive

Lo bueno y curioso, es que las funciones de transformación y de atributos de color, me valen igual para las entidades 3d (modelos .x) :)

Hablando con los del Harvest, lo que hacen ellos es transformar los vértices de los sprites por software, y guardarlos en un array ya transformados, vamos, que no envian la matriz de mundo a la tarjeta. Así puede agrupar por sprite y hacer un DrawPrimitiveUp de todos los que tengan el mismo sprite.

Que creo que es lo que comentaban prompt y Ak47. Lo cual nos obligaría a hacer muchos cambios. Voy a hacer unas cuentas pruebas tochas, a ver si puedo tener en pantalla tantos bichos como los del Harvest :D
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: AK47 en 20 de Marzo de 2008, 12:04:18 PM
Hombre, es que si el rendimiento es bueno con el sistema que usas actualmente, yo no lo cambiaria. Sobre todo si requiere muchos cambios... Como dijo uno alguna vez, al final "nobody cares how you engine is done" ;)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 20 de Marzo de 2008, 06:50:30 PM
Cita de: LooverBastaba con un: "uso un DrawPrimitiveUP() por sprite", jajaja.
Encima que me tomo la molestia de explayarme en la explicacion tecnica de "la poesia" que es la implementacion del render de dx_lib32, si es que... xDDDD

Cita de: LooverQue creo que es lo que comentaban prompt y Ak47. Lo cual nos obligaría a hacer muchos cambios.
A mi al menos no me merece la pena invertir mas tiempo en Visual Basic 6.0 con dx_lib32 y si en C# con el motor del juego, total, los efectos si no puedes aplicarlos te buscas las castañas para simularlos minimamente, recuerda lo de las luces dinamicas en el TLSA.Core ;)

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 20 de Marzo de 2008, 08:45:35 PM
Fínisimas esas luces  :shock:
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 03 de Abril de 2008, 04:14:30 PM
¡Funciona! Muy, muy chulo en movimiento. Muy... "Aquaria" :D

(http://www.pixelartgames.com/temporal/grid_animation.jpg)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 03 de Abril de 2008, 04:24:49 PM
Hey, ha quedado bien :) Un test para verlo en movimiento seria la caña ;)

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 03 de Abril de 2008, 04:26:50 PM
¡Sí! Hay que preparar algo chulo. Ahora que ya he llegado por fin a la versión  1.0 voy a preparar los tutoriales. Y ahí pondré varios tests :)

Si te interesa implementarlo en tu motor avisame que te pase el código fuente, es relativamente sencillo.
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 03 de Abril de 2008, 09:09:50 PM
La verdad que curiosidad me entra por ver como calculas las variaciones de los vertices, por que la verdad, con un pequeño apaño en la dx_lib32 (variar la funcion de dibujo de sprites en perspectiva para que acepte valores distintos para lo 4 vertices) podria intentar armar de forma similar el efecto :)

Podrias subirlo como COTW, que anda un poco abandonada esa seccion y codigos como estos siempre llaman la atencion :D

Salu2...
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: Loover en 04 de Abril de 2008, 01:41:34 PM
Pues mover los vértices haciendo el efecto onda es lo más sencillo. Son 3 líneas de código: un for anidado y un SetPos usando una función sinosuidal.

Pero vamos, ese es solo uno de los muchos efectos que puedes hacer. También podrías usar dichos vértices en un sistema de física y simular telas. O dibujar al estilo del Aquaria, serpientes y tal (mallas subdivididas verticalmente).

Toy preparando el tutorial ;)
Título: Efecto "ondas" o "burbuja" en Direct3d
Publicado por: [EX3] en 04 de Abril de 2008, 02:22:03 PM
Lo interesante es que se podria aplicar a nivel de escena en un tileado, por ejemplo para simular el efecto submarino como me supongo hara el Aquaria :)

Salu2...