2013-09-01 5 views
17

Istnieje wiele pytań dotyczących renderowania czcionek OpenGL, wiele z nich jest zadowolonych z atlasów tekstur (szybko, ale źle) lub tekstur tekstur (tylko tekst stały).Renderowanie tekstu/czcionki w OpenGLES 2 (iOS - CoreText?) - opcje i najlepsza praktyka?

Jednak te podejścia są słabe i wydają się być przestarzałe (a co z używaniem shaderów do robienia tego lepiej/szybciej?). OpenGL 4.1 jest to doskonałe pytanie, patrząc na "co należy użyć dzisiaj?":

What is state-of-the-art for text rendering in OpenGL as of version 4.1?

Więc co powinniśmy używać 2 dzisiaj na iOS GL ES?

Jestem rozczarowany, że wydaje się, że nie ma rozwiązania open source (lub nawet komercyjnego). Wiem, że wiele drużyn łapie to i spędza tygodnie czasu na dev wymyślaniu tego koła, stopniowo ucząc się, jak kern i przestrzeń itd. (Ugh) - ale musi istnieć lepszy sposób niż ponowne pisanie całych "czcionek" od zera?


O ile widzę, istnieją dwie części to:

  1. jaki sposób renderowania tekstu przy użyciu czcionek?
  2. Jak wyświetlić dane wyjściowe?

Za 1 (jak renderować), Apple zapewnia WIELU sposobów na uzyskanie "poprawnego" renderowanego wyjścia - ale te "łatwe" nie obsługują OpenGL (być może niektóre z nich to robią - np. Czy istnieje prosty sposób mapowania wyjścia CoreText do OpenGL?).

Dla 2 (jak do wyświetlania), mamy shadery, mamy VBOs mamy glifów-faktur, mamy odnośników-faktur i innych tecniques (np OpenGL 4.1 rzeczy związane powyżej?)

Tutaj są dwa wspólne OpenGL zbliża znam:

  1. texture atlas (wykonywali wszystkie glify raz, a następnie renderowanie 1 x teksturą quad na znak, ze wspólnego tekstury)
    1. to jest złe, chyba że” ponownie używają "czcionki bitmapowej" z lat 80. (a nawet wtedy: atlas tekstury wymaga więcej pracy, niż mogłoby się wydawać, jeśli potrzebujesz jej do nietrywialnych czcionek). farbowanie, waga, atlasy itp texture fail)
  2. Stały ciąg (użyj dowolnej klasy firmy Apple do renderowania poprawnie, a następnie screenshot tworzenie kopii obrazu-dane i przesłać jako tekstury)
    1. w kategoriach ludzkich, to jest szybkie. W renderowaniu ramek jest to bardzo, bardzo powolne.Jeśli zrobisz to z dużo zmieniającym tekst, współczynnik rama przechodzi przez podłogę
    2. Technicznie, to w większości poprawne (nie do końca: można stracić trochę informacji w ten sposób), ale niezwykle nieefektywne

I Wcześniej też widział, ale słyszał zarówno dobre i złe rzeczy o:

  1. Wyobraźnia/PowerVR «Print3D» (Link złamane) (od facetów które produkują GPU ale ich witryna została przeniesiona/usunął stronę renderowania tekstu!)
  2. FreeType (wymaga wstępnego przetwarzania, interpretacji, dużej ilości kodu, dodatkowych bibliotek?)
  3. ... i/lub FTGL http://sourceforge.net/projects/ftgl/ (pogłoski: wolne? powozik? nie aktualizowana od dłuższego czasu?)
  4. Font-Stash http://digestingduck.blogspot.co.uk/2009/08/font-stash.html (wysoka jakość, ale bardzo wolno?)
  5. 1.

obrębie własnych OS/standardowych bibliotek Apple'a, wiem z kilku źródeł renderowania tekstu. NB: Użyłem większość z nich szczegółowo na 2D renderowania projektów, moje wypowiedzi na temat ich wyprowadzanie inny renderowania są oparte na bezpośrednim doświadczeniu

  1. CoreGraphics z NSString
    1. najprostszych wszystko: render „w CGRect”
    2. wydają się być nieco szybsza wersja«stałe string»ludzie podchodzą polecam (choć można się spodziewać, że będzie tak samo)
  2. UILabel i UITextArea ze zwykłym tekstem
    1. Uwaga: NIE są takie same! Nieznaczne różnice w jaki czynią one tekst smae
  3. NSAttributedString, świadczonych jednemu z powyższym
    1. jeszcze: renderuje różnie (różnice znam są dość subtelne i klasyfikowane jako „pluskwy”, różne SO pytania o tym)
  4. CATextLayer
    1. hybryda pomiędzy czcionkami iOS i starych C renderowania. Wykorzystuje "nie do końca" toll-free-zmostkowane CFFont/UIFont, który wykazuje pewne różnice bardziej renderowania/obcość
  5. CoreText
    1. ... najlepsze rozwiązanie? Ale bestia z własnej ...
+0

Czy dokonano postępu? podążam twoim śladem. ale ... –

+3

Mam to działa, z kilkoma błędami. Obsługuję niektóre bardzo fantazyjne czcionki i glify wieloliterowe, ale wciąż mam kilka drobnych błędów. Zapisuję je jako posty na blogu krok po kroku, ale część z tekstem nie będzie gotowa do świąt Bożego Narodzenia 2013 lub wiosny 2014, przepraszam. Blog pod adresem http://t-machine.org/index.php/2013/09/08/opengl-es-2-basic-drawing/ – Adam

+0

Tak, chętnie usłyszę o twoim układzie tekstu. Czy do tej pory działało tak dobrze, jak powinno? – kamziro

Odpowiedz

7

zrobiłem kilka eksperymentów, i wydaje się, że CoreText może zrobić idealne rozwiązanie w połączeniu z atlasem faktura i podpisana różnicy tekstur zaworu (który może przekształcić glif z mapy bitowej w niezależną od rozdzielczości teksturę w wysokiej rozdzielczości).

...ale nie działam jeszcze, wciąż eksperymentuję.


UPDATE: docs Apple twierdzi, że daje dostęp do wszystkiego z wyjątkiem końcowego szczegółowo: który glif + układ glifów do renderowania (można dostać układ linii, a liczba glifów, ale nie sam glif, według dokumentów). Bez wyraźnego powodu, ten rdzeń informacji jest prawdopodobnie nieobecny w CoreText (jeśli tak, to sprawia, że ​​CT jest prawie bezwartościowy) Wciąż poluję, aby sprawdzić, czy mogę znaleźć sposób na uzyskanie aktualnych danych glpyhs + per-glyph).


Update2: mam teraz ten działa poprawnie z CT Apple (ale nie różni-faktur), ale kończy się jak 3 plików klas, 10 struktur danych, około 300 linii kodu, plus kod OpenGL do renderowania to. Zbyt wiele dla SO odpowiedzieć :(

Krótka odpowiedź brzmi: tak., Można to zrobić, i to działa, jeśli:

  1. Tworzenie CTFrameSetter
  2. Tworzenie CTFrame dla teoretycznego ramy 2D
  3. Tworzenie CGContext że będziesz konwertować do GL tekstury
  4. przejść glifów-by-glifów, pozwalając Apple czynią z CGContext
  5. każdym razem Jabłko renderuje glif, obliczyć boundingbox (to jest HARD), d zapisz go gdzieś
  6. I zapisz unikatowy identyfikator glifu (będzie to inne dla np. „O”, „f” i „o” (jeden glif!))
  7. Wreszcie wysłać CGContext do GL jako tekstury

Podczas renderowania, należy użyć listy glifów identyfikatorów że Firma Apple stworzyła i dla każdego używa zapisanych informacji i tekstury, aby renderować kwadraty z teksturami, które wyciągają pojedyncze glify z przesłanej tekstury.

To działa, jest szybki, działa ze wszystkimi czcionkami, robi wszystko układ czcionki i kerningiem poprawne, itp

+0

Poszukuję czegoś takiego, jeśli nie masz nic przeciwko temu, aby go pozyskać, brzmi to jak świetny projekt Github! – David

+0

@David sorry, no - to kosztowało mnie ogromne ilości nieodpłatnego czasu (więcej niż miesiąc pracy w pełnym wymiarze czasu) Jeśli wydam cokolwiek, będzie to reklama komercyjna. Bardziej prawdopodobne jest, że skonsultuję się z konkretnymi firmami/projektami - tańsze dla nich i mniej kłopotliwe dla mnie (nie chcę prowadzić strona internetowa/firma/etc)). Przepraszam! – Adam

+0

W porządku, nie ma problemu! Dla każdego, kto szuka kierunku, myślę, że moja firma może zbudować nasz system z FreeType, co wydaje się, że to nie będzie zbyt dużo pracy i jest platformą. – David

0

1.

Tworzenie dowolny ciąg przez NSMutableAttributedString.

let mabstring = NSMutableAttributedString(string: "This is a test of characterAttribute.") 
mabstring.beginEditing() 
var matrix = CGAffineTransform(rotationAngle: CGFloat(GLKMathDegreesToRadians(0))) 
let font = CTFontCreateWithName("Georgia" as CFString?, 40, &matrix) 
mabstring.addAttribute(kCTFontAttributeName as String, value: font, range: NSRange(location: 0, length: 4)) 
var number: Int8 = 2 
let kdl = CFNumberCreate(kCFAllocatorDefault, .sInt8Type, &number)! 
mabstring.addAttribute(kCTStrokeWidthAttributeName as String, value: kdl, range: NSRange(location: 0, length: mabstring.length)) 
mabstring.endEditing() 

2.

Tworzenie CTFrame. The rect obliczyć z mabstring przez CoreText. CTFramesetterSuggestFrameSizeWithConstraints

let framesetter = CTFramesetterCreateWithAttributedString(mabstring) 
let path = CGMutablePath() 
path.addRect(rect) 
let frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, nil) 

3.

Tworzenie kontekstu bitmapy.

let imageWidth = Int(rect.width) 
let imageHeight = Int(rect.height) 
var rawData = [UInt8](repeating: 0, count: Int(imageWidth * imageHeight * 4)) 
let bitmapInfo = CGBitmapInfo(rawValue: CGBitmapInfo.byteOrder32Big.rawValue | CGImageAlphaInfo.premultipliedLast.rawValue) 
let rgbColorSpace = CGColorSpaceCreateDeviceRGB() 
let bitsPerComponent = 8 
let bytesPerRow = Int(rect.width) * 4 
let context = CGContext(data: &rawData, width: imageWidth, height: imageHeight, bitsPerComponent: bitsPerComponent, bytesPerRow: bytesPerRow, space: rgbColorSpace, bitmapInfo: bitmapInfo.rawValue)! 

4.

Draw CTFrame w kontekście bitmapy.

CTFrameDraw(frame, context) 

Teraz mamy surowe dane pikselowe rawData. Utwórz OpenGL Texture, MTLTexture, z rawData jest w porządku.


Przykład,

OpenGL Tekstura: Convert an UIImage in a texture

konfiguracji swojej Tekstura:

GLuint textureID;  
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
glGenTextures(1, &textureID); 

glBindTexture(GL_TEXTURE_2D, textureID); 
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData); 

,

//to MTLTexture 
let textureDescriptor = MTLTextureDescriptor.texture2DDescriptor(pixelFormat: .rgba8Unorm, width: Int(imageWidth), height: Int(imageHeight), mipmapped: true) 
let device = MTLCreateSystemDefaultDevice()! 
let texture = device.makeTexture(descriptor: textureDescriptor) 
let region = MTLRegionMake2D(0, 0, Int(imageWidth), Int(imageHeight)) 
texture.replace(region: region, mipmapLevel: 0, withBytes: &rawData, bytesPerRow: imageRef.bytesPerRow) 

,

//to UIImage 
    let providerRef = CGDataProvider(data: NSData(bytes: &rawData, length: rawData.count * MemoryLayout.size(ofValue: UInt8(0)))) 
    let renderingIntent = CGColorRenderingIntent.defaultIntent 
    let imageRef = CGImage(width: imageWidth, height: imageHeight, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: bytesPerRow, space: rgbColorSpace, bitmapInfo: bitmapInfo, provider: providerRef!, decode: nil, shouldInterpolate: false, intent: renderingIntent)! 
    let image = UIImage.init(cgImage: imageRef) 
1

Znam ten post jest stary, ale natknąłem się na niego, starając się zrobić to dokładnie w mojej aplikacji. W moich poszukiwaniach natknąłem tego projektu próbki

http://metalbyexample.com/rendering-text-in-metal-with-signed-distance-fields/

Jest to doskonała realizacja CoreText z OpenGL przy użyciu technik tekstury atlasing i podpisane boiska. Pomogło mi to osiągnąć pożądane rezultaty. Mam nadzieję, że to pomoże komuś innemu.

Powiązane problemy