diff --git a/include/td/misc/ObjectNotifier.h b/include/td/misc/ObjectNotifier.h deleted file mode 100644 index 83e076d..0000000 --- a/include/td/misc/ObjectNotifier.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace td { -namespace utils { - -template -class ObjectNotifier { -protected: - std::vector m_Listeners; - -public: - void BindListener(Listener* listener) { - m_Listeners.push_back(listener); - } - - void UnbindListener(Listener* listener) { - auto iter = std::find(m_Listeners.begin(), m_Listeners.end(), listener); - - if (iter == m_Listeners.end()) return; - - m_Listeners.erase(iter); - } - - template - void NotifyListeners(Func function, Args... args) { - for (Listener* listener : m_Listeners) - std::bind(function, listener, args...)(); - } -}; - -} // namespace utils -} // namespace td diff --git a/include/td/misc/Signal.h b/include/td/misc/Signal.h new file mode 100644 index 0000000..b8dbf17 --- /dev/null +++ b/include/td/misc/Signal.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include +#include + +namespace td { +namespace utils { + +template +class Signal : private NonCopyable { + private: + using CallBack = std::function; + + std::vector m_Callbacks; + + public: + void Connect(CallBack&& a_Callback) { + m_Callbacks.push_back(std::move(a_Callback)); + } + + void operator()(Args... args) const { + for (const CallBack& callback : m_Callbacks) { + callback(args...); + } + } +}; + +} // namespace utils +} // namespace td diff --git a/include/td/render/Camera.h b/include/td/render/Camera.h index 6cd1907..a0d386b 100644 --- a/include/td/render/Camera.h +++ b/include/td/render/Camera.h @@ -1,20 +1,12 @@ #pragma once #include -#include +#include namespace td { namespace render { -class ICameraListener { - public: - virtual void OnPerspectiveChange() {} - virtual void OnViewChange() {} -}; - -using CameraNotifier = utils::ObjectNotifier; - -class Camera : public CameraNotifier { +class Camera { private: Mat4f m_ViewMatrix; Mat4f m_ProjectionMatrix; @@ -29,6 +21,9 @@ class Camera : public CameraNotifier { float m_Pitch = -PI / 2.0f + 0.0000001f; public: + utils::Signal<> OnPerspectiveChange; + utils::Signal<> OnViewChange; + const Mat4f& GetViewMatrix() const { return m_ViewMatrix; } diff --git a/include/td/render/Renderer.h b/include/td/render/Renderer.h index 407134c..7e2bca9 100644 --- a/include/td/render/Renderer.h +++ b/include/td/render/Renderer.h @@ -1,35 +1,42 @@ #pragma once +#include #include #include -#include +#include namespace td { namespace render { -class Renderer { - protected: - Camera& m_Camera; - +class BasicRenderer { public: - Renderer(Camera& a_Camera) : m_Camera(a_Camera) {} - virtual ~Renderer() {} - virtual void Render() = 0; void Render(const GL::VertexArray& a_Vao); }; +class Renderer : public BasicRenderer { + protected: + std::unique_ptr m_Shader; + Camera& m_Camera; + + public: + Renderer(std::unique_ptr&& a_Shader, Camera& a_Camera); + + virtual ~Renderer() {} +}; + class RenderPipeline { private: - std::vector> m_Renderers; + std::vector> m_Renderers; public: RenderPipeline(); ~RenderPipeline() = default; - void AddRenderer(std::unique_ptr&& a_Renderer) { - m_Renderers.push_back(std::move(a_Renderer)); + template + void AddRenderer(Args&&... args) { + m_Renderers.push_back(std::make_unique(args ...)); } void Clear() { diff --git a/include/td/render/renderer/WorldRenderer.h b/include/td/render/renderer/WorldRenderer.h index f57662d..095f6be 100644 --- a/include/td/render/renderer/WorldRenderer.h +++ b/include/td/render/renderer/WorldRenderer.h @@ -2,16 +2,15 @@ #include #include -#include #include +#include namespace td { namespace render { -class WorldRenderer : public Renderer, public ICameraListener { +class WorldRenderer : public Renderer { private: const game::World& m_World; - shader::WorldShader m_Shader; std::unique_ptr m_WorldVao; public: @@ -19,9 +18,6 @@ class WorldRenderer : public Renderer, public ICameraListener { virtual ~WorldRenderer(); virtual void Render() override; - - virtual void OnPerspectiveChange() override; - virtual void OnViewChange() override; }; } // namespace render diff --git a/include/td/render/shader/CameraShaderProgram.h b/include/td/render/shader/CameraShaderProgram.h new file mode 100644 index 0000000..66960ce --- /dev/null +++ b/include/td/render/shader/CameraShaderProgram.h @@ -0,0 +1,23 @@ +#pragma once + +#include + +namespace td { +namespace shader { + +class CameraShaderProgram : public ShaderProgram { + private: + unsigned int m_LocationProjection = 0, m_LocationView = 0; + + public: + CameraShaderProgram() {} + + void SetProjectionMatrix(const Mat4f& proj) const; + void SetViewMatrix(const Mat4f& view) const; + + virtual void GetAllUniformLocation(); +}; + + +} // namespace shader +} // namespace td diff --git a/include/td/render/shader/ShaderProgram.h b/include/td/render/shader/ShaderProgram.h index 23aef9d..66db83f 100755 --- a/include/td/render/shader/ShaderProgram.h +++ b/include/td/render/shader/ShaderProgram.h @@ -1,10 +1,15 @@ #pragma once +#include #include #include -#include namespace td { + +namespace render { +class Renderer; +} // namespace render + namespace shader { class ShaderProgram { @@ -15,10 +20,10 @@ class ShaderProgram { void Start() const; void Stop() const; + protected: void LoadProgramFile(const std::string& vertexFile, const std::string& fragmentFile); void LoadProgram(const std::string& vertexSource, const std::string& fragmentSource); - protected: virtual void GetAllUniformLocation() = 0; int GetUniformLocation(const std::string& uniformName) const; diff --git a/include/td/render/shader/WorldShader.h b/include/td/render/shader/WorldShader.h index f7d743e..8765708 100644 --- a/include/td/render/shader/WorldShader.h +++ b/include/td/render/shader/WorldShader.h @@ -1,20 +1,13 @@ #pragma once -#include +#include namespace td { namespace shader { -class WorldShader : public ShaderProgram { -private: - unsigned int m_LocationProjection = 0, m_LocationView = 0; -protected: - void GetAllUniformLocation(); +class WorldShader : public CameraShaderProgram { public: WorldShader(); - - void SetProjectionMatrix(const Mat4f& proj) const; - void SetViewMatrix(const Mat4f& view) const; }; } // namespace shader diff --git a/src/main.cpp b/src/main.cpp index ac43d5b..f0a6b0a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -196,7 +196,7 @@ int main(int argc, char** argv) { td::render::Camera cam; td::render::RenderPipeline renderer; - renderer.AddRenderer(std::make_unique(cam, w)); + renderer.AddRenderer(cam, w); cam.SetCamPos({77, 25, 13}); cam.UpdatePerspective(display.GetAspectRatio()); diff --git a/src/td/render/Camera.cpp b/src/td/render/Camera.cpp index 0d2a567..260a467 100644 --- a/src/td/render/Camera.cpp +++ b/src/td/render/Camera.cpp @@ -8,7 +8,7 @@ namespace render { void Camera::UpdatePerspective(float a_AspectRatio) { m_ProjectionMatrix = maths::Perspective(80.0f / 180.0f * PI, a_AspectRatio, 0.1f, 160.0f); m_InvProjectionMatrix = maths::Inverse(m_ProjectionMatrix); - NotifyListeners(&ICameraListener::OnPerspectiveChange); + OnPerspectiveChange(); } void Camera::SetCamPos(const Vec3f& a_NewPos) { @@ -21,7 +21,7 @@ void Camera::SetCamPos(const Vec3f& a_NewPos) { m_CamPos = a_NewPos; m_ViewMatrix = maths::Look(m_CamPos, front, { 0, 1, 0 }); m_InvViewMatrix = maths::Transpose(maths::Inverse(m_ViewMatrix)); // why transpose ? I don't know - NotifyListeners(&ICameraListener::OnViewChange); + OnViewChange(); } } // namespace render diff --git a/src/td/render/Renderer.cpp b/src/td/render/Renderer.cpp index cf811eb..9c03453 100644 --- a/src/td/render/Renderer.cpp +++ b/src/td/render/Renderer.cpp @@ -5,13 +5,27 @@ namespace td { namespace render { -void Renderer::Render(const GL::VertexArray& a_Vao) { +void BasicRenderer::Render(const GL::VertexArray& a_Vao) { a_Vao.Bind(); glDrawArrays(GL_TRIANGLES, 0, a_Vao.GetVertexCount()); // glDrawElements(GL_TRIANGLES, a_Vao.GetVertexCount(), GL_UNSIGNED_INT, nullptr); a_Vao.Unbind(); } +Renderer::Renderer(std::unique_ptr&& a_Shader, Camera& a_Camera) : + m_Shader(std::move(a_Shader)), m_Camera(a_Camera) { + a_Camera.OnPerspectiveChange.Connect([this]() { + m_Shader->Start(); + m_Shader->SetProjectionMatrix(m_Camera.GetProjectionMatrix()); + }); + + a_Camera.OnViewChange.Connect([this]() { + m_Shader->Start(); + m_Shader->SetViewMatrix(m_Camera.GetViewMatrix()); + }); +} + + RenderPipeline::RenderPipeline() { glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); diff --git a/src/td/render/renderer/WorldRenderer.cpp b/src/td/render/renderer/WorldRenderer.cpp index f9b55f7..c189111 100644 --- a/src/td/render/renderer/WorldRenderer.cpp +++ b/src/td/render/renderer/WorldRenderer.cpp @@ -7,28 +7,17 @@ namespace td { namespace render { -WorldRenderer::WorldRenderer(Camera& a_Camera, const game::World& a_World) : Renderer(a_Camera), m_World(a_World) { +WorldRenderer::WorldRenderer(Camera& a_Camera, const game::World& a_World) : Renderer(std::make_unique(), a_Camera), m_World(a_World) { m_WorldVao = std::make_unique(std::move(WorldLoader::LoadWorldModel(&a_World))); - a_Camera.BindListener(this); } WorldRenderer::~WorldRenderer() {} void WorldRenderer::Render() { - m_Shader.Start(); + m_Shader->Start(); Renderer::Render(*m_WorldVao); ImGui::ShowDemoWindow(); } -void WorldRenderer::OnPerspectiveChange() { - m_Shader.Start(); - m_Shader.SetProjectionMatrix(m_Camera.GetProjectionMatrix()); -} - -void WorldRenderer::OnViewChange() { - m_Shader.Start(); - m_Shader.SetViewMatrix(m_Camera.GetViewMatrix()); -} - } // namespace render } // namespace td diff --git a/src/td/render/shader/CameraShaderProgram.cpp b/src/td/render/shader/CameraShaderProgram.cpp new file mode 100644 index 0000000..a54aeed --- /dev/null +++ b/src/td/render/shader/CameraShaderProgram.cpp @@ -0,0 +1,21 @@ +#include + +namespace td { +namespace shader { + +void CameraShaderProgram::SetProjectionMatrix(const Mat4f& proj) const { + LoadMat4(m_LocationProjection, proj); +} + +void CameraShaderProgram::SetViewMatrix(const Mat4f& view) const { + LoadMat4(m_LocationView, view); +} + +void CameraShaderProgram::GetAllUniformLocation() { + m_LocationProjection = static_cast(GetUniformLocation("projectionMatrix")); + m_LocationView = static_cast(GetUniformLocation("viewMatrix")); +} + + +} // namespace shader +} // namespace td diff --git a/src/td/render/shader/WorldShader.cpp b/src/td/render/shader/WorldShader.cpp index 469882d..01d9e64 100644 --- a/src/td/render/shader/WorldShader.cpp +++ b/src/td/render/shader/WorldShader.cpp @@ -81,22 +81,9 @@ void main(void){ )"; #endif -WorldShader::WorldShader() : ShaderProgram() { +WorldShader::WorldShader() : CameraShaderProgram() { ShaderProgram::LoadProgram(vertexSource, fragmentSource); } -void WorldShader::GetAllUniformLocation() { - m_LocationProjection = static_cast(GetUniformLocation("projectionMatrix")); - m_LocationView = static_cast(GetUniformLocation("viewMatrix")); -} - -void WorldShader::SetProjectionMatrix(const Mat4f& proj) const { - LoadMat4(m_LocationProjection, proj); -} - -void WorldShader::SetViewMatrix(const Mat4f& view) const { - LoadMat4(m_LocationView, view); -} - } // namespace shader } // namespace td \ No newline at end of file