Advertisement
Guest User

Untitled

a guest
Jul 26th, 2024
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 16.81 KB | None | 0 0
  1. // shader.h
  2. #ifndef SHADER_H
  3. #define SHADER_H
  4.  
  5. #include <glad/glad.h>
  6. #include <glm/glm.hpp>
  7.  
  8. #include <string>
  9. #include <fstream>
  10. #include <sstream>
  11. #include <iostream>
  12.  
  13. class Shader
  14. {
  15. public:
  16.     unsigned int ID;
  17.     // constructor generates the shader on the fly
  18.     // ------------------------------------------------------------------------
  19.     Shader(const char* vertexPath, const char* fragmentPath, const char* geometryPath = nullptr)
  20.     {
  21.         // 1. retrieve the vertex/fragment source code from filePath
  22.         std::string vertexCode;
  23.         std::string fragmentCode;
  24.         std::string geometryCode;
  25.         std::ifstream vShaderFile;
  26.         std::ifstream fShaderFile;
  27.         std::ifstream gShaderFile;
  28.         // ensure ifstream objects can throw exceptions:
  29.         vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
  30.         fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
  31.         gShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
  32.         try
  33.         {
  34.             // open files
  35.             vShaderFile.open(vertexPath);
  36.             fShaderFile.open(fragmentPath);
  37.             std::stringstream vShaderStream, fShaderStream;
  38.             // read file's buffer contents into streams
  39.             vShaderStream << vShaderFile.rdbuf();
  40.             fShaderStream << fShaderFile.rdbuf();      
  41.             // close file handlers
  42.             vShaderFile.close();
  43.             fShaderFile.close();
  44.             // convert stream into string
  45.             vertexCode = vShaderStream.str();
  46.             fragmentCode = fShaderStream.str();        
  47.             // if geometry shader path is present, also load a geometry shader
  48.             if(geometryPath != nullptr)
  49.             {
  50.                 gShaderFile.open(geometryPath);
  51.                 std::stringstream gShaderStream;
  52.                 gShaderStream << gShaderFile.rdbuf();
  53.                 gShaderFile.close();
  54.                 geometryCode = gShaderStream.str();
  55.             }
  56.         }
  57.         catch (std::ifstream::failure& e)
  58.         {
  59.             std::cout << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
  60.         }
  61.         const char* vShaderCode = vertexCode.c_str();
  62.         const char * fShaderCode = fragmentCode.c_str();
  63.         // 2. compile shaders
  64.         unsigned int vertex, fragment;
  65.         // vertex shader
  66.         vertex = glCreateShader(GL_VERTEX_SHADER);
  67.         glShaderSource(vertex, 1, &vShaderCode, NULL);
  68.         glCompileShader(vertex);
  69.         checkCompileErrors(vertex, "VERTEX");
  70.         // fragment Shader
  71.         fragment = glCreateShader(GL_FRAGMENT_SHADER);
  72.         glShaderSource(fragment, 1, &fShaderCode, NULL);
  73.         glCompileShader(fragment);
  74.         checkCompileErrors(fragment, "FRAGMENT");
  75.         // if geometry shader is given, compile geometry shader
  76.         unsigned int geometry;
  77.         if(geometryPath != nullptr)
  78.         {
  79.             const char * gShaderCode = geometryCode.c_str();
  80.             geometry = glCreateShader(GL_GEOMETRY_SHADER);
  81.             glShaderSource(geometry, 1, &gShaderCode, NULL);
  82.             glCompileShader(geometry);
  83.             checkCompileErrors(geometry, "GEOMETRY");
  84.         }
  85.         // shader Program
  86.         ID = glCreateProgram();
  87.         glAttachShader(ID, vertex);
  88.         glAttachShader(ID, fragment);
  89.         if(geometryPath != nullptr)
  90.             glAttachShader(ID, geometry);
  91.         glLinkProgram(ID);
  92.         checkCompileErrors(ID, "PROGRAM");
  93.         // delete the shaders as they're linked into our program now and no longer necessary
  94.         glDeleteShader(vertex);
  95.         glDeleteShader(fragment);
  96.         if(geometryPath != nullptr)
  97.             glDeleteShader(geometry);
  98.  
  99.     }
  100.     // activate the shader
  101.     // ------------------------------------------------------------------------
  102.     void use()
  103.     {
  104.         glUseProgram(ID);
  105.     }
  106.     // utility uniform functions
  107.     // ------------------------------------------------------------------------
  108.     void setBool(const std::string &name, bool value) const
  109.     {        
  110.         glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
  111.     }
  112.     // ------------------------------------------------------------------------
  113.     void setInt(const std::string &name, int value) const
  114.     {
  115.         glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
  116.     }
  117.     // ------------------------------------------------------------------------
  118.     void setFloat(const std::string &name, float value) const
  119.     {
  120.         glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
  121.     }
  122.     // ------------------------------------------------------------------------
  123.     void setVec2(const std::string &name, const glm::vec2 &value) const
  124.     {
  125.         glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
  126.     }
  127.     void setVec2(const std::string &name, float x, float y) const
  128.     {
  129.         glUniform2f(glGetUniformLocation(ID, name.c_str()), x, y);
  130.     }
  131.     // ------------------------------------------------------------------------
  132.     void setVec3(const std::string &name, const glm::vec3 &value) const
  133.     {
  134.         glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
  135.     }
  136.     void setVec3(const std::string &name, float x, float y, float z) const
  137.     {
  138.         glUniform3f(glGetUniformLocation(ID, name.c_str()), x, y, z);
  139.     }
  140.     // ------------------------------------------------------------------------
  141.     void setVec4(const std::string &name, const glm::vec4 &value) const
  142.     {
  143.         glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
  144.     }
  145.     void setVec4(const std::string &name, float x, float y, float z, float w)
  146.     {
  147.         glUniform4f(glGetUniformLocation(ID, name.c_str()), x, y, z, w);
  148.     }
  149.     // ------------------------------------------------------------------------
  150.     void setMat2(const std::string &name, const glm::mat2 &mat) const
  151.     {
  152.         glUniformMatrix2fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
  153.     }
  154.     // ------------------------------------------------------------------------
  155.     void setMat3(const std::string &name, const glm::mat3 &mat) const
  156.     {
  157.         glUniformMatrix3fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
  158.     }
  159.     // ------------------------------------------------------------------------
  160.     void setMat4(const std::string &name, const glm::mat4 &mat) const
  161.     {
  162.         glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
  163.     }
  164.  
  165. private:
  166.     // utility function for checking shader compilation/linking errors.
  167.     // ------------------------------------------------------------------------
  168.     void checkCompileErrors(GLuint shader, std::string type)
  169.     {
  170.         GLint success;
  171.         GLchar infoLog[1024];
  172.         if(type != "PROGRAM")
  173.         {
  174.             glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
  175.             if(!success)
  176.             {
  177.                 glGetShaderInfoLog(shader, 1024, NULL, infoLog);
  178.                 std::cout << "ERROR::SHADER_COMPILATION_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
  179.             }
  180.         }
  181.         else
  182.         {
  183.             glGetProgramiv(shader, GL_LINK_STATUS, &success);
  184.             if(!success)
  185.             {
  186.                 glGetProgramInfoLog(shader, 1024, NULL, infoLog);
  187.                 std::cout << "ERROR::PROGRAM_LINKING_ERROR of type: " << type << "\n" << infoLog << "\n -- --------------------------------------------------- -- " << std::endl;
  188.             }
  189.         }
  190.     }
  191. };
  192. #endif
  193.  
  194.  
  195. // text_rendering.cpp
  196. #include <iostream>
  197. #include <map>
  198. #include <string>
  199.  
  200. #include <glad/glad.h>
  201. #include <GLFW/glfw3.h>
  202.  
  203. #include <glm/glm.hpp>
  204. #include <glm/gtc/matrix_transform.hpp>
  205. #include <glm/gtc/type_ptr.hpp>
  206.  
  207. #include <ft2build.h>
  208. #include FT_FREETYPE_H
  209.  
  210. #include <learnopengl/shader.h>
  211.  
  212. void framebuffer_size_callback(GLFWwindow* window, int width, int height);
  213. void processInput(GLFWwindow *window);
  214. void RenderText(Shader &shader, std::string text, float x, float y, float scale, glm::vec3 color);
  215.  
  216. // settings
  217. const unsigned int SCR_WIDTH = 800;
  218. const unsigned int SCR_HEIGHT = 600;
  219.  
  220. /// Holds all state information relevant to a character as loaded using FreeType
  221. struct Character {
  222.     unsigned int TextureID; // ID handle of the glyph texture
  223.     glm::ivec2   Size;      // Size of glyph
  224.     glm::ivec2   Bearing;   // Offset from baseline to left/top of glyph
  225.     unsigned int Advance;   // Horizontal offset to advance to next glyph
  226. };
  227.  
  228. std::map<GLchar, Character> Characters;
  229. unsigned int VAO, VBO;
  230.  
  231. int main()
  232. {
  233.     // glfw: initialize and configure
  234.     // ------------------------------
  235.     glfwInit();
  236.     glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
  237.     glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
  238.     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  239.  
  240. #ifdef __APPLE__
  241.     glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
  242. #endif
  243.  
  244.     // glfw window creation
  245.     // --------------------
  246.     GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
  247.     if (window == NULL)
  248.     {
  249.         std::cout << "Failed to create GLFW window" << std::endl;
  250.         glfwTerminate();
  251.         return -1;
  252.     }
  253.     glfwMakeContextCurrent(window);
  254.     glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
  255.  
  256.     // glad: load all OpenGL function pointers
  257.     // ---------------------------------------
  258.     if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
  259.     {
  260.         std::cout << "Failed to initialize GLAD" << std::endl;
  261.         return -1;
  262.     }
  263.    
  264.     // OpenGL state
  265.     // ------------
  266.     glEnable(GL_CULL_FACE);
  267.     glEnable(GL_BLEND);
  268.     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  269.    
  270.     // compile and setup the shader
  271.     // ----------------------------
  272.     Shader shader("text.vs", "text.fs");
  273.     glm::mat4 projection = glm::ortho(0.0f, static_cast<float>(SCR_WIDTH), 0.0f, static_cast<float>(SCR_HEIGHT));
  274.     shader.use();
  275.     glUniformMatrix4fv(glGetUniformLocation(shader.ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
  276.  
  277.     // FreeType
  278.     // --------
  279.     FT_Library ft;
  280.     // All functions return a value different than 0 whenever an error occurred
  281.     if (FT_Init_FreeType(&ft))
  282.     {
  283.         std::cout << "ERROR::FREETYPE: Could not init FreeType Library" << std::endl;
  284.         return -1;
  285.     }
  286.  
  287.     // find path to font
  288.     std::string font_name = FileSystem::getPath("resources/fonts/Antonio-Bold.ttf");
  289.     if (font_name.empty())
  290.     {
  291.         std::cout << "ERROR::FREETYPE: Failed to load font_name" << std::endl;
  292.         return -1;
  293.     }
  294.    
  295.     // load font as face
  296.     FT_Face face;
  297.     if (FT_New_Face(ft, font_name.c_str(), 0, &face)) {
  298.         std::cout << "ERROR::FREETYPE: Failed to load font" << std::endl;
  299.         return -1;
  300.     }
  301.     else {
  302.         // set size to load glyphs as
  303.         FT_Set_Pixel_Sizes(face, 0, 48);
  304.  
  305.         // disable byte-alignment restriction
  306.         glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  307.  
  308.         // load first 128 characters of ASCII set
  309.         for (unsigned char c = 0; c < 128; c++)
  310.         {
  311.             // Load character glyph
  312.             if (FT_Load_Char(face, c, FT_LOAD_RENDER))
  313.             {
  314.                 std::cout << "ERROR::FREETYTPE: Failed to load Glyph" << std::endl;
  315.                 continue;
  316.             }
  317.             // generate texture
  318.             unsigned int texture;
  319.             glGenTextures(1, &texture);
  320.             glBindTexture(GL_TEXTURE_2D, texture);
  321.             glTexImage2D(
  322.                 GL_TEXTURE_2D,
  323.                 0,
  324.                 GL_RED,
  325.                 face->glyph->bitmap.width,
  326.                 face->glyph->bitmap.rows,
  327.                 0,
  328.                 GL_RED,
  329.                 GL_UNSIGNED_BYTE,
  330.                 face->glyph->bitmap.buffer
  331.             );
  332.             // set texture options
  333.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  334.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  335.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  336.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  337.             // now store character for later use
  338.             Character character = {
  339.                 texture,
  340.                 glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
  341.                 glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
  342.                 static_cast<unsigned int>(face->glyph->advance.x)
  343.             };
  344.             Characters.insert(std::pair<char, Character>(c, character));
  345.         }
  346.         glBindTexture(GL_TEXTURE_2D, 0);
  347.     }
  348.     // destroy FreeType once we're finished
  349.     FT_Done_Face(face);
  350.     FT_Done_FreeType(ft);
  351.  
  352.    
  353.     // configure VAO/VBO for texture quads
  354.     // -----------------------------------
  355.     glGenVertexArrays(1, &VAO);
  356.     glGenBuffers(1, &VBO);
  357.     glBindVertexArray(VAO);
  358.     glBindBuffer(GL_ARRAY_BUFFER, VBO);
  359.     glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
  360.     glEnableVertexAttribArray(0);
  361.     glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
  362.     glBindBuffer(GL_ARRAY_BUFFER, 0);
  363.     glBindVertexArray(0);
  364.  
  365.     // render loop
  366.     // -----------
  367.     while (!glfwWindowShouldClose(window))
  368.     {
  369.         // input
  370.         // -----
  371.         processInput(window);
  372.  
  373.         // render
  374.         // ------
  375.         glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
  376.         glClear(GL_COLOR_BUFFER_BIT);
  377.  
  378.         RenderText(shader, "Hello World!", 25.0f, 25.0f, 1.0f, glm::vec3(0.5, 0.8f, 0.2f));
  379.        
  380.         // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
  381.         // -------------------------------------------------------------------------------
  382.         glfwSwapBuffers(window);
  383.         glfwPollEvents();
  384.     }
  385.  
  386.     glfwTerminate();
  387.     return 0;
  388. }
  389.  
  390. // process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
  391. // ---------------------------------------------------------------------------------------------------------
  392. void processInput(GLFWwindow *window)
  393. {
  394.     if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
  395.         glfwSetWindowShouldClose(window, true);
  396. }
  397.  
  398. // glfw: whenever the window size changed (by OS or user resize) this callback function executes
  399. // ---------------------------------------------------------------------------------------------
  400. void framebuffer_size_callback(GLFWwindow* window, int width, int height)
  401. {
  402.     // make sure the viewport matches the new window dimensions; note that width and
  403.     // height will be significantly larger than specified on retina displays.
  404.     glViewport(0, 0, width, height);
  405. }
  406.  
  407.  
  408. // render line of text
  409. // -------------------
  410. void RenderText(Shader &shader, std::string text, float x, float y, float scale, glm::vec3 color)
  411. {
  412.     // activate corresponding render state 
  413.     shader.use();
  414.     glUniform3f(glGetUniformLocation(shader.ID, "textColor"), color.x, color.y, color.z);
  415.     glActiveTexture(GL_TEXTURE0);
  416.     glBindVertexArray(VAO);
  417.  
  418.     // iterate through all characters
  419.     std::string::const_iterator c;
  420.     for (c = text.begin(); c != text.end(); c++)
  421.     {
  422.         Character ch = Characters[*c];
  423.  
  424.         float xpos = x + ch.Bearing.x * scale;
  425.         float ypos = y - (ch.Size.y - ch.Bearing.y) * scale;
  426.  
  427.         float w = ch.Size.x * scale;
  428.         float h = ch.Size.y * scale;
  429.         // update VBO for each character
  430.         float vertices[6][4] = {
  431.             { xpos,     ypos + h,   0.0f, 0.0f },            
  432.             { xpos,     ypos,       0.0f, 1.0f },
  433.             { xpos + w, ypos,       1.0f, 1.0f },
  434.  
  435.             { xpos,     ypos + h,   0.0f, 0.0f },
  436.             { xpos + w, ypos,       1.0f, 1.0f },
  437.             { xpos + w, ypos + h,   1.0f, 0.0f }          
  438.         };
  439.         // render glyph texture over quad
  440.         glBindTexture(GL_TEXTURE_2D, ch.TextureID);
  441.         // update content of VBO memory
  442.         glBindBuffer(GL_ARRAY_BUFFER, VBO);
  443.         glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); // be sure to use glBufferSubData and not glBufferData
  444.  
  445.         glBindBuffer(GL_ARRAY_BUFFER, 0);
  446.         // render quad
  447.         glDrawArrays(GL_TRIANGLES, 0, 6);
  448.         // now advance cursors for next glyph (note that advance is number of 1/64 pixels)
  449.         x += (ch.Advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64 (divide amount of 1/64th pixels by 64 to get amount of pixels))
  450.     }
  451.     glBindVertexArray(0);
  452.     glBindTexture(GL_TEXTURE_2D, 0);
  453. }
  454.  
  455. // Credit: https://learnopengl.com/In-Practice/Text-Rendering
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement