|
|
|
|
/******************************************************************************
|
|
|
|
|
* File - OGLGraphics.cpp
|
|
|
|
|
* Author - Joey Pollack
|
|
|
|
|
* Date - 2021/08/30 (y/m/d)
|
|
|
|
|
* Mod Date - 2021/09/02 (y/m/d)
|
|
|
|
|
* Description - An openGL implementation of the engine Graphics interface.
|
|
|
|
|
******************************************************************************/
|
|
|
|
|
|
|
|
|
|
#include "glGraphics.h"
|
|
|
|
|
#include "defaultShaders.h"
|
|
|
|
|
#include <window/window.h>
|
|
|
|
|
#include "../image.h"
|
|
|
|
|
#include "../internalFont.h"
|
|
|
|
|
#include <utils/logger.h>
|
|
|
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
|
#include <glm/gtc/type_ptr.hpp>
|
|
|
|
|
|
|
|
|
|
#include <utils/stb/stb_image.h>
|
|
|
|
|
|
|
|
|
|
namespace lunarium
|
|
|
|
|
{
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
// DEBUG MESSAGE CALLBACK
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
std::map<int, std::string> OglGraphics::mDebugMsgTypes;
|
|
|
|
|
std::map<int, std::string> OglGraphics::mDebugMsgSources;
|
|
|
|
|
std::map<int, std::string> OglGraphics::mDebugMsgSeverity;
|
|
|
|
|
|
|
|
|
|
void GLAPIENTRY MessageCallback(GLenum source, GLenum type, GLuint id,
|
|
|
|
|
GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::OGL_DEBUG,
|
|
|
|
|
"%s (type: %s, source: %s, severity: %s), message: %s",
|
|
|
|
|
(type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : ""),
|
|
|
|
|
OglGraphics::mDebugMsgSources[source].c_str(),
|
|
|
|
|
OglGraphics::mDebugMsgTypes[type].c_str(),
|
|
|
|
|
OglGraphics::mDebugMsgSeverity[severity].c_str(),
|
|
|
|
|
message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
// RESTRICTED METHODS
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
OglGraphics::OglGraphics()
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
OpRes OglGraphics::Initialize(Window* pWindow, bool enableDebugMessages)
|
|
|
|
|
{
|
|
|
|
|
if (!pWindow->IsInit())
|
|
|
|
|
{
|
|
|
|
|
return OpRes::Fail("Can not initialize Graphics interface. The Window must be initialized first!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mbIsInit)
|
|
|
|
|
{
|
|
|
|
|
return OpRes::Fail("Can not initialize Graphics interface. It is already initialized");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mpWindow = pWindow;
|
|
|
|
|
mpFBTexture = new Image;
|
|
|
|
|
ResizeCanvas(); // Also calls InitTextureFrameBuffer
|
|
|
|
|
|
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
|
|
|
|
|
|
if (enableDebugMessages)
|
|
|
|
|
{
|
|
|
|
|
InitDebugMsgSystem();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize the 2D drawing systems
|
|
|
|
|
InitImageSystem();
|
|
|
|
|
InitShapeSystem();
|
|
|
|
|
|
|
|
|
|
// Init text rendering
|
|
|
|
|
OpRes res = mText.Initialize();
|
|
|
|
|
if (Failed(res))
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Could not initialized the text renderer - %s", res.Description);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Load the default internal font
|
|
|
|
|
const char* font = "OpenSans-Regular.ttf";
|
|
|
|
|
GenerateFontFileAt(font);
|
|
|
|
|
mDefaultFont = mText.LoadFont(font);
|
|
|
|
|
if (mDefaultFont < 0)
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to load the default font: %s", font);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO, "Successfully created default font: %s", font);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return OpRes::OK();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::Shutdown()
|
|
|
|
|
{
|
|
|
|
|
// Nothing to clean up at this point
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void OglGraphics::ResizeCanvas()
|
|
|
|
|
{
|
|
|
|
|
// Get viewport size from glfw window
|
|
|
|
|
glfwGetFramebufferSize(mpWindow->GetWindow(), &mFBWidth, &mFBHeight);
|
|
|
|
|
|
|
|
|
|
glViewport(0, 0, mFBWidth, mFBHeight);
|
|
|
|
|
mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, (GLfloat)mFBHeight, 0.0f, -1.0f, 1.0f);
|
|
|
|
|
// mProjection = glm::ortho(0.0f, (GLfloat)mFBWidth, 0.0f, (GLfloat)mFBHeight, -1.0f, 1.0f);
|
|
|
|
|
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE,
|
|
|
|
|
"glViewport set to %d, %d", mFBWidth, mFBHeight);
|
|
|
|
|
|
|
|
|
|
InitTextureFrameBuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void OglGraphics::BeginDraw(RenderTarget rt)
|
|
|
|
|
{
|
|
|
|
|
mRT = rt;
|
|
|
|
|
|
|
|
|
|
if (mRT == RenderTarget::RT_IMAGE)
|
|
|
|
|
{
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Image* OglGraphics::EndDraw()
|
|
|
|
|
{
|
|
|
|
|
if (mRT == RenderTarget::RT_IMAGE)
|
|
|
|
|
{
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mpFBTexture->mGLTextureID);
|
|
|
|
|
|
|
|
|
|
// Buffer width and height (in pixels) is the same as the screen size
|
|
|
|
|
// Need to multiply these by the number bytes per pixel
|
|
|
|
|
//int bufferSize = mFBWidth * mFBHeight * 4; // NOTE: Assuming 4 channels for now
|
|
|
|
|
//unsigned char* buffer = new unsigned char[bufferSize];
|
|
|
|
|
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, (void*)buffer);
|
|
|
|
|
|
|
|
|
|
//FlipImageVertically(buffer, mFBWidth, mFBHeight, 1);
|
|
|
|
|
|
|
|
|
|
//glSetTexImage()
|
|
|
|
|
|
|
|
|
|
mpFBTexture->FreeRawData();
|
|
|
|
|
mpFBTexture->mWidth = mFBWidth;
|
|
|
|
|
mpFBTexture->mHeight = mFBHeight;
|
|
|
|
|
mpFBTexture->mFormat = ImageFormat::RGBA;
|
|
|
|
|
|
|
|
|
|
// return a copy of the image
|
|
|
|
|
return mpFBTexture;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
mpWindow->SwapBuffers();
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
// USER METHODS
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
void OglGraphics::SetClearColor(Color c)
|
|
|
|
|
{
|
|
|
|
|
mClearColor = c;
|
|
|
|
|
glClearColor(mClearColor.Red, mClearColor.Green, mClearColor.Blue, mClearColor.Alpha);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Color OglGraphics::GetClearColor() const
|
|
|
|
|
{
|
|
|
|
|
return mClearColor;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Draw Methods
|
|
|
|
|
void OglGraphics::DrawLine(glm::vec2 point1, glm::vec2 point2, Color color, float lineWidth)
|
|
|
|
|
{
|
|
|
|
|
mShapeShader.MakeActive();
|
|
|
|
|
mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
glBindVertexArray(mRectVAO);
|
|
|
|
|
|
|
|
|
|
GLfloat lineVerts[6][4] = {
|
|
|
|
|
{ point1.x, point1.y, },
|
|
|
|
|
{ point2.x, point2.y, },
|
|
|
|
|
{ 0.0f, 0.0f, },
|
|
|
|
|
|
|
|
|
|
{ 0.0f, 0.0f, },
|
|
|
|
|
{ 0.0f, 0.0f, },
|
|
|
|
|
{ 0.0f, 0.0f, }
|
|
|
|
|
};
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mRectVBO);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(lineVerts), lineVerts);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
|
|
glLineWidth(lineWidth);
|
|
|
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawEllipse(glm::vec2 center, glm::vec2 radii, Color color, float thickness, int resolution)
|
|
|
|
|
{
|
|
|
|
|
mShapeShader.MakeActive();
|
|
|
|
|
mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
glBindVertexArray(mEllipseVAO);
|
|
|
|
|
|
|
|
|
|
GLfloat points[360][2];
|
|
|
|
|
for (int i = 0; i < 360; i++)
|
|
|
|
|
{
|
|
|
|
|
float rad = i * 3.14159f / 180.0f;
|
|
|
|
|
points[i][0] = center.x + (radii.x * cos(rad));
|
|
|
|
|
points[i][1] = center.y + (radii.y * sin(rad));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
|
|
glLineWidth(thickness);
|
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, 360);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawFilledEllipse(glm::vec2 center, glm::vec2 radii, Color color, int resolution)
|
|
|
|
|
{
|
|
|
|
|
mShapeShader.MakeActive();
|
|
|
|
|
mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
glBindVertexArray(mEllipseVAO);
|
|
|
|
|
|
|
|
|
|
GLfloat points[362][2];
|
|
|
|
|
points[0][0] = center.x;
|
|
|
|
|
points[0][1] = center.y;
|
|
|
|
|
for (int i = 1; i < 362; i++)
|
|
|
|
|
{
|
|
|
|
|
float rad = (i - 1) * 3.14159f / 180.0f;
|
|
|
|
|
points[i][0] = center.x + (radii.x * cos(rad));
|
|
|
|
|
points[i][1] = center.y + (radii.y * sin(rad));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(points), points);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
|
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 362);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawFilledBox(glm::vec2 topLeft, glm::vec2 botRight, Color color)
|
|
|
|
|
{
|
|
|
|
|
mShapeShader.MakeActive();
|
|
|
|
|
mShapeShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
mShapeShader.SetUniformf("shapeColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
glBindVertexArray(mRectVAO);
|
|
|
|
|
|
|
|
|
|
GLfloat vertices[6][4] = {
|
|
|
|
|
{ topLeft.x, botRight.y, },
|
|
|
|
|
{ botRight.x, topLeft.y, },
|
|
|
|
|
{ topLeft.x, topLeft.y, },
|
|
|
|
|
|
|
|
|
|
{ topLeft.x, botRight.y, },
|
|
|
|
|
{ botRight.x, botRight.y, },
|
|
|
|
|
{ botRight.x, topLeft.y, }
|
|
|
|
|
};
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mRectVBO);
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
// Render quad
|
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawBox(Rectangle dimensions, Color color, float thickness)
|
|
|
|
|
{
|
|
|
|
|
glm::vec2 topLeft(dimensions.Left, dimensions.Top);
|
|
|
|
|
glm::vec2 botRight(dimensions.right(), dimensions.bottom());
|
|
|
|
|
|
|
|
|
|
// left side top to bottom
|
|
|
|
|
DrawLine(glm::vec2(topLeft.x, topLeft.y), glm::vec2(topLeft.x, botRight.y), color, thickness);
|
|
|
|
|
|
|
|
|
|
// bottom left to right
|
|
|
|
|
DrawLine(glm::vec2(topLeft.x, botRight.y), glm::vec2(botRight.x, botRight.y), color, thickness);
|
|
|
|
|
|
|
|
|
|
// right side bottom to top
|
|
|
|
|
DrawLine(glm::vec2(botRight.x, botRight.y), glm::vec2(botRight.x, topLeft.y), color, thickness);
|
|
|
|
|
|
|
|
|
|
// top right to left
|
|
|
|
|
DrawLine(glm::vec2(botRight.x, topLeft.y), glm::vec2(topLeft.x, topLeft.y), color, thickness);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawImage(Image& image, glm::vec2 topLeft, Color color)
|
|
|
|
|
{
|
|
|
|
|
DrawImage(image, Rectangle(0.0f, 0.0f, (float)image.GetWidth(), (float)image.GetHeight()),
|
|
|
|
|
Rectangle(topLeft.x, topLeft.y, (float)image.GetWidth(), (float)image.GetHeight()), color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawImage(Image& image, Rectangle source, Rectangle destination, Color color)
|
|
|
|
|
{
|
|
|
|
|
glm::mat4 id = glm::mat4(1.0f);
|
|
|
|
|
glm::vec3 pos = glm::vec3(destination.Left, destination.Top, 0.0f);
|
|
|
|
|
glm::mat4 trans = glm::translate(id, pos);
|
|
|
|
|
trans = glm::scale(trans, glm::vec3(destination.Width, destination.Height, 1.0f));
|
|
|
|
|
|
|
|
|
|
mImageShader.MakeActive();
|
|
|
|
|
|
|
|
|
|
// float widthDiff = image.GetWidth() - source.Width;
|
|
|
|
|
|
|
|
|
|
// if (source.Width == image.GetWidth() && source.Height == image.GetHeight())
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
|
|
// mImageShader.SetUniformf("uvManip", { 1.0f, 0.0f, 1.0f, 0.0f }); // No uv Manipulation
|
|
|
|
|
// mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans));
|
|
|
|
|
// mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
// mImageShader.SetUniformf("spriteColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
// }
|
|
|
|
|
// else
|
|
|
|
|
// {
|
|
|
|
|
|
|
|
|
|
// NOTE: Pretty sure these values will work out to be correct with out the if check
|
|
|
|
|
float xScale = source.Width / image.GetWidth();
|
|
|
|
|
float xOffset = source.Left / image.GetWidth();
|
|
|
|
|
float yScale = source.Height / image.GetHeight();
|
|
|
|
|
float yOffset = source.Top / image.GetHeight();
|
|
|
|
|
|
|
|
|
|
// Logger::Log(LogCategory::GRAPHICS, LogLevel::INFO_VERBOSE, "uvManip Values: %f, %f, %f, %f", xScale, xOffset, yScale, yOffset);
|
|
|
|
|
|
|
|
|
|
// * -1.0f on yScale will flip the image vertically
|
|
|
|
|
mImageShader.SetUniformf("uvManip", { xScale, xOffset, yScale /** -1.0f*/, yOffset});
|
|
|
|
|
mImageShader.SetUniformMatrix("model", 1, glm::value_ptr(trans));
|
|
|
|
|
mImageShader.SetUniformMatrix("projection", 1, glm::value_ptr(mProjection));
|
|
|
|
|
mImageShader.SetUniformf("spriteColor", { color.Red, color.Green, color.Blue, color.Alpha });
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, image.GetGLTextureID());
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(mImageVAO);
|
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DrawString(const char* string, Rectangle boundingArea, Color color, float scale, int font)
|
|
|
|
|
{
|
|
|
|
|
mText.DrawString(font, string, glm::vec2(boundingArea.Left, boundingArea.Top),
|
|
|
|
|
glm::vec2(boundingArea.right(), boundingArea.bottom()), color, scale, mProjection);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Takes raw image data and creates and Image class instance out of it.
|
|
|
|
|
// The raw data must be in one of the ImageFormats and it must be 1 byte per channel.
|
|
|
|
|
Image* OglGraphics::CreateImage(const unsigned char* pData, int width, int height, ImageFormat format)
|
|
|
|
|
{
|
|
|
|
|
unsigned int glFormat[4] = { GL_RGB, GL_RGBA, GL_BGR, GL_BGRA };
|
|
|
|
|
unsigned int textureID = 0;
|
|
|
|
|
glGenTextures(1, &textureID);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, textureID);
|
|
|
|
|
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, glFormat[format], width, height, 0, glFormat[format], GL_UNSIGNED_BYTE, pData);
|
|
|
|
|
glGenerateMipmap(GL_TEXTURE_2D);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: Move this to a different function to allow for more user options
|
|
|
|
|
// Or make a version of the method that takes a struct for these options
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
|
|
|
|
|
Image* image = new Image;
|
|
|
|
|
image->mWidth = width;
|
|
|
|
|
image->mHeight = height;
|
|
|
|
|
image->mGLTextureID = textureID;
|
|
|
|
|
|
|
|
|
|
return image;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::DestroyImage(Image* i)
|
|
|
|
|
{
|
|
|
|
|
i->FreeRawData();
|
|
|
|
|
delete i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fonts
|
|
|
|
|
int OglGraphics::DefaultFont() const
|
|
|
|
|
{
|
|
|
|
|
return mDefaultFont;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// For weight, 400 is normal and 700 is bold
|
|
|
|
|
int OglGraphics::CreateNewFont(const char* fontName, float size, int weight)
|
|
|
|
|
{
|
|
|
|
|
return mText.LoadFont(fontName, size, weight);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
// HELPER INIT METHODS
|
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void OglGraphics::InitDebugMsgSystem()
|
|
|
|
|
{
|
|
|
|
|
// DEBUG MESSAGE TYPES
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_ERROR] = "ERROR";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR] = "DEPRECATED_BEHAVIOR";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR] = "UNDEFINED_BEHAVIOR";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_PORTABILITY] = "PORTABILITY";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_PERFORMANCE] = "PERFORMANCE";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_OTHER] = "OTHER";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_MARKER] = "MARKER";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_PUSH_GROUP] = "PUSH_GROUP";
|
|
|
|
|
mDebugMsgTypes[GL_DEBUG_TYPE_POP_GROUP] = "POP_GROUP";
|
|
|
|
|
|
|
|
|
|
// DEBUG MESSAGE SOURCES
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_API] = "API";
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_WINDOW_SYSTEM] = "WINDOW_SYSTEM";
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_SHADER_COMPILER] = "SHADER_COMPILER";
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_THIRD_PARTY] = "THIRD_PARTY";
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_APPLICATION] = "APPLICATION";
|
|
|
|
|
mDebugMsgSources[GL_DEBUG_SOURCE_OTHER] = "OTHER";
|
|
|
|
|
|
|
|
|
|
// DEBUG MESSAGE SEVERITY
|
|
|
|
|
mDebugMsgSeverity[GL_DEBUG_SEVERITY_HIGH] = "HIGH";
|
|
|
|
|
mDebugMsgSeverity[GL_DEBUG_SEVERITY_MEDIUM] = "MEDIUM";
|
|
|
|
|
mDebugMsgSeverity[GL_DEBUG_SEVERITY_LOW] = "LOW";
|
|
|
|
|
mDebugMsgSeverity[GL_DEBUG_SEVERITY_NOTIFICATION] = "NOTIFICATION";
|
|
|
|
|
|
|
|
|
|
glEnable(GL_DEBUG_OUTPUT);
|
|
|
|
|
glDebugMessageCallback(MessageCallback, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::InitImageSystem()
|
|
|
|
|
{
|
|
|
|
|
// Setup geometry
|
|
|
|
|
// https://learnopengl.com/In-Practice/2D-Game/Rendering-Sprites
|
|
|
|
|
GLuint VBO;
|
|
|
|
|
GLfloat vertices[] = {
|
|
|
|
|
// Pos // Tex
|
|
|
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
|
|
|
1.0f, 0.0f, 1.0f, 1.0f,
|
|
|
|
|
0.0f, 0.0f, 0.0f, 1.0f,
|
|
|
|
|
|
|
|
|
|
0.0f, 1.0f, 0.0f, 0.0f,
|
|
|
|
|
1.0f, 1.0f, 1.0f, 0.0f,
|
|
|
|
|
1.0f, 0.0f, 1.0f, 1.0f
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// GLfloat vertices[] = {
|
|
|
|
|
// // Pos // Tex
|
|
|
|
|
// 0.0f, 1.0f, 0.0f, 1.0f,
|
|
|
|
|
// 1.0f, 0.0f, 1.0f, 0.0f,
|
|
|
|
|
// 0.0f, 0.0f, 0.0f, 0.0f,
|
|
|
|
|
|
|
|
|
|
// 0.0f, 1.0f, 0.0f, 1.0f,
|
|
|
|
|
// 1.0f, 1.0f, 1.0f, 1.0f,
|
|
|
|
|
// 1.0f, 0.0f, 1.0f, 0.0f
|
|
|
|
|
// };
|
|
|
|
|
|
|
|
|
|
glGenVertexArrays(1, &mImageVAO);
|
|
|
|
|
glGenBuffers(1, &VBO);
|
|
|
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
|
|
|
|
|
|
|
|
|
glBindVertexArray(mImageVAO);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), (GLvoid*)0);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
|
|
// Setup Shader Program
|
|
|
|
|
mImageShader.SetSource(glShader::TYPE_VERTEX, OGLDefaultShaders.DefaultSpriteVertex, false);
|
|
|
|
|
mImageShader.SetSource(glShader::TYPE_FRAGMENT, OGLDefaultShaders.DefaultSpriteFragment, false);
|
|
|
|
|
if (!mImageShader.BuildProgram())
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::ERROR, "Unable to build default image shader program");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::InitShapeSystem()
|
|
|
|
|
{
|
|
|
|
|
// Create rectangle buffers
|
|
|
|
|
glGenVertexArrays(1, &mRectVAO);
|
|
|
|
|
glGenBuffers(1, &mRectVBO);
|
|
|
|
|
glBindVertexArray(mRectVAO);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mRectVBO);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
|
|
// Create Ellipse buffers
|
|
|
|
|
glGenVertexArrays(1, &mEllipseVAO);
|
|
|
|
|
glGenBuffers(1, &mEllipseVBO);
|
|
|
|
|
glBindVertexArray(mEllipseVAO);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, mEllipseVBO);
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 362 * 2, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
|
glEnableVertexAttribArray(0);
|
|
|
|
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), 0);
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
|
glBindVertexArray(0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Load shape shaders
|
|
|
|
|
mShapeShader.SetSource(glShader::TYPE_VERTEX, OGLDefaultShaders.DefaultShapeVertex, false);
|
|
|
|
|
mShapeShader.SetSource(glShader::TYPE_FRAGMENT, OGLDefaultShaders.DefaultShapeFragment, false);
|
|
|
|
|
if (!mShapeShader.BuildProgram())
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to build shape shader program.");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void OglGraphics::InitTextureFrameBuffer()
|
|
|
|
|
{
|
|
|
|
|
// Frame buffer
|
|
|
|
|
glGenFramebuffers(1, &mFBO);
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
|
|
|
|
|
|
|
|
|
// Texture
|
|
|
|
|
glGenTextures(1, &mpFBTexture->mGLTextureID);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, mpFBTexture->mGLTextureID);
|
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, mFBWidth, mFBHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
|
|
// Attach texture
|
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mpFBTexture->mGLTextureID, 0);
|
|
|
|
|
|
|
|
|
|
// Render Buffer for depth/stencil testing
|
|
|
|
|
glGenRenderbuffers(1, &mRBO);
|
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, mRBO);
|
|
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, mFBWidth, mFBHeight);
|
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
|
|
|
|
|
|
|
|
|
// Atach the render buffer
|
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRBO);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
|
{
|
|
|
|
|
Logger::Log(LogCategory::GRAPHICS, LogLevel::WARNING, "Unable to initialize framebuffer for rendering to a texture");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|