Pregunta

Leí en alguna parte que al renderizar una gran cantidad de objetos 3D, uno podría fusionarlos para formar una malla gigante, de modo que solo se realizaría una llamada de sorteo. Por lo tanto, deje que la cita "GPU haga su magia", mientras que la CPU está libre para otras llamadas que no sean sorteo.

Entonces, para mi pregunta, ¿sería factible hacerlo en un entorno 2D con rendimiento en mente?

Por ejemplo, supongamos que tenemos un sistema de mosaico simple y en lugar de hacer una llamada de sorteo para cada mosaico a la vista, uno fusionaría todos los mosaicos para formar un sprite grande y luego llamar a un sorteo en ella.

Cualquier idea sobre el asunto, ya sea consejos, enlaces o cualquier otra cosa, es muy apreciada ya que no tengo experiencia previa en rendimiento gráfico.

Editar: Perdón por mi pobre explicación. Estoy creando un tileengine para uso personal y quiero que sea lo más versátil posible. Por lo tanto, quiero optimizar en caso de que tenga que dibujar muchos mosaicos en el futuro cercano.

I do uso una hoja de mosaico, pero lo que quise decir con la pregunta es si fusionar todos los mosaicos que se van a dibujar de la hoja en una nueva Texture2D ganará rendimiento. Por ejemplo:

Tenemos mosaicos de 128x72 para dibujar en la pantalla. En lugar de recorrer todas las fichas e invocar el sorteo de cada ficha que se dibujará, fusionamos todas las fichas en un nuevo sprite de 1280x720 de tamaño y lo dibuja. De esta forma, el método draw () solo se llamará una vez por fotograma . Mi pregunta era si esto mejoraría el rendimiento, ya que fusionaría objetos 3D en una sola malla cuando se realiza 3D.

Debido a que la información que he reunido es que llamar a draw () es un gran rendimiento y debería llamarse lo menos posible. Alguien para confirmar o negar? :)

¿Fue útil?

Solución

No tengo ninguna experiencia con XNA y 3D, pero te daré algunos consejos para juegos 2D. Pasé un tiempo creando un motor de mosaico en XNA a principios de este año y me preguntaba lo mismo. Creo que la respuesta corta aquí es sí, combinar tus fichas en un sprite más grande es una buena idea si te preocupa el rendimiento. Sin embargo, hay una respuesta mucho más larga si está interesado.

En general, cuando se trata de optimizaciones de rendimiento, la respuesta es casi siempre, "no lo hagas". Si está seguro de que necesita optimizar el rendimiento, la siguiente respuesta es casi siempre, "no lo haga aún". Finalmente, si intenta optimizar el rendimiento, lo más importante que puede hacer es utilizar puntos de referencia para recopilar mediciones precisas del rendimiento antes y después de los cambios. ¡Sin eso, no sabes si estás teniendo éxito!

Ahora, relacionado más con los juegos en 2D, aprendí que vi un rendimiento mucho mejor en mi motor de mosaico cuanto menos cambiaba las texturas. Por ejemplo, digamos que tengo un azulejo de hierba y un azulejo de grava. Si estas son dos texturas separadas en la memoria, y dibujo un mosaico de hierba, luego un mosaico de grava, luego un mosaico de hierba en la pantalla, la GPU cargará la textura de hierba, luego la cambiará para cargar la textura de grava, luego cambiará textura de hierba nuevamente para dibujar otro mosaico de hierba. ¡Esto mata el rendimiento realmente rápido! La forma más fácil de evitar esto es tener una hoja de sprites, donde colocas los azulejos de hierba y grava en una textura, y solo le dices a SpriteBatch que dibuje desde un área diferente en la misma textura cada vez.

Otra cosa a considerar es cuántos mosaicos vas a dibujar en la pantalla a la vez. No puedo recordar específicamente, pero estaba dibujando miles de mosaicos a la vez (en una vista alejada). Noté que cuando utilicé mosaicos más grandes y dibujé menos, como sugiere en su pregunta, ese rendimiento también mejoró. Sin embargo, esto no fue una mejora tan grande como la que describí en el último párrafo, y aún así lo alentaría a que mida los cambios de rendimiento que resultan de las diferentes implementaciones. Además, si solo está dibujando una docena o unos cientos de mosaicos, puede que no valga la pena intentar optimizar eso en este momento (vea el segundo párrafo).

Para que sepas que no estoy inventando todo esto, aquí hay un enlace a una publicación de Shawn Hargreaves sobre intercambio de texturas, hojas de sprites, etc. Probablemente haya mejores publicaciones en los foros de XNA y en el blog de Shawn Hargreaves si busca en el tema.

http://forums.xna.com/forums/p/ 24254 / 131437.aspx # 131437

Update:

Dado que actualizó su pregunta, permítame actualizar mi publicación. Decidí comparar algunas muestras para darle una idea de cuáles podrían ser las diferencias de rendimiento. En mi función Draw () tengo lo siguiente:

        GraphicsDevice.Clear(Color.CornflowerBlue);

        Stopwatch sw = new Stopwatch();
        sw.Start();

        spriteBatch.Begin();

#if !DEBUG
        spriteBatch.Draw(tex, new Rectangle(0, 0, 
                         GraphicsDevice.Viewport.Width,
                         GraphicsDevice.Viewport.Height), 
                         Color.White);            
#else
        for (int i = 0; i < 128; i++)
            for (int j = 0; j < 72; j++)
            {
                Rectangle r = new Rectangle(i * 10, j * 10, 10, 10);
                spriteBatch.Draw(tex, r, r, Color.White);
            }
#endif
        spriteBatch.End();

        sw.Stop();

        if (draws > 60)
        {
            numTicks += sw.ElapsedTicks;
        }
        draws++;

        if (draws % 100 == 0)
            Console.WriteLine("avg ticks: " + numTicks / (draws - 60));

        base.Draw(gameTime);

Simplemente suelte el signo de exclamación en el " #if! DEBUG " declaración para cambiar entre los dos métodos. Me salteé los primeros 60 sorteos porque incluían una configuración inicial (no estoy seguro de qué) y estaban sesgando los promedios. Descargué una imagen de 1280x720, y para el caso de prueba superior, la dibujé una vez. Para el caso de prueba inferior, dibujé la única imagen de origen en mosaicos, 128x72 como usted preguntó en su pregunta. Aquí están los resultados.

Dibujo de una imagen:

avg ticks: 68566
avg ticks: 73668
avg ticks: 82659
avg ticks: 81654
avg ticks: 81104
avg ticks: 84664
avg ticks: 86626
avg ticks: 88211
avg ticks: 87677
avg ticks: 86694
avg ticks: 86713
avg ticks: 88116
avg ticks: 89380
avg ticks: 92158

Dibujo de mosaicos de 128x72:

avg ticks: 7902592
avg ticks: 8052819
avg ticks: 8012696
avg ticks: 8008819
avg ticks: 7985545
avg ticks: 8028217
avg ticks: 8046837
avg ticks: 8291755
avg ticks: 8309384
avg ticks: 8336120
avg ticks: 8320260
avg ticks: 8322150
avg ticks: 8381845
avg ticks: 8364629

Como puede ver, hay un par de diferencia de magnitud allí, por lo que es bastante significativo. Es bastante simple probar este tipo de cosas, y le recomiendo que ejecute sus propios puntos de referencia para su configuración específica para tener en cuenta algo que podría haber pasado por alto.

Otros consejos

Cuanto menos tenga que cambiar la tarjeta gráfica de texturas, mejor será el rendimiento. Puede ordenar por textura en el método SpriteBatch.Begin () si lo desea para que la tarjeta gráfica cambie las texturas lo menos posible.

Puse mis fichas / sprites en hojas cuando tiene sentido. Por ejemplo, un personaje puede estar en una hoja y una capa de mosaicos puede estar en la misma hoja. Esto ha funcionado bastante bien hasta ahora.

Diría que no optimices hasta que tengas que hacerlo. Si sus juegos se ejecutan lo suficientemente rápido, es por eso que se molestan con la optimización.

  

Rectángulo r = nuevo Rectángulo (i * 10, j * 10, 10, 10);

¡Crear muchos objetos nuevos llamará a la recolección de basura, lo que puede ralentizarse mucho! no debe asignar nuevos objetos en bucles grandes:

El desempeño no es un imperativo universal o un mandamiento de Dios; Es un medio para un fin. Si lo que tiene funciona lo suficientemente bien, literalmente no tiene nada que ganar al mejorar su rendimiento. Mantener "el mejor rendimiento posible en todo momento" es la definición de optimización prematura y causará más dolores de cabeza de los que previene.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top