# Metin Sahneleme

Grafik maceralarınızın bir aşamasında, OpenGL' de metin çizmek isteyeceksiniz. Beklediğinizin aksine, ekranda işlenebilecek basit bir karakter dizesi elde etmek, OpenGL gibi düşük seviyeli bir API ile kolaydır. 128' den fazla farklı aynı boyutta karakter oluşturmayı umursamıyorsanız, muhtemelen çok zor değildir. Her karakterin farklı bir genişliği, yüksekliği ve kenar boşluğu olduğu anda işler zorlaşıyor. Yaşadığınız yere bağlı olarak, 128' den fazla karaktere de ihtiyacınız olabilir ve matematiksel ifadeler veya notalar gibi özel sembolleri ifade etmek istiyorsanız ve metni yukarıdan aşağıya doğru oluşturmaya ne dersiniz? Tüm bu karmaşık metin konularını düşündüğünüzde, bunun muhtemelen OpenGL gibi düşük seviyeli bir API' ye ait olmadığı sizi şaşırtmayacaktır.

OpenGL içinde metin yetenekleri için destek olmadığından, ekranda metin oluşturmak için bir sistem tanımlamak bize kalmış. Metin karakterleri için grafik ilkelleri yoktur, burada yaratıcı olmalıyız. Bazı örnek teknikler şunlardır: `GL_LINES` ile harf şekilleri çizmek, harflerin 3B kafeslerini oluşturmak veya karakter dokularını 3B ortamda 2B dördeylere dönüştürmek.

Çoğu geliştirici, karakter dokularını dördeylere dönüştürmeyi tercih eder. Dokulu dördeyleri tek başına işlemek çok zor olmamalı, ancak ilgili karakter(ler)i bir dokuya almak zor olabilir. Bu bölümde, çeşitli yöntemleri inceleyeceğiz ve FreeType kütüphanesini kullanarak metin oluşturmak için daha gelişmiş ancak esnek bir teknik uygulayacağız.

### Klasik metin oluşturma: bitmap yazı tipleri

İlk günlerde, metin oluşturma, uygulamanız için istediğiniz bir yazı tipini seçmeyi (veya kendiniz oluşturmayı) ve bunları tek bir büyük dokuya yerleştirmek için bu yazı tipinden ilgili tüm karakterleri çıkarmayı içeriyordu. Bitmap yazı tipi olarak adlandırdığımız böyle bir doku, dokunun önceden tanımlanmış bölgelerinde kullanmak istediğimiz tüm karakter sembollerini içerir. Yazı tipinin bu karakter sembolleri Glifler olarak bilinir. Her glif, onlarla ilişkili belirli bir doku koordinatları bölgesine sahiptir. Bir karakter oluşturmak istediğinizde, bitmap yazı tipinin bu bölümünü bir 2D dörtlüye dönüştürerek karşılık gelen glifi seçersiniz.

![](https://2620264560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7cnEMgeCaTVG-cd6Qp%2F-MUc-qNU48KY-YkVgtcl%2F-MUc1WT0gFesQ4TflbBT%2Fbitmapfont.png?alt=media\&token=bd9e29da-e126-4aa5-8621-c10e1521f2d8)

Burada, bir bitmap yazı tipi alarak ve birkaç dördey üzerinde oluşturduğumuz dokudan (doku koordinatlarını dikkatlice seçerek) karşılık gelen glifleri örnekleyerek 'OpenGL' metnini nasıl oluşturacağımızı görebilirsiniz. Harmanlamayı etkinleştirerek ve arka planı şeffaf tutarak, ekrana işlenen sadece bir karakter dizisiyle sonuçlanacağız. Bu özel bit eşlem yazı tipi Codehead'ın bit eşlem [Yazı Tipi Üreteci ](http://www.codehead.co.uk/cbfg/)kullanılarak oluşturuldu.

Bu yaklaşımın çeşitli avantajları ve dezavantajları vardır. Uygulanması nispeten kolaydır ve bitmap yazı tipleri önceden pikselleştirildikelrinde oldukça verimlidirler. Ancak, özellikle de esnek değildir. Farklı bir yazı tipi kullanmak istediğinizde, tam yeni bir bitmap yazı tipini yeniden derlemeniz gerekir ve sistem tek bir çözünürlükle sınırlıdır; yakınlaştırma hızlı bir şekilde pikselli kenarları gösterecektir. Ayrıca, küçük bir karakter kümesiyle sınırlıdır, bu nedenle _Genişletilmiş_ veya _Unicode_ karakterler genellikle söz konusu değildir.

Bu yaklaşım, hızlı olduğu ve herhangi bir platformda çalıştığı için gün içinde oldukça popülerdi (ve halen de öyle), ancak bugün itibariyle daha esnek yaklaşımlar var. Bu yaklaşımlardan biri, Freetype kütüphanesini kullanarak TrueType yazı tiplerini yüklemektir.

### Modern metin sahneleme: FreeType

FreeType, yazı tiplerini yükleyebilen, bunları bit eşlemlere dönüştürebilen ve yazı tipiyle ilgili çeşitli işlemler için destek sağlayan bir yazılım geliştirme kütüphanesidir. Mac OS X, Java, PlayStation, Linux ve Android tarafından kullanılan popüler bir kütüphanedir. Freetype'ı özellikle çekici kılan şey, TrueType yazı tiplerini yükleyebilmesidir.

TrueType yazı tipi, pikseller veya ölçeklenemeyen başka bir çözüm tarafından tanımlanmayan, ancak matematiksel denklemler (Spline kombinasyonları) tarafından tanımlanan karakter glifleri topluluğudur. Vektör görüntülerine benzer şekilde, rasterleştirilmiş yazı tipi görüntüleri, bunları elde etmek istediğiniz tercih edilen yazı tipi yüksekliğine göre prosedürel olarak oluşturulabilir. TrueType yazı tiplerini kullanarak, herhangi bir kalite kaybı olmadan çeşitli boyutlardaki karakter gliflerini kolayca görselleştirebilirsiniz.

FreeType kendi web sitesinden indirilebilir. Hedef platformunuz listeleniyorsa, kitaplığı kendiniz derleyebilir veya önceden derlenmiş kitaplıklarından birini kullanabilirsiniz. Freetype ile bağlantı kurduğunuzdan emin olun.lib ve derleyicinizin başlık dosyalarını nerede bulacağını bildiğinden emin olun.

Ardından uygun başlık dosyalarını ekleyin:

```cpp
#include <ft2build.h>
#include FT_FREETYPE_H 
```

{% hint style="danger" %}
Freetype'ın nasıl geliştirildiğinden dolayı (en azından bu yazı yazıldığı sırada), başlık dosyalarını yeni bir dizine koyamazsınız; bunlar include dizinlerinizin kökünde bulunmalıdır. #İnclude \<FreeType/ft2build gibi FreeType dahil.H> muhtemelen birkaç başlık çakışmasına neden olur.
{% endhint %}

FreeType bu TrueType yazı tiplerini yükler ve her glif için bir bitmap görüntüsü oluşturur ve birkaç metrik hesaplar. Dokular oluşturmak için bu bitmap görüntüleri ayıklayabilir ve yüklenen metrikleri kullanarak her karakter glifini uygun şekilde konumlandırabiliriz.

Bir yazı tipi yüklemek için, tek yapmamız gereken FreeType kütüphanesini başlatmak ve yazı tipini FreeType olarak adlandırmayı sevdiği bir yüz olarak yüklemek. Burada arial'ı yüklüyoruz.Windows/Fonts dizininden kopyalanan ttf TrueType yazı tipi dosyası:

```cpp
FT_Library ft;
if (FT_Init_FreeType(&ft))
{
    std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
    return -1;
}

FT_Face face;
if (FT_New_Face(ft, "fonts/arial.ttf", 0, &face))
{
    std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;  
    return -1;
}
```

Bu FreeType işlevlerinin her biri, bir hata oluştuğunda sıfır olmayan bir tamsayı döndürür.

Yüzü yükledikten sonra, bu yüzden ayıklamak istediğimiz piksel yazı tipi boyutunu tanımlamalıyız:

```cpp
FT_Set_Pixel_Sizes(face, 0, 48);  
```

İşlev, yazı tipinin genişlik ve yükseklik parametrelerini ayarlar. Genişliği 0 olarak ayarlamak, yüzün verilen yüksekliğe göre genişliği dinamik olarak hesaplamasını sağlar.

Bir FreeType yüzü bir glif koleksiyonuna ev sahipliği yapar. FT\_Load\_Char çağırarak bu gliflerden birini aktif glif olarak ayarlayabiliriz. Burada 'X'karakter glifini yüklemeyi seçiyoruz:

```cpp
if (FT_Load_Char(face, 'X', FT_LOAD_RENDER))
{
    std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;  
    return -1;
}
```

Ft\_load\_render'i yükleme bayraklarından biri olarak ayarlayarak, freetype'a face - > glyph - >bitmap aracılığıyla erişebileceğimiz 8 bitlik bir gri tonlamalı bitmap görüntüsü oluşturmasını söyleriz.

Bununla birlikte, FreeType ile yüklediğimiz gliflerin her biri aynı boyuta sahip değildir (bitmap yazı tipleriyle olduğu gibi). FreeType tarafından oluşturulan bitmap görüntüsü, bir karakterin görünür kısmını içerecek kadar büyüktür. Örneğin, nokta karakterinin bitmap görüntüsü '.'x' karakterinin bitmap görüntüsünden çok daha küçüktür. Bu nedenle, FreeType, her karakterin ne kadar büyük olması gerektiğini ve bunları nasıl düzgün bir şekilde konumlandıracağınızı belirten birkaç metriği de yükler. Sonraki, her karakter glifi için hesapladığı tüm metrikleri gösteren Freetype'tan bir görüntüdür:

![](https://2620264560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7cnEMgeCaTVG-cd6Qp%2F-MUc-qNU48KY-YkVgtcl%2F-MUc7bqUm3hVujqPqmoj%2Fglyph.png?alt=media\&token=4e347743-5963-4490-9f4d-571362aaa44f)

Gliflerin her biri yatay bir taban çizgisinde (yatay okla gösterildiği gibi) bulunur; burada bazı Glifler tam olarak bu taban çizgisinin üstünde ('X' gibi) veya baz çizgisinin biraz altında ('g' veya 'p'gibi) bulunur. Bu metrikler, her bir glifi taban çizgisinde düzgün bir şekilde konumlandırmak için kesin ofsetleri, her bir glifin ne kadar büyük olması gerektiğini ve bir sonraki glifi oluşturmak için kaç piksel ilerlememiz gerektiğini tanımlar. Sırada ihtiyacımız olan mülklerin küçük bir listesi var:

* **width**: the width (in pixels) of the bitmap accessed via `face->glyph->bitmap.width`.
* **height**: the height (in pixels) of the bitmap accessed via `face->glyph->bitmap.rows`.
* **bearingX**: the horizontal bearing e.g. the horizontal position (in pixels) of the bitmap relative to the origin accessed via `face->glyph->bitmap_left`.
* **bearingY**: the vertical bearing e.g. the vertical position (in pixels) of the bitmap relative to the baseline accessed via `face->glyph->bitmap_top`.
* **advance**: the horizontal advance e.g. the horizontal distance (in 1/64th pixels) from the origin to the origin of the next glyph. Accessed via `face->glyph->advance.x`.

Bir karakter glifi yükleyebilir, metriklerini alabilir ve ekrana bir karakter oluşturmak istediğimizde bir doku oluşturabiliriz, ancak bunu her karede yapmak verimsiz olacaktır. Oluşturulan verileri uygulamada bir yerde saklamayı ve bir karakter oluşturmak istediğimizde sorgulamayı tercih ederiz. Bir haritada saklayacağımız uygun bir yapı tanımlayacağız:

```cpp
struct Character {
    unsigned int TextureID;  // ID handle of the glyph texture
    glm::ivec2   Size;       // Size of glyph
    glm::ivec2   Bearing;    // Offset from baseline to left/top of glyph
    unsigned int Advance;    // Offset to advance to next glyph
};

std::map<char, Character> Characters;
```

Bu bölüm için, ASCII karakter kümesinin ilk 128 karakteriyle sınırlayarak işleri basit tutacağız. Her karakter için bir doku oluşturuyoruz ve ilgili verilerini karakter haritasına eklediğimiz bir karakter yapısına saklıyoruz. Bu şekilde, her karakteri işlemek için gereken tüm veriler daha sonra kullanılmak üzere saklanır.

```cpp
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
  
for (unsigned char c = 0; c < 128; c++)
{
    // load character glyph 
    if (FT_Load_Char(face, c, FT_LOAD_RENDER))
    {
        std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
        continue;
    }
    // generate texture
    unsigned int texture;
    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(
        GL_TEXTURE_2D,
        0,
        GL_RED,
        face->glyph->bitmap.width,
        face->glyph->bitmap.rows,
        0,
        GL_RED,
        GL_UNSIGNED_BYTE,
        face->glyph->bitmap.buffer
    );
    // set texture options
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // now store character for later use
    Character character = {
        texture, 
        glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
        glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
        face->glyph->advance.x
    };
    Characters.insert(std::pair<char, Character>(c, character));
}
```

For döngüsünde, ASCII kümesinin tüm 128 karakterini listeliyoruz ve karşılık gelen karakter gliflerini alıyoruz. Her karakter için: bir doku oluşturuyoruz, seçeneklerini belirliyoruz ve metriklerini saklıyoruz. Burada dikkat edilmesi gereken ilginç olan şey, gl\_red'i doku iç biçimi ve biçim argümanları olarak kullanmamızdır. Gliften oluşturulan bit eşlem, her rengin tek bir baytla temsil edildiği gri tonlamalı 8 bitlik bir görüntüdür. Bu nedenle, bitmap arabelleğinin her baytını dokunun tek renk değeri olarak saklamak istiyoruz. Bunu, her baytın doku renginin kırmızı bileşenine (renk vektörünün ilk baytı) karşılık geldiği bir doku oluşturarak gerçekleştiririz. Bir dokunun renklerini temsil etmek için tek bir bayt kullanırsak, OpenGL kısıtlamasına dikkat etmemiz gerekir:

```cpp
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);   
```

OpenGL, tüm dokuların 4 baytlık bir hizalamaya sahip olmasını gerektirir, örneğin boyutları her zaman 4 baytlık bir kattır. Genellikle bu bir sorun olmayacaktır, çünkü çoğu doku 4'ün katları olan bir genişliğe sahiptir ve / veya piksel başına 4 bayt kullanır, ancak şimdi piksel başına sadece bir bayt kullandığımızdan, doku herhangi bir olası genişliğe sahip olabilir. Açma hizalamasını 1 olarak ayarlayarak, hizalama sorunları olmadığından emin oluruz (segmentasyon hatalarına neden olabilir).

Glifleri işlemeyi bitirdikten sonra FreeType kaynaklarını temizlediğinizden emin olun:

```cpp
FT_Done_Face(face);
FT_Done_FreeType(ft);
```

#### Tonlandırıcılar

Glifleri oluşturmak için aşağıdaki köşe gölgelendiricisini kullanacağız:

```c
#version 330 core
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
out vec2 TexCoords;

uniform mat4 projection;

void main()
{
    gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
    TexCoords = vertex.zw;
}  
```

Hem konum hem de doku koordinat verilerini tek bir vec4'te birleştiriyoruz. Köşe gölgelendirici koordinatları bir projeksiyon matrisi ile çarpar ve doku koordinatlarını parça gölgelendiricisine iletir:

```c
#version 330 core
in vec2 TexCoords;
out vec4 color;

uniform sampler2D text;
uniform vec3 textColor;

void main()
{    
    vec4 sampled = vec4(1.0, 1.0, 1.0, texture(text, TexCoords).r);
    color = vec4(textColor, 1.0) * sampled;
}
```

Parça gölgelendirici iki üniforma alır: biri glifin tek renkli bitmap görüntüsüdür ve diğeri metnin son rengini ayarlamak için bir renk üniformasıdır. Önce bitmap dokusunun renk değerini örnekliyoruz. Doku verileri sadece kırmızı bileşeninde saklandığından, doku r bileşenini örneklenmiş alfa değeri olarak örnekleriz. Çıktı renginin alfa değerini değiştirerek, ortaya çıkan piksel tüm glifin arka plan renkleri için saydam ve gerçek karakter pikselleri için saydam olmayacaktır. Ayrıca, metin rengini değiştirmek için RGB renklerini textColor uniform ile çarpıyoruz.

Bunun işe yaraması için harmanlamayı etkinleştirmemiz gerekiyor:

```cpp
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  
```

Projeksiyon matrisi için bir ortografik projeksiyon matrisi kullanacağız. Metni oluşturmak için (genellikle) perspektife ihtiyacımız yoktur ve ortografik bir projeksiyon matrisi kullanmak, aşağıdaki gibi yapılandırırsak, ekran koordinatlarındaki tüm köşe koordinatlarını belirtmemize izin verir:

```cpp
glm::mat4 projection = glm::ortho(0.0f, 800.0f, 0.0f, 600.0f);
```

Projeksiyon matrisinin alt parametresini 0.0 f'ye ve üst parametresini pencerenin yüksekliğine eşit olarak ayarladık. Sonuç, ekranın alt kısmından (0.0 f) ekranın üst kısmına (600.0 f) kadar değişen y değerleriyle koordinatları belirtmemizdir. Bu, noktanın (0.0, 0.0) şimdi sol alt köşeye karşılık geldiği anlamına gelir.

Son olarak, dörtlüleri oluşturmak için bir VBO ve VAO oluşturmaktır. Şimdilik, vbo'yu başlatırken yeterli bellek ayırıyoruz, böylece karakterleri oluştururken VBO'NUN belleğini daha sonra güncelleyebiliriz:

```cpp
unsigned int VAO, VBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0); 
```

2D dörtlü, her biri 4 şamandıranın 6 köşesini gerektirir, bu yüzden 6 \* 4 şamandıra belleği ayırırız. VBO'NUN belleğinin içeriğini oldukça sık güncelleyeceğimiz için belleği GL\_DYNAMİC\_DRAW ile ayıracağız.

#### Metin satırı sahneleme

Bir karakteri işlemek için, karakter haritasının karşılık gelen karakter yapısını çıkarırız ve karakterin metriklerini kullanarak dörtlü boyutlarını hesaplarız. Dörtlü hesaplanan boyutlarla, glBufferSubData kullanarak VBO tarafından yönetilen belleğin içeriğini güncellemek için kullandığımız 6 köşe kümesini dinamik olarak oluştururuz.

Bir karakter dizisi oluşturan RenderText adlı bir işlev oluşturuyoruz:

```cpp
void RenderText(Shader &s, std::string text, float x, float y, float scale, glm::vec3 color)
{
    // activate corresponding render state	
    s.Use();
    glUniform3f(glGetUniformLocation(s.Program, "textColor"), color.x, color.y, color.z);
    glActiveTexture(GL_TEXTURE0);
    glBindVertexArray(VAO);

    // iterate through all characters
    std::string::const_iterator c;
    for (c = text.begin(); c != text.end(); c++)
    {
        Character ch = Characters[*c];

        float xpos = x + ch.Bearing.x * scale;
        float ypos = y - (ch.Size.y - ch.Bearing.y) * scale;

        float w = ch.Size.x * scale;
        float h = ch.Size.y * scale;
        // update VBO for each character
        float vertices[6][4] = {
            { xpos,     ypos + h,   0.0f, 0.0f },            
            { xpos,     ypos,       0.0f, 1.0f },
            { xpos + w, ypos,       1.0f, 1.0f },

            { xpos,     ypos + h,   0.0f, 0.0f },
            { xpos + w, ypos,       1.0f, 1.0f },
            { xpos + w, ypos + h,   1.0f, 0.0f }           
        };
        // render glyph texture over quad
        glBindTexture(GL_TEXTURE_2D, ch.textureID);
        // update content of VBO memory
        glBindBuffer(GL_ARRAY_BUFFER, VBO);
        glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); 
        glBindBuffer(GL_ARRAY_BUFFER, 0);
        // render quad
        glDrawArrays(GL_TRIANGLES, 0, 6);
        // now advance cursors for next glyph (note that advance is number of 1/64 pixels)
        x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
    }
    glBindVertexArray(0);
    glBindTexture(GL_TEXTURE_2D, 0);
}
```

Fonksiyonun içeriğinin çoğu nispeten kendi kendini açıklayıcı olmalıdır: önce quad'in başlangıç konumunu (xpos ve ypos olarak) ve quad'in boyutunu (w ve h olarak) hesaplarız ve 2D quad'i oluşturmak için 6 köşe kümesi oluştururuz; her metriği ölçeğe göre ölçeklendirdiğimizi unutmayın. Daha sonra VBO'NUN içeriğini güncelliyoruz ve dörtlüyü oluşturuyoruz.

Bununla birlikte, aşağıdaki kod satırı biraz daha dikkat gerektirir:

```
float ypos = y - (ch.Size.y - ch.Bearing.y);  
```

Bazı karakterler ('p' veya 'g' gibi) taban çizgisinin biraz altında işlenir, bu nedenle dörtlü de Rendertext'in y değerinin biraz altına yerleştirilmelidir. Ypo'ları taban çizgisinin altında dengelemek için ihtiyacımız olan tam miktar, glif metriklerinden anlaşılabilir:

![](https://2620264560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7cnEMgeCaTVG-cd6Qp%2F-MUc-qNU48KY-YkVgtcl%2F-MUcAIFHBNqv2T1I0ETj%2Fglyph_offset.png?alt=media\&token=af9d2fb1-f697-47d4-a51a-24d1c1dbec4d)

Bu mesafeyi hesaplamak için, örneğin ofset, bir glifin taban çizgisinin altına uzandığı mesafeyi bulmamız gerekir; bu mesafe kırmızı okla gösterilir. Glif metriklerinden de görebileceğiniz gibi, bu vektörün uzunluğunu, glifin (bitmap) yüksekliğinden ayı çıkararak hesaplayabiliriz. Bu değer daha sonra taban çizgisinde ('X' gibi) kalan karakterler için 0.0 ve taban çizgisinin biraz altında ('g' veya 'j'gibi) bulunan karakterler için pozitiftir.

Her şeyi doğru yaptıysanız, şimdi aşağıdaki ifadelerle metin dizelerini başarılı bir şekilde görselleştirebilmelisiniz:

```cpp
RenderText(shader, "This is sample text", 25.0f, 25.0f, 1.0f, glm::vec3(0.5, 0.8f, 0.2f));
RenderText(shader, "(C) LearnOpenGL.com", 540.0f, 570.0f, 0.5f, glm::vec3(0.3, 0.7f, 0.9f));
```

Bu daha sonra aşağıdaki resme benzer görünmelidir:

![](https://2620264560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7cnEMgeCaTVG-cd6Qp%2F-MUc-qNU48KY-YkVgtcl%2F-MUcAycObtKUt004YTEb%2Ftext_rendering.png?alt=media\&token=7212dfe9-3239-4dc4-8dfc-aea45d519eb2)

Bu örneğin kodunu [burada ](https://learnopengl.com/code_viewer_gh.php?code=src/7.in_practice/2.text_rendering/text_rendering.cpp)bulabilirsiniz.

Dörtgen köşelerini nasıl hesapladığımıza dair bir fikir vermek ve gerçek işlenmiş dörtgenlerin neye benzediğini görmek için harmanlamayı devre dışı bırakabiliriz:

![](https://2620264560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M7cnEMgeCaTVG-cd6Qp%2F-MUc-qNU48KY-YkVgtcl%2F-MUcB4nKGuqJYrFBfJ7c%2Ftext_rendering_quads.png?alt=media\&token=d06c507b-9579-40a8-9888-a8746b21d2fc)

Burada, 'P' veya ' ( ' ) gibi gliflere karşılık gelen dörtlülerin aşağı doğru kayarken, (hayali) taban çizgisine dayanan dörtlülerin çoğunu açıkça görebilirsiniz.

### Daha da ileri

Bu bölümde Freetype kitaplığını kullanarak TrueType yazı tipleri ile bir metin işleme tekniği gösterilmiştir. Bu yaklaşım esnek, ölçeklenebilir ve birçok karakter kodlaması ile çalışır. Bununla birlikte, her glif için dokular oluşturduğumuzda ve oluşturduğumuzda, bu yaklaşım uygulamanız için aşırı olacaktır. Performans açısından, bitmap yazı tipleri tercih edilir, çünkü tüm gliflerimiz için sadece bir dokuya ihtiyacımız vardır. En iyi yaklaşım, freetype ile yüklenen tüm karakter gliflerini içeren bir bitmap yazı tipi dokusunu dinamik olarak oluşturarak iki yaklaşımı birleştirmek olacaktır. Bu, oluşturucuyu önemli miktarda doku anahtarından kurtarır ve her glifin ne kadar sıkı bir şekilde paketlendiğine bağlı olarak, bazı performanslardan tasarruf edebilir.

FreeType yazı tipi bit eşlemleri ile ilgili bir başka sorun, glif dokularının sabit bir yazı tipi boyutu ile depolanmasıdır, bu nedenle önemli miktarda Ölçekleme pürüzlü kenarlara neden olabilir. Ayrıca, gliflere uygulanan rotasyonlar bulanık görünmelerine neden olur. Bu, gerçek rasterleştirilmiş piksel renklerini depolamak yerine, piksel başına en yakın glif anahatlarına olan mesafeyi depolayarak hafifletilebilir. Bu tekniğe imzalı mesafe alanı yazı tipleri denir ve Valve birkaç yıl önce 3D render uygulamaları için şaşırtıcı derecede iyi çalışan bu tekniğin uygulanması hakkında bir [makale ](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf)yayınladı.

### Ek Okuma

[Tasarımcılar için 70'den fazla en iyi ücretsiz yazı tipi:](https://www.websiteplanet.com/blog/best-free-fonts/) kişisel veya ticari kullanım için projenizde kullanılacak büyük bir yazı tipi grubunun özetlenmiş listesi.

Orijinal Kaynak: [Text Rendering](https://learnopengl.com/In-Practice/Text-Rendering)

Çeviri: [Nezihe Sözen](https://github.com/NeziheSozen)
