Advertisement
Guest User

Untitled

a guest
Jul 16th, 2018
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.73 KB | None | 0 0
  1. #include <SDL.h>
  2. #include <GL/glew.h>
  3. #include <freetype-gl.h>
  4. #include <glm.hpp>
  5. #include <gtc/matrix_transform.hpp>
  6. #include <gtc/type_ptr.hpp>
  7.  
  8. #include <vector>
  9. #include <fstream>
  10. #include <iostream>
  11. #include <sstream>
  12.  
  13. GLenum GLCheckError();
  14. bool GLLogCall(const char* function, const char* file, int line);
  15.  
  16. #ifndef NDEBUG
  17. #define glError(x) GLCheckError();\
  18.         x; \
  19.         if (!GLLogCall(#x, __FILE__, __LINE__)) __debugbreak();
  20. #else
  21. #define glCall(x) x
  22. #endif
  23.  
  24. //----------------------------------------------------------------------------------------------------------------------------------------
  25. struct Shader
  26. {
  27.     std::string LoadFromFile(const std::string &filePath);
  28.  
  29.     void CreateShaderProgram();
  30.     void CreateShaders(const GLchar* vertexShader, const GLchar* fragmentShader);
  31.     void UseShaderProgram();
  32.  
  33.     GLint getUniformLocation(const std::string &uniformName);
  34.  
  35.     GLuint p_ShaderProgram;
  36. };
  37. //----------------------------------------------------------------------------------------------------------------------------------------
  38. struct Font
  39. {
  40.     Font(const std::string& filename, float size);
  41.  
  42.     GLuint getTexture() const;
  43.  
  44.     ftgl::texture_atlas_t* pp_FTAtlas = nullptr;
  45.     ftgl::texture_font_t* pp_FTFont = nullptr;
  46.  
  47.     GLuint p_Texture = 0;
  48. };
  49. //----------------------------------------------------------------------------------------------------------------------------------------
  50. struct VertexData
  51. {
  52.     glm::vec2 p_TexUV;
  53.     glm::vec3 p_Position;
  54.     GLuint p_Color;
  55. };
  56.  
  57. #define RENDERER_MAX_SPRITES 60000
  58. #define RENDERER_MAX_ELEMENTS RENDERER_MAX_SPRITES * 6
  59. #define RENDERER_SPRITE_SIZE sizeof(VertexData) * 4
  60. #define RENDERER_VERTEX_BUFFER RENDERER_SPRITE_SIZE * RENDERER_MAX_SPRITES
  61. #define RENDERER_ELEMENT_BUFFER RENDERER_MAX_ELEMENTS * sizeof(GLuint)
  62.  
  63. class Renderer
  64. {
  65. public:
  66.     Renderer() = default;
  67.    
  68.     void Initialize();
  69.  
  70.     void Start();
  71.     void DrawString(const std::string& text, const glm::vec2& position, GLuint color, const Font& font);
  72.     void End();
  73.  
  74.     GLuint p_Vao, p_Vbo, p_Ebo, p_IndexCount, p_Texture;
  75.  
  76.     Shader p_Shader;
  77.  
  78.     VertexData* pp_VertexData = nullptr;
  79.  
  80.     GLuint* setIndices();
  81.     void setVertexData(const glm::vec3& position,
  82.                        const glm::vec2& texUV,
  83.                        GLuint color);
  84. };
  85. //----------------------------------------------------------------------------------------------------------------------------------------
  86. GLuint CreateFromSource(int w, int h, int format, const void* pixels);
  87. void UpdateData(GLuint tex, int w, int h, int format, const void* pixels);
  88. //----------------------------------------------------------------------------------------------------------------------------------------
  89. int main(int argc, char* args[])
  90. {
  91.     SDL_Init(SDL_INIT_EVERYTHING);
  92.  
  93.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
  94.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
  95.     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
  96.     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
  97.  
  98.     SDL_Window* pp_Window = SDL_CreateWindow("FontTest", 0, 0, 1280, 720, SDL_WINDOW_OPENGL);
  99.     SDL_GLContext p_Context = SDL_GL_CreateContext(pp_Window);
  100.     SDL_Event p_Event;
  101.  
  102.     glewExperimental = true;
  103.     glewInit();
  104.  
  105.     Renderer renderer;
  106.     renderer.Initialize();
  107.  
  108.     Font* pp_Font = new Font("test.ttf", 150);
  109.  
  110.     glError(glClearColor(0.5, 0.5, 0.5, 1.0));
  111.  
  112.     bool quit = false;
  113.     while (!quit) {
  114.         while (SDL_PollEvent(&p_Event)) {
  115.             if (p_Event.type == SDL_QUIT) {
  116.                 quit = true;
  117.             }
  118.         }
  119.  
  120.         glError(glClear(GL_COLOR_BUFFER_BIT));
  121.  
  122.         renderer.Start();
  123.         renderer.DrawString("TESTOWY", glm::vec2(100.0f, 100.0f), 0xffffffff, *pp_Font);
  124.         renderer.End();
  125.  
  126.         SDL_GL_SwapWindow(pp_Window);
  127.     }
  128.    
  129.     return 0;
  130. }
  131.  
  132. GLuint CreateFromSource(int w, int h, int format, const void* pixels)
  133. {
  134.     GLuint texture = 0;
  135.     glError(glGenTextures(1, &texture));
  136.     glError(glBindTexture(GL_TEXTURE_2D, texture));
  137.  
  138.     glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
  139.     glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
  140.     glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
  141.     glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
  142.  
  143.     glError(glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, nullptr));
  144.     glError(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, pixels));
  145.     glError(glGenerateMipmap(GL_TEXTURE_2D));
  146.  
  147.     glError(glBindTexture(GL_TEXTURE_2D, 0));
  148.  
  149.     return texture;
  150. }
  151.  
  152. void UpdateData(GLuint tex, int w, int h, int format, const void* pixels)
  153. {
  154.     glError(glBindTexture(GL_TEXTURE_2D, tex));
  155.     glError(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, pixels));
  156. }
  157.  
  158. GLenum GLCheckError()
  159. {
  160.     return glGetError();
  161. }
  162.  
  163. bool GLLogCall(const char* function, const char* file, int line)
  164. {
  165.     GLenum error = GLCheckError();
  166.     if (error != GL_NO_ERROR) {
  167.         std::cout << "[OpenGL Error] (" + std::to_string(error) + "): " + function + " " + file + ":" + std::to_string(line) << std::endl;
  168.         return false;
  169.     }
  170.     return true;
  171. }
  172. //----------------------------------------------------------------------------------------------------------------------------------------
  173. std::string Shader::LoadFromFile(const std::string& filePath)
  174. {
  175.     std::ifstream openFile(filePath);
  176.     std::stringstream sstream;
  177.  
  178.     sstream << openFile.rdbuf();
  179.  
  180.     return sstream.str();
  181. }
  182.  
  183. void Shader::CreateShaderProgram()
  184. {
  185.     p_ShaderProgram = glCreateProgram();
  186. }
  187.  
  188. void Shader::CreateShaders(const GLchar* vertexShader, const GLchar* fragmenShader)
  189. {
  190.     GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
  191.     GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
  192.  
  193.     glError(glShaderSource(vertexShaderID, 1, &vertexShader, NULL));
  194.     glError(glCompileShader(vertexShaderID));
  195.  
  196.     GLint isCompiled = 0;
  197.     glError(glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &isCompiled));
  198.     if (isCompiled == GL_FALSE) {
  199.         GLint maxLength = 0;
  200.         glError(glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &maxLength));
  201.  
  202.         std::vector<GLchar> infoLog(maxLength);
  203.         glError(glGetShaderInfoLog(vertexShaderID, maxLength, &maxLength, &infoLog[0]));
  204.  
  205.         glError(glDeleteShader(vertexShaderID));
  206.  
  207.         std::cout << '%s\n' << &infoLog[0] << std::endl;
  208.  
  209.         return;
  210.     }
  211.  
  212.     glError(glShaderSource(fragmentShaderID, 1, &fragmenShader, NULL));
  213.     glError(glCompileShader(fragmentShaderID));
  214.  
  215.     glError(glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &isCompiled));
  216.     if (isCompiled == GL_FALSE) {
  217.         GLint maxLength = 0;
  218.         glError(glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &maxLength));
  219.  
  220.         std::vector<GLchar> infoLog(maxLength);
  221.         glError(glGetShaderInfoLog(fragmentShaderID, maxLength, &maxLength, &infoLog[0]));
  222.  
  223.         glError(glDeleteShader(fragmentShaderID));
  224.         glError(glDeleteShader(vertexShaderID));
  225.  
  226.         std::cout << '%s\n' << &infoLog[0] << std::endl;
  227.  
  228.         return;
  229.     }
  230.  
  231.     glError(glAttachShader(p_ShaderProgram, vertexShaderID));
  232.     glError(glAttachShader(p_ShaderProgram, fragmentShaderID));
  233.  
  234.     glError(glLinkProgram(p_ShaderProgram));
  235.  
  236.     GLint isLinked = 0;
  237.     glError(glGetProgramiv(p_ShaderProgram, GL_LINK_STATUS, (int *)&isLinked));
  238.     if (isLinked == GL_FALSE) {
  239.         GLint maxLength = 0;
  240.         glError(glGetProgramiv(p_ShaderProgram, GL_INFO_LOG_LENGTH, &maxLength));
  241.  
  242.         std::vector<GLchar> infoLog(maxLength);
  243.         glError(glGetProgramInfoLog(p_ShaderProgram, maxLength, &maxLength, &infoLog[0]));
  244.  
  245.         glError(glDeleteProgram(p_ShaderProgram));
  246.         glError(glDeleteShader(vertexShaderID));
  247.         glError(glDeleteShader(fragmentShaderID));
  248.  
  249.         std::cout << '%s\n' << &infoLog[0] << std::endl;
  250.  
  251.         return;
  252.     }
  253.  
  254.     glError(glDetachShader(p_ShaderProgram, vertexShaderID));
  255.     glError(glDetachShader(p_ShaderProgram, fragmentShaderID));
  256.  
  257.     glError(glDeleteShader(vertexShaderID));
  258.     glError(glDeleteShader(fragmentShaderID));
  259. }
  260.  
  261. void Shader::UseShaderProgram()
  262. {
  263.     glError(glUseProgram(p_ShaderProgram));
  264. }
  265.  
  266. GLint Shader::getUniformLocation(const std::string &uniformName)
  267. {
  268.     return glGetUniformLocation(p_ShaderProgram, uniformName.c_str());
  269. }
  270. //----------------------------------------------------------------------------------------------------------------------------------------
  271. void Renderer::Initialize()
  272. {
  273.     p_Vao = 0;
  274.     p_Vbo = 0;
  275.     p_Ebo = 0;
  276.     p_IndexCount = 0;
  277.     p_Texture = 0;
  278.  
  279.     glError(glGenVertexArrays(1, &p_Vao));
  280.     glError(glBindVertexArray(p_Vao));
  281.  
  282.     glError(glGenBuffers(1, &p_Vbo));
  283.     glError(glBindBuffer(GL_ARRAY_BUFFER, p_Vbo));
  284.     glError(glBufferData(GL_ARRAY_BUFFER, RENDERER_VERTEX_BUFFER, nullptr, GL_DYNAMIC_DRAW));
  285.  
  286.     glError(glEnableVertexAttribArray(0));
  287.     glError(glEnableVertexAttribArray(1));
  288.     glError(glEnableVertexAttribArray(2));
  289.  
  290.     glError(glVertexAttribPointer(0, 2, GL_FLOAT,         GL_FALSE, sizeof(VertexData), (const void*)offsetof(VertexData, p_Position)));
  291.     glError(glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE,  sizeof(VertexData), (const void*)offsetof(VertexData, p_Color)));
  292.     glError(glVertexAttribPointer(2, 2, GL_FLOAT,         GL_FALSE, sizeof(VertexData), (const void*)offsetof(VertexData, p_TexUV)));
  293.  
  294.     glError(glGenBuffers(1, &p_Ebo));
  295.     glError(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_Ebo));
  296.     glError(glBufferData(GL_ELEMENT_ARRAY_BUFFER, RENDERER_ELEMENT_BUFFER, setIndices(), GL_STATIC_DRAW));
  297.  
  298.     glError(glBindVertexArray(0));
  299.  
  300.     std::string vertex = p_Shader.LoadFromFile("textVertex.glsl");
  301.     std::string fragment = p_Shader.LoadFromFile("textFragment.glsl");
  302.  
  303.     p_Shader.CreateShaderProgram();
  304.     p_Shader.CreateShaders(vertex.c_str(), fragment.c_str());
  305.     p_Shader.UseShaderProgram();
  306.  
  307.     GLint u_textureSampler = p_Shader.getUniformLocation("u_textureSampler");
  308.     glError(glUniform1i(u_textureSampler, 0));
  309. }
  310.  
  311. void Renderer::Start()
  312. {
  313.     glm::mat4 projection = glm::mat4(1.0f);
  314.     projection = glm::ortho(0.0f, 1280.0f, 720.0f, 0.0f);
  315.  
  316.     glError(glUniformMatrix4fv(p_Shader.getUniformLocation("projection"), 1, GL_FALSE, glm::value_ptr(projection)));
  317.  
  318.     pp_VertexData = (VertexData*)glMapNamedBufferRange(p_Vbo, NULL, RENDERER_VERTEX_BUFFER, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
  319. }
  320.  
  321. void Renderer::DrawString(const std::string& text, const glm::vec2& position, GLuint color, const Font& font)
  322. {
  323.     float x = position.x;
  324.     texture_font_t* ftFont = font.pp_FTFont;
  325.  
  326.     for (GLuint i = 0; i < text.length(); ++i) {
  327.         texture_glyph_t* glyph = texture_font_get_glyph(ftFont, text.c_str() + i);
  328.         if (glyph) {
  329.             if (i > 0) {
  330.                 float kerning = texture_glyph_get_kerning(glyph, text.c_str() + i - 1);
  331.                 x += kerning;
  332.             }
  333.            
  334.             p_Texture = font.getTexture();
  335.  
  336.             float x0 = x + glyph->offset_x;
  337.             float x1 = x0 + glyph->width;
  338.  
  339.             float y0 = position.y + glyph->offset_y;
  340.             float y1 = y0 - glyph->height;
  341.  
  342.             float u0 = glyph->s0;
  343.             float u1 = glyph->s1;
  344.  
  345.             float v0 = glyph->t0;
  346.             float v1 = glyph->t1;
  347.  
  348.             setVertexData(glm::vec3(x0, y0, 0.0f), glm::vec2(u0, v0), color);
  349.             setVertexData(glm::vec3(x0, y1, 0.0f), glm::vec2(u0, v1), color);
  350.             setVertexData(glm::vec3(x1, y1, 0.0f), glm::vec2(u1, v1), color);
  351.             setVertexData(glm::vec3(x1, y0, 0.0f), glm::vec2(u1, v0), color);
  352.  
  353.             p_IndexCount += 6;
  354.  
  355.             x += glyph->advance_x;
  356.         }
  357.     }
  358. }
  359.  
  360. void Renderer::End()
  361. {
  362.     glError(glUnmapNamedBuffer(p_Vbo));
  363.  
  364.     glError(glEnable(GL_BLEND));
  365.     glError(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
  366.  
  367.     glError(glActiveTexture(GL_TEXTURE0));
  368.     glError(glBindTexture(GL_TEXTURE_2D, p_Texture));
  369.  
  370.     glError(glBindVertexArray(p_Vao));
  371.     glError(glDrawElements(GL_TRIANGLES, p_IndexCount, GL_UNSIGNED_INT, nullptr));
  372.     glError(glBindVertexArray(0));
  373.  
  374.     p_IndexCount = 0;
  375. }
  376.  
  377. GLuint* Renderer::setIndices()
  378. {
  379.     GLuint* indices = new GLuint[RENDERER_ELEMENT_BUFFER],
  380.         offset = 0;
  381.     for (int i = 0; i < RENDERER_ELEMENT_BUFFER; i += 6) {
  382.         indices[i] = offset;
  383.         indices[i + 1] = offset + 1;
  384.         indices[i + 2] = offset + 2;
  385.         indices[i + 3] = offset + 2;
  386.         indices[i + 4] = offset + 3;
  387.         indices[i + 5] = offset;
  388.  
  389.         offset += 4;
  390.     }
  391.  
  392.     return indices;
  393. }
  394.  
  395. void Renderer::setVertexData(const glm::vec3& position, const glm::vec2& texUV, GLuint color)
  396. {
  397.     pp_VertexData->p_Position = position;
  398.     pp_VertexData->p_TexUV = texUV;
  399.     pp_VertexData->p_Color = color;
  400.     pp_VertexData++;
  401. }
  402. //----------------------------------------------------------------------------------------------------------------------------------------
  403. Font::Font(const std::string& filename, float size)
  404. {
  405.     pp_FTAtlas = ftgl::texture_atlas_new(512, 512, 1);
  406.     pp_FTFont = ftgl::texture_font_new_from_file(pp_FTAtlas, size, filename.c_str());
  407.  
  408.     p_Texture = CreateFromSource(512, 512, GL_RED, pp_FTAtlas->data);
  409. }
  410.  
  411. GLuint Font::getTexture() const
  412. {
  413.     UpdateData(p_Texture, 512, 512, GL_RED, pp_FTAtlas->data);
  414.     return p_Texture;
  415. }
  416.  
  417.  
  418. //----------------------------------------------------------------------------------------------------------------------------------------
  419. //----------------------------------------------------------------------------------------------------------------------------------------
  420. #version 430 core
  421.  
  422. layout (location = 0) in vec3 a_position;
  423. layout (location = 1) in vec4 a_color;
  424. layout (location = 2) in vec2 a_texUV;
  425.  
  426. out vec3 v_position;
  427. out vec4 v_color;
  428. out vec2 v_texUV;
  429. uniform mat4 projection;
  430.  
  431. void main()
  432. {
  433.     gl_Position = projection * vec4(a_position, 1.0);
  434.    
  435.     v_position = a_position;
  436.     v_color = a_color;
  437.     v_texUV = vec2(a_texUV.x, 1 - a_texUV.y);
  438. }
  439. //----------------------------------------------------------------------------------------------------------------------------------------
  440. #version 430 core
  441.  
  442. out vec4 finalColor;
  443.  
  444. in vec2 v_position;
  445. in vec4 v_color;
  446. in vec2 v_texUV;
  447.  
  448. uniform sampler2D u_textureSampler;
  449.  
  450. void main()
  451. {
  452.     float texColor = texture(u_textureSampler, v_texUV).a;
  453.  
  454.     finalColor= vec4(1.0f, 1.0f, 1.0f, texColor);
  455. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement