From a8a38716bd5ccbcd86f794be26741aece9f16996 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Fri, 11 Dec 2015 16:12:29 +0100 Subject: [PATCH] Text renderer up and working, needs more work to be compatible with the ResourceManager and the Entity Component system --- assets | 2 +- include/Engine/Rendering/Renderer.h | 3 + include/Engine/Rendering/ShaderProgram.h | 5 + include/Engine/Rendering/TextRenderer.h | 28 ++++ resources/Shaders/Text.frag.glsl | 12 ++ resources/Shaders/Text.vert.glsl | 13 ++ src/Engine/Rendering/Renderer.cpp | 7 +- src/Engine/Rendering/TextRenderer.cpp | 171 +++++++++++++++++++++++ 8 files changed, 239 insertions(+), 2 deletions(-) create mode 100644 resources/Shaders/Text.frag.glsl create mode 100644 resources/Shaders/Text.vert.glsl diff --git a/assets b/assets index 1434cdcb..fa95bf43 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1434cdcb2139e2158d5b50b986bc48569b1ec5b8 +Subproject commit fa95bf4383e558a5cb86e35e9d20362e5cb2dcb6 diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 76de0818..7f692a3c 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -14,6 +14,8 @@ #include "../Core/EventBroker.h" #include "EPicking.h" +#include "TextRenderer.h" + class Renderer : public IRenderer { public: @@ -28,6 +30,7 @@ public: private: //----------------------Variables----------------------// EventBroker* m_EventBroker; + TextRenderer* m_TextRenderer; Texture* m_ErrorTexture; Texture* m_WhiteTexture; diff --git a/include/Engine/Rendering/ShaderProgram.h b/include/Engine/Rendering/ShaderProgram.h index 1b87650e..6fb17b61 100644 --- a/include/Engine/Rendering/ShaderProgram.h +++ b/include/Engine/Rendering/ShaderProgram.h @@ -1,4 +1,7 @@ +#ifndef ShaderProgram_h__ +#define ShaderProgram_h__ + #include "../Common.h" #include "../OpenGL.h" #include @@ -79,3 +82,5 @@ private: GLuint m_ShaderProgramHandle; std::vector> m_Shaders; }; + +#endif diff --git a/include/Engine/Rendering/TextRenderer.h b/include/Engine/Rendering/TextRenderer.h index 5250d066..99852b4b 100644 --- a/include/Engine/Rendering/TextRenderer.h +++ b/include/Engine/Rendering/TextRenderer.h @@ -4,12 +4,40 @@ #include #include FT_FREETYPE_H +#include "OpenGL.h" +#include "GLM.h" +#include "ShaderProgram.h" + class TextRenderer { public: + TextRenderer(); + void Initialize(); + void Update(); + void Draw(glm::mat4 projection, glm::mat4 view); private: + + struct Character { + GLuint TextureID; // ID handle of the glyph texture + glm::ivec2 Size; // Size of glyph + glm::ivec2 Bearing; // Offset from baseline to left/top of glyph + GLuint Advance; // Offset to advance to next glyph + }; + + std::map Characters; + + + GLuint VAO, VBO; + + void RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color, glm::mat4 projection, glm::mat4 view); + + ShaderProgram m_TextProgram; + + std::string text = ""; + + int counter = 0; }; diff --git a/resources/Shaders/Text.frag.glsl b/resources/Shaders/Text.frag.glsl new file mode 100644 index 00000000..2726b5d1 --- /dev/null +++ b/resources/Shaders/Text.frag.glsl @@ -0,0 +1,12 @@ +#version 430 +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; +} \ No newline at end of file diff --git a/resources/Shaders/Text.vert.glsl b/resources/Shaders/Text.vert.glsl new file mode 100644 index 00000000..43c86795 --- /dev/null +++ b/resources/Shaders/Text.vert.glsl @@ -0,0 +1,13 @@ +#version 430 +layout (location = 0) in vec4 vertex; // +out vec2 TexCoords; + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +void main() +{ + gl_Position = P * V * M * vec4(vertex.xy, 0.0, 1.0); + TexCoords = vertex.zw; +} \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 6f4235d2..3ee559c5 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -15,6 +15,9 @@ void Renderer::Initialize() InitializeTextures(); InitializeFrameBuffers(); + m_TextRenderer = new TextRenderer(); + m_TextRenderer->Initialize(); + m_ScreenQuad = ResourceManager::Load("Models/Core/ScreenQuad.obj"); m_UnitQuad = ResourceManager::Load("Models/Core/UnitQuad.obj"); @@ -142,6 +145,7 @@ void Renderer::Update(double dt) { m_EventBroker->Process(); InputUpdate(dt); + m_TextRenderer->Update(); } @@ -149,9 +153,10 @@ void Renderer::Draw(RenderQueueCollection& rq) { //TODO: Renderer: Kanske borde vara längst upp i update. PickingPass(rq); - DrawScreenQuad(m_PickingTexture); + // DrawScreenQuad(m_PickingTexture); DrawScene(rq); + m_TextRenderer->Draw(m_Camera->ProjectionMatrix(), m_Camera->ViewMatrix()); glfwSwapBuffers(m_Window); } diff --git a/src/Engine/Rendering/TextRenderer.cpp b/src/Engine/Rendering/TextRenderer.cpp index e69de29b..0fd46f32 100644 --- a/src/Engine/Rendering/TextRenderer.cpp +++ b/src/Engine/Rendering/TextRenderer.cpp @@ -0,0 +1,171 @@ +#include "Rendering/TextRenderer.h" + +TextRenderer::TextRenderer() +{ + +} + +void TextRenderer::Initialize() +{ + FT_Library library; + FT_Face face; + + if (FT_Init_FreeType(&library)) { + LOG_ERROR("FreeType error: init failed"); + } + + if (FT_New_Face(library, "fonts/arial.ttf", 0, &face)) { + LOG_ERROR("FreeType error: loading font"); + } + + FT_Set_Pixel_Sizes(face, 0, 48); + + if (FT_Load_Char(face, 'X', FT_LOAD_RENDER)) { + LOG_ERROR("FreeType error: loading char"); + } + + + + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + for (GLubyte c = 0; c < 128; c++) { + //Load character glyph + if (FT_Load_Char(face, c, FT_LOAD_RENDER)) { + continue; + } + printf("Char: %c\n", c); + //Generate texture + GLuint 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(c, character)); + } + + FT_Done_Face(face); + FT_Done_FreeType(library); + + + + + glGenVertexArrays(1, &VAO); + glGenBuffers(1, &VBO); + glBindVertexArray(VAO); + glBindBuffer(GL_ARRAY_BUFFER, VBO); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + glBindVertexArray(0); + + + + m_TextProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/Text.vert.glsl"))); + m_TextProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/Text.frag.glsl"))); + m_TextProgram.Compile(); + m_TextProgram.Link(); +} + +void TextRenderer::Update() +{ + +} + +void TextRenderer::Draw(glm::mat4 projection, glm::mat4 view) +{ + if(counter > 2) { + if (text == "") { + text = text + "~wub "; + } else if (text == "~wub ") { + text = text + "wub "; + } else if (text == "~wub wub ") { + text = ""; + } + counter = 0; + } else { + counter++; + } + + RenderText(text, 0.f, 0.f, 1.0f, glm::vec3(1.f, 1.f, 1.f), projection, view); +} + +void TextRenderer::RenderText(std::string text, GLfloat x, GLfloat y, GLfloat scale, glm::vec3 color, glm::mat4 projection, glm::mat4 view) +{ + + glm::mat4 modelMatrix = glm::translate(glm::mat4(), glm::vec3(0.5f, 0.3f, 0.f)) * glm::toMat4(glm::quat()) * glm::scale(glm::vec3(0.01f)); + + // Activate corresponding render state + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_TextProgram.Bind(); + glUniform3f(glGetUniformLocation(m_TextProgram.GetHandle(), "textColor"), color.x, color.y, color.z); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram.GetHandle(), "M"), 1, GL_FALSE, glm::value_ptr(modelMatrix)); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram.GetHandle(), "V"), 1, GL_FALSE, glm::value_ptr(view)); + glUniformMatrix4fv(glGetUniformLocation(m_TextProgram.GetHandle(), "P"), 1, GL_FALSE, glm::value_ptr(projection)); + 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]; + + GLfloat xpos = x + ch.Bearing.x * scale; + GLfloat ypos = y - (ch.Size.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, 0.0 }, + { xpos, ypos, 0.0, 1.0 }, + { xpos + w, ypos, 1.0, 1.0 }, + + { xpos, ypos + h, 0.0, 0.0 }, + { xpos + w, ypos, 1.0, 1.0 }, + { xpos + w, ypos + h, 1.0, 0.0 } + }; + + // 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); + + GLERROR("Text rendering Error"); +} +