引言
上次我们构建了渲染命令并重构了渲染 API 架构,今天我们来看看相机。
相机设计
为了在引擎中构建合适的相机系统,我们需要考虑相机的架构以及它们如何正常工作,需要真正了解渲染的工作原理(不仅包括渲染方面,但包括 GamePlay 方面)。相机真的很有趣,它们对于渲染至关重要。
相机被定义为如何看待一个场景,它有些像真实世界中的相机,为我们提供了一种正确查看世界的方法。所以我们在 3D 场景中有一堆对象,我们想做的是从一个特定的角度来看待它们,像现实世界一样可以拿着相机。
proj x view(TRS) x model x vertexPos
|
在 Infinite/Renderer/
新建 OrthographicCamera.h
和 OrthographicCame.cpp
。
头文件 OrthographicCamera.h
包含相机位置、角度和所需的投影矩阵及其访问器:
#pragma once
#include <glm/glm.hpp>
namespace Infinite {
class OrthographicCamera { public: OrthographicCamera(float left, float right, float bottom, float top);
const glm::vec3& GetPosition() const { return m_Position; } void SetPosition(const glm::vec3& position) { m_Position = position; RecalculateViewMatrix(); }
float GetRotation() const { return m_Rotation; } void SetRotation(float rotation) { m_Rotation = rotation; RecalculateViewMatrix(); }
const glm::mat4& GetProjectionMatrix() const { return m_ProjectionMatrix; } const glm::mat4& GetViewMatrix() const { return m_ViewMatrix; } const glm::mat4& GetViewProjectionMatrix() const { return m_ViewProjectionMatrix; } private: void RecalculateViewMatrix();
private: glm::mat4 m_ProjectionMatrix; glm::mat4 m_ViewMatrix; glm::mat4 m_ViewProjectionMatrix;
glm::vec3 m_Position = {0.0f, 0.0f, 0.0f}; float m_Rotation = 0.0f; };
}
|
OrthographicCamera.cpp
实现 RecalculateViewMatrix()
方法,实时更新我们的 VP 矩阵:
#include "ifnpch.h" #include "OrthographicCamera.h"
#include <glm/gtc/matrix_transform.hpp>
namespace Infinite {
OrthographicCamera::OrthographicCamera(float left, float right, float bottom, float top) :m_ProjectionMatrix(glm::ortho(left, right, bottom, top, -1.0f, 1.0f)), m_ViewMatrix(1.0f) { m_ViewProjectionMatrix = m_ProjectionMatrix * m_ProjectionMatrix; }
void OrthographicCamera::RecalculateViewMatrix() { glm::mat4 transform = glm::translate(glm::mat4(1.0f), m_Position) * glm::rotate(glm::mat4(1.0f), m_Rotation, glm::vec3(0, 0, 1));
m_ViewMatrix = glm::inverse(transform); m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix; }
}
|
应用类调整
Application.h
加入相机:
#include "./Renderer/Buffer.h" #include "./Renderer/VertexArray.h"
+#include "./Renderer/OrthographicCamera.h"
namespace Infinite { class INFINITE_API Application { @@ -41,6 +43,8 @@ namespace Infinite {
std::shared_ptr<Shader> m_BlueShader; std::shared_ptr<VertexArray> m_SquareVertexArray;
+ OrthographicCamera m_Camera; private: static Application* s_Instance; };
|
Application.cpp
首先先调整 Shader:
Application* Application::s_Instance = nullptr;
- Application::Application() + Application::Application() + : m_Camera(-1.6f, 1.6f, -0.9f, 0.9f) { IFN_CORE_ASSERT(!s_Instance, "Application already exists!"); s_Instance = this; @@ -78,14 +79,16 @@ namespace Infinite { layout(location = 0) in vec3 a_Position; layout(location = 1) in vec4 a_Color; + uniform mat4 u_ViewProjection; out vec3 v_Position; out vec4 v_Color; void main() { v_Position = a_Position; v_Color = a_Color; - gl_Position = vec4(a_Position, 1.0); + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); } )";
@@ -112,11 +115,14 @@ namespace Infinite { #version 330 core layout(location = 0) in vec3 a_Position; + uniform mat4 u_ViewProjection; out vec3 v_Position; void main() { v_Position = a_Position; - gl_Position = vec4(a_Position, 1.0); + gl_Position = u_ViewProjection * vec4(a_Position, 1.0); } )";
|
其次是调整 Submit()
方法:
@@ -167,14 +173,13 @@ namespace Infinite { RenderCommand::SetClearColor({ 0.1f, 0.1f, 0.1f, 1 }); RenderCommand::Clear();
- Renderer::BeginScene(); - - m_BlueShader->Bind(); - Renderer::Submit(m_SquareVertexArray); + m_Camera.SetPosition({ 0.5f, 0.5f, 0.0f }); + m_Camera.SetRotation(45.0f);
+ Renderer::BeginScene(m_Camera);
- m_Shader->Bind(); - Renderer::Submit(m_VertexArray); + Renderer::Submit(m_BlueShader, m_SquareVertexArray); + Renderer::Submit(m_Shader, m_VertexArray);
Renderer::EndScene();
|
而 Submit()
方法涉及到 Renderer.h
和 Renderer.cpp
:
#include "RenderCommand.h"
+#include "OrthographicCamera.h" +#include "Shader.h"
namespace Infinite {
class Renderer { public: - static void BeginScene(); + static void BeginScene(OrthographicCamera& camera); static void EndScene();
- static void Submit(const std::shared_ptr<VertexArray>& vertexArray); + static void Submit(const std::shared_ptr<Shader>& shader, const std::shared_ptr<VertexArray>& vertexArray);
inline static RendererAPI::API GetAPI() { return RendererAPI::GetAPI(); }
+ private: + struct SceneData + { + glm::mat4 ViewProjectionMatrix; + }; + + static SceneData* m_SceneData; };
|
头文件定义场景数据集,目前暂时包含 VP 矩阵。
#include <glad/glad.h>
+#include <glm/gtc/type_ptr.hpp>
namespace Infinite {
Shader::Shader(const std::string& vertexSrc, const std::string& fragmentSrc) @@ -137,4 +139,10 @@ namespace Infinite { glUseProgram(0); }
+ void Shader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix) + { + GLint location = glGetUniformLocation(m_RendererID, name.c_str()); + glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix)); + }
}
|
调试
Application::Application() : m_Camera(1.0f, 1.0f, -1.0f, 1.0f)
|
Application::Application() : m_Camera(-1.6f, 1.6f, -0.9f, 0.9f)
|