HazelEngine 学习记录 - Creating an Orthographic Camera

Creating an Orthographic Camera

本节主要是完成一个正交相机的实现:

创建OrthographicCamera.h OrthographicCamera.cpp ,然后添加相关函数:

	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; RecalculateViewMatirx(); }

		float GetRotation() const { return m_Rotation; }
		void SetRotation(float rotation) { m_Rotation = rotation; RecalculateViewMatirx(); }

		const glm::mat4 GetProjectionMatrix() { return m_ProjectionMatrix; }
		const glm::mat4 GetViewMatrix() { return m_ViewMatrix; }
		const glm::mat4 GetViewProjectionMatrix() { return m_ViewProjectionMatrix; }

	private:
		//use for update
		void RecalculateViewMatirx();

	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;
	};
}

在正交相机中,我们拥有相机的 View 矩阵和 Projection 矩阵,这两个矩阵用于场景中所有物体的视口投影变换,最终结果是将所有物体变换到一个 (-1, 1) 的立方体中,此外,为了控制相机的移动和旋转,我们还拥有相机的位置和旋转角这两个参数,在函数的设置中,除了获取和设置相机的 Pos、 Rotation,还能够取得相机的 VP矩阵。

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_ViewMatrix; 
	}
	void OrthographicCamera::RecalculateViewMatirx()
	{
		glm::mat4 transform = glm::translate(glm::mat4(1.0f), m_Position) *
			glm::rotate(glm::mat4(1.0f), glm::radians(m_Rotation), glm::vec3(0, 0, 1));
		m_ViewMatrix = glm::inverse(transform);
		//注意矩阵相乘的顺序,先乘 view 矩阵 之后再乘 proj 矩阵
		m_ViewProjectionMatrix = m_ProjectionMatrix * m_ViewMatrix;
	}

在构造函数中,利用传入的四个视口的参数初始化了用于正交投影的投影矩阵,这里目前没有添加远近平面,而是简单的设置为了 -1 和 1 , View 矩阵也仅仅是用单位矩阵进行了初始化,然后计算得到 VP 矩阵,然后由于我们每次设置完相机的位置和旋转之后,需要 update VP 矩阵,所以设置了RecalculateViewMatirx 这个函数,这个函数是根据修改后的相机位置和旋转角度,重新计算 VP 矩阵,具体做法是,相机进行 transform 之后,View 矩阵便是其逆矩阵,因为 View 矩阵的作用是假定相机在原点不动,将所有物体沿着相机移动的相反方向移动,以实现相机的移动。

然后在 BeginScene 函数中我们要获取渲染的一些基本数据,例如 Camera 的属性参数,环境光照的各种信息,这里我们仅仅只是先添加了相机的参数,在 renderer 中,创建了一个 SceneData 的结构体,用于保存相机的 VP 矩阵。

struct SceneData
		{
			glm::mat4 ViewProjectionMatrix;
		};

		static SceneData* s_SceneData;

然后在 BeginScene 中进行该 data 的初始化:

void Renderer::BeginScene(OrthographicCamera& camera)
	{
		s_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix();
	}

然后我们在 Submit 函数中希望进行 Shader 的 Bind 以及 unform 变量的设置,对于 uniform ,实际上就是把我们经常会用到的数据放在一块区域,然后放在显存中的某个区域,这样就不用每次从内存读取数据。

Uniform变量 -- 即统一变量,简单理解就是一个 GLSL shader 中的全局常量,可以随意在任意shader(vertex shader, geometry shader, or fragment shader)访问,不同的shader中uniform是一起链接的,初始化之后,不能修改其值,否则会引起编译错误。

所以在 Shader 中需要完成 uniform 变量的设置:

void Shader::UpLoadUniformMat4(const std::string& name, const glm::mat4 matrix)
	{
		//返回一个 int 值,这个值会验证我们传入的值是否有效
		GLint location = glGetUniformLocation(m_RendererID, name.c_str());
		glUniformMatrix4fv(location, 1, GL_FALSE, glm::value_ptr(matrix));
	}

之后 Submit 函数:

void Renderer::Submit(const std::shared_ptr<Shader>& shader, const std::shared_ptr<VertexArray>& vertexArray)
	{
		//在OpenGL 中 Bind 顺序不分先后
		shader->Bind();
		shader->UpLoadUniformMat4("u_ViewProjection", s_SceneData->ViewProjectionMatrix);

		vertexArray->Bind();
		RenderCommand::DrawIndexed(vertexArray);
	}

在 Application 中添加成员变量 m_Camera 然后在构造函数中进行初始化,之后在 Shader 中设置 uniform 变量然后进行测试:

		Application::Application()
		:m_Camera(-1.6f, 1.6f, -0.9f, 0.9f)
      
    //VertexShader
      uniform mat4 u_ViewProjection;
			out vec3 v_Position;
			out vec4 v_Color;
			void main()
			{
				v_Position = a_Position;
				v_Color = a_Color;
				gl_Position = u_ViewProjection * vec4(a_Position, 1.0);	
      }

		//RunLoop
			RenderCommand::SetClearColor({ 0.1f, 0.1f, 0.1f, 1 });
			RenderCommand::Clear();

			m_Camera.SetPosition({ 0.5f, 0.5f, 0.0f });
			m_Camera.SetRotation(45.0f);

			Renderer::BeginScene(m_Camera);

			Renderer::Submit(m_blueShader, m_SquareVA);
			Renderer::Submit(m_Shader, m_VertexArray);

			Renderer::EndScene(); 

运行结果:
HazelEngine 学习记录 - Creating an Orthographic Camera_第1张图片

你可能感兴趣的:(HazelEngine,学习记录,学习)