D3D11 Font Rendering
-
Oh, d.h. du verwendest die Textur nur für das Alpha und setzt die Farbe auf eine Konstante? Erklär uns vielleicht doch nochmal, wie genau du deine Texcoords berechnest...
-
Irgendwie habe ich das Gefühl gleich eins auf den Deckel zu kriegen für irgendeinen dummen Fehler, aber dafür bin ich ja hier fürchte ich.
Beim Zeichnen teile ich die Bildschirmkoordinaten im Shader durch die Hälfte der Bildschirmgröße. (So kann ich immer gleich viele Pixel zeichnen, auch wenn das Fenster vergrößter/kleinert wird.)std::vector<float> generate_coords(const std::string& s, const glyph_map& glyphs, float /* font_height */, float shift, float tex_width, float tex_height) { std::vector<float> coords; shift = 0.f; float xbase = 0.f; for (const auto c : s) { auto found = glyphs.find(static_cast<std::uint8_t>(c)); if (found != glyphs.end()) { const glyph& g = found->second; const float screen_left = xbase + g.xoffset; const float screen_top = g.yoffset; const float screen_right = screen_left + g.width; const float screen_bottom = screen_top + g.height; const float tex_left = (g.x + shift) / tex_width; const float tex_top = g.y / tex_height; const float tex_right = (g.x + g.width + shift) / tex_width; const float tex_bottom = (g.y + g.height) / tex_height; xbase += g.xadvance; coords.push_back(screen_left); coords.push_back(screen_top); coords.push_back(tex_left); coords.push_back(tex_top); coords.push_back(screen_left); coords.push_back(screen_bottom); coords.push_back(tex_left); coords.push_back(tex_bottom); coords.push_back(screen_right); coords.push_back(screen_top); coords.push_back(tex_right); coords.push_back(tex_top); coords.push_back(screen_left); coords.push_back(screen_bottom); coords.push_back(tex_left); coords.push_back(tex_bottom); coords.push_back(screen_right); coords.push_back(screen_top); coords.push_back(tex_right); coords.push_back(tex_top); coords.push_back(screen_right); coords.push_back(screen_bottom); coords.push_back(tex_right); coords.push_back(tex_bottom); } } return coords; }
-
cooky451 schrieb:
Beim Zeichnen teile ich die Bildschirmkoordinaten im Shader durch die Hälfte der Bildschirmgröße. (So kann ich immer gleich viele Pixel zeichnen, auch wenn das Fenster vergrößter/kleinert wird.)
Du meinst die Größe des BackBuffers? Ein Fehler, der gern gemacht wird, ist auf den Unterschied zwischen den äußeren Abmessungen eines Fenster und der Größe der Client Area zu vergessen, was dann dazu führt, dass der BackBuffer in das Fenster gestaucht wird...
-
Ich fange WM_SIZE ab und resize den BackBuffer daraufhin. Das sollte recht präzise die Client-Area sein. (Ich bekomme auch genau 1600x900 beim ersten WM_SIZE, und ja, ich verwende AdjustWindowRect. ;))
-
Hm ok, klingt eigentlich gut. Schalt vielleicht einfach mal um auf Point Sampling statt bilinearem Filtering und schau, ob es dann besser aussieht...
-
Es sieht tatsächlich deutlich besser aus , weil die Buchstaben jetzt nicht mehr so "verwaschen" sind. Am Ausrufezeichen fehlen aber nach wie vor die gleichen Teile, daran lag's also nicht. Bei kleineren Fonts fällt das noch mehr auf:
Original: http://imgur.com/2Gqvvqy
Gerendert: http://imgur.com/AUWAYwi
Hier sieht man auch, dass teilweise oben (und unten?) Pixel abgeschnitten sind. Ich habe schon mal versucht etwas zu tricksen und einfach 1-4 Pixel auf die normalen Koordinaten zu addieren, aber das hilft nicht wirklich was interessanterweise.
-
So lang was mit bilinearem Filtering "verwaschen" aussieht, stimmt was am Pixel <-> Texel Mapping nicht. Ich mach mir das selbst immer zunutze, um zu checken, ob ich mich nicht verrechnet hab. Denn sobald Texelcenter exakt auf Pixelcenter mappen, muss bilineares Filtering praktisch aufs Bit genau exakt das gleiche Ergebnis liefern wie Point Sampling..
-
Hm, vielleicht, ich probiere das noch mal, aber wenn ich so darüber nachdenke kann es eigentlich nicht an den Koordinaten liegen, denn ich bekomme ja exakt die gleichen Artefakte wenn ich einfach die ganze Textur auf einmal zeichne. Das muss ja schon eigentlich schon irgendwas mit dem Blending zu tun haben. Sind 8 Alpha Bits vielleicht irgendwie nicht genau genug oder so?
-
Wie lädst du die Textur? Kanns sein, dass sie auf eine 2er Potenz gepadded wird oder sowas und du das nicht berücksichtigst?
-
Hm.. nicht wirklich.., es gibt zwar eine "conversion" zwischen char und uint8_t, aber das passiert hinterm memcpy, da sollte eigentlich nichts geändert werden. Komisch, komisch.
-
Ich seh zwar auf die Schnelle kein Problem, aber evtl. stimmt bei deiner Berechnung irgendwo was nicht von wegen x + width bzw. y + height ist nicht der letzte Pixel, sondern der erste Pixel nach dem letzten. Denk dir das vielleicht nochmal genau durch, auch ob Breite und Höhe der Textur bzw. des Viewport die richtige Normalisierung bringen...
-
Was uns wieder dazu führt dass die exakt identischen (!) Artefakte auftauchen wenn ich die Textur als ganzes zeichne. Hier mal Bilder:
Original: http://imgur.com/rOM8Dl2
Gerendert: http://imgur.com/ownboyI
-
Und dabei setzt du die Texcoords manuell direkt auf und dein Quad liegt an ganzzahligen Koordinaten und hat exakt die Abmessungen der Textur!?
-
Jap, ich rendere exakt mit
float vertices []= { 0.f, 0.f, 0.f, 0.f, width, 0.f, 1.f, 0.f, 0.f, height, 0.f, 1.f, width, height, 1.f, 1.f, };
Edit: Aha, wenn ich das hier im Pixel Shader mache
return float4(tex.Sample(samp, input.tc).a, 0.0, 0.0, 1.0);
verschwinden die Artefakte! Es muss also irgendwie am Alpha-Blending liegen.
-
Achja, aber dein BackBuffer hatte ja kein SRGB Format. Mach deine SwapChain mal mit DXGI_FORMAT_R8G8B8A8_UNORM_SRGB...
-
Scheint nichts zu ändern. (Siehe Edit von meinem letzten Beitrag)
-
Ich nehme an, du renderst direkt in den BackBuffer? Hast du es auch an allen relevanten Stellen geändert (CreateSwapChain als auch ResizeBuffers)?
-
Ja, wie gesagt, siehe mein edit. Ich sehe nicht mehr wirklich wie es etwas anderes als das Alpha-Blending sein kann, wenn die Artefakte verschwinden sobald ich den Wert direkt als Farbe nehme.
Edit: Man könnte jetzt auch denken das hier sollte funktionierenfloat4 ps_main(ps_input input) : SV_TARGET { float a = tex.Sample(samp, input.tc).a; return float4(color.r * a, color.g * a, color.b * a, color.a); }
Und ja, die Artefakte verschwinden, aber letztlich ist das leider unbrauchbar, weil die Quads überlappen.
-
blend_desc.AlphaToCoverageEnable = FALSE;
Fixed
-
lol, ok, das hätt mir auch auffallen können, damit ist alles klar