2012-01-26 21 views
6

Czy ktoś mógłby podać przykład wydajnego sposobu pracy z pikselami za pomocą Direct2D?Jak pracować z pikselami za pomocą Direct2D

Na przykład, w jaki sposób można zamienić wszystkie zielonych pikseli (RGB = 0x00FF00) z czerwonych pikseli (RGB = 0xFF0000) na celu uczynić? Jakie jest standardowe podejście? Czy można do tego użyć ID2D1HwndRenderTarget? Tutaj zakładam użycie pewnego rodzaju akceleracji sprzętowej. Czy powinienem stworzyć inny obiekt do bezpośredniego manipulowania pikselami?

Używając DirectDraw, użyłbym metody BltFast na IDirectDrawSurface7 z operacją logiczną. Czy jest coś podobnego z Direct2D?

Kolejnym zadaniem jest dynamiczne generowanie złożonych obrazów, w których każde położenie punktu i kolor jest wynikiem funkcji matematycznej. Dla przykładu, uprośmy wszystko i narysuj Y = X^2. Jak to zrobić z Direct2D? Ostatecznie będę potrzebował rysować złożone funkcje, ale jeśli ktoś mógłby dać mi prosty przykład dla Y = X^2.

Odpowiedz

11

Po pierwsze, pomaga myśleć o ID2D1Bitmap jako "bitmapie urządzenia". Może, ale nie musi, żyć w lokalnej pamięci, którą można przypisać do procesora, i nie daje żadnego wygodnego (lub przynajmniej szybkiego) sposobu na odczyt/zapis pikseli po stronie procesora magistrali. Podchodzenie pod tym kątem jest prawdopodobnie niewłaściwym podejściem.

To, czego chcę, to zwykła mapa bitowa WIC, IWICBitmap, którą można utworzyć za pomocą IWICImagingFactory :: CreateBitmap(). Stamtąd możesz wywołać Lock(), aby dostać się do bufora, a następnie odczytać/zapisać za pomocą wskaźników i robić, co chcesz. Następnie, kiedy chcesz narysować go na ekranie za pomocą Direct2D, użyj ID2D1RenderTarget :: CreateBitmap(), aby utworzyć mapę bitową nowego urządzenia lub ID2D1Bitmap :: CopyFromMemory(), aby zaktualizować istniejącą bitmapę urządzenia. Można również renderować do IWICBitmap za pomocą ID2D1Factory :: CreateWicBitmapRenderTarget() (nie sprzęt przyspieszony).

Nie uzyskasz przyspieszenia sprzętowego dla tego typu operacji. Zaktualizowany Direct2D w Win8 (powinien być również dostępny dla Win7) ma trochę skomplikowanych rzeczy, ale jest dość skomplikowany.

0

Specyficzny problem z zamiana wszystkie zielone piksele z czerwonych pikseli można rozwiązać poprzez ID2D1Effect jak Windows 8 i aktualizacji platformy dla systemu Windows 7.

Dokładniej Color matrix effect.

8

Ricka odpowiedź mówi o metodach ty można użyć, jeśli nie zależy Ci na utracie akceleracji sprzętowej. Skupiam się na tym, jak to osiągnąć, wykorzystując znaczne przyspieszenie GPU.

Aby zapewnić przyspieszenie sprzętu renderującego i uzyskać najlepszą wydajność, należy przełączyć się z ID2DHwndRenderTarget na nowszy interfejs ID2DDevice i ID2DDeviceContext. Szczerze mówiąc, nie dodaje to o wiele więcej logiki do kodu, a korzyści z wydajności są znaczne. Działa również na Windows 7 z platformą Update. Podsumowując proces:

  1. Utwórz fabrykę DXGI podczas tworzenia fabryki D2D.
  2. Utwórz urządzenie D3D11 i urządzenie D2D do dopasowania.
  3. Utwórz łańcuch wymiany za pomocą fabryki DXGI i urządzenia D3D.
  4. Poproś łańcuch wymiany o bufor tylny i zawiń go w mapę bitową D2D.
  5. Renderuj jak wcześniej, między wywołaniami BeginDraw() i EndDraw(). Pamiętaj o rozwiązaniu tylnego bufora i zniszcz go, owijając go bitmapą D2D!
  6. Zadzwoń do Present() w łańcuchu wymiany, aby zobaczyć wyniki.
  7. Powtórz od 4.

Gdy już to zrobisz, masz odblokowany szereg możliwych rozwiązań. Prawdopodobnie najprostszym i najbardziej wydajnym sposobem rozwiązania twojego problemu (zamiana kanałów kolorów) jest użycie color matrix effect jako jednej z pozostałych wspomnianych odpowiedzi. Ważne jest, aby rozpoznać, że musisz użyć nowszego interfejsu ID2DDeviceContext zamiast ID2DHwndRenderTarget, aby uzyskać to jednak. Istnieje wiele innych efektów, które mogą wykonywać bardziej skomplikowane operacje, jeśli tak zdecydujesz. Oto niektóre z najbardziej użytecznych dla prostych manipulacji pikseli:

Na ogół rozwiązania problemu manipulowania pikseli bezpośrednio bez pomijania akceleracji sprzętowej lub robi ton kopiowania, są dwie opcje. Pierwszym z nich jest napisanie modułu cieniującego pikseli i zawijanie go w całkowicie niestandardowy efekt D2D. To więcej pracy niż tylko uzyskanie bufora pikseli na procesorze i wykonanie staromodnego bity bitowej, ale robienie tego wszystkiego na GPU jest znacznie szybsze. Ramy efektów D2D również bardzo ułatwiają ponowne wykorzystanie twojego efektu do innych celów, łączenie go z innymi efektami, itp.

Dla tych czasów, kiedy absolutnie musisz robić manipulacje pikselami procesora, ale wciąż potrzebujesz znacznego przyspieszenia, możesz zarządzać swoimi własnymi mapowanymi teksturami D3D11. Na przykład możesz użyć tekstury przemieszczania, jeśli chcesz asynchronicznie manipulować zasobami tekstur z procesora. Istnieje another answer, który jest bardziej szczegółowy. Aby uzyskać więcej informacji, patrz ID3D11Texture2D.

+2

Warto zauważyć, że możesz użyć 'QueryInterface' na' ID2D1RenderTarget' (dowolnego rodzaju), aby uzyskać 'ID2D1DeviceContext'. To pozwala ci na użycie znacznie prostszej metody 'ID2D1Factory :: CreateHwndRenderTarget', ale wciąż dostajesz nowszy interfejs API i unikasz zajmowania się papierkową robotą DXGI/Direct3D. Jest to nieudokumentowane, ale wydaje mi się, że jest celowe, z tego, co potrafię powiedzieć. –