2010-04-05 17 views
7

Estoy buscando una manera de acelerar el dibujo de mi motor de juego, que actualmente es el importante cuello de botella y está causando ralentizaciones. Estoy a punto de convertirlo a XNA, pero acabo de notar algo.¿Por qué el dibujo en gráficos OnPaint es más rápido que los gráficos de imagen?

Supongamos que tengo una imagen pequeña que he cargado.

Image img = Image.FromFile("mypict.png"); 

Tenemos un recuadro de imagen en la pantalla que queremos dibujar. Entonces tenemos un controlador.

pictureBox1.Paint += new PaintEventHandler(pictureBox1_Paint); 

Quiero que nuestra imagen cargada a revestir en el cuadro de imagen (esto es para un juego, después de todo). ¿Por qué en la tierra es este código:

void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     for (int y = 0; y < 16; y++) 
      for (int x = 0; x < 16; x++) 
       e.Graphics.DrawImage(image, x * 16, y * 16, 16, 16); 
    } 

más de 25 veces más rápido que este código:

Image buff = new Bitmap(256, 256, PixelFormat.Format32bppPArgb); // actually a form member 
    void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     using (Graphics g = Graphics.FromImage(buff)) 
     { 
      for (int y = 0; y < 16; y++) 
       for (int x = 0; x < 16; x++) 
        g.DrawImage(image, x * 16, y * 16, 16, 16); 
     } 
     e.Graphics.DrawImage(buff, 0, 0, 256, 256); 
    } 

Para eliminar lo obvio, lo he intentado comentando la última e.Graphics.DrawImage (lo que significa No veo nada, pero elimina una llamada que no está en el primer ejemplo). También me he quedado en el bloque de uso (innecesariamente) en el primer ejemplo, pero sigue siendo increíblemente rápido. Establecí las propiedades de g para que coincida con e.Graphics - cosas como InterpolationMode, CompositingQuality, etc., pero nada de lo que haga supera esta increíble brecha de rendimiento. No puedo encontrar ninguna diferencia entre los dos objetos de Gráficos. ¿Lo que da?

Mi prueba con un System.Diagnostics.Stopwatch dice que el primer fragmento de código se ejecuta a aproximadamente 7100 fps, mientras que el segundo funciona a unos míseros 280 fps. Mi imagen de referencia es VS2010ImageLibrary\Objects\png_format\WinVista\SecurityLock.png, que es de 48x48 px, y la modifiqué para que fuera de 72 dpi en lugar de 96, pero tampoco importó.

Respuesta

1

Cuando dibuja en la pantalla, el sistema operativo puede aprovechar el hardware especial en el adaptador de gráficos para realizar operaciones simples como copiar una imagen.

0

¿Estás seguro de que la diferencia no es del bloque de uso, es decir, configurar el bloque try-finally y crear la instancia Graphics desde el búfer de imagen.

Pude ver fácilmente esto último como una operación costosa, a diferencia del evento de pintura donde simplemente se obtiene una referencia a una instancia de gráficos ya creada.

+1

Crear objetos gráficos es muy costoso, creo que tiene razón y la configuración como parte de la cláusula de uso (y la creación del búfer) afectará el rendimiento, sin embargo, eso significa que no debe preocuparse por asegurarse de que el objeto gráfico se destruye después. Intente crearlos en el momento del inicio y vuelva a usarlos durante el tiempo de ejecución, pero asegúrese de destruirlos al salir. – Frozenskys

+0

Dije en mi publicación, traté de irme en el bloque de uso. Es decir, tome el segundo fragmento, comente e.Graphics.DrawImage y cambie g.DrawImage en e.Graphics.DrawImage. De repente es tan rápido como el primer fragmento. – Tesserex

1

Obtendré ~ 5 mseg para ambos. 7100 fps es manera demasiado rápido para la representación de software realizada por GDI +. Los controladores de video engañan notoriamente para ganar puntos de referencia, pueden detectar que no se debe realizar un BitBlt porque la imagen no cambió. Intente pasar valores aleatorios a e.Graphics.TranslateTransform para eliminar el truco.

+0

He insertado 'e.Graphics.TranslateTransform ((float) rand.NextDouble(), (float) rand.NextDouble());' dentro del ciclo de dibujo. Disminuyó de 7100 a 5000 fps. ¿Inténtalo de nuevo? – Tesserex

+0

¡Qué diablos ... ese mismo cambio, en el método más lento, lo hizo MÁS RÁPIDO, de 280 a 380 fps! – Tesserex

Cuestiones relacionadas