Hazel游戏引擎(033)渲染器架构抽象

文章讨论了如何将原始的OpenGL函数替换为封装的渲染架构,以调用drawcall命令。渲染流程涉及物体的材质、变换矩阵,以及场景的光照、环境和摄像机信息。在多线程游戏引擎中,提交的渲染命令会被放入队列,在单独的渲染线程处理。文章给出了Renderer类和RendererAPI的设计示例,包括OpenGLRendererAPI的实现。
摘要由CSDN通过智能技术生成

文中若有代码、术语等错误,欢迎指正

前言

  • 此节目的

    Application绘制层存在OpenGL->gl开头的原始函数代码,想删掉它,并用封装的渲染架构来调用drawcall命令(glDrawElements)。

  • 渲染器架构抽象前要讨论的工作方式才能更好设计

    • 渲染一个物体需要什么

      材质信息、转换矩阵信息等

    • 渲染一个场景需要什么

      光的信息、环境的信息、摄像机等

    • 渲染一个场景中两个物体的大概流程

      • 文字描述

        绘制一个场景,并且这个场景中有两个物体,应该是从一台相机上查看场景,场景负责渲染2个物体,渲染这2个物体拥有共有场景的环境信息、光的信息

      • 总结描述

        开始场景(设置场景的信息)->绘制物体(设置物体的信息=提交物体到场景)->结束场景

        结束场景后的一步代表提交到场景的物体要渲染。

        • 在多线程游戏引擎中,关于结束场景后

          不会立即渲染,只是被提交到渲染中,就像命令队列一样,可以在单独的渲染线程上进行计算

  • API设计

    // 光、环境、摄像机暂未有,这里只是一个通用设计
    Renderer::BeginScene(camera, lights, environment);
    m_Shader1->Bind();
    Renderer::Submit(VertexArray1);// 给场景提交要渲染的物体
    m_Shader2->Bind();
    Renderer::Submit(VertexArray2);// 给场景提交要渲染的物体
    Renderer::EndScene();
    Renderer::Flush();
    
  • 此节完成后的类图

    请添加图片描述

    解释:

    • 照样动态多态

      RendererCommand有静态RendererAPI*,在cpp中可以根据选择的渲染API,来基类指针指向子类对象OpenGlRendererAPI、D3DRendererAPI,C++的动态多态。

    • 此节并未写D3DRendererAPI类,但为了完整,还是这样画的类图

项目相关

代码修改

  • 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
    	}
    }
    
  • RendererAPI

    #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();
            .......
    

效果

没变

请添加图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘建杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值