Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SDL.h>
- #include <SDL_image.h>
- #include <GL/glew.h>
- #include <freetype-gl.h>
- #include <glm.hpp>
- #include <gtc/matrix_transform.hpp>
- #include <gtc/type_ptr.hpp>
- #include <vector>
- #include <fstream>
- #include <iostream>
- #include <sstream>
- GLenum GLCheckError();
- bool GLLogCall(const char* function, const char* file, int line);
- #ifndef NDEBUG
- #define glError(x) GLCheckError();\
- x; \
- if (!GLLogCall(#x, __FILE__, __LINE__)) __debugbreak();
- #else
- #define glCall(x) x
- #endif
- //----------------------------------------------------------------------------------------------------------------------------------------
- struct Shader
- {
- std::string LoadFromFile(const std::string &filePath);
- void CreateShaderProgram();
- void CreateShaders(const GLchar* vertexShader, const GLchar* fragmentShader);
- void UseShaderProgram();
- GLint getUniformLocation(const std::string &uniformName);
- GLuint p_ShaderProgram;
- };
- //----------------------------------------------------------------------------------------------------------------------------------------
- struct Font
- {
- Font(const std::string& filename, float size);
- GLuint getTexture() const;
- ftgl::texture_atlas_t* pp_FTAtlas = nullptr;
- ftgl::texture_font_t* pp_FTFont = nullptr;
- GLuint p_Texture = 0;
- };
- //----------------------------------------------------------------------------------------------------------------------------------------
- struct VertexData
- {
- glm::vec2 p_TexUV;
- glm::vec3 p_Position;
- GLuint p_Color;
- };
- #define RENDERER_MAX_SPRITES 60000
- #define RENDERER_MAX_ELEMENTS RENDERER_MAX_SPRITES * 6
- #define RENDERER_SPRITE_SIZE sizeof(VertexData) * 4
- #define RENDERER_VERTEX_BUFFER RENDERER_SPRITE_SIZE * RENDERER_MAX_SPRITES
- #define RENDERER_ELEMENT_BUFFER RENDERER_MAX_ELEMENTS * sizeof(GLuint)
- class Renderer
- {
- public:
- Renderer() = default;
- void Initialize();
- void Start();
- void Draw(const glm::vec4& destRect, const glm::vec4& uvRect, GLuint texture);
- void DrawString(const std::string& text, const glm::vec2& position, GLuint color, const Font& font);
- void End();
- GLuint p_Vao, p_Vbo, p_Ebo, p_IndexCount, p_Texture;
- Shader p_Shader;
- VertexData* pp_VertexData = nullptr;
- GLuint* setIndices();
- void setVertexData(const glm::vec3& position,
- const glm::vec2& texUV,
- GLuint color);
- };
- //----------------------------------------------------------------------------------------------------------------------------------------
- GLuint LoadFromFile(const std::string& filePath);
- GLuint CreateFromSource(int w, int h, int format, const void* pixels);
- void UpdateData(GLuint tex, int w, int h, int format, const void* pixels);
- //----------------------------------------------------------------------------------------------------------------------------------------
- int main(int argc, char* args[])
- {
- SDL_Init(SDL_INIT_EVERYTHING);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
- SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
- SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_Window* pp_Window = SDL_CreateWindow("FontTest", 0, 0, 1280, 720, SDL_WINDOW_OPENGL);
- SDL_GLContext p_Context = SDL_GL_CreateContext(pp_Window);
- SDL_Event p_Event;
- glewExperimental = true;
- glewInit();
- Renderer renderer;
- renderer.Initialize();
- Font* pp_Font = new Font("Vera.ttf", 150);
- glError(glClearColor(0.5, 0.5, 0.5, 1.0));
- bool quit = false;
- while (!quit) {
- while (SDL_PollEvent(&p_Event)) {
- if (p_Event.type == SDL_QUIT) {
- quit = true;
- }
- }
- glError(glClear(GL_COLOR_BUFFER_BIT));
- renderer.Start();
- renderer.DrawString("TESTOWY", glm::vec2(100.0f, 100.0f), 0xffff00ff, *pp_Font);
- renderer.End();
- SDL_GL_SwapWindow(pp_Window);
- }
- return 0;
- }
- GLuint LoadFromFile(const std::string& filePath)
- {
- SDL_Surface* surface = IMG_Load(filePath.c_str());
- int w = surface->w,
- h = surface->h,
- format = surface->format->BytesPerPixel == 4 ? GL_RGBA : GL_RGB;
- GLuint texture = 0;
- glError(glGenTextures(1, &texture));
- glError(glBindTexture(GL_TEXTURE_2D, texture));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- glError(glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, nullptr));
- glError(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, surface->pixels));
- glError(glGenerateMipmap(GL_TEXTURE_2D));
- glError(glBindTexture(GL_TEXTURE_2D, 0));
- return texture;
- }
- GLuint CreateFromSource(int w, int h, int format, const void* pixels)
- {
- GLuint texture = 0;
- glError(glGenTextures(1, &texture));
- glError(glBindTexture(GL_TEXTURE_2D, texture));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- glError(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- glError(glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, nullptr));
- glError(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, pixels));
- glError(glGenerateMipmap(GL_TEXTURE_2D));
- glError(glBindTexture(GL_TEXTURE_2D, 0));
- return texture;
- }
- void UpdateData(GLuint tex, int w, int h, int format, const void* pixels)
- {
- glError(glBindTexture(GL_TEXTURE_2D, tex));
- glError(glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, format, GL_UNSIGNED_BYTE, pixels));
- }
- GLenum GLCheckError()
- {
- return glGetError();
- }
- bool GLLogCall(const char* function, const char* file, int line)
- {
- GLenum error = GLCheckError();
- if (error != GL_NO_ERROR) {
- std::cout << "[OpenGL Error] (" + std::to_string(error) + "): " + function + " " + file + ":" + std::to_string(line) << std::endl;
- return false;
- }
- return true;
- }
- //----------------------------------------------------------------------------------------------------------------------------------------
- std::string Shader::LoadFromFile(const std::string& filePath)
- {
- std::ifstream openFile(filePath);
- std::stringstream sstream;
- sstream << openFile.rdbuf();
- return sstream.str();
- }
- void Shader::CreateShaderProgram()
- {
- p_ShaderProgram = glCreateProgram();
- }
- void Shader::CreateShaders(const GLchar* vertexShader, const GLchar* fragmenShader)
- {
- GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
- GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
- glError(glShaderSource(vertexShaderID, 1, &vertexShader, NULL));
- glError(glCompileShader(vertexShaderID));
- GLint isCompiled = 0;
- glError(glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &isCompiled));
- if (isCompiled == GL_FALSE) {
- GLint maxLength = 0;
- glError(glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &maxLength));
- std::vector<GLchar> infoLog(maxLength);
- glError(glGetShaderInfoLog(vertexShaderID, maxLength, &maxLength, &infoLog[0]));
- glError(glDeleteShader(vertexShaderID));
- std::cout << '%s\n' << &infoLog[0] << std::endl;
- return;
- }
- glError(glShaderSource(fragmentShaderID, 1, &fragmenShader, NULL));
- glError(glCompileShader(fragmentShaderID));
- glError(glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &isCompiled));
- if (isCompiled == GL_FALSE) {
- GLint maxLength = 0;
- glError(glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &maxLength));
- std::vector<GLchar> infoLog(maxLength);
- glError(glGetShaderInfoLog(fragmentShaderID, maxLength, &maxLength, &infoLog[0]));
- glError(glDeleteShader(fragmentShaderID));
- glError(glDeleteShader(vertexShaderID));
- std::cout << '%s\n' << &infoLog[0] << std::endl;
- return;
- }
- glError(glAttachShader(p_ShaderProgram, vertexShaderID));
- glError(glAttachShader(p_ShaderProgram, fragmentShaderID));
- glError(glLinkProgram(p_ShaderProgram));
- GLint isLinked = 0;
- glError(glGetProgramiv(p_ShaderProgram, GL_LINK_STATUS, (int *)&isLinked));
- if (isLinked == GL_FALSE) {
- GLint maxLength = 0;
- glError(glGetProgramiv(p_ShaderProgram, GL_INFO_LOG_LENGTH, &maxLength));
- std::vector<GLchar> infoLog(maxLength);
- glError(glGetProgramInfoLog(p_ShaderProgram, maxLength, &maxLength, &infoLog[0]));
- glError(glDeleteProgram(p_ShaderProgram));
- glError(glDeleteShader(vertexShaderID));
- glError(glDeleteShader(fragmentShaderID));
- std::cout << '%s\n' << &infoLog[0] << std::endl;
- return;
- }
- glError(glDetachShader(p_ShaderProgram, vertexShaderID));
- glError(glDetachShader(p_ShaderProgram, fragmentShaderID));
- glError(glDeleteShader(vertexShaderID));
- glError(glDeleteShader(fragmentShaderID));
- }
- void Shader::UseShaderProgram()
- {
- glError(glUseProgram(p_ShaderProgram));
- }
- GLint Shader::getUniformLocation(const std::string &uniformName)
- {
- return glGetUniformLocation(p_ShaderProgram, uniformName.c_str());
- }
- //----------------------------------------------------------------------------------------------------------------------------------------
- void Renderer::Initialize()
- {
- p_Vao = 0;
- p_Vbo = 0;
- p_Ebo = 0;
- p_IndexCount = 0;
- p_Texture = 0;
- glError(glGenVertexArrays(1, &p_Vao));
- glError(glBindVertexArray(p_Vao));
- glError(glGenBuffers(1, &p_Vbo));
- glError(glBindBuffer(GL_ARRAY_BUFFER, p_Vbo));
- glError(glBufferData(GL_ARRAY_BUFFER, RENDERER_VERTEX_BUFFER, nullptr, GL_DYNAMIC_DRAW));
- glError(glEnableVertexAttribArray(0));
- glError(glEnableVertexAttribArray(1));
- glError(glEnableVertexAttribArray(2));
- glError(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*)offsetof(VertexData, p_Position)));
- glError(glVertexAttribPointer(1, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VertexData), (const void*)offsetof(VertexData, p_Color)));
- glError(glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(VertexData), (const void*)offsetof(VertexData, p_TexUV)));
- glError(glGenBuffers(1, &p_Ebo));
- glError(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p_Ebo));
- glError(glBufferData(GL_ELEMENT_ARRAY_BUFFER, RENDERER_ELEMENT_BUFFER, setIndices(), GL_STATIC_DRAW));
- glError(glBindVertexArray(0));
- std::string vertex = p_Shader.LoadFromFile("vertex.shader");
- std::string fragment = p_Shader.LoadFromFile("fragment.shader");
- p_Shader.CreateShaderProgram();
- p_Shader.CreateShaders(vertex.c_str(), fragment.c_str());
- p_Shader.UseShaderProgram();
- GLint u_textureSampler = p_Shader.getUniformLocation("u_textureSampler");
- glError(glUniform1i(u_textureSampler, 0));
- }
- void Renderer::Start()
- {
- glm::mat4 projection = glm::mat4(1.0f);
- projection = glm::ortho(0.0f, 1280.0f, 720.0f, 0.0f);
- glError(glUniformMatrix4fv(p_Shader.getUniformLocation("projection"), 1, GL_FALSE, glm::value_ptr(projection)));
- pp_VertexData = (VertexData*)glMapNamedBufferRange(p_Vbo, NULL, RENDERER_VERTEX_BUFFER, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT);
- }
- void Renderer::DrawString(const std::string& text, const glm::vec2& position, GLuint color, const Font& font)
- {
- float x = position.x;
- texture_font_t* ftFont = font.pp_FTFont;
- for (GLuint i = 0; i < text.length(); ++i) {
- texture_glyph_t* glyph = texture_font_get_glyph(ftFont, text.c_str() + i);
- if (glyph) {
- if (i > 0) {
- float kerning = texture_glyph_get_kerning(glyph, text.c_str() + i - 1);
- x += kerning;
- }
- p_Texture = font.getTexture();
- float x0 = x + glyph->offset_x;
- float x1 = x0 + glyph->width;
- float y0 = position.y + glyph->offset_y;
- float y1 = y0 - glyph->height;
- float u0 = glyph->s0;
- float u1 = glyph->s1;
- float v0 = glyph->t0;
- float v1 = glyph->t1;
- setVertexData(glm::vec3(x0, y0, 0.0f), glm::vec2(u0, v0), color);
- setVertexData(glm::vec3(x0, y1, 0.0f), glm::vec2(u0, v1), color);
- setVertexData(glm::vec3(x1, y1, 0.0f), glm::vec2(u1, v1), color);
- setVertexData(glm::vec3(x1, y0, 0.0f), glm::vec2(u1, v0), color);
- p_IndexCount += 6;
- x += glyph->advance_x;
- }
- }
- }
- void Renderer::End()
- {
- glError(glUnmapNamedBuffer(p_Vbo));
- glError(glEnable(GL_BLEND));
- glError(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
- glError(glActiveTexture(GL_TEXTURE0));
- glError(glBindTexture(GL_TEXTURE_2D, p_Texture));
- glError(glBindVertexArray(p_Vao));
- glError(glDrawElements(GL_TRIANGLES, p_IndexCount, GL_UNSIGNED_INT, nullptr));
- glError(glBindVertexArray(0));
- p_IndexCount = 0;
- }
- GLuint* Renderer::setIndices()
- {
- GLuint* indices = new GLuint[RENDERER_ELEMENT_BUFFER],
- offset = 0;
- for (int i = 0; i < RENDERER_ELEMENT_BUFFER; i += 6) {
- indices[i] = offset;
- indices[i + 1] = offset + 1;
- indices[i + 2] = offset + 2;
- indices[i + 3] = offset + 2;
- indices[i + 4] = offset + 3;
- indices[i + 5] = offset;
- offset += 4;
- }
- return indices;
- }
- void Renderer::setVertexData(const glm::vec3& position, const glm::vec2& texUV, GLuint color)
- {
- pp_VertexData->p_Position = position;
- pp_VertexData->p_TexUV = texUV;
- pp_VertexData->p_Color = color;
- pp_VertexData++;
- }
- //----------------------------------------------------------------------------------------------------------------------------------------
- Font::Font(const std::string& filename, float size)
- {
- pp_FTAtlas = ftgl::texture_atlas_new(512, 512, 1);
- pp_FTFont = ftgl::texture_font_new_from_file(pp_FTAtlas, size, filename.c_str());
- p_Texture = CreateFromSource(512, 512, GL_RED, pp_FTAtlas->data);
- }
- GLuint Font::getTexture() const
- {
- UpdateData(p_Texture, 512, 512, GL_RED, pp_FTAtlas->data);
- return p_Texture;
- }
- //----------------------------------------------------------------------------------------------------------------------------------------
- //----------------------------------------------------------------------------------------------------------------------------------------
- #version 430 core
- layout (location = 0) in vec3 a_position;
- layout (location = 1) in vec4 a_color;
- layout (location = 2) in vec2 a_texUV;
- out vec3 v_position;
- out vec4 v_color;
- out vec2 v_texUV;
- uniform mat4 projection;
- void main()
- {
- gl_Position = projection * vec4(a_position, 1.0);
- v_position = a_position;
- v_color = a_color;
- v_texUV = vec2(a_texUV.x, 1 - a_texUV.y);
- }
- //----------------------------------------------------------------------------------------------------------------------------------------
- #version 430 core
- out vec4 finalColor;
- in vec2 v_position;
- in vec4 v_color;
- in vec2 v_texUV;
- uniform sampler2D u_textureSampler;
- void main()
- {
- float texColor = texture(u_textureSampler, v_texUV).a;
- finalColor= vec4(1.0f, 1.0f, 1.0f, texColor);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement