2012-01-26 25 views
6

¿Podría alguien proporcionar un ejemplo de una forma eficiente de trabajar con píxeles utilizando Direct2D?Cómo trabajar con píxeles con Direct2D

Por ejemplo, ¿cómo se puede intercambiar I todos los píxeles verdes (RGB = 0x00FF00) con píxeles rojos (RGB = 0xFF0000) en un objetivo rendir? ¿Cuál es el enfoque estándar? ¿Es posible usar ID2D1HwndRenderTarget para eso? Aquí supongo que usar algún tipo de aceleración de hardware. ¿Debería crear un objeto diferente para manipulaciones directas de píxeles?

Usando DirectDraw usaría el método BltFast en el IDirectDrawSurface7 con operación lógica. ¿Hay algo similar con Direct2D?

Otra tarea es generar dinámicamente imágenes complejas donde cada ubicación de punto y color es el resultado de una función matemática. En aras de un ejemplo, simplifiquemos todo y dibuje Y = X^2. ¿Cómo hacer eso con Direct2D? En definitiva, voy a necesitar dibujar funciones complejas, pero si alguien pudiera darme un ejemplo simple para Y = X^2.

Respuesta

11

En primer lugar, ayuda a pensar en ID2D1Bitmap como un "mapa de bits del dispositivo". Puede o no puede vivir en la memoria local, direccionable por CPU, y no le proporciona ninguna forma conveniente (o al menos rápida) de leer/escribir los píxeles desde el lado de la CPU del bus. Entonces acercarse desde ese ángulo es probablemente el enfoque equivocado.

Lo que creo que quiere es un mapa de bits de WIC normal, IWICBitmap, que puede crear con IWICImagingFactory :: CreateBitmap(). Desde allí, puede llamar a Lock() para acceder al búfer, y luego leer/escribir usando punteros y hacer lo que quiera. Luego, cuando necesite dibujarlo en pantalla con Direct2D, use ID2D1RenderTarget :: CreateBitmap() para crear un nuevo mapa de bits del dispositivo, o ID2D1Bitmap :: CopyFromMemory() para actualizar un mapa de bits del dispositivo existente. También puede procesar en un IWICBitmap haciendo uso de ID2D1Factory :: CreateWicBitmapRenderTarget() (no hardware acelerado).

No obtendrá aceleración de hardware para este tipo de operaciones. El Direct2D actualizado en Win8 (también debería estar disponible para Win7 eventualmente) tiene algunas cosas interesantes para esto, pero es bastante complejo.

0

El tema específico de intercambio de todos los píxeles verdes con píxeles rojos se pueden abordar a través de ID2D1Effect como de Windows 8 y la actualización de plataforma para Windows 7.

Más específicamente, Color matrix effect.

8

de Rick respuesta habla de los métodos que se puede usar si no te importa perder aceleración de hardware. Me estoy enfocando en cómo lograr esto usando una cantidad sustancial de aceleración GPU.

Para mantener su hardware de renderizado acelerado y obtener el mejor rendimiento, querrá cambiar de ID2DHwndRenderTarget a usar las nuevas interfaces ID2DDevice e ID2DDeviceContext. Honestamente, no agrega mucha más lógica a su código y los beneficios de rendimiento son sustanciales. También funciona en Windows 7 con la Actualización de plataforma. Para resumir el proceso:

  1. Cree una fábrica DXGI cuando cree su fábrica D2D.
  2. Cree un dispositivo D3D11 y un dispositivo D2D para que coincida.
  3. Crea una cadena de intercambio usando tu fábrica DXGI y el dispositivo D3D.
  4. Pregunte a la cadena de intercambio por su memoria intermedia posterior y envuélvala en un mapa de bits D2D.
  5. Renderizar como antes, entre llamadas a BeginDraw() y EndDraw(). ¡Recuerda destrabar el búfer posterior y destruir el mapa de bits D2D envolviéndolo!
  6. Llamar Presente() en la cadena de intercambio para ver los resultados.
  7. Repetir desde 4.

Una vez que hayas hecho esto, usted ha desbloqueado una serie de posibles soluciones. Probablemente, la forma más simple y efectiva de resolver su problema exacto (intercambiando canales de color) es usar el color matrix effect como una de las otras respuestas mencionadas. Es importante reconocer que necesita utilizar la nueva interfaz ID2DDeviceContext en lugar de ID2DHwndRenderTarget para obtener esto. Hay muchos otros efectos que pueden hacer operaciones más complicadas si así lo desea. Éstos son algunos de los más útil para facilitar la manipulación de píxeles:

Por lo general la solución del problema de la manipulación de los píxeles directamente sin dejar caer la aceleración de hardware o hacer toneladas de copia, hay dos opciones. El primero es escribir un sombreador de píxeles y envolverlo en un efecto D2D completamente personalizado. Es más trabajo que solo obtener el búfer de píxeles en la CPU y realizar el masteado de bits anticuado, pero hacerlo todo en la GPU es mucho más rápido. El marco de efectos D2D también hace que sea super simple reutilizar su efecto para otros fines, combinarlo con otros efectos, etc.

Para esos momentos en los que absolutamente tiene que hacer la manipulación de píxeles de la CPU pero aún quiere un grado sustancial de aceleración, puede administrar sus propias texturas D3D11 asignables. Por ejemplo, puede usar texturas de transición si desea manipular de forma asincrónica sus recursos de textura desde la CPU. Hay another answer que entra en más detalles. Vea ID3D11Texture2D para más información.

+2

Vale la pena señalar que puede utilizar 'QueryInterface' en un' ID2D1RenderTarget' (de cualquier tipo) para obtener 'ID2D1DeviceContext'. Esto le permite usar el método mucho más simple 'ID2D1Factory :: CreateHwndRenderTarget', pero aún así obtener la API más nueva y evitar lidiar con el papeleo DXGI/Direct3D. Esto no está documentado, pero parece ser intencional, por lo que puedo decir. –