Advertisement
Guest User

Untitled

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