2012-05-26 18 views
9

enter image description herePixels in Direct2D

Die dunklen grauen Linien sollen schwarz und 1 Pixel breit sein:

pRT->DrawLine(Point2F(100, 120), Point2F(300, 120), blackbrush, 1); 

Die hellgrauen Linien sollen schwarz sein und 0,5 Pixel breit:

pRT->DrawLine(Point2F(120, 130), Point2F(280, 130), blackbrush, 0.5); 

Stattdessen sind sie beide 2 Pixel breit. Wenn ich nach 2 Pixel Breite frage, ist die Linie schwarz, aber natürlich 2 Pixel breit.

Das Renderziel hat dieselbe Größe wie der Clientbereich des Fensters. Ich möchte Pixelgenauigkeit wie in GDI, eine Koordinate = ein Pixel und reine Farben ...

Danke.

Antwort

13

Direct2D hilft richtig zu machen. Wenn Sie ihm eine Pixelkoordinate wie (100, 120) geben, bezieht sich das auf die obere und linke Ecke des Pixelelements, das sich von den Pixelkoordinaten (100, 120) bis (101, 121) erstreckt (oben/links sind inklusive). rechts/unten sind exklusiv). Da es sich um eine gerade horizontale Linie handelt, erhalten Sie effektiv ein ausgefülltes Rechteck von (99.5, 119.5) - (300.5, 120.5). Da die Ränder davon in benachbarte Pixel übergehen, erhalten Sie deshalb "2 Pixel breite" Linien mit der "falschen" Helligkeit. Sie müssen in Bezug auf Pixel Koordinaten (Punkte ohne Bereich) und Pixel Elemente (physikalische Punkte auf dem Bildschirm mit einer Fläche von 1x1, oder nur 1 natürlich) denken.

Wenn Sie eine gerade Linie zeichnen wollen, die die Pixel (100, 120) bis (300, 120) abdeckt, sollten Sie entweder SemMike's Vorschlag der Verwendung von Alias-Rendering verwenden (was für gerade Linien ideal ist!), Oder Sie können Halbpixel-Offsets verwenden (da strokeWidth = 1 ist; für andere strokeWidths passen Sie sie nach strokeWidth/2 an). Das Zeichnen von (100.5, 120.5) - (299.5, 120.5) mit einer Strichstärke von 1.0 wird Ihnen helfen, wonach Sie suchen. Dieser Strich erstreckt sich um die von Ihnen angegebenen Pixelkoordinaten, sodass Sie das "gefüllte Rechteck" über den Pixelelementen (100, 120) - (300, 121) erhalten. Und wieder, das ist ein exklusiver Bereich, also ist 'y = 121' nicht wirklich gefüllt, auch ist x = 300.

Wenn Sie sich wundern, warum dies nicht mit etwas wie GDI passiert, ist es, weil es nicht Antialiasing-Rendering tut, so dass alles immer auf Pixelelemente rastet. Wenn Sie sich fragen, warum dies bei der Verwendung von Shapes nicht mit WPF geschieht, liegt das daran, dass es Layout-Abrundung (UseLayoutRounding) und Pixelfang verwendet. Direct2D bietet diese Dienste nicht an, da es sich um eine API auf relativ niedriger Ebene handelt.

+0

Danke für die Erklärung, macht Sinn. Habe ich das in den MSDN-Dokumenten auf Direct2D irgendwo vermisst oder ist es nicht da und ich sollte es wissen? "Zeichnen von (100.5, 120.5) - (299.5, 120.5) mit einer Strichstärke von 1.0 wird Sie bekommen, was Sie suchen" Wenn ich Sie richtig verstehe, wäre das (100.5, 120.5) - (300.5, 120.5) . Andernfalls wird das letzte Pixel der Zeile weggelassen. Übrigens, "SemMike's Vorschlag": derselbe Typ, ich beantwortete meine eigene Frage ... – SemMike

+0

Ob Sie 299.5 oder 300.5 verwenden, hängt davon ab, ob Sie eine 200px breite Linie oder eine 201px Linie möchten. Und das ist wahrscheinlich nicht in der Dokumentation, denn es ist ziemlich Standard für moderne 2D-Grafik-APIs, aber es ist auch ein bisschen nicht offensichtlich und fortgeschritten, und oft vergessen Menschen, die an fortgeschrittenen Sachen arbeiten, was sie vorher nicht wussten das ist fortgeschritten. Ich finde es hilft, es wie ein Blatt Rasterpapier zu denken. Wo die horizontalen und vertikalen Linien sich schneiden, sind die ganzzahligen Pixelkoordinaten und die Quadrate zwischen ihnen sind die "physikalischen" Pixelelemente. –

5

Sie können mit pRenderTarget->DrawLine(Point2F(100-0.5, 120-0.5), Point2F(300-0.5, 120-0.5), blackbrush, 1) spielen, aber es wird schnell knifflig. Die einfachste ist:

pRenderTarget->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); 

Hoffe, dass es jemand ...

+0

Ich würde nicht empfehlen, das richtige geistige Bild zu vermeiden. Die Minute, die Sie benötigen, um Antialias oder zeichnen Sie eine Form, die nicht eine Achse ausgerichtet Linie ist, wird Ihr Code (auf eine falsche geistige Annahme geschrieben) verwirren. Das ist Standard, das gleiche gilt auch für GDI +. – jnm2

+0

Mit Ausnahme von DX11 sind die Texel-Koordinatenmittelpunktorientiert, so dass es nicht so "Standard" ist, wie es einmal war. –

Verwandte Themen