From d941bb94816f9daf2b127bf5e6e36fa04dc5c768 Mon Sep 17 00:00:00 2001 From: progrematic <20295773+progrematic@users.noreply.github.com> Date: Wed, 1 Sep 2021 11:13:41 -0700 Subject: [PATCH] [LMAE-23] - Materials --- hippo/include/hippo/graphics/material.h | 82 +++++++++++++++++++ hippo/include/hippo/graphics/rendercommands.h | 27 +++++- hippo/src/graphics/material.cpp | 82 +++++++++++++++++++ hippo/src/graphics/rendercommands.cpp | 64 +++++++++++++++ hippoeditor/src/main.cpp | 67 ++++++++------- 5 files changed, 285 insertions(+), 37 deletions(-) create mode 100644 hippo/include/hippo/graphics/material.h create mode 100644 hippo/src/graphics/material.cpp diff --git a/hippo/include/hippo/graphics/material.h b/hippo/include/hippo/graphics/material.h new file mode 100644 index 0000000..0389aac --- /dev/null +++ b/hippo/include/hippo/graphics/material.h @@ -0,0 +1,82 @@ +#pragma once + +#include +#include +#include +#include + +#include "external/glm/glm.hpp" + +namespace hippo::graphics +{ + class Shader; + class Texture; + class Material + { + public: + Material(std::shared_ptr shader, std::shared_ptr texture = nullptr); + Material(const Material& other); + ~Material(); + + inline Shader* GetShader() const { return mShader.get(); } + inline Texture* GetTexture() const { return mTexture.get(); } + + void SetShader(std::shared_ptr shader); + void SetTexture(std::shared_ptr texture); + void UpdateShaderUniforms(); + +#define GETUNIFORMVALUE(mapName, defaultReturn) \ + const auto& it = mapName.find(name);\ + if (it != mapName.end())\ + {\ + return it->second;\ + }\ + return defaultReturn; + + template + inline T GetUniformValue(const std::string& name) const + { + if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformInts, 0) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformFloats, 0.f) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformFloat2s, glm::vec2(0.f)) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformFloat3s, glm::vec3(0.f)) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformFloat4s, glm::vec4(0.f)) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformMat3s, glm::mat3(1.f)) } + else if constexpr (std::is_same()) { GETUNIFORMVALUE(mUniformMat4s, glm::mat4(1.f)) } + else + { + static_assert(false, "Unsupported data type in Material::GetUniformValue()"); + } + } +#undef GETUNIFORMVALUE + + template + inline void SetUniformValue(const std::string& name, const T& val) + { + if constexpr (std::is_same()) { mUniformInts[name] = val; } + else if constexpr (std::is_same()) { mUniformFloats[name] = val; } + else if constexpr (std::is_same()) { mUniformFloat2s[name] = val; } + else if constexpr (std::is_same()) { mUniformFloat3s[name] = val; } + else if constexpr (std::is_same()) { mUniformFloat4s[name] = val; } + else if constexpr (std::is_same()) { mUniformMat3s[name] = val; } + else if constexpr (std::is_same()) { mUniformMat4s[name] = val; } + else + { + static_assert(false, "Unsupported data type in Material::SetUniformValue()"); + } + } + + private: + std::shared_ptr mShader; + std::shared_ptr mTexture; + + // Data + std::unordered_map mUniformInts; + std::unordered_map mUniformFloats; + std::unordered_map mUniformFloat2s; + std::unordered_map mUniformFloat3s; + std::unordered_map mUniformFloat4s; + std::unordered_map mUniformMat3s; + std::unordered_map mUniformMat4s; + }; +} \ No newline at end of file diff --git a/hippo/include/hippo/graphics/rendercommands.h b/hippo/include/hippo/graphics/rendercommands.h index 992f1c2..ac6dcac 100644 --- a/hippo/include/hippo/graphics/rendercommands.h +++ b/hippo/include/hippo/graphics/rendercommands.h @@ -2,6 +2,8 @@ #include +#include "external/glm/glm.hpp" + namespace hippo::graphics { class VertexArray; @@ -9,6 +11,7 @@ namespace hippo::graphics class Texture; class Framebuffer; class Camera; + class Material; namespace rendercommands { @@ -22,24 +25,27 @@ namespace hippo::graphics class RenderVertexArray : public RenderCommand { public: - RenderVertexArray(std::weak_ptr vertexArray, std::weak_ptr shader) + RenderVertexArray(std::weak_ptr vertexArray, std::weak_ptr shader, const glm::mat4 modelMatrix = glm::mat4(1.f)) : mVertexArray(vertexArray) , mShader(shader) + , mModelMatrix(modelMatrix) {} virtual void Execute() override; private: std::weak_ptr mVertexArray; std::weak_ptr mShader; + glm::mat4 mModelMatrix; }; class RenderVertexArrayTextured : public RenderCommand { public: - RenderVertexArrayTextured(std::weak_ptr vertexArray, std::weak_ptr texture, std::weak_ptr shader) + RenderVertexArrayTextured(std::weak_ptr vertexArray, std::weak_ptr texture, std::weak_ptr shader, const glm::mat4 modelMatrix = glm::mat4(1.f)) : mVertexArray(vertexArray) , mTexture(texture) , mShader(shader) + , mModelMatrix(modelMatrix) {} virtual void Execute() override; @@ -47,6 +53,23 @@ namespace hippo::graphics std::weak_ptr mVertexArray; std::weak_ptr mTexture; std::weak_ptr mShader; + glm::mat4 mModelMatrix; + }; + + class RenderVertexArrayMaterial: public RenderCommand + { + public: + RenderVertexArrayMaterial(std::weak_ptr vertexArray, std::weak_ptr material, const glm::mat4 modelMatrix = glm::mat4(1.f)) + : mVertexArray(vertexArray) + , mMaterial(material) + , mModelMatrix(modelMatrix) + {} + virtual void Execute() override; + + private: + std::weak_ptr mVertexArray; + std::weak_ptr mMaterial; + glm::mat4 mModelMatrix; }; class PushFramebuffer : public RenderCommand diff --git a/hippo/src/graphics/material.cpp b/hippo/src/graphics/material.cpp new file mode 100644 index 0000000..f7beed8 --- /dev/null +++ b/hippo/src/graphics/material.cpp @@ -0,0 +1,82 @@ +#include "hippo/graphics/material.h" +#include "hippo/graphics/shader.h" + +#include "hippo/log.h" + +namespace hippo::graphics +{ + + Material::Material(std::shared_ptr shader, std::shared_ptr texture /*= nullptr*/) + : mShader(shader) + , mTexture(texture) + { + HIPPO_ASSERT(mShader, "Attempting to instantiate a material with a nullptr shader"); + } + + Material::Material(const Material& other) + { + mShader = other.mShader; + mTexture = other.mTexture; + + // Data + mUniformInts = other.mUniformInts; + mUniformFloats = other.mUniformFloats; + mUniformFloat2s = other.mUniformFloat2s; + mUniformFloat3s = other.mUniformFloat3s; + mUniformFloat4s = other.mUniformFloat4s; + mUniformMat3s = other.mUniformMat3s; + mUniformMat4s = other.mUniformMat4s; + } + + Material::~Material() {} + + void Material::SetShader(std::shared_ptr shader) + { + HIPPO_ASSERT(shader, "Attempting to set a nullptr shader"); + if (shader) + { + mShader = shader; + } + } + + void Material::SetTexture(std::shared_ptr texture) + { + mTexture = texture; + } + + void Material::UpdateShaderUniforms() + { + if (mShader) + { + for (const auto& it : mUniformInts) + { + mShader->SetUniformInt(it.first, it.second); + } + for (const auto& it : mUniformFloats) + { + mShader->SetUniformFloat(it.first, it.second); + } + for (const auto& it : mUniformFloat2s) + { + mShader->SetUniformFloat2(it.first, it.second); + } + for (const auto& it : mUniformFloat3s) + { + mShader->SetUniformFloat3(it.first, it.second); + } + for (const auto& it : mUniformFloat4s) + { + mShader->SetUniformFloat4(it.first, it.second); + } + for (const auto& it : mUniformMat3s) + { + mShader->SetUniformMat3(it.first, it.second); + } + for (const auto& it : mUniformMat4s) + { + mShader->SetUniformMat4(it.first, it.second); + } + } + } + +} \ No newline at end of file diff --git a/hippo/src/graphics/rendercommands.cpp b/hippo/src/graphics/rendercommands.cpp index 844a258..3f575fa 100644 --- a/hippo/src/graphics/rendercommands.cpp +++ b/hippo/src/graphics/rendercommands.cpp @@ -8,6 +8,7 @@ #include "hippo/graphics/texture.h" #include "hippo/graphics/framebuffer.h" #include "hippo/graphics/camera.h" +#include "hippo/graphics/material.h" #include "glad/glad.h" @@ -34,6 +35,8 @@ namespace hippo::graphics::rendercommands shader->SetUniformMat4("view", cam->GetViewMatrix()); } + shader->SetUniformMat4("model", mModelMatrix); + if (va->GetElementCount() > 0) { glDrawElements(GL_TRIANGLES, va->GetElementCount(), GL_UNSIGNED_INT, 0); @@ -76,6 +79,8 @@ namespace hippo::graphics::rendercommands shader->SetUniformMat4("view", cam->GetViewMatrix()); } + shader->SetUniformMat4("model", mModelMatrix); + if (va->GetElementCount() > 0) { glDrawElements(GL_TRIANGLES, va->GetElementCount(), GL_UNSIGNED_INT, 0); @@ -96,6 +101,65 @@ namespace hippo::graphics::rendercommands } } + void RenderVertexArrayMaterial::Execute() + { + std::shared_ptr va = mVertexArray.lock(); + std::shared_ptr mat = mMaterial.lock(); + if (va && mat) + { + HIPPO_ASSERT(va->IsValid(), "Attempting to execute invalid RenderVertexArrayMaterial - did you forget to call VertexArray::Upload()?"); + if (va->IsValid()) + { + va->Bind(); + + Shader* shader = mat->GetShader(); + Texture* texture = mat->GetTexture(); + HIPPO_ASSERT(shader, "Attempting to execute invalid RenderVertexArrayMaterial - shader is nullptr"); + if (shader) + { + mat->UpdateShaderUniforms(); + shader->Bind(); + if (texture) + { + texture->Bind(); + } + + // TODO: Convert camera matrices to leverage UBOs + const auto& rm = Engine::Instance().GetRenderManager(); + const auto& cam = rm.GetActiveCamera(); + if (cam) + { + shader->SetUniformMat4("proj", cam->GetProjectionMatrix()); + shader->SetUniformMat4("view", cam->GetViewMatrix()); + } + + shader->SetUniformMat4("model", mModelMatrix); + + if (va->GetElementCount() > 0) + { + glDrawElements(GL_TRIANGLES, va->GetElementCount(), GL_UNSIGNED_INT, 0); + } + else + { + glDrawArrays(GL_TRIANGLE_STRIP, 0, va->GetVertexCount()); HIPPO_CHECK_GL_ERROR; + } + + if (texture) + { + texture->Unbind(); + } + shader->Unbind(); + } + + va->Unbind(); + } + } + else + { + HIPPO_WARN("Attempting to execute RenderVertexArrayMaterial with invalid data"); + } + } + void PushFramebuffer::Execute() { std::shared_ptr fb = mFramebuffer.lock(); diff --git a/hippoeditor/src/main.cpp b/hippoeditor/src/main.cpp index 5006779..d72aba6 100644 --- a/hippoeditor/src/main.cpp +++ b/hippoeditor/src/main.cpp @@ -11,6 +11,7 @@ #include "hippo/graphics/framebuffer.h" #include "hippo/graphics/texture.h" #include "hippo/graphics/camera.h" +#include "hippo/graphics/material.h" #include "hippo/input/mouse.h" #include "hippo/input/keyboard.h" @@ -32,8 +33,8 @@ class Editor : public hippo::App float mCameraRot; std::shared_ptr mVA; - std::shared_ptr mShader; - std::shared_ptr mTexture; + std::shared_ptr mMaterial1; + std::shared_ptr mMaterial2; glm::vec2 mRectPos, mRectSize; @@ -41,6 +42,7 @@ class Editor : public hippo::App core::AssetLibrary mVALibrary; core::AssetLibrary mShaderLibrary; core::AssetLibrary mTextureLibrary; + core::AssetLibrary mMaterialLibrary; public: core::WindowProperties GetWindowProperties() override @@ -68,8 +70,8 @@ class Editor : public hippo::App mRectSize = glm::vec2(1.f); mVA = mVALibrary.Get("Rect"); - mShader = mShaderLibrary.Get("Rect"); - mTexture = mTextureLibrary.Get("Bro"); + mMaterial1 = mMaterialLibrary.Get("RectRed"); + mMaterial2 = mMaterialLibrary.Get("RectGreen"); } void Shutdown() override @@ -85,17 +87,25 @@ class Editor : public hippo::App auto& window = Engine::Instance().GetWindow(); window.SetShouldRenderToScreen(!mImguiEnabled); } - - glm::mat4 model = glm::mat4(1.f); - model = glm::translate(model, { mRectPos.x, mRectPos.y, 0.f }); - model = glm::scale(model, { mRectSize.x, mRectSize.y, 0.f }); - mShader->SetUniformMat4("model", model); } void Render() override { Engine::Instance().GetRenderManager().Submit(HIPPO_SUBMIT_RC(PushCamera, mCamera)); - Engine::Instance().GetRenderManager().Submit(HIPPO_SUBMIT_RC(RenderVertexArrayTextured, mVA, mTexture, mShader)); + + { + glm::mat4 model = glm::mat4(1.f); + model = glm::translate(model, { mRectPos.x, mRectPos.y, 0.f }); + model = glm::scale(model, { mRectSize.x, mRectSize.y, 0.f }); + Engine::Instance().GetRenderManager().Submit(HIPPO_SUBMIT_RC(RenderVertexArrayMaterial, mVA, mMaterial1, model)); + } + { + glm::mat4 model = glm::mat4(1.f); + model = glm::translate(model, { mRectPos.x + 2.f, mRectPos.y, 0.f }); + model = glm::scale(model, { mRectSize.x, mRectSize.y, 0.f }); + Engine::Instance().GetRenderManager().Submit(HIPPO_SUBMIT_RC(RenderVertexArrayMaterial, mVA, mMaterial2, model)); + } + Engine::Instance().GetRenderManager().Submit(HIPPO_SUBMIT_RC(PopCamera)); } @@ -126,31 +136,6 @@ class Editor : public hippo::App } ImGui::End(); - if (ImGui::Begin("Options")) - { - if (ImGui::Button("Rect")) - { - mVA = mVALibrary.Get("Rect"); - mShader = mShaderLibrary.Get("Rect"); - } - ImGui::SameLine(); - if (ImGui::Button("RectTextured")) - { - mVA = mVALibrary.Get("TexturedRect"); - mShader = mShaderLibrary.Get("TexturedRect"); - } - if (ImGui::Button("Bro")) - { - mTexture = mTextureLibrary.Get("Bro"); - } - ImGui::SameLine(); - if (ImGui::Button("Bro2")) - { - mTexture = mTextureLibrary.Get("Bro2"); - } - } - ImGui::End(); - if (ImGui::Begin("GameView")) { if (ImGui::IsWindowHovered()) @@ -362,6 +347,18 @@ class Editor : public hippo::App tex->SetTextureFilter(graphics::TextureFilter::Nearest); mTextureLibrary.Load("Bro2", tex); } + + // Material + { + std::shared_ptr mat = std::make_shared(mShaderLibrary.Get("Rect")); + mat->SetUniformValue("col", glm::vec4(1, 0, 0, 1)); + mMaterialLibrary.Load("RectRed", mat); + } + { + std::shared_ptr mat = std::make_shared(mShaderLibrary.Get("Rect")); + mat->SetUniformValue("col", glm::vec4(0, 1, 0, 1)); + mMaterialLibrary.Load("RectGreen", mat); + } } };