2010-03-15 17 views
6

Estoy ejecutando una animación en una aplicación de WinForms a 18.66666 ... fotogramas por segundo (está sincronizada con música a 140 BPM, por lo que la velocidad de fotogramas es extraña). Cada celda de la animación está precalculada, y la animación es impulsada por un temporizador multimedia de alta resolución. La animación en sí es fluida, pero estoy viendo una cantidad significativa de "desgarro", o artefactos que resultan de la captura de celdas a través de una actualización de pantalla.¿Cómo eliminar el desgarro de la animación?

Cuando tomo el conjunto de celdas renderizadas por mi programa y las escribo en un archivo AVI, y luego reproduzco el archivo AVI en Windows Media Player, no veo ninguna rotura en absoluto. Supongo que WMP reproduce el archivo sin problemas porque usa DirectX (u otra cosa) y puede sincronizar la representación con la actividad de actualización de la pantalla. No está cambiando la velocidad de cuadros, ya que la animación permanece sincronizada con el audio.

¿Es esta la razón por la que WMP puede renderizar la animación sin romperse, o me falta algo? ¿Hay alguna forma de que pueda usar DirectX (u otra cosa) para permitir que mi programa sepa dónde está la línea de exploración actual y, de ser así, hay alguna forma de que pueda usar esa información para eliminar el desgarro sin utilizar DirectX? para mostrar los cel? ¿O tengo que usar DirectX por completo para procesar este problema?

Actualización: se olvidó de un detalle. Mi aplicación representa cada celda en un PictureBox usando Graphics.DrawImage. ¿Es esto significativamente más lento que el uso de BitBlt, de modo que podría eliminar al menos parte del desgarro utilizando BitBlt?

Actualización 2: el efecto que estoy viendo definitivamente no es parpadeo (que es diferente de lagrimeo). Mi panel tiene doble amortiguación, establece los estilos de control para AllPaintingInWmPaint, UserPaint, OptimizedDoubleBuffer, etc., anula onPaintBackGround y así sucesivamente. Todos estos son necesarios para eliminar el parpadeo, pero el problema de lagrimeo permanece. Es especialmente pronunciado cuando la animación tiene objetos u objetos que se mueven muy rápido y cambian de claro a oscuro muy rápidamente. Cuando los objetos se mueven lentamente y no cambian de color rápidamente, el efecto de rasgado es mucho menos notorio (porque los cels consecutivos son siempre muy similares entre sí).

+0

¿Está ejecutando la representación en un hilo separado? –

+0

@Ardman: sí, el renderizado se realiza en un hilo separado (separado del hilo de UI). – MusiGenesis

Respuesta

3

Se produce un desgarro cuando la actualización de la imagen no está sincronizada con la frecuencia de actualización del monitor. El monitor muestra parte de la imagen anterior, parte de la nueva imagen. Cuando los objetos en la imagen se mueven rápido, el efecto es bastante notorio.

No se puede reparar en Windows Forms, no se puede obtener la señal v-sync del adaptador de video. Puedes en un DirectX app.

0

Será mejor que use directx (o opengl) para tales tareas. Pero si solo quiere usar winforms, use la propiedad DoubleBuffered.

+1

Uso DoubleBuffered para eliminar el parpadeo, pero no ayuda con el desgarro. – MusiGenesis

+0

Además, estoy tratando de hacer que mi aplicación sea multiplataforma con Mono, por lo que quiero evitar cosas específicas de la plataforma como DirectX, si es posible. – MusiGenesis

+0

así que use opengl! es un análogo multiplataforma de directx. bueno, pensé que los winforms no son cross-pl. – Andrey

0

Doble buffer it.

Puede habilitar el doble almacenamiento en búfer usando estilos de Windows o, lo que probablemente sea más fácil, es dibujar una imagen desde fuera de la pantalla y luego cambiarla.

Si esto no funciona, lo mejor que puede hacer es bitblit y doble buffer.

Esencialmente es lo mismo.

Tiene una referencia a dos mapas de bits, uno es la pantalla, el otro es el búfer. Primero dibuja en el búfer y luego modifica toda la información en la pantalla. De esta manera, solo escribe datos en vivo en el búfer. La escena simplemente muestra algo que hizo anteriormente (estilo peter azul)

+2

Lo siento, debería haber sido más claro en mi pregunta. El doble buffering (que ya estoy usando) no ayuda con los efectos de rasgado. – MusiGenesis

+0

Ah ok sin preocupaciones. No utilice el cuadro de imagen y escriba directamente en la pantalla (con doble almacenamiento en búfer) – Chris

2

Probé la idea del doble buffer en el proyecto en el que estoy trabajando en este momento, pero no obtuve muy buenos resultados con él. Al final, creé lo siguiente:

  1. A System.Drawing.Bitmap para mi buffer fuera de pantalla. Decodifica la animación en este mapa de bits.
  2. Un usuario Controle el mismo tamaño que la imagen en (1) y donde el método OnPaintBackground estaba vacío (sin dibujo, sin llamadas a la clase base) y OnPaint hizo un Graphics.DrawImage para copiar la imagen fuera de pantalla en la pantalla.

Ahora, tiene una tasa de animación extraña, por lo que la rasgadura casi seguramente tiene que ver con una falta de coincidencia entre la frecuencia de actualización de la pantalla y la frecuencia de actualización de la pantalla. Está actualizando la pantalla a mitad de la actualización de la pantalla para que la pantalla dibuje el marco antiguo en la parte superior de la pantalla y el nuevo marco en la parte inferior de la pantalla. Si puede sincronizar la frecuencia de cuadros con la frecuencia de actualización de la pantalla, la rotura debería desaparecer.

+1

Lo que describe es esencialmente lo que estoy haciendo, aunque utilizo dos mapas de bits como almacenamientos intermedios fuera de la pantalla, de modo que puedo actualizar uno mientras que el otro se dibuja a la pantalla. Voy a intentar sincronizar mi animación con mi frecuencia de actualización (60Hz) y ver qué hace eso para mí. – MusiGenesis

0

Lagrimeo es un artefacto de un marco que se dibuja encima de otro. La única forma segura de evitarlo es a) esperar desde vsync o b) dibujar detrás del haz (esto es bastante complicado). El búfer doble por sí solo no garantiza que no se rompa, ya que puede tener doble búfer, pero igual puede desconectarse la función vsync. Algunas tarjetas también pueden tener la opción de espera vsync "forzada desactivada". Debe verificar la documentación relacionada con vsync y cómo verificar dónde está. Esta es la única forma segura de hacerlo. Además, tenga en cuenta que esto bloqueará su framerate.

+1

Debe haber alguna manera de animar esto sin romper utilizando la tasa de fotogramas elegida (la velocidad de fotogramas está restringida porque la animación debe estar sincronizada con la música), porque WMP puede reproducirla sin romperse. ¿Tal vez WMP hace algún tipo de interpolación entre cuadros? – MusiGenesis

Cuestiones relacionadas