From 003378525133aa5e699b6156cd7077691a5acd81 Mon Sep 17 00:00:00 2001
From: Dominic Masters <dominic@domsplace.com>
Date: Wed, 19 Oct 2022 22:59:48 -0700
Subject: [PATCH] Material

---
 src/dawn/display/Shader.hpp                   | 11 ---
 src/dawn/display/_RenderManager.hpp           | 17 ++++
 src/dawn/display/shader/_Shader.hpp           | 80 ++++++++++++++++
 src/dawn/scene/SceneItem.cpp                  |  4 +-
 src/dawn/scene/SceneItem.hpp                  |  1 +
 src/dawn/scene/components/Components.hpp      |  3 +-
 .../scene/components/display/CMakeLists.txt   |  1 +
 src/dawn/scene/components/display/Camera.cpp  |  9 ++
 src/dawn/scene/components/display/Camera.hpp  | 10 ++
 .../scene/components/display/Material.cpp     | 68 ++++++++++++++
 .../scene/components/display/Material.hpp     | 39 ++++++++
 src/dawnopengl/display/CMakeLists.txt         |  3 +-
 src/dawnopengl/display/RenderManager.cpp      |  6 ++
 src/dawnopengl/display/RenderManager.hpp      |  4 +
 .../display/StandardRenderPipeline.cpp        | 17 +++-
 src/dawnopengl/display/shader/CMakeLists.txt  | 10 ++
 src/dawnopengl/display/shader/Shader.cpp      | 93 +++++++++++++++++++
 src/dawnopengl/display/shader/Shader.hpp      | 49 ++++++++++
 .../display/shader/SimpleTexturedShader.hpp   | 90 ++++++++++++++++++
 src/dawnpokergame/game/DawnPokerGame.cpp      |  2 +
 20 files changed, 502 insertions(+), 15 deletions(-)
 delete mode 100644 src/dawn/display/Shader.hpp
 create mode 100644 src/dawn/display/shader/_Shader.hpp
 create mode 100644 src/dawn/scene/components/display/Material.cpp
 create mode 100644 src/dawn/scene/components/display/Material.hpp
 create mode 100644 src/dawnopengl/display/shader/CMakeLists.txt
 create mode 100644 src/dawnopengl/display/shader/Shader.cpp
 create mode 100644 src/dawnopengl/display/shader/Shader.hpp
 create mode 100644 src/dawnopengl/display/shader/SimpleTexturedShader.hpp

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<Shader> 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<typename T>
+  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<T, enum ShaderParameterType> 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<Shader> Material::getShader() {
+  return this->shader;
+}
+
+void Material::setShader(std::shared_ptr<Shader> 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> shader;
+
+      void updateShaderParameters();
+
+
+    public:
+      std::map<shaderparameter_t, enum ShaderParameterType> parameters;
+
+      std::map<shaderparameter_t, struct Color> colorValues;
+      std::map<shaderparameter_t, bool_t> boolValues;
+      std::map<shaderparameter_t, glm::mat4> matrixValues;
+      std::map<shaderparameter_t, glm::vec3> vec3Values;
+
+      Material(SceneItem &item);
+
+      std::shared_ptr<Shader> getShader();
+      void setShader(std::shared_ptr<Shader> 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<StandardRenderPipeline>(*this);
+  this->simpleShader = std::make_shared<SimpleTexturedShader>();
 }
 
 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<Shader> 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<SimpleTexturedShader> simpleShader;
 
       /**
        * Construct a new RenderManager for a game instance.
        */
       RenderManager(DawnGame &game);
+      
       RenderTarget & getBackBuffer() override;
       RenderPipeline & getRenderPipeline() override;
+      std::shared_ptr<Shader> 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<MeshRenderer>();
   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<Material>();
+
+    // 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<shaderparameter_t> {
+    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<shaderparameter_t, enum ShaderParameterType>
+      getParameters() override {
+        std::map<shaderparameter_t, enum ShaderParameterType> 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>();
+  camera->lookAt(glm::vec3(3, 3, 3), glm::vec3(0, 0, 0));
 
   auto cubeObject = this->scene->createSceneItem();
   auto cubeMeshRenderer = cubeObject->addComponent<MeshRenderer>();
+  auto cubeMaterial = cubeObject->addComponent<Material>();
   cubeMeshRenderer->mesh = std::make_shared<Mesh>();
   TriangleMesh::createTriangleMesh(*cubeMeshRenderer->mesh);