Comunidad Game Maker

Ayuda => Preguntas y respuestas => Mensaje iniciado por: :StonerStanley: en Septiembre 01, 2019, 09:53:25 pm

Título: Optimización del dibujado en 3D
Publicado por: :StonerStanley: en Septiembre 01, 2019, 09:53:25 pm
Buenas. Resulta que tengo una 'room' en la que tengo una gran cantidad de instancias que dibujan en 3D. Mi problema es que estas instancias dibujan una figura (un cubo, con la función 'd3d_draw_block()'), resulta de hacen bajar bastante los fps (45-55 / +60), y además de que si desactivo su dibujado, los fps aumentan bastante (80 - 120 / +60).

¿Alguno sabe como se podría optimizar el dibujado del 3D, o si acaso, una alternativa?

Gracias
Título: Re:Optimización del dibujado en 3D
Publicado por: dixon en Septiembre 02, 2019, 03:35:43 am
Aquí esta el tema que habla al respecto.

Para resumirtelo tienes que miniaturizar todo, hacer cubos pequeños y bajar la cámara para que se vean grandes. Así procesará menos dibujo.

https://www.comunidadgm.org/preguntas-y-respuestas/detalles-en-los-graficos/
Título: Re:Optimización del dibujado en 3D
Publicado por: Goganpis en Septiembre 02, 2019, 06:53:27 am
Pues solo dibuja lo que tienes al frente eso hacia NeedForSpeed: Most Wanted para aquella epoca en la que fue lanzada y una consola soporto graficos y calculos muy buenos tanto que era una ciudad bien detallada y particulas, etc etc... Eso se lo logra con la diferencia de angulos.

No dibujes mas alla de lo que no necesitas.

Cambia modelos detallados por modelos low poly cuando veas necesario para bajar recursos puedes usarlo en la distancia que no se logra detallar la deformacion de objetos.

Usa modelos en lugar de dibujar lo que necesitas en tiempo real.

Si no lo ves, no lo dibujes: Haz un algoritmo el cual cree el modelo del terreno que necesitas dibujar entre menos poligonos es mas fps.

No uses modelos detallados muy a menudo, mejor usa texturas bien hechas para simular realidad te recomiendo GamingEngineer, es un youtuber que usa GM y todos sus proyectos se notan muy realistas y gracias a lo que he diferenciado he mejorado mucho link del canal: https://www.youtube.com/channel/UCXTGsXscHY4vZE4TyVw9JzA

Lo que agrego dixon tambien funciona y tiene mucha razon aun no encuentro logica pero creo que es por el procesamiento de que game maker funciona es pixel por pixel.

Dejo un proyecto abjunto.
PD: El modelo tienes que vorverlo a actualizar en included files para que dibuje el modelo del skybox basico.
Título: Re:Optimización del dibujado en 3D
Publicado por: dixon en Septiembre 02, 2019, 09:31:43 pm
Que es el md_skybox.gmmod?
Título: Re:Optimización del dibujado en 3D
Publicado por: Clamud en Septiembre 02, 2019, 10:44:30 pm
Las funciones d3d_draw_* siempre son lentas, es mejor crear un modelo con código o cargarlo desde un archivo.
Usar un formato personalizado con vertex buffers es más óptimo, pero más difícil de implementar.
Título: Re:Optimización del dibujado en 3D
Publicado por: Goganpis en Septiembre 03, 2019, 12:48:34 am
Dixon eso es solo un modelo hecho de un cubo para simular un skybox en donde configure visualmente la figura del cubo invirtiendo las caras y repitiendo la textura de las estrellas 10 veces con Model Creator (by Maarten Baert).
Pense que conocias ese tipo de archivo  :-[
Que es el md_skybox.gmmod?




Clamud lei una parte en el foro de yoyo el cual un usuario explica lo que se traga todo el rendimiento es: el procesamiento de estar dibujando en tiempo real demasiados poligonos y la memoria de video o algo asi es la que se cae en rendimiento y por ello sucede lo mismo que vemos al crear 100 estructuras por separado de un edificio en lugar de optimizarlo uniendo esas piezas y dibujarlo en un solo modelo. Las funciones de dibujos son rapidas, el costo de procesamiento es calcular a tiempo real cada poligono en distancia y cada textura, por eso se crean los modelos lo que hacen es tener eso listo ya para rellenarlo de una textura que seria menos procesamiento.
ej: Si en la vida real quieres hacer la figura de un circulo moneda o lo que sea en una hoja blanca manualmente sin ningun molde te costara hacerlo mientras que teniendo un molde solo subrayas lo que ya te indica la figura (el circulo en este ejemplo se dibuja mas rapido con un molde que dibujarlo sin molde). No se como explique espero que se entienda
Las funciones d3d_draw_* siempre son lentas, es mejor crear un modelo con código o cargarlo desde un archivo.
Usar un formato personalizado con vertex buffers es más óptimo, pero más difícil de implementar.
Título: Re:Optimización del dibujado en 3D
Publicado por: Jucarave en Septiembre 03, 2019, 04:57:05 pm
Hay varias razones por las cuales te estan bajando los FPS.

Cuando usas d3d_draw_block, en cada frame estas creando un modelo para cada cubo y luego dibujándolo, eso toma mucho tiempo no solo en crearlo sino en enviarlo a la GPU (Que es un proceso bastante lento), lo que tienes que hacer es crear en el evento create el modelo de los cubos (o de un solo cubo si es que lo estas dibujando muchas veces) y luego dibujarlo con d3d_model_draw

Ahora, no es solo eso, en general cada vez que haces un cambio de alguna información a la GPU es un proceso que se toma bastante tiempo, por ejemplo si tienes 100 cubos diferentes con 100 texturas diferentes entonces por cada cubo que trates de dibujar tienes que enviar nueva información a la GPU no solo para el modelo (vertices, coordenadas de texturas, normales, etc) sino también para la textura de cada uno de esos objetos.

Para trabajar con esto puedes hacer:

* Usar un atlas de texturas: En vez de tener una imagen por cada edifico por ejemplo, ten una imagen que contenga todas las texturas de todos los edificios, así estos pueden compartir esa textura y no necesitas reenviar esa data a la GPU (esto lo debes hacer manualmente igualmente) pero para que esto funcione todos los edificios tienen que dibujarse continuamente, es decir: si tienes 2 edificios y una esfera entonces es mas optimo dibujarlos así: edificio->edificio->esfera, ya que si los dibujas así: edificio->esfera->edificio entonces entras en el mismo problema de volver a mandar la data de las texturas multiples veces.

Por otro lado, es mucho más optimo tener todos los edificios en un solo modelo y enviarlo así sea que se dibujen todos en cada frame, que tener cada edificio individualmente.. por la misma razón, cuando los tienes todos en un solo modelo, solo necesitas enviar esa data a la GPU una vez por frame, incluso si estas dibujando 100 edificios.

Por ejemplo, en este pequeño ejemplo que hice, todo el nivel se dibuja en un solo objeto, a pesar de que el suelo y los muros tienen texturas diferentes:

[youtube]https://www.youtube.com/watch?v=3z46zZvp9BM[/youtube]

Ahí te copié unos pensamientos de modo desordenado, la verdad es que esto es un tema bastante complejo y deberías dedicarle un tiempo a aprender como funciona el rendering pipeline en openGL para que entiendas cuales son los mejores procedimientos.

Saludos
Título: Re:Optimización del dibujado en 3D
Publicado por: :StonerStanley: en Septiembre 03, 2019, 05:35:41 pm
Hay varias razones por las cuales te estan bajando los FPS.

Cuando usas d3d_draw_block, en cada frame estas creando un modelo para cada cubo y luego dibujándolo, eso toma mucho tiempo no solo en crearlo sino en enviarlo a la GPU (Que es un proceso bastante lento), lo que tienes que hacer es crear en el evento create el modelo de los cubos (o de un solo cubo si es que lo estas dibujando muchas veces) y luego dibujarlo con d3d_model_draw

Ahora, no es solo eso, en general cada vez que haces un cambio de alguna información a la GPU es un proceso que se toma bastante tiempo, por ejemplo si tienes 100 cubos diferentes con 100 texturas diferentes entonces por cada cubo que trates de dibujar tienes que enviar nueva información a la GPU no solo para el modelo (vertices, coordenadas de texturas, normales, etc) sino también para la textura de cada uno de esos objetos.

Para trabajar con esto puedes hacer:

* Usar un atlas de texturas: En vez de tener una imagen por cada edifico por ejemplo, ten una imagen que contenga todas las texturas de todos los edificios, así estos pueden compartir esa textura y no necesitas reenviar esa data a la GPU (esto lo debes hacer manualmente igualmente) pero para que esto funcione todos los edificios tienen que dibujarse continuamente, es decir: si tienes 2 edificios y una esfera entonces es mas optimo dibujarlos así: edificio->edificio->esfera, ya que si los dibujas así: edificio->esfera->edificio entonces entras en el mismo problema de volver a mandar la data de las texturas multiples veces.

Por otro lado, es mucho más optimo tener todos los edificios en un solo modelo y enviarlo así sea que se dibujen todos en cada frame, que tener cada edificio individualmente.. por la misma razón, cuando los tienes todos en un solo modelo, solo necesitas enviar esa data a la GPU una vez por frame, incluso si estas dibujando 100 edificios.

Por ejemplo, en este pequeño ejemplo que hice, todo el nivel se dibuja en un solo objeto, a pesar de que el suelo y los muros tienen texturas diferentes:

[youtube]https://www.youtube.com/watch?v=3z46zZvp9BM[/youtube]

Ahí te copié unos pensamientos de modo desordenado, la verdad es que esto es un tema bastante complejo y deberías dedicarle un tiempo a aprender como funciona el rendering pipeline en openGL para que entiendas cuales son los mejores procedimientos.

Saludos

Entiendo gran parte de tu comentario, pero hay una pequeña parte que no. La del atlas de textura. Entiendo lo de usar una textura global en vez de diferentes, pero no lo del orden, ¿te refieres a su orden de dibujado o al 'depth' de la instancia?

Otra cosa, ¿lo que hace consumir la CPU es enviar a la GPU la información del dibujado?

Y por último, gracias.
Título: Re:Optimización del dibujado en 3D
Publicado por: Jucarave en Septiembre 03, 2019, 05:55:51 pm
Me refiero al orden de dibujo, como te decía lo mas costoso es enviar cosas a la GPU, por eso debes minimizar ese número de llamados lo más que puedas... En general hablando de GMS no hay mucho que puedas hacer en ese sentido pero igual debes tratar de agrupar los objetos antes de dibujarlo de la siguiente forma:

Para todos los objetos opacos:

* textura -> modelo -> otras propiedades

Luego de dibujar todos los objetos opacos dibujas los objetos semitransparentes agrupándolos así:

* profundidad -> textura -> modelo -> otras propiedades

Eso quiere decir, que si tienes la siguiente lista de objetos:

Código: [Seleccionar]
1. ModeloA -> TexturaA
2. ModeloB -> TexturaA
3. ModeloB -> TexturaB
4. ModeloA -> TexturaA
5. ModeloA -> TexturaA
6. ModeloA -> TexturaA
7. ModeloA -> TexturaB
8. ModeloC -> TexturaA

En vez de dibujarlos en el orden en el que los creaste, deberías agruparlos y ordenarlos para que al momento de dibujarlos queden así:

Código: [Seleccionar]
1. ModeloA -> TexturaA
4. ModeloA -> TexturaA
5. ModeloA -> TexturaA
6. ModeloA -> TexturaA
2. ModeloB -> TexturaA
8. ModeloC -> TexturaA
7. ModeloA -> TexturaB
3. ModeloB -> TexturaB

Como puedes ver ahí: primero dibujamos todos los modelosA que tengan texturaA luego dibujamos todos los modelosB con texturaA y los modelosC con texturaA... luego pasamos a la texturaB y dibujamos todos los modelosA con texturaB luegos los modelosB, etc...

Con esto lo que logramos es: mandar a la GPU la texturaA, luego mandar a la GPU el modeloA, cuando ya no necesitemos el modeloA pero si la texturaA entonces enviamos el modeloB pero conservamos la texturaA hasta que ya no necesitemos el modeloB y luego hasta que no necesitemos la texturaA en ese caso enviamos la texturaB y de ese modo solo enviamos cosas a la GPU cuando necesitemos hacerlo.

No se si me expliqué bien.

Saludos
Título: Re:Optimización del dibujado en 3D
Publicado por: :StonerStanley: en Septiembre 03, 2019, 06:29:08 pm
Me refiero al orden de dibujo, como te decía lo mas costoso es enviar cosas a la GPU, por eso debes minimizar ese número de llamados lo más que puedas... En general hablando de GMS no hay mucho que puedas hacer en ese sentido pero igual debes tratar de agrupar los objetos antes de dibujarlo de la siguiente forma:

Para todos los objetos opacos:

* textura -> modelo -> otras propiedades

Luego de dibujar todos los objetos opacos dibujas los objetos semitransparentes agrupándolos así:

* profundidad -> textura -> modelo -> otras propiedades

Eso quiere decir, que si tienes la siguiente lista de objetos:

Código: [Seleccionar]
1. ModeloA -> TexturaA
2. ModeloB -> TexturaA
3. ModeloB -> TexturaB
4. ModeloA -> TexturaA
5. ModeloA -> TexturaA
6. ModeloA -> TexturaA
7. ModeloA -> TexturaB
8. ModeloC -> TexturaA

En vez de dibujarlos en el orden en el que los creaste, deberías agruparlos y ordenarlos para que al momento de dibujarlos queden así:

Código: [Seleccionar]
1. ModeloA -> TexturaA
4. ModeloA -> TexturaA
5. ModeloA -> TexturaA
6. ModeloA -> TexturaA
2. ModeloB -> TexturaA
8. ModeloC -> TexturaA
7. ModeloA -> TexturaB
3. ModeloB -> TexturaB

Como puedes ver ahí: primero dibujamos todos los modelosA que tengan texturaA luego dibujamos todos los modelosB con texturaA y los modelosC con texturaA... luego pasamos a la texturaB y dibujamos todos los modelosA con texturaB luegos los modelosB, etc...

Con esto lo que logramos es: mandar a la GPU la texturaA, luego mandar a la GPU el modeloA, cuando ya no necesitemos el modeloA pero si la texturaA entonces enviamos el modeloB pero conservamos la texturaA hasta que ya no necesitemos el modeloB y luego hasta que no necesitemos la texturaA en ese caso enviamos la texturaB y de ese modo solo enviamos cosas a la GPU cuando necesitemos hacerlo.

No se si me expliqué bien.

Saludos

Vale ahora si ya lo entiendo :), todo depende del orden del modelo y textura.
Título: Re:Optimización del dibujado en 3D
Publicado por: Goganpis en Septiembre 03, 2019, 09:44:31 pm
Wao Jucarave No sabia eso... Bueno se me ocurrio que para ordenarlos solo añadimos una lista con un script de actualizacion y asi un objeto control lo ira dibujando de forma ordenada recorriendo todos los indices que tiene que dibujar.