diff --git a/src/dawn/display/Shader.hpp b/src/dawn/display/Shader.hpp deleted file mode 100644 index 31b68e0a..00000000 --- a/src/dawn/display/Shader.hpp +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2022 Dominic Masters -// -// This software is released under the MIT License. -// https://opensource.org/licenses/MIT - -#pragma once -#include "dawnlibs.hpp" - -namespace Dawn { - class Shader; -} \ No newline at end of file diff --git a/src/dawn/display/_RenderManager.hpp b/src/dawn/display/_RenderManager.hpp index 23bac126..b9695480 100644 --- a/src/dawn/display/_RenderManager.hpp +++ b/src/dawn/display/_RenderManager.hpp @@ -5,6 +5,7 @@ #pragma once #include "RenderTarget.hpp" +#include "display/shader/Shader.hpp" namespace Dawn { class DawnGame; @@ -30,8 +31,22 @@ namespace Dawn { */ virtual RenderTarget & getBackBuffer() = 0; + /** + * Returns the current render pipeline intended to be used for rendering + * the currently active scene on the game instance. + * + * @return Reference to the currently active main scene render pipeline. + */ virtual RenderPipeline & getRenderPipeline() = 0; + /** + * Returns the default shader, the default shader will be applied to the + * materials first. + * + * @return Reference to the default shader. + */ + virtual std::shared_ptr getDefaultShader() = 0; + /** * Initialize / Start the Render Manager. * @@ -43,5 +58,7 @@ namespace Dawn { * Perform a synchronous frame update on the render manager. */ virtual void update() = 0; + + }; } \ No newline at end of file diff --git a/src/dawn/display/shader/_Shader.hpp b/src/dawn/display/shader/_Shader.hpp new file mode 100644 index 00000000..f60a6a3a --- /dev/null +++ b/src/dawn/display/shader/_Shader.hpp @@ -0,0 +1,80 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "dawnlibs.hpp" + +namespace Dawn { + class Material; + + enum ShaderParameterType { + SHADER_PARAMETER_TYPE_MATRIX, + SHADER_PARAMETER_TYPE_BOOLEAN, + SHADER_PARAMETER_TYPE_COLOR, + SHADER_PARAMETER_TYPE_VECTOR3 + }; + + template + class IShader { + public: + /** + * Attaches the supplied shader as the current shader. + */ + virtual void bind() = 0; + + // virtual void setCamera(glm::mat4 projection, glm::mat4 view) = 0; + // virtual void setLocalPosition(glm::mat4 position) = 0; + + virtual void setDefaultParameters(Material &material) = 0; + + virtual void setGlobalParameters( + glm::mat4 projection, + glm::mat4 view + ) = 0; + + virtual void setMeshParameters(glm::mat4 position) = 0; + + /** + * Retreives the list of all parameters that the shader supports. This + * should not include the GLOBAL shader parameters (listed above) since + * those will be modified by the engine directly. + * + * @return Key-Value-Pair of Shader parameters and their type. + */ + virtual std::map getParameters() = 0; + + /** + * Set's a specific shader parameter to a matrix. + * + * @param parameter parameter on the shader to set. + * @param matrix Matrix to apply. + */ + virtual void setMatrix(T parameter, glm::mat4 matrix) = 0; + + /** + * Attaches a boolean to a shader. + * + * @param parameter parameter to set. + * @param value Value to set. + */ + virtual void setBoolean(T parameter, bool_t value) = 0; + + /** + * Set a color on to the shader. + * + * @param parameter parameter to set the color to. + * @param color Color to set. + */ + virtual void setColor(T parameter, struct Color color) = 0; + + /** + * Set a 3D vector on to the shader. + * + * @param parameter parameter to set the vector to. + * @param vector Vector to set. + */ + virtual void setVector3(T parameter, glm::vec3 vector) = 0; + }; +} \ No newline at end of file diff --git a/src/dawn/scene/SceneItem.cpp b/src/dawn/scene/SceneItem.cpp index dbbe555f..4a428bca 100644 --- a/src/dawn/scene/SceneItem.cpp +++ b/src/dawn/scene/SceneItem.cpp @@ -10,9 +10,11 @@ using namespace Dawn; SceneItem::SceneItem(Scene &scene, sceneitemid_t id) : scene(scene), - id(id) + id(id), + transform(1.0f) { this->id = id; + this->transform = glm::translate(this->transform, glm::vec3(0, 0, 0)); } void SceneItem::init() { diff --git a/src/dawn/scene/SceneItem.hpp b/src/dawn/scene/SceneItem.hpp index 4499e852..dcdc6977 100644 --- a/src/dawn/scene/SceneItem.hpp +++ b/src/dawn/scene/SceneItem.hpp @@ -18,6 +18,7 @@ namespace Dawn { public: Scene &scene; sceneitemid_t id; + glm::mat4 transform; /** * Constructor for a SceneItem. Scene Items should only be called and diff --git a/src/dawn/scene/components/Components.hpp b/src/dawn/scene/components/Components.hpp index 398483cb..99fcc4af 100644 --- a/src/dawn/scene/components/Components.hpp +++ b/src/dawn/scene/components/Components.hpp @@ -6,4 +6,5 @@ #pragma once #include "scene/components/DummyComponent.hpp" #include "scene/components/display/Camera.hpp" -#include "scene/components/display/MeshRenderer.hpp" \ No newline at end of file +#include "scene/components/display/MeshRenderer.hpp" +#include "scene/components/display/Material.hpp" \ No newline at end of file diff --git a/src/dawn/scene/components/display/CMakeLists.txt b/src/dawn/scene/components/display/CMakeLists.txt index 169f9f01..eadb4a5c 100644 --- a/src/dawn/scene/components/display/CMakeLists.txt +++ b/src/dawn/scene/components/display/CMakeLists.txt @@ -7,5 +7,6 @@ target_sources(${DAWN_TARGET_NAME} PRIVATE Camera.cpp + Material.cpp MeshRenderer.cpp ) \ No newline at end of file diff --git a/src/dawn/scene/components/display/Camera.cpp b/src/dawn/scene/components/display/Camera.cpp index 7fd9828c..8cb6fc09 100644 --- a/src/dawn/scene/components/display/Camera.cpp +++ b/src/dawn/scene/components/display/Camera.cpp @@ -12,6 +12,7 @@ using namespace Dawn; Camera::Camera(SceneItem &item) : SceneItemComponent(item) { + this->updateProjection(); } void Camera::updateProjection() { @@ -38,6 +39,14 @@ void Camera::updateProjection() { } } +void Camera::lookAt(glm::vec3 pos, glm::vec3 look) { + this->lookAt(pos, look, glm::vec3(0, 1, 0)); +} + +void Camera::lookAt(glm::vec3 pos, glm::vec3 look, glm::vec3 up) { + this->item.transform = glm::lookAt(pos, look, up); +} + RenderTarget & Camera::getRenderTarget() { if(this->target == nullptr) { return this->getGame().renderManager.getBackBuffer(); diff --git a/src/dawn/scene/components/display/Camera.hpp b/src/dawn/scene/components/display/Camera.hpp index 6513a0ad..c22d807f 100644 --- a/src/dawn/scene/components/display/Camera.hpp +++ b/src/dawn/scene/components/display/Camera.hpp @@ -44,6 +44,16 @@ namespace Dawn { */ void updateProjection(); + void lookAt(glm::vec3 position, glm::vec3 look); + + void lookAt(glm::vec3 position, glm::vec3 look, glm::vec3 up); + + /** + * Returns the intended render target for this camera to render to, will + * automatically revert to the back buffer if no frame buffer is provided. + * + * @return The target render target framebuffer. + */ RenderTarget & getRenderTarget(); /** diff --git a/src/dawn/scene/components/display/Material.cpp b/src/dawn/scene/components/display/Material.cpp new file mode 100644 index 00000000..1642b2c8 --- /dev/null +++ b/src/dawn/scene/components/display/Material.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "Material.hpp" +#include "scene/Scene.hpp" +#include "game/DawnGame.hpp" + +using namespace Dawn; + +Material::Material(SceneItem &item) : + SceneItemComponent(item), + shader(item.scene.game.renderManager.getDefaultShader()) +{ + this->updateShaderParameters(); +} + +void Material::updateShaderParameters() { + std::cout << "Updating params" << std::endl; + this->colorValues.clear(); + this->boolValues.clear(); + + this->parameters = this->shader->getParameters(); + this->shader->setDefaultParameters(*this); + + // We do need to validate these params at some point to make sure that the + // shader has actually bound them. +} + +void Material::setShaderParameters() { + auto it = this->parameters.begin(); + while(it != this->parameters.end()) { + switch(it->second) { + case SHADER_PARAMETER_TYPE_COLOR: + this->shader->setColor(it->first, this->colorValues[it->first]); + break; + + case SHADER_PARAMETER_TYPE_MATRIX: + this->shader->setMatrix(it->first, this->matrixValues[it->first]); + break; + + case SHADER_PARAMETER_TYPE_BOOLEAN: + this->shader->setBoolean(it->first, this->boolValues[it->first]); + break; + + case SHADER_PARAMETER_TYPE_VECTOR3: + this->shader->setVector3(it->first, this->vec3Values[it->first]); + break; + + default: + throw "An unsupported or invalid shader parameter type was supplied."; + } + ++it; + } +} + +std::shared_ptr Material::getShader() { + return this->shader; +} + +void Material::setShader(std::shared_ptr shader) { + this->shader = shader; + this->updateShaderParameters(); +} + +void Material::start() { +} \ No newline at end of file diff --git a/src/dawn/scene/components/display/Material.hpp b/src/dawn/scene/components/display/Material.hpp new file mode 100644 index 00000000..85b83c61 --- /dev/null +++ b/src/dawn/scene/components/display/Material.hpp @@ -0,0 +1,39 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "scene/SceneItemComponent.hpp" +#include "display/shader/Shader.hpp" + +namespace Dawn { + class Shader; + + class Material : public SceneItemComponent { + friend class RenderPipeline; + + private: + std::shared_ptr shader; + + void updateShaderParameters(); + + + public: + std::map parameters; + + std::map colorValues; + std::map boolValues; + std::map matrixValues; + std::map vec3Values; + + Material(SceneItem &item); + + std::shared_ptr getShader(); + void setShader(std::shared_ptr shader); + + void setShaderParameters(); + + void start() override; + }; +} \ No newline at end of file diff --git a/src/dawnopengl/display/CMakeLists.txt b/src/dawnopengl/display/CMakeLists.txt index 65aef970..6ad995a1 100644 --- a/src/dawnopengl/display/CMakeLists.txt +++ b/src/dawnopengl/display/CMakeLists.txt @@ -12,4 +12,5 @@ target_sources(${DAWN_TARGET_NAME} ) # Subdirs -add_subdirectory(mesh) \ No newline at end of file +add_subdirectory(mesh) +add_subdirectory(shader) \ No newline at end of file diff --git a/src/dawnopengl/display/RenderManager.cpp b/src/dawnopengl/display/RenderManager.cpp index 79ec7699..a6784b21 100644 --- a/src/dawnopengl/display/RenderManager.cpp +++ b/src/dawnopengl/display/RenderManager.cpp @@ -15,10 +15,12 @@ RenderManager::RenderManager(DawnGame &game) : backBuffer(*this) { this->standardRenderPipeline=std::make_shared(*this); + this->simpleShader = std::make_shared(); } void RenderManager::init() { this->standardRenderPipeline->init(); + this->simpleShader->compile(); } RenderTarget & RenderManager::getBackBuffer() { @@ -29,6 +31,10 @@ RenderPipeline & RenderManager::getRenderPipeline() { return *this->standardRenderPipeline; } +std::shared_ptr RenderManager::getDefaultShader() { + return this->simpleShader; +} + void RenderManager::update() { this->getRenderPipeline().render(); } diff --git a/src/dawnopengl/display/RenderManager.hpp b/src/dawnopengl/display/RenderManager.hpp index 4be522e9..207772e1 100644 --- a/src/dawnopengl/display/RenderManager.hpp +++ b/src/dawnopengl/display/RenderManager.hpp @@ -6,6 +6,7 @@ #pragma once #include "display/_RenderManager.hpp" #include "display/BackBufferRenderTarget.hpp" +#include "display/shader/SimpleTexturedShader.hpp" namespace Dawn { class StandardRenderPipeline; @@ -16,13 +17,16 @@ namespace Dawn { public: BackBufferRenderTarget backBuffer; + std::shared_ptr simpleShader; /** * Construct a new RenderManager for a game instance. */ RenderManager(DawnGame &game); + RenderTarget & getBackBuffer() override; RenderPipeline & getRenderPipeline() override; + std::shared_ptr getDefaultShader() override; void init() override; void update() override; diff --git a/src/dawnopengl/display/StandardRenderPipeline.cpp b/src/dawnopengl/display/StandardRenderPipeline.cpp index 7ac24997..8e9dbcfa 100644 --- a/src/dawnopengl/display/StandardRenderPipeline.cpp +++ b/src/dawnopengl/display/StandardRenderPipeline.cpp @@ -49,7 +49,22 @@ void StandardRenderPipeline::renderSceneCamera(Scene &scene, Camera &camera) { auto meshes = scene.findComponents(); auto it = meshes.begin(); while(it != meshes.end()) { - (*it)->mesh->draw(MESH_DRAW_MODE_TRIANGLES, 0, -1); + auto mesh = *it; + auto item = mesh->item; + auto material = item.getComponent(); + + // TODO: fallback material? + if(material == nullptr) { + continue; + } + + auto shader = material->getShader(); + shader->bind(); + shader->setGlobalParameters(camera.projection, camera.item.transform); + shader->setMeshParameters(item.transform); + material->setShaderParameters(); + + mesh->mesh->draw(MESH_DRAW_MODE_TRIANGLES, 0, -1); ++it; } } \ No newline at end of file diff --git a/src/dawnopengl/display/shader/CMakeLists.txt b/src/dawnopengl/display/shader/CMakeLists.txt new file mode 100644 index 00000000..d66d1bd2 --- /dev/null +++ b/src/dawnopengl/display/shader/CMakeLists.txt @@ -0,0 +1,10 @@ +# Copyright (c) 2022 Dominic Masters +# +# This software is released under the MIT License. +# https://opensource.org/licenses/MIT + +# Sources +target_sources(${DAWN_TARGET_NAME} + PRIVATE + Shader.cpp +) \ No newline at end of file diff --git a/src/dawnopengl/display/shader/Shader.cpp b/src/dawnopengl/display/shader/Shader.cpp new file mode 100644 index 00000000..decfe8b8 --- /dev/null +++ b/src/dawnopengl/display/shader/Shader.cpp @@ -0,0 +1,93 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#include "Shader.hpp" + +using namespace Dawn; + +void Shader::compileShader( + std::string vertexShader, + std::string fragmentShader +) { + GLint isSuccess; + int32_t maxLength; + char error[1024]; + + // Load the vertex shader first + this->shaderVertex = glCreateShader(GL_VERTEX_SHADER); + auto vertShaderC = vertexShader.c_str(); + glShaderSource(this->shaderVertex, 1, &vertShaderC, 0); + glCompileShader(this->shaderVertex); + + // Validate + glGetShaderiv(this->shaderVertex, GL_COMPILE_STATUS, &isSuccess); + if(!isSuccess) { + glGetShaderiv(this->shaderVertex, GL_INFO_LOG_LENGTH, &maxLength); + glGetShaderInfoLog(this->shaderVertex, maxLength, &maxLength, error); + throw error; + } + + // Now load the Frag shader + this->shaderFrag = glCreateShader(GL_FRAGMENT_SHADER); + auto fragShaderC = fragmentShader.c_str(); + glShaderSource(this->shaderFrag, 1, &fragShaderC, 0); + glCompileShader(this->shaderFrag); + glGetShaderiv(this->shaderFrag, GL_COMPILE_STATUS, &isSuccess); + if(!isSuccess) { + glGetShaderiv(this->shaderFrag, GL_INFO_LOG_LENGTH, &maxLength); + glGetShaderInfoLog(this->shaderFrag, maxLength, &maxLength, error); + glDeleteShader(this->shaderVertex); + throw error; + } + + // Now create the shader program. + this->shaderProgram = glCreateProgram(); + glAttachShader(this->shaderProgram, this->shaderVertex); + glAttachShader(this->shaderProgram, this->shaderFrag); + + //Bind, Verify & Use the shader program + glLinkProgram(this->shaderProgram); + glGetProgramiv(this->shaderProgram, GL_LINK_STATUS, &isSuccess); + if(!isSuccess) { + glGetProgramiv(this->shaderProgram, GL_INFO_LOG_LENGTH, &maxLength); + glGetProgramInfoLog(this->shaderProgram, maxLength, &maxLength, error); + glDeleteShader(this->shaderVertex); + glDeleteShader(this->shaderFrag); + throw error; + } + + // Now parse out the variables. +} + +shaderparameter_t Shader::getParameterByName(std::string name) { + return glGetUniformLocation(this->shaderProgram, name.c_str()); +} + +void Shader::setMatrix(shaderparameter_t uniform, glm::mat4 matrix) { + glUniformMatrix4fv(uniform, 1, GL_FALSE, glm::value_ptr(matrix)); +} + +void Shader::setBoolean(shaderparameter_t uni, bool value) { + glUniform1i(uni, value); +} + +void Shader::setColor(shaderparameter_t uniform, struct Color color) { + glUniform4f(uniform, color.r, color.g, color.b, color.a); +} + +void Shader::setVector3(shaderparameter_t uniform, glm::vec3 vector) { + glUniform3f(uniform, vector.x, vector.y, vector.z); +} + +void Shader::bind() { + if(this->shaderProgram == -1) throw "Shader has not yet been compiled"; + glUseProgram(this->shaderProgram); +} + +Shader::~Shader() { + if(this->shaderProgram != -1) glDeleteProgram(this->shaderProgram); + if(this->shaderVertex != -1) glDeleteShader(this->shaderVertex); + if(this->shaderFrag != -1) glDeleteShader(this->shaderFrag); +} \ No newline at end of file diff --git a/src/dawnopengl/display/shader/Shader.hpp b/src/dawnopengl/display/shader/Shader.hpp new file mode 100644 index 00000000..a02c6e29 --- /dev/null +++ b/src/dawnopengl/display/shader/Shader.hpp @@ -0,0 +1,49 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "display/shader/_Shader.hpp" +#include "dawnopengl.hpp" +#include "display/Color.hpp" + +typedef GLuint shaderparameter_t; + +namespace Dawn { + class Shader : public IShader { + private: + /** Pointer to an uploaded vertex shader program */ + GLuint shaderVertex = -1; + + /** Pointer to an uploaded fragment shader program */ + GLuint shaderFrag = -1; + + /** Pointer to an uploaded shader program linked */ + GLuint shaderProgram = -1; + + protected: + void compileShader( + std::string vertexShader, + std::string fragmentShader + ); + + public: + /** + * Locate a shader parameter by its name. + * + * @param name Name of the parameter to get. + * @return The shader parameter. + */ + shaderparameter_t getParameterByName(std::string name); + + void bind() override; + virtual void compile() = 0; + void setMatrix(shaderparameter_t parameter, glm::mat4 matrix) override; + void setBoolean(shaderparameter_t parameter, bool_t value) override; + void setColor(shaderparameter_t parameter, struct Color color) override; + void setVector3(shaderparameter_t parameter, glm::vec3 vector) override; + + ~Shader(); + }; +} \ No newline at end of file diff --git a/src/dawnopengl/display/shader/SimpleTexturedShader.hpp b/src/dawnopengl/display/shader/SimpleTexturedShader.hpp new file mode 100644 index 00000000..4febd064 --- /dev/null +++ b/src/dawnopengl/display/shader/SimpleTexturedShader.hpp @@ -0,0 +1,90 @@ +// Copyright (c) 2022 Dominic Masters +// +// This software is released under the MIT License. +// https://opensource.org/licenses/MIT + +#pragma once +#include "display/shader/Shader.hpp" +#include "scene/components/Components.hpp" + +namespace Dawn { + class SimpleTexturedShader : public Shader { + private: + shaderparameter_t paramProjection; + shaderparameter_t paramView; + shaderparameter_t paramModel; + shaderparameter_t paramColor; + shaderparameter_t paramTexture; + shaderparameter_t paramHasTexture; + + public: + std::map + getParameters() override { + std::map ps; + + ps[this->paramColor] = SHADER_PARAMETER_TYPE_COLOR; + // ps[paramTexture] SHADER_PARAMETER_TYPE_TEXTURE; + // ps[this->paramHasTexture] = SHADER_PARAMETER_TYPE_BOOLEAN; + + return ps; + } + + void setDefaultParameters(Material &material) override { + material.colorValues[this->paramColor] = COLOR_MAGENTA; + } + + void setGlobalParameters(glm::mat4 proj, glm::mat4 view) override { + this->setMatrix(this->paramProjection, proj); + this->setMatrix(this->paramView, view); + } + + void setMeshParameters(glm::mat4 transform) override { + this->setMatrix(this->paramModel, transform); + } + + void compile() override { + this->compileShader( + // Vertex Shader + "#version 330 core\n" + "layout (location = 0) in vec3 aPos;\n" + "layout (location = 1) in vec2 aTexCoord;\n" + + "uniform mat4 u_Proj;\n" + "uniform mat4 u_View;\n" + "uniform mat4 u_Model;\n" + + "out vec2 o_TextCoord;\n" + "void main() {\n" + "gl_Position = u_Proj * u_View * u_Model * vec4(aPos, 1.0);\n" + "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n" + "}", + + // Fragment Shader + "#version 330 core\n" + "out vec4 o_Color;\n" + "in vec2 o_TextCoord;\n" + "uniform vec4 u_Color;\n" + "uniform sampler2D u_Text;\n" + "uniform bool u_HasTexture;\n" + + "void main() {\n" + "if(u_HasTexture) {\n" + "o_Color = texture(u_Text, o_TextCoord) * u_Color;\n" + "} else {\n" + "o_Color = u_Color;" + "}\n" + "}\n" + ); + + this->paramProjection = this->getParameterByName("u_Proj"); + this->paramView = this->getParameterByName("u_View"); + this->paramModel = this->getParameterByName("u_Model"); + this->paramColor = this->getParameterByName("u_Color"); + this->paramTexture = this->getParameterByName("u_Text"); + this->paramHasTexture = this->getParameterByName("u_HasTexture"); + + this->setBoolean(this->paramHasTexture, false); + this->setColor(this->paramColor, COLOR_WHITE); + } + }; +} \ No newline at end of file diff --git a/src/dawnpokergame/game/DawnPokerGame.cpp b/src/dawnpokergame/game/DawnPokerGame.cpp index 8b35bb3c..e0f694be 100644 --- a/src/dawnpokergame/game/DawnPokerGame.cpp +++ b/src/dawnpokergame/game/DawnPokerGame.cpp @@ -20,9 +20,11 @@ int32_t DawnGame::init() { auto cameraObject = this->scene->createSceneItem(); auto camera = cameraObject->addComponent(); + camera->lookAt(glm::vec3(3, 3, 3), glm::vec3(0, 0, 0)); auto cubeObject = this->scene->createSceneItem(); auto cubeMeshRenderer = cubeObject->addComponent(); + auto cubeMaterial = cubeObject->addComponent(); cubeMeshRenderer->mesh = std::make_shared(); TriangleMesh::createTriangleMesh(*cubeMeshRenderer->mesh);