This shows you the differences between two versions of the page.
|
egc:laboratoare:bonusrendertext [2019/11/25 17:29] victor.asavei [Redare text] |
egc:laboratoare:bonusrendertext [2019/12/03 07:56] (current) alexandru.gradinaru |
||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ===== Laborator bonus ===== | + | ===== Resurse bonus ===== |
| ==== Redare text în OpenGL ==== | ==== Redare text în OpenGL ==== | ||
| Line 18: | Line 18: | ||
| Cea de-a doua variantă (și cea care este folosită și pentru implementare în continuarea laboratorului) este ca pentru fiecare caracter/simbol să se creeze câte o textură individuală ce va avea dimensiunea (lătime/înălțime) caracterului/simbolului. Această metodă permite o mai bună flexibilitate în manipularea fiecărui caracter/simbol în parte pentru poziționarea/scalarea acestuia. | Cea de-a doua variantă (și cea care este folosită și pentru implementare în continuarea laboratorului) este ca pentru fiecare caracter/simbol să se creeze câte o textură individuală ce va avea dimensiunea (lătime/înălțime) caracterului/simbolului. Această metodă permite o mai bună flexibilitate în manipularea fiecărui caracter/simbol în parte pentru poziționarea/scalarea acestuia. | ||
| - | Pentru a obtine textura pentru fiecare caracter/simbol necesar dintr-un font dat, a fost folosită biblioteca //FreeType//. | + | Pentru a obtine imaginea (bitmapul) pentru fiecare caracter/simbol necesar dintr-un font dat, a fost folosită biblioteca //FreeType//. |
| ==== Utilizare FreeType ==== | ==== Utilizare FreeType ==== | ||
| Line 87: | Line 87: | ||
| * Vertex shader | * Vertex shader | ||
| <code glsl> | <code glsl> | ||
| - | layout(location = 0) in vec4 vertex; // <vec2 pos, vec2 tex> | + | layout(location = 0) in vec4 vertex; // <x,y,u,v> |
| out vec2 TexCoords; | out vec2 TexCoords; | ||
| Line 137: | Line 137: | ||
| </code> | </code> | ||
| - | ==== Redarea unei linii de text ==== | + | ==== Redarea textului ==== |
| + | Pentru redarea unei linii de text se va folosi functia | ||
| + | <code glsl> | ||
| + | void RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color) | ||
| + | </code> | ||
| + | unde: | ||
| + | * x,y: coordonatele (x,y) din fereastra de afișare de unde va fi afișată linia de text ( 0,0 corespunde colțului stânga sus al ecranului) | ||
| + | * scale: factor de scalare pentru text (dimensiunea font-ului ales la încărcare va fi înmulțită cu acest factor) | ||
| + | * color: culoarea textului | ||
| + | |||
| + | Întreaga funcție: | ||
| + | |||
| + | <code glsl> | ||
| + | void TextRenderer::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color) | ||
| + | { | ||
| + | // Activate corresponding render state | ||
| + | //this->TextShader.Use(); | ||
| + | if (this->TextShader) | ||
| + | { | ||
| + | glUseProgram(this->TextShader->program); | ||
| + | CheckOpenGLError(); | ||
| + | } | ||
| + | |||
| + | int loc_text_color = glGetUniformLocation(this->TextShader->program, "textColor"); | ||
| + | glUniform3f(loc_text_color, color.r, color.g, color.b); | ||
| + | //this->TextShader.SetVector3f("textColor", color); | ||
| + | glActiveTexture(GL_TEXTURE0); | ||
| + | glBindVertexArray(this->VAO); | ||
| + | |||
| + | // Iterate through all characters | ||
| + | std::string::const_iterator c; | ||
| + | for (c = text.begin(); c != text.end(); c++) | ||
| + | { | ||
| + | Character ch = Characters[*c]; | ||
| + | |||
| + | GLfloat xpos = x + ch.Bearing.x * scale; | ||
| + | GLfloat ypos = y + (this->Characters['H'].Bearing.y - ch.Bearing.y) * scale; | ||
| + | |||
| + | GLfloat w = ch.Size.x * scale; | ||
| + | GLfloat h = ch.Size.y * scale; | ||
| + | // Update VBO for each character | ||
| + | GLfloat vertices[6][4] = { | ||
| + | { xpos, ypos + h, 0.0, 1.0 }, | ||
| + | { xpos + w, ypos, 1.0, 0.0 }, | ||
| + | { xpos, ypos, 0.0, 0.0 }, | ||
| + | |||
| + | { xpos, ypos + h, 0.0, 1.0 }, | ||
| + | { xpos + w, ypos + h, 1.0, 1.0 }, | ||
| + | { xpos + w, ypos, 1.0, 0.0 } | ||
| + | }; | ||
| + | // Render glyph texture over quad | ||
| + | glBindTexture(GL_TEXTURE_2D, ch.TextureID); | ||
| + | // Update content of VBO memory | ||
| + | glBindBuffer(GL_ARRAY_BUFFER, this->VBO); | ||
| + | glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // Be sure to use glBufferSubData and not glBufferData | ||
| + | |||
| + | glBindBuffer(GL_ARRAY_BUFFER, 0); | ||
| + | // Render quad | ||
| + | glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); | ||
| + | glEnable(GL_BLEND); | ||
| + | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||
| + | glDrawArrays(GL_TRIANGLES, 0, 6); | ||
| + | glDisable(GL_BLEND); | ||
| + | // Now advance cursors for next glyph | ||
| + | x += (ch.Advance >> 6) * scale; // Bitshift by 6 to get value in pixels (1/64th times 2^6 = 64) | ||
| + | } | ||
| + | glBindVertexArray(0); | ||
| + | glBindTexture(GL_TEXTURE_2D, 0); | ||
| + | } | ||
| + | </code> | ||
| + | Astfel se procesează fiecare caracter din care este alcătuit quad-ul după cum urmează: | ||
| + | * Pentru fiecare caracter se avansează pe ecran pe linia orizontală (variabila //x//) la poziția de început de unde urmează a fi desenat (//xpos, ypos//) | ||
| + | * Se crează quad-ul de dimensiunea lățimea și înălțimea texturii asociate caracterului | ||
| + | * Quad-ul va fi desenat folosind două triunghiuri: 6 vertecși (câte 3 pentru fiecare triunghi) fiecare cu 4 valori: | ||
| + | * x,y: coodonatele vârfului (după cum s-a explicat mai sus z va fi zero deoarece se desenează folosind o proiecție ortografică în planul Z = 0 al volumului vizual canonic) | ||
| + | * z,w: coordonatele de textură asociate vârfului | ||
| + | * Se desenează quad-ul format din cele două triunghiuri cu textura corespunzătoare caracterului (//glBindTexture(GL_TEXTURE_2D, ch.TextureID)//) și cu mecanismul de blending activat pentru a nu desena decât pixelii caracterului și a ignora restul quad-ului care este transparent | ||
| + | |||
| + | ==== Utilizare ==== | ||
| + | - Descărcați [[https://github.com/UPB-Graphics/Framework-EGC/archive/withrendertext.zip|framework-ul de laborator]] ce are implementat redarea textului | ||
| + | - Rulați exemplul de redare a textului: clasa ''Laborator_BonusTextRenderer'' | ||
| + | - Dacă doriți să vedeți în detaliu implementarea redării textului examinați: | ||
| + | * Clasa ''TextRenderer'' din /TextRenderer | ||
| + | * Shaderele ''VertexShaderText.glsl'' și ''FragmentShaderText.glsl'' din /TextRenderer/Shaders | ||