• HazelEngine 学习记录 - 2D Renderer


    2D Renderer

    Preparing for 2D Rendering

    本节主要是为即将要完成的 2D渲染的渲染器创建一个新的 Layer 来使用,首先将 Hazel.h 中的 EntryPoint.h 放到我们的 SandBox 中,因为这个头文件实际上是整个项目的 main 函数,我们后面再进行 Hazel.h 包含的时候会出问题

    #pragma once
    
    #include "Hazel.h"
    
    class Sandbox2D : public Hazel::Layer
    {
    public:
    	Sandbox2D();
    	virtual ~Sandbox2D() = default;
    
    	virtual void OnAttach() override;
    	virtual void OnDetach() override;
    
    	void OnUpdate(Hazel::Timestep ts) override;
    	virtual void OnImGuiRender() override;
    	void OnEvent(Hazel::Event& e) override;
    private:
    	Hazel::OrthographicCameraController m_CameraController;
    
    	// Temp
    	Hazel::Ref<Hazel::VertexArray> m_SquareVA;
    	Hazel::Ref<Hazel::Shader> m_FlatColorShader;
    
    	glm::vec4 m_SquareColor = { 0.2f, 0.3f, 0.8f, 1.0f };
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    SandBox2D Layer 中也是包含了一个 Layer 的基本函数:OnAttach OnDetach OnUpdate OnImGuiRender OnEvent

    然后还创建了一个 CameraController 一个顶点数组和一个 shader

    Cpp 文件中:

    #include "Sandbox2D.h"
    #include "imgui/imgui.h"
    
    #include 
    #include 
    
    #include "Platform/OpenGL/OpenGLShader.h"
    
    Sandbox2D::Sandbox2D()
    	: Layer("Sandbox2D"), m_CameraController(1280.0f / 720.0f)
    {
    }
    
    void Sandbox2D::OnAttach()
    {
    	m_SquareVA = Hazel::VertexArray::Create(); //之前 Create 函数返回的指针改为了 shared_ptr
    
    	float squareVertices[3 * 4] = {
    		-0.5f, -0.5f, 0.0f,
    		 0.5f, -0.5f, 0.0f,
    		 0.5f,  0.5f, 0.0f,
    		-0.5f,  0.5f, 0.0f
    	};
    
    	Hazel::Ref<Hazel::VertexBuffer> squareVB;
    	squareVB.reset(Hazel::VertexBuffer::Create(squareVertices, sizeof(squareVertices)));
    	squareVB->SetLayout({
    		{ Hazel::ShaderDataType::Float3, "a_Position" }
    	});
    	m_SquareVA->AddVertexBuffer(squareVB);
    
    	uint32_t squareIndices[6] = { 0, 1, 2, 2, 3, 0 };
    	Hazel::Ref<Hazel::IndexBuffer> squareIB;
    	squareIB.reset(Hazel::IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t)));
    	m_SquareVA->SetIndexBuffer(squareIB);
    
    	m_FlatColorShader = Hazel::Shader::Create("assets/shaders/FlatColor.glsl");
    }
    
    void Sandbox2D::OnDetach()
    {
    }
    
    void Sandbox2D::OnUpdate(Hazel::Timestep ts)
    {
    	// Update
    	m_CameraController.OnUpdate(ts);
    
    	// Render
    	Hazel::RenderCommand::SetClearColor({ 0.1f, 0.1f, 0.1f, 1 });
    	Hazel::RenderCommand::Clear();
    
    	Hazel::Renderer::BeginScene(m_CameraController.GetCamera());
    
    	std::dynamic_pointer_cast<Hazel::OpenGLShader>(m_FlatColorShader)->Bind();
    	std::dynamic_pointer_cast<Hazel::OpenGLShader>(m_FlatColorShader)->UploadUniformFloat4("u_Color", m_SquareColor);
    
    	Hazel::Renderer::Submit(m_FlatColorShader, m_SquareVA, glm::scale(glm::mat4(1.0f), glm::vec3(1.5f)));
    
    	Hazel::Renderer::EndScene();
    }
    
    void Sandbox2D::OnImGuiRender()
    {
    	ImGui::Begin("Settings");
    	ImGui::ColorEdit4("Square Color", glm::value_ptr(m_SquareColor));
    	ImGui::End();
    }
    
    void Sandbox2D::OnEvent(Hazel::Event& e)
    {
    	m_CameraController.OnEvent(e);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    OnAttach 函数中,创建了一个 VertexArray ,然后创建 VertexBuffer,并存储了 4 个顶点,以及一个 IndexBuffer,

    存放了矩形的顶点索引,然后绑定一个 shader.

    OnUpdate 函数中,首先进行 CameraController 的更新,然后进行渲染步骤:clear,BeginScene,BindShader,setUniform,Submit,EndScene。

    然后在OnEvent 函数中,将产生的 event 传给 CameraController。

    Starting our 2D Renderer

    为了更高效率的进行 2D 渲染,需要为 2D Renderer 单独创建属于其的 renderer 以及其他相应的配置,创建 Renderer2D.h Renderer2D.cpp

    #pragma once
    
    #include "OrthographicCamera.h"
    
    namespace Hazel {
    
    	class Renderer2D
    	{
    	public:
    		static void Init();
    		static void Shutdown();
    
    		static void BeginScene(const OrthographicCamera& camera);
    		static void EndScene();
    
    		// Primitives
    		static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color);
    		static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color);
    	};
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    所有的函数都被定义为 static,是因为我们不希望在创建多个 renderer2D 实例时,每个实例都调用各自的函数,定义为static 之后,函数可以被所有的实例共享。由于 2D Renderer 渲染物体实际上都是通过画2D图形实现的,所以创建了 DrawQuad 函数,专门用于矩形的绘制。

    #include "hzpch.h"
    #include "Renderer2D.h"
    
    #include "VertexArray.h"
    #include "Shader.h"
    #include "RenderCommand.h"
    
    #include "Platform/OpenGL/OpenGLShader.h"
    
    namespace Hazel {
    
    	struct Renderer2DStorage
    	{
    		Ref<VertexArray> QuadVertexArray;
    		Ref<Shader> FlatColorShader;
    	};
    
    	static Renderer2DStorage* s_Data;
    
    	void Renderer2D::Init()
    	{
    		s_Data = new Renderer2DStorage();
    		s_Data->QuadVertexArray = VertexArray::Create();
    
    		float squareVertices[3 * 4] = {
    			-0.5f, -0.5f, 0.0f,
    			 0.5f, -0.5f, 0.0f,
    			 0.5f,  0.5f, 0.0f,
    			-0.5f,  0.5f, 0.0f
    		};
    
    		Ref<VertexBuffer> squareVB;
    		squareVB = VertexBuffer::Create(squareVertices, sizeof(squareVertices));
     
    		squareVB->SetLayout({
    			{ ShaderDataType::Float3, "a_Position" }
    		});
    		s_Data->QuadVertexArray->AddVertexBuffer(squareVB);
    
    		uint32_t squareIndices[6] = { 0, 1, 2, 2, 3, 0 };
    		Ref<IndexBuffer> squareIB;
    		squareIB = IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t));
     
    		s_Data->QuadVertexArray->SetIndexBuffer(squareIB);
    
    		s_Data->FlatColorShader = Shader::Create("assets/shaders/FlatColor.glsl");
    	}
    
    	void Renderer2D::Shutdown()
    	{
    		delete s_Data;
    	}
    
    	void Renderer2D::BeginScene(const OrthographicCamera& camera)
    	{
    		std::dynamic_pointer_cast<OpenGLShader>(s_Data->FlatColorShader)->Bind();
    		std::dynamic_pointer_cast<OpenGLShader>(s_Data->FlatColorShader)->UploadUniformMat4("u_ViewProjection", camera.GetViewProjectionMatrix());
    		std::dynamic_pointer_cast<OpenGLShader>(s_Data->FlatColorShader)->UploadUniformMat4("u_Transform", glm::mat4(1.0f));
    	}
    
    	void Renderer2D::EndScene()
    	{
    
    	}
    
    	void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color)
    	{
    		DrawQuad({ position.x, position.y, 0.0f }, size, color);
    	}
    
    	void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color)
    	{
    		std::dynamic_pointer_cast<OpenGLShader>(s_Data->FlatColorShader)->Bind();
    		std::dynamic_pointer_cast<Hazel::OpenGLShader>(s_Data->FlatColorShader)->UploadUniformFloat4("u_Color", color);
    
    		s_Data->QuadVertexArray->Bind();
    		RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    这里将之前的 SandBox2D 中的 OnAttach 的部分全部移到 Renderer2D 的 Init 函数中,创建了一个结构体,用于存放 VertexArray 和我们的 shader,创建了一个 static 指针 s_Data 用于进行访问,然后在 Shutdown 中要对其进行delete 避免内存泄漏BeginScene 中,进行 shader 绑定,uniform 设置,DrawQuad 函数进行颜色设置,然后利用 RenderCommand 函数 DrawIndexed 进行绘制。

  • 相关阅读:
    照明设计乙级资质怎么办理,办理照明工程设计专项乙级资条件
    EasyCode(IntelliJ IDEA 2023.2.3)
    【书籍篇】Git 学习指南(一)基础概念及入门
    GC FullGC
    8万字带你入门Rust
    java key锁 实现对某个key(字符串)加同步锁 带详细注释
    0049【Edabit ★☆☆☆☆☆】【修改Bug代码】Buggy Code
    当数字孪生与智慧园区结合,能够实现什么样的应用?
    Docker Networking
    Postman接口调用api
  • 原文地址:https://blog.csdn.net/miyazono_/article/details/127820472