diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h new file mode 100644 index 00000000..74ed45bd --- /dev/null +++ b/include/Engine/Rendering/Renderer.h @@ -0,0 +1,23 @@ +#ifndef Renderer_h__ +#define Renderer_h__ + +#include + +#include "IRenderer.h" +#include "ShaderProgram.h" + +class Renderer : public IRenderer +{ +public: + virtual void Initialize() override; + virtual void Draw(RenderQueueCollection& rq) override; + +private: + void InitializeWindow(); + void InitializeShaders(); + + + ShaderProgram m_BasicForwardProgram; +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/ShaderProgram.h b/include/Engine/Rendering/ShaderProgram.h new file mode 100644 index 00000000..edb0c1e5 --- /dev/null +++ b/include/Engine/Rendering/ShaderProgram.h @@ -0,0 +1,91 @@ + +#include + +#include "../Core/Util/Logging.h" +// OpenGL +#include +#define GLFW_INCLUDE_GLU +#include +#include +#include "Util/GLError.h" + +#include +#include + + +class Shader +{ +public: + static GLuint CompileShader(GLenum shaderType, std::string fileName); + + Shader(GLenum shaderType, std::string fileName); + + virtual ~Shader(); + + GLuint Compile(); + + GLenum GetType() const; + std::string GetFileName() const; + GLuint GetHandle() const; + bool IsCompiled() const; + +protected: + GLenum m_ShaderType; + std::string m_FileName; + GLint m_ShaderHandle; +}; + +template +class ShaderType : public Shader +{ +public: + ShaderType(std::string fileName) + : Shader(SHADERTYPE, fileName) { } +}; + +class VertexShader : public ShaderType +{ +public: + VertexShader(std::string fileName) + : ShaderType(fileName) { } +}; + +class FragmentShader : public ShaderType +{ +public: + FragmentShader(std::string fileName) + : ShaderType(fileName) { } +}; + +class GeometryShader : public ShaderType +{ +public: + GeometryShader(std::string fileName) + : ShaderType(fileName) { } +}; + +class ComputeShader : public ShaderType +{ +public: + ComputeShader(std::string fileName) + : ShaderType(fileName) { } +}; + +class ShaderProgram +{ +public: + ShaderProgram() + : m_ShaderProgramHandle(0) { } + ~ShaderProgram(); + + void AddShader(std::shared_ptr shader); + void Compile(); + GLuint Link(); + GLuint GetHandle(); + void Bind(); + void Unbind(); + +private: + GLuint m_ShaderProgramHandle; + std::vector> m_Shaders; +}; diff --git a/include/Game/Game.h b/include/Game/Game.h index 6a942164..a5f24fd6 100644 --- a/include/Game/Game.h +++ b/include/Game/Game.h @@ -5,7 +5,7 @@ #include "Core/ConfigFile.h" #include "Core/EventBroker.h" -#include "Rendering/DummyRenderer.h" +#include "Rendering/Renderer.h" #include "Core/InputManager.h" #include "GUI/Frame.h" diff --git a/resources/Shaders/BasicForward.frag.glsl b/resources/Shaders/BasicForward.frag.glsl new file mode 100644 index 00000000..1461e51f --- /dev/null +++ b/resources/Shaders/BasicForward.frag.glsl @@ -0,0 +1,25 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +uniform sampler2D texture0; + + +in VertexData{ + vec3 VertexPosition; + vec3 Normal; + vec2 TextureCoordinate; +} Input; + +out vec4 fragmentColor; + + +void main() +{ + vec4 texel = texture2D(texture0, Input.TextureCoordinate); + fragmentColor = texel; +} + + diff --git a/resources/Shaders/BasicForward.vert.glsl b/resources/Shaders/BasicForward.vert.glsl new file mode 100644 index 00000000..e5f8e7ac --- /dev/null +++ b/resources/Shaders/BasicForward.vert.glsl @@ -0,0 +1,24 @@ +#version 430 + +uniform mat4 M; +uniform mat4 V; +uniform mat4 P; + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TextureCoord; +layout(location = 2) in vec3 Normal; + +out VertexData{ + vec3 VertexPosition; + vec3 Normal; + vec2 TextureCoordinate; +} Output; + +void main() +{ + gl_Position = P*V*M * vec4(Position, 1.0); + + Output.VertexPosition = Position; + Output.TextureCoordinate = TextureCoord; + Output.Normal = Normal; +} \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp new file mode 100644 index 00000000..2c1c6a1c --- /dev/null +++ b/src/Engine/Rendering/Renderer.cpp @@ -0,0 +1,73 @@ +#include "Rendering/Renderer.h" + +void Renderer::Initialize() +{ + InitializeWindow(); + + // Create default camera + m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); + m_DefaultCamera->SetPosition(glm::vec3(0, 0, 0)); + if (m_Camera == nullptr) { + m_Camera = m_DefaultCamera; + } + + glfwSwapInterval(m_VSYNC); + + InitializeShaders(); +} + +void Renderer::InitializeWindow() +{ + // Initialize GLFW + if (!glfwInit()) { + LOG_ERROR("GLFW: Initialization failed"); + exit(EXIT_FAILURE); + } + + // Create a window + GLFWmonitor* monitor = nullptr; + if (m_Fullscreen) { + monitor = glfwGetPrimaryMonitor(); + } + //glfwWindowHint(GLFW_SAMPLES, 8); + m_Window = glfwCreateWindow(m_Resolution.Width, m_Resolution.Height, "daydream", monitor, nullptr); + if (!m_Window) { + LOG_ERROR("GLFW: Failed to create window"); + exit(EXIT_FAILURE); + } + glfwMakeContextCurrent(m_Window); + + // GL version info + glGetIntegerv(GL_MAJOR_VERSION, &m_GLVersion[0]); + glGetIntegerv(GL_MINOR_VERSION, &m_GLVersion[1]); + m_GLVendor = (GLchar*)glGetString(GL_VENDOR); + std::stringstream ss; + ss << m_GLVendor << " OpenGL " << m_GLVersion[0] << "." << m_GLVersion[1]; +#ifdef DEBUG + ss << " DEBUG"; +#endif + LOG_INFO(ss.str().c_str()); + glfwSetWindowTitle(m_Window, ss.str().c_str()); + + // Initialize GLEW + if (glewInit() != GLEW_OK) { + LOG_ERROR("GLEW: Initialization failed"); + exit(EXIT_FAILURE); + } +} + +void Renderer::InitializeShaders() +{ + m_BasicForwardProgram.AddShader(std::shared_ptr(new VertexShader("Shaders/BasicForward.vert.glsl"))); + m_BasicForwardProgram.AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); + m_BasicForwardProgram.Compile(); + m_BasicForwardProgram.Link(); +} + +void Renderer::Draw(RenderQueueCollection& rq) +{ + glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f); + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(m_Window); +} + diff --git a/src/Engine/Rendering/ShaderProgram.cpp b/src/Engine/Rendering/ShaderProgram.cpp new file mode 100644 index 00000000..5200ff22 --- /dev/null +++ b/src/Engine/Rendering/ShaderProgram.cpp @@ -0,0 +1,153 @@ +#include "Rendering/ShaderProgram.h" + +GLuint Shader::CompileShader(GLenum shaderType, std::string fileName) +{ + LOG_INFO("Compiling shader \"%s\"", fileName.c_str()); + + std::string shaderFile; + std::ifstream in(fileName, std::ios::in); + if (!in) { + LOG_ERROR("Error: Failed to open shader file \"%s\"", fileName.c_str()); + return 0; + } + in.seekg(0, std::ios::end); + shaderFile.resize((int)in.tellg()); + in.seekg(0, std::ios::beg); + in.read(&shaderFile[0], shaderFile.size()); + in.close(); + + GLuint shader = glCreateShader(shaderType); + if (GLERROR("glCreateShader")) + return 0; + + const GLchar* shaderFiles = shaderFile.c_str(); + const GLint length = shaderFile.length(); + glShaderSource(shader, 1, &shaderFiles, &length); + if (GLERROR("glShaderSource")) + return 0; + + glCompileShader(shader); + + GLint compileStatus; + glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); + if (compileStatus != GL_TRUE) { + LOG_ERROR("Shader compilation failed"); + GLsizei infoLogLength; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); + GLchar* infolog = new GLchar[infoLogLength]; + glGetShaderInfoLog(shader, infoLogLength, &infoLogLength, infolog); + LOG_ERROR(infolog); + delete[] infolog; + } + + if (GLERROR("glCompileShader")) + return 0; + + return shader; +} + +Shader::Shader(GLenum shaderType, std::string fileName) : m_ShaderType(shaderType), m_FileName(fileName) +{ + m_ShaderHandle = 0; +} + +Shader::~Shader() +{ + if (m_ShaderHandle != 0) { + glDeleteShader(m_ShaderHandle); + } +} + +GLuint Shader::Compile() +{ + m_ShaderHandle = CompileShader(m_ShaderType, m_FileName); + return m_ShaderHandle; +} + +GLenum Shader::GetType() const +{ + return m_ShaderType; +} + +std::string Shader::GetFileName() const +{ + return m_FileName; +} + +GLuint Shader::GetHandle() const +{ + return m_ShaderHandle; +} + +bool Shader::IsCompiled() const +{ + return m_ShaderHandle != 0; +} + +ShaderProgram::~ShaderProgram() +{ + if (m_ShaderProgramHandle != 0) { + glDeleteProgram(m_ShaderProgramHandle); + } +} + +void ShaderProgram::AddShader(std::shared_ptr shader) +{ + m_Shaders.push_back(shader); +} + +void ShaderProgram::Compile() +{ + if (m_ShaderProgramHandle == 0) + { + m_ShaderProgramHandle = glCreateProgram(); + } + + for (auto &shader : m_Shaders) + { + if (!shader->IsCompiled()) + { + shader->Compile(); + } + } +} + +GLuint ShaderProgram::Link() +{ + if (m_Shaders.size() == 0) + { + LOG_ERROR("Failed to link shader program: No shaders bound"); + return 0; + } + + LOG_INFO("Linking shader program"); + + for (auto &shader : m_Shaders) + { + glAttachShader(m_ShaderProgramHandle, shader->GetHandle()); + } + glLinkProgram(m_ShaderProgramHandle); + if (GLERROR("glLinkProgram")) + return 0; + m_Shaders.clear(); + + return m_ShaderProgramHandle; +} + +GLuint ShaderProgram::GetHandle() +{ + return m_ShaderProgramHandle; +} + +void ShaderProgram::Bind() +{ + if (m_ShaderProgramHandle == 0) + return; + + glUseProgram(m_ShaderProgramHandle); +} + +void ShaderProgram::Unbind() +{ + glActiveShaderProgram(0, 0); +} \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index c710e218..47aae53d 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -11,7 +11,7 @@ Game::Game(int argc, char* argv[]) m_EventBroker = new EventBroker(); // Create the renderer - m_Renderer = new DummyRenderer(); + m_Renderer = new Renderer(); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); m_Renderer->SetVSYNC(m_Config->Get("Video.VSYNC", false)); m_Renderer->SetResolution(Rectangle(