Continue adding opengl font support.
This commit is contained in:
parent
649079a5c7
commit
eef93efc29
37 changed files with 530 additions and 157 deletions
|
@ -19,8 +19,14 @@ set(OpenGL_GL_PREFERENCE "GLVND")
|
|||
find_package(OpenGL QUIET)
|
||||
if (OpenGL_FOUND)
|
||||
list(APPEND platform_LIBS OpenGL::GL OpenGL::GLU)
|
||||
list(APPEND graphics_LIB_INCLUDES opengl/OpenGlPainter.cpp)
|
||||
list(APPEND graphics_HEADERS opengl/OpenGlPainter.h)
|
||||
list(APPEND graphics_LIB_INCLUDES
|
||||
opengl/OpenGlPainter.cpp
|
||||
opengl/OpenGlFontTexture.cpp
|
||||
opengl/OpenGlShaderProgram.cpp)
|
||||
list(APPEND graphics_HEADERS
|
||||
opengl/OpenGlPainter.h
|
||||
opengl/OpenGlFontTexture.h
|
||||
opengl/OpenGlShaderProgram.h)
|
||||
else()
|
||||
message(STATUS "OpenGL headers not found - skipping OpenGL support")
|
||||
endif()
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "AbstractPainter.h"
|
||||
#include "OpenGlPainter.h"
|
||||
#include "OpenGlShaderProgram.h"
|
||||
#include "OpenGlFontTexture.h"
|
||||
#include "RasterPainter.h"
|
||||
#include "Grid.h"
|
||||
#include "TriMesh.h"
|
||||
|
@ -40,6 +42,11 @@ DrawingSurface* DrawingContext::getSurface() const
|
|||
return mSurface;
|
||||
}
|
||||
|
||||
FontsManager* DrawingContext::getFontsManager() const
|
||||
{
|
||||
return mFontsManager;
|
||||
}
|
||||
|
||||
void DrawingContext::paint()
|
||||
{
|
||||
mScene->update(mFontsManager, mDrawingMode == DrawingMode::RASTER ? mSurface->getImage() : nullptr);
|
||||
|
|
|
@ -25,6 +25,8 @@ public:
|
|||
|
||||
DrawingSurface* getSurface() const;
|
||||
|
||||
FontsManager* getFontsManager() const;
|
||||
|
||||
void paint();
|
||||
|
||||
private:
|
||||
|
|
36
src/graphics/opengl/OpenGlFontTexture.cpp
Normal file
36
src/graphics/opengl/OpenGlFontTexture.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "OpenGlFontTexture.h"
|
||||
|
||||
#include "FontGlyph.h"
|
||||
#include "Image.h"
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
|
||||
OpenGlFontTexture::OpenGlFontTexture(FontGlyph* glyph)
|
||||
: mGlyph(glyph)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
glGenTextures(1, &mHandle);
|
||||
glBindTexture(GL_TEXTURE_2D, mHandle);
|
||||
|
||||
auto buffer = glyph->getImage()->getDataPtr();
|
||||
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D,
|
||||
0,
|
||||
GL_RED,
|
||||
mGlyph->getWidth(),
|
||||
mGlyph->getHeight(),
|
||||
0,
|
||||
GL_RED,
|
||||
GL_UNSIGNED_BYTE,
|
||||
buffer
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
}
|
13
src/graphics/opengl/OpenGlFontTexture.h
Normal file
13
src/graphics/opengl/OpenGlFontTexture.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
class FontGlyph;
|
||||
|
||||
class OpenGlFontTexture
|
||||
{
|
||||
public:
|
||||
OpenGlFontTexture(FontGlyph* glyph);
|
||||
|
||||
private:
|
||||
unsigned int mHandle{0};
|
||||
FontGlyph* mGlyph{nullptr};
|
||||
};
|
|
@ -5,6 +5,15 @@
|
|||
#include "Scene.h"
|
||||
#include "TriMesh.h"
|
||||
|
||||
#include "FontsManager.h"
|
||||
#include "FontGlyph.h"
|
||||
|
||||
#include "OpenGlFontTexture.h"
|
||||
#include "OpenGlShaderProgram.h"
|
||||
#include "TextData.h"
|
||||
|
||||
#include "File.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
@ -14,30 +23,18 @@
|
|||
#include <GL/glu.h>
|
||||
#include <GL/glx.h>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
const char* vertexShaderSource = "#version 330 core\n"
|
||||
"layout (location = 0) in vec3 aPos;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
|
||||
"}\0";
|
||||
|
||||
|
||||
const char* fragmentShaderSource = "#version 330 core\n"
|
||||
"out vec4 FragColor;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
"FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
|
||||
"}\n";
|
||||
|
||||
|
||||
OpenGlPainter::OpenGlPainter()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void OpenGlPainter::initialize()
|
||||
void OpenGlPainter::initializeMeshShader()
|
||||
{
|
||||
if (auto context = glXGetCurrentContext())
|
||||
{
|
||||
|
@ -54,99 +51,70 @@ void OpenGlPainter::initialize()
|
|||
glGetIntegerv(GL_MINOR_VERSION, &minor_version);
|
||||
std::cout << "Using opengl version " << major_version << "|" << minor_version << std::endl;
|
||||
|
||||
std::cout << "Creating opengl painter" << std::endl;
|
||||
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
auto vert_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/default.vert";
|
||||
auto frag_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/default.frag";
|
||||
|
||||
int success;
|
||||
char infoLog[512];
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
mMeshShaderProgram = std::make_unique<OpenGlShaderProgram>(vert_shader_path, frag_shader_path);
|
||||
}
|
||||
|
||||
void OpenGlPainter::initializeTextShader()
|
||||
{
|
||||
auto vert_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/text.vert";
|
||||
auto frag_shader_path = std::filesystem::path(__FILE__).parent_path() / "shaders/text.frag";
|
||||
|
||||
mTextShaderProgram = std::make_unique<OpenGlShaderProgram>(vert_shader_path, frag_shader_path);
|
||||
}
|
||||
|
||||
void OpenGlPainter::renderTextLayer(const TextData& textData, DrawingContext* context)
|
||||
{
|
||||
if (!mTextShaderProgram)
|
||||
{
|
||||
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
|
||||
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << std::string(infoLog) << std::endl;
|
||||
initializeTextShader();
|
||||
}
|
||||
|
||||
if (auto errCode = glGetError(); errCode != GL_NO_ERROR)
|
||||
{
|
||||
auto errString = gluErrorString(errCode);
|
||||
std::cout << "Got gl error" << errString << std::endl;
|
||||
}
|
||||
auto first_char = textData.mContent[0];
|
||||
auto iter = mFontTextures.find(first_char);
|
||||
OpenGlFontTexture* working_texture{nullptr};
|
||||
if (iter == mFontTextures.end())
|
||||
{
|
||||
auto glyph = context->getFontsManager()->getGlyph(first_char);
|
||||
auto new_texture = std::make_unique<OpenGlFontTexture>(nullptr);
|
||||
working_texture = new_texture.get();
|
||||
mFontTextures[first_char] = std::move(new_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Shader compiled ok" << std::endl;
|
||||
if (auto errCode = glGetError(); errCode != GL_NO_ERROR)
|
||||
{
|
||||
auto errString = gluErrorString(errCode);
|
||||
std::cout << "Got gl error after ok" << errString << std::endl;
|
||||
}
|
||||
working_texture = iter->second.get();
|
||||
}
|
||||
|
||||
unsigned int fragmentShader;
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
|
||||
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << infoLog << std::endl;
|
||||
}
|
||||
|
||||
mShaderProgram = glCreateProgram();
|
||||
|
||||
glAttachShader(mShaderProgram, vertexShader);
|
||||
glAttachShader(mShaderProgram, fragmentShader);
|
||||
glLinkProgram(mShaderProgram);
|
||||
|
||||
glGetProgramiv(mShaderProgram, GL_LINK_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetProgramInfoLog(mShaderProgram, 512, NULL, infoLog);
|
||||
std::cout << "Shader linking FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
mInitialized = true;
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void OpenGlPainter::paint(DrawingContext* context)
|
||||
void OpenGlPainter::renderMeshLayer(TriMesh* mesh, DrawingContext* context)
|
||||
{
|
||||
if (!mInitialized)
|
||||
if (!mMeshShaderProgram)
|
||||
{
|
||||
initialize();
|
||||
initializeMeshShader();
|
||||
}
|
||||
|
||||
auto surface = context->getSurface();
|
||||
const auto width = double(surface->getWidth());
|
||||
const auto height = double(surface->getHeight());
|
||||
const auto num_mesh = context->getScene()->getNumMeshes();
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
//glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
|
||||
//glScissor(0, 0, width, height);
|
||||
//glMatrixMode(GL_PROJECTION);
|
||||
//glLoadIdentity();
|
||||
|
||||
glClearColor(0.5, 0.5, 1.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
//glMatrixMode(GL_MODELVIEW);
|
||||
//glLoadIdentity();
|
||||
|
||||
float vertices[] = {
|
||||
-0.5f, -0.5f, 0.0f,
|
||||
0.5f, -0.5f, 0.0f,
|
||||
0.0f, 0.5f, 0.0f
|
||||
0.5f, 0.5f, 0.0f, // top right
|
||||
0.5f, -0.5f, 0.0f, // bottom right
|
||||
-0.5f, -0.5f, 0.0f, // bottom left
|
||||
-0.5f, 0.5f, 0.0f // top left
|
||||
};
|
||||
|
||||
unsigned int indices[] = { // note that we start from 0!
|
||||
0, 1, 3, // first triangle
|
||||
1, 2, 3 // second triangle
|
||||
};
|
||||
unsigned int vbo{0};
|
||||
glGenBuffers(1, &vbo);
|
||||
|
||||
unsigned int EBO;
|
||||
glGenBuffers(1, &EBO);
|
||||
|
||||
unsigned int VAO;
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
@ -154,14 +122,22 @@ void OpenGlPainter::paint(DrawingContext* context)
|
|||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glUseProgram(mShaderProgram);
|
||||
int vertexColorLocation = glGetUniformLocation(mMeshShaderProgram->getHandle(), "ourColor");
|
||||
|
||||
glUseProgram(mMeshShaderProgram->getHandle());
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||
glUniform4f(vertexColorLocation, 0.0f, 1.0, 0.0f, 1.0f);
|
||||
|
||||
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
/*
|
||||
std::cout << "Bounds are : " << width << " | " << height << std::endl;
|
||||
|
||||
|
@ -207,6 +183,31 @@ void OpenGlPainter::paint(DrawingContext* context)
|
|||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void OpenGlPainter::paint(DrawingContext* context)
|
||||
{
|
||||
auto surface = context->getSurface();
|
||||
const auto width = double(surface->getWidth());
|
||||
const auto height = double(surface->getHeight());
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
//glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
|
||||
//glScissor(0, 0, width, height);
|
||||
//glMatrixMode(GL_PROJECTION);
|
||||
//glLoadIdentity();
|
||||
|
||||
glClearColor(0.5, 0.5, 1.0, 0.0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
//glMatrixMode(GL_MODELVIEW);
|
||||
//glLoadIdentity();
|
||||
|
||||
const auto num_mesh = context->getScene()->getNumMeshes();
|
||||
//renderMeshLayer(nullptr, context);
|
||||
|
||||
auto text_data = context->getScene()->getTextData();
|
||||
renderTextLayer(text_data[0], context);
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
|
|
@ -2,21 +2,33 @@
|
|||
|
||||
#include "AbstractPainter.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
class DrawingContext;
|
||||
class OpenGlFontTexture;
|
||||
class OpenGlShaderProgram;
|
||||
|
||||
class TextData;
|
||||
class TriMesh;
|
||||
|
||||
class OpenGlPainter : public AbstractPainter
|
||||
{
|
||||
public:
|
||||
|
||||
OpenGlPainter();
|
||||
|
||||
|
||||
void initialize();
|
||||
void paint(DrawingContext* context) override;
|
||||
|
||||
private:
|
||||
bool mInitialized{false};
|
||||
unsigned int mShaderProgram{0};
|
||||
void initializeMeshShader();
|
||||
void initializeTextShader();
|
||||
|
||||
void renderTextLayer(const TextData& textData, DrawingContext* context);
|
||||
void renderMeshLayer(TriMesh* mesh, DrawingContext* context);
|
||||
|
||||
std::unique_ptr<OpenGlShaderProgram> mMeshShaderProgram;
|
||||
std::unique_ptr<OpenGlShaderProgram> mTextShaderProgram;
|
||||
std::unordered_map<char, std::unique_ptr<OpenGlFontTexture> > mFontTextures;
|
||||
};
|
||||
|
||||
|
||||
|
|
68
src/graphics/opengl/OpenGlShaderProgram.cpp
Normal file
68
src/graphics/opengl/OpenGlShaderProgram.cpp
Normal file
|
@ -0,0 +1,68 @@
|
|||
#include "OpenGlShaderProgram.h"
|
||||
|
||||
#include "File.h"
|
||||
#include "FileLogger.h"
|
||||
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glu.h>
|
||||
|
||||
OpenGlShaderProgram::OpenGlShaderProgram(const Path& vertShaderPath, const Path& fragShaderPath)
|
||||
{
|
||||
const auto vert_shader_source = File(vertShaderPath).read();
|
||||
const auto frag_shader_source = File(fragShaderPath).read();
|
||||
|
||||
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
|
||||
const char* vert_source = vert_shader_source.c_str();
|
||||
glShaderSource(vertexShader, 1, &vert_source, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
|
||||
int success;
|
||||
char infoLog[512];
|
||||
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(vertexShader, 512, nullptr, infoLog);
|
||||
MLOG_ERROR("ERROR::SHADER::VERTEX::COMPILATION_FAILED: " << infoLog);
|
||||
if (auto errCode = glGetError(); errCode != GL_NO_ERROR)
|
||||
{
|
||||
auto errString = gluErrorString(errCode);
|
||||
MLOG_ERROR("Got gl error " << errString);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int fragmentShader;
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
const char* frag_source = frag_shader_source.c_str();
|
||||
glShaderSource(fragmentShader, 1, &frag_source, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
|
||||
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
|
||||
MLOG_ERROR("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED: " << infoLog);
|
||||
}
|
||||
|
||||
mHandle = glCreateProgram();
|
||||
|
||||
glAttachShader(mHandle, vertexShader);
|
||||
glAttachShader(mHandle, fragmentShader);
|
||||
glLinkProgram(mHandle);
|
||||
|
||||
glGetProgramiv(mHandle, GL_LINK_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetProgramInfoLog(mHandle, 512, NULL, infoLog);
|
||||
MLOG_ERROR("Shader linking FAILED: " << infoLog);
|
||||
}
|
||||
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
}
|
||||
|
||||
unsigned int OpenGlShaderProgram::getHandle() const
|
||||
{
|
||||
return mHandle;
|
||||
}
|
15
src/graphics/opengl/OpenGlShaderProgram.h
Normal file
15
src/graphics/opengl/OpenGlShaderProgram.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
using Path = std::filesystem::path;
|
||||
|
||||
class OpenGlShaderProgram
|
||||
{
|
||||
public:
|
||||
OpenGlShaderProgram(const Path& vertShaderPath, const Path& fragShaderPath);
|
||||
|
||||
unsigned int getHandle() const;
|
||||
private:
|
||||
unsigned int mHandle{0};
|
||||
};
|
11
src/graphics/opengl/shaders/default.frag
Normal file
11
src/graphics/opengl/shaders/default.frag
Normal file
|
@ -0,0 +1,11 @@
|
|||
#version 330 core
|
||||
out vec4 FragColor;
|
||||
|
||||
in vec4 vertexColor; // the input variable from the vertex shader (same name and same type)
|
||||
|
||||
uniform vec4 ourColor; // we set this variable in the OpenGL code.
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = ourColor;
|
||||
}
|
10
src/graphics/opengl/shaders/default.vert
Normal file
10
src/graphics/opengl/shaders/default.vert
Normal file
|
@ -0,0 +1,10 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec3 aPos; // the position variable has attribute position 0
|
||||
|
||||
out vec4 vertexColor; // specify a color output to the fragment shader
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = vec4(aPos, 1.0); // see how we directly give a vec3 to vec4's constructor
|
||||
vertexColor = vec4(aPos.x, aPos.y, 0.0, 1.0); // set the output variable to a dark-red color
|
||||
}
|
12
src/graphics/opengl/shaders/text.frag
Normal file
12
src/graphics/opengl/shaders/text.frag
Normal file
|
@ -0,0 +1,12 @@
|
|||
#version 330 core
|
||||
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;
|
||||
}
|
11
src/graphics/opengl/shaders/text.vert
Normal file
11
src/graphics/opengl/shaders/text.vert
Normal file
|
@ -0,0 +1,11 @@
|
|||
#version 330 core
|
||||
layout (location = 0) in vec4 vertex; // <vec2 pos, vec2 tex>
|
||||
out vec2 TexCoords;
|
||||
|
||||
uniform mat4 projection;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = projection * vec4(vertex.xy, 0.0, 1.0);
|
||||
TexCoords = vertex.zw;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue