Hazel Game Engine (033) Renderer Architecture Abstraction

If there are errors in the code, terminology, etc. in the text, please correct me

foreword

  • of this program

    The original function code at the beginning of OpenGL->gl exists in the Application drawing layer, and I want to delete it, and use the encapsulated rendering architecture to call the drawcall command (glDrawElements).

  • Before the renderer architecture is abstracted, it is necessary to discuss its working method in order to better design

    • what is needed to render an object

      Material information, transformation matrix information, etc.

    • what is needed to render a scene

      Light information, environment information, cameras, etc.

    • The approximate process of rendering two objects in a scene

      • word description

        Draw a scene, and there are two objects in this scene, you should view the scene from a camera , the scene is responsible for rendering two objects, and rendering these two objects has the environment information and light information of the common scene

      • summary description

        Start the scene (set the information of the scene) -> draw the object (set the information of the object = submit the object to the scene) -> end the scene

        The step after ending the scene represents the objects submitted to the scene to be rendered.

        • In a multi-threaded game engine, after the end scene

          Does not render immediately, but is submitted to the rendering, just like the command queue, can be calculated on a separate rendering thread

  • API design

    // 光、环境、摄像机暂未有,这里只是一个通用设计
    Renderer::BeginScene(camera, lights, environment);
    m_Shader1->Bind();
    Renderer::Submit(VertexArray1);// 给场景提交要渲染的物体
    m_Shader2->Bind();
    Renderer::Submit(VertexArray2);// 给场景提交要渲染的物体
    Renderer::EndScene();
    Renderer::Flush();
    
  • The class diagram after completing this section

    Please add a picture description

    explain:

    • dynamic polymorphism

      RendererCommand has static RendererAPI*. In cpp, according to the selected rendering API, the base class pointer can point to subclass objects OpenGlRendererAPI, D3DRendererAPI, and dynamic polymorphism of C++.

    • This section does not write the D3DRendererAPI class, but for completeness, the class diagram is still drawn like this

project related

code modification

  • RenderCommand

    #pragma once
    #include "RendererAPI.h"
    namespace Hazel {
          
          
    	class RenderCommand{
          
          
    	public:
    		inline static void SetClearColor(const glm::vec4& color){
          
          
    			s_RendererAPI->SetClearColor(color);
    		}
    		inline static void Clear(){
          
          
    			s_RendererAPI->Clear();
    		}
    		inline static void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray){
          
          
    			s_RendererAPI->DrawIndexed(vertexArray);
    		}
    	private:
    		static RendererAPI* s_RendererAPI;
    	};
    }
    
    #include "hzpch.h"
    #include "RenderCommand.h"
    #include "Platform/OpenGL/OpenGLRendererAPI.h"
    namespace Hazel {
          
          
        // 默认先指向OpenGLRendererAPI子类
    	RendererAPI* RenderCommand::s_RendererAPI = new OpenGLRendererAPI; // 基类指针指向子类对象
    }
    
  • Renderer

    #pragma once
    #include "RenderCommand.h"
    namespace Hazel {
          
          
    	class Renderer{
          
          
    	public:
    		static void BeginScene();	// 开始场景
    		static void EndScene();		// 结束场景
    		static void Submit(const std::shared_ptr<VertexArray>& vertexArray);// 提交物体的顶点数组
    		inline static RendererAPI::API GetAPI() {
          
           return RendererAPI::GetAPI(); }
    	};
    }
    
    #include "hzpch.h"
    #include "Renderer.h"
    namespace Hazel {
          
          
    	void Renderer::BeginScene(){
          
          }
    	void Renderer::EndScene(){
          
          }
    	void Renderer::Submit(const std::shared_ptr<VertexArray>& vertexArray){
          
          
    		vertexArray->Bind();					// 顶点数组绑定
    		RenderCommand::DrawIndexed(vertexArray);// 调用drawcall
    	}
    }
    
  • Renderer API

    #pragma once
    #include <glm/glm.hpp>
    #include "VertexArray.h"
    namespace Hazel {
          
          
    	class RendererAPI{
          
          
    	public:
    		enum class API{
          
          
    			None = 0, OpenGL = 1
    		};
    	public:
    		virtual void SetClearColor(const glm::vec4& color) = 0;	// 设置清除后的颜色
    		virtual void Clear() = 0;								// 清除哪些缓冲
    		virtual void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray) = 0;
    		inline static API GetAPI() {
          
           return s_API; }
    	private:
    		static API s_API;
    	};
    }
    
    #include "hzpch.h"
    #include "RendererAPI.h"
    namespace Hazel {
          
          
    	RendererAPI::API RendererAPI::s_API = RendererAPI::API::OpenGL;
    }
    
  • OpenGLRendererAPI

    #pragma once
    #include "Hazel/Renderer/RendererAPI.h"
    namespace Hazel {
          
          
    	class OpenGLRendererAPI : public RendererAPI{
          
          
    	public:
    		virtual void SetClearColor(const glm::vec4& color) override;// 设置清除后的颜色	
    		virtual void Clear() override;								// 清除哪些缓冲
    		// 通过顶点数组绘制
    		virtual void DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray) override;
    	};
    }
    
    #include "hzpch.h"
    #include "OpenGLRendererAPI.h"
    #include <glad/glad.h>
    namespace Hazel {
          
          
    	void OpenGLRendererAPI::SetClearColor(const glm::vec4& color){
          
          
    		glClearColor(color.r, color.g, color.b, color.a);
    	}
    	void OpenGLRendererAPI::Clear(){
          
          
    		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    	}
    	void OpenGLRendererAPI::DrawIndexed(const std::shared_ptr<VertexArray>& vertexArray){
          
          
    		glDrawElements(GL_TRIANGLES, vertexArray->GetIndexBuffer()->GetCount(), GL_UNSIGNED_INT, nullptr);
    	}
    }
    
  • Application

    void Application::Run(){
          
          
        while (m_Running){
          
          
            /
            RenderCommand::SetClearColor({
          
           0.1f, 0.1f, 0.1f, 1 });
            RenderCommand::Clear();
    
            Renderer::BeginScene();
            // 绘制四边形
            m_BlueShader->Bind();// 绑定着色器
            Renderer::Submit(m_SquareVA);
    
            // 绘制三角形
            m_Shader->Bind();// 绑定着色器
            Renderer::Submit(m_VertexArray);
            
            Renderer::EndScene();
            .......
    

Effect

Unchanged

Please add a picture description

Guess you like

Origin blog.csdn.net/qq_34060370/article/details/131447268