Differences

This shows you the differences between two versions of the page.

Link to this comparison view

egc:laboratoare:bonusrendertext [2019/11/25 17:14]
victor.asavei [Shadere]
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 posvec2 tex>+layout(location = 0) in vec4 vertex; // <x,y,u,v>
 out vec2 TexCoords; out vec2 TexCoords;
  
Line 99: Line 99:
 </​code>​ </​code>​
 Pe coordonatele .xy se transmit coordonatele x,y din cadrul ferestrei de afișare care reprezintă poziția unde va fi afișat caracterul. Pe coordonatele .xy se transmit coordonatele x,y din cadrul ferestrei de afișare care reprezintă poziția unde va fi afișat caracterul.
-Coordonata z va fi zero deoarece afișarea se va face direct pe fața cubului corespunzător volumului vizual canonic în planul Z = 0. + 
 +Coordonata z va fi zero deoarece afișarea se va face direct pe fața cubului corespunzător volumului vizual canonic în planul Z = 0. 
 + 
 Astfel acestea vor fi transformate in vertex shader doar cu matricea de proiecție. Astfel acestea vor fi transformate in vertex shader doar cu matricea de proiecție.
 +
 Se va folosi o proiecție ortografică ce va avea //near// = //far// = 0 și pentru a considera colțul stânga sus ca fiind 0,0 va avea //bottom// inversat cu //top// astfel: Se va folosi o proiecție ortografică ce va avea //near// = //far// = 0 și pentru a considera colțul stânga sus ca fiind 0,0 va avea //bottom// inversat cu //top// astfel:
 <code glsl> <code glsl>
Line 123: Line 126:
 } }
 </​code>​ </​code>​
-==== Redare text ==== 
  
 +Fragment shader-ul primește ca uniforme id-ul texturii unde a fost încărcat bitmap-ul monocolor al caracterului și culoarea cu care se dorește a fi afișat textul.
 +Astfel, deoarece am folosit doar canalul roșu pentru textură (GL_RED) se face eșantionarea din textură doar de pe acesta (//​texture(text,​ TexCoords).r//​) și se stochează în culoarea finală pe canalul de alpha (componenta a 4-a). În acest fel, considerând quad-ul pe care se afisează ca fiind transparent (in bitmap acolo unde nu există pixeli pentru caracter, va fi intors 0 iar un alpha de 0 înseamnă perfect transparent) textul va fi afișat iar restul conținutului quad-ului pe care a fost mapată textură va fi ignorat permițând astfel combinarea naturală cu ce deja a fost afișat anterior în frame buffer. ​
 +Ca ultim pas, se înmulțește culoarea obținută cu culoarea //​textColor//​ pentru a desena textul cu o culoare dorită.
 +
 +Pentru a putea fi folosit acest mecanism de transparență trebuie activat și folosit mecanismul de blending din OpenGL astfel:
 +<code glsl>
 +glEnable(GL_BLEND);​
 +glBlendFunc(GL_SRC_ALPHA,​ GL_ONE_MINUS_SRC_ALPHA);​
 +</​code>​
 +
 +==== 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
  
egc/laboratoare/bonusrendertext.1574694886.txt.gz · Last modified: 2019/11/25 17:14 by victor.asavei
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0