跟着cherno手搓游戏引擎【15】DrawCall的封装

目标:

Application.cpp:把渲染循环里的glad代码封装成自己的类:

cpp 复制代码
#include"ytpch.h"
#include "Application.h"

#include"Log.h"
#include "YOTO/Renderer/Renderer.h"
#include"Input.h"


namespace YOTO {
#define BIND_EVENT_FN(x) std::bind(&x, this, std::placeholders::_1)

	 Application* Application::s_Instance = nullptr;

	Application::Application() {

		YT_CORE_ASSERT(!s_Instance, "Application需要为空!")
		s_Instance = this;
		//智能指针
		m_Window = std::unique_ptr<Window>(Window::Creat());
		//设置回调函数
		m_Window->SetEventCallback(BIND_EVENT_FN(Application::OnEvent));
		//new一个Layer,放在最后层进行渲染
		m_ImGuiLayer = new ImGuiLayer();
		PushOverlay(m_ImGuiLayer);  
		//unsigned int id;
		//glGenBuffers(1, &id);

		uint32_t indices[3] = { 0,1,2 };
		float vertices[3 * 7] = {
			-0.5f,-0.5f,0.0f, 0.8f,0.2f,0.8f,1.0f,
			0.5f,-0.5f,0.0f,  0.2f,0.3f,0.8f,1.0f,
			0.0f,0.5f,0.0f,   0.8f,0.8f,0.2f,1.0f,
		};

		m_VertexArray.reset(VertexArray::Create());


		std::shared_ptr<VertexBuffer> m_VertexBuffer;
		m_VertexBuffer.reset(VertexBuffer::Create(vertices, sizeof(vertices)));

		{
			BufferLayout setlayout = {

	{ShaderDataType::Float3,"a_Position"},
		{ShaderDataType::Float4,"a_Color"}
			};
			m_VertexBuffer->SetLayout(setlayout);

		}

		m_VertexArray->AddVertexBuffer(m_VertexBuffer);
		
		 
		std::shared_ptr<IndexBuffer>m_IndexBuffer;
		m_IndexBuffer.reset(IndexBuffer::Create(indices, sizeof(indices)/sizeof(uint32_t)));

		m_VertexArray->AddIndexBuffer(m_IndexBuffer);

		std::string vertexSource = R"(
		#version 330 core
		layout(location = 0) in vec3 a_Position;
		layout(location = 1) in vec4 a_Color;
		out vec3 v_Position;
		out vec4 v_Color;
		void main(){
		v_Position=a_Position;
		v_Color=a_Color;
		gl_Position =vec4( a_Position+0.5,1.0);
		}
		)";
		//绘制颜色
		std::string fragmentSource = R"(
		#version 330 core
		layout(location = 0) out vec4 color;
		in vec3 v_Position;
		in vec4 v_Color;
		void main(){
		color=vec4(v_Color);
		}
		)";
		m_Shader.reset(new Shader(vertexSource, fragmentSource));

		///测试/

		m_SquareVA.reset(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
		};
		std::shared_ptr<VertexBuffer> squareVB;
		squareVB.reset(VertexBuffer::Create(squareVertices, sizeof(squareVertices)));
		squareVB->SetLayout({
			{ShaderDataType::Float3,"a_Position"}
		});
		m_SquareVA->AddVertexBuffer(squareVB);
		uint32_t squareIndices[6] = { 0,1,2,2,3,0 };
		std::shared_ptr<IndexBuffer> squareIB; 

		squareIB.reset((IndexBuffer::Create(squareIndices, sizeof(squareIndices) / sizeof(uint32_t))));

		m_SquareVA->AddIndexBuffer(squareIB);
		
		//测试:
		std::string BlueShaderVertexSource = R"(
		#version 330 core
		layout(location = 0) in vec3 a_Position;
		out vec3 v_Position;
		void main(){
		v_Position=a_Position;
		gl_Position =vec4( a_Position,1.0);
		}
		)";
		//绘制颜色
		std::string BlueShaderFragmentSource = R"(
		#version 330 core
		layout(location = 0) out vec4 color;
		in vec3 v_Position;
		void main(){
		color=vec4(0.2,0.3,0.8,1.0);
		}
		)";
		m_BlueShader.reset(new Shader(BlueShaderVertexSource, BlueShaderFragmentSource));
	}
	Application::~Application() {

	}
	/// <summary>
	/// 所有的Window事件都会在这触发,作为参数e
	/// </summary>
	/// <param name="e"></param>
	void Application::OnEvent(Event& e) {
		//根据事件类型绑定对应事件
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(Application::OnWindowClosed));
		//输出事件信息
		YT_CORE_INFO("Application:{0}",e);
		for (auto it = m_LayerStack.end(); it != m_LayerStack.begin();) {
			(*--it)->OnEvent(e);
			if (e.m_Handled)
				break;
		}
	}

	bool Application::OnWindowClosed(WindowCloseEvent& e) {
		m_Running = false;
		return true;
	}
	void Application::Run() {
		WindowResizeEvent e(1280, 720);
		if (e.IsInCategory(EventCategoryApplication)) {
			YT_CORE_TRACE(e);
		}
		if (e.IsInCategory(EventCategoryInput)) {
			YT_CORE_ERROR(e);
		}

		while (m_Running)
		{
			/*	glClearColor(0.2f, 0.2f, 0.2f,1);
				glClear(GL_COLOR_BUFFER_BIT);*/
			RenderCommand::SetClearColor({0.2f, 0.2f, 0.2f, 1.0f});
			RenderCommand::Clear();

			Renderer::BeginScene();
			{
				m_BlueShader->Bind();
				Renderer::Submit(m_SquareVA);
				m_Shader->Bind();
				Renderer::Submit(m_VertexArray);
				Renderer::EndScene();
			}

	

			//m_BlueShader->Bind();
			//m_SquareVA->Bind();
			//glDrawElements(GL_TRIANGLES, m_SquareVA->GetIndexBuffer()->GetCount(), GL_UNSIGNED_INT, nullptr);
			glBindVertexArray(m_VertexArray);
			//m_Shader->Bind();
			//m_VertexArray->Bind();
			//glDrawElements(GL_TRIANGLES,m_VertexArray->GetIndexBuffer()->GetCount(),GL_UNSIGNED_INT,nullptr); 

			for (Layer* layer : m_LayerStack) {
				layer->OnUpdate();
			}
			//将ImGui的刷新放到APP中,与Update分开
			m_ImGuiLayer->Begin();
			
			for (Layer* layer : m_LayerStack) {
				layer->OnImGuiRender();
			}
			m_ImGuiLayer->End();
			m_Window->OnUpdate();
		}
	}
	void Application::PushLayer(Layer* layer) {
		m_LayerStack.PushLayer(layer);
		layer->OnAttach();
	}
	void Application::PushOverlay(Layer* layer) {
		m_LayerStack.PushOverlay(layer);
		layer->OnAttach();
	}
}

抽象:

RendererAPI.h:渲染API的抽象,包括API实现的功能都封装一下:

cpp 复制代码
#pragma once
#include<glm/glm.hpp>
#include "VertexArray.h"
namespace YOTO {
	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;
	};
}

RendererAPI.cpp:给当前API赋值:

cpp 复制代码
#include "ytpch.h"
#include "RendererAPI.h"
namespace YOTO {
	RendererAPI::API RendererAPI::s_API = RendererAPI::API::OpenGL;
}

实现:

OpenGLRendererAPI.h:实现接口,制定重写方法,在cpp中封账glad代码:

cpp 复制代码
#pragma once
#include"YOTO/Renderer/RendererAPI.h"
namespace YOTO {
	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;
	};
}

OpenGLRendererAPI.cpp:

cpp 复制代码
#include "ytpch.h"
#include "OpenGLRendererAPI.h"
#include <glad/glad.h>
namespace YOTO {
	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);
	}
}

调用:

RenderCommand.h:根据当前API调用API的一些通用方法:

cpp 复制代码
#pragma once
#include"RendererAPI.h"
namespace YOTO {
	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;

	};

}

RenderCommand.cpp:(个人觉得应该在new的时候再给API的枚举赋值,在 RendererAPI

.cpp中导致可以new 其他API枚举选另一个API)(不知道后面会不会改)

cpp 复制代码
#include "ytpch.h"
#include "RenderCommand.h"
#include"Platform/OpenGL/OpenGLRendererAPI.h"
namespace YOTO {
	RendererAPI* RenderCommand::s_RendererAPI = new OpenGLRendererAPI;
}

Renderer.h: 对command的一些方法进行进一步封装,并拓展出Begin和End方法:

cpp 复制代码
#pragma once
#include"RenderCommand.h"
namespace YOTO {
	
	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();
		}
	};

}

Renderer.cpp:

cpp 复制代码
#include"ytpch.h"
#include"Renderer.h"
namespace YOTO {
	void Renderer::BeginScene()
	{
	}
	void Renderer::EndScene()
	{
	}
	void Renderer::Submit(const std::shared_ptr<VertexArray>& vertexArray)
	{
		vertexArray->Bind();
		RenderCommand::DrawIndexed(vertexArray);
	}
}

修改:

所有switch的枚举都改成这样(会报错,报了再改也行)

cpp 复制代码
RendererAPI::API::OpenGL:

测试:

原汁原味儿~能跑出来就对了!

相关推荐
mxwin10 小时前
Unity Shader 半透明物体为什么不能写入深度缓冲?
unity·游戏引擎·shader
晚枫歌F11 小时前
三层时间轮的实现
网络·unity·游戏引擎
努力长头发的程序猿16 小时前
Unity使用ScriptableObject序列化资源
unity·游戏引擎
mxwin16 小时前
Unity Shader 手写基于 PBR 的 URP Lit Shader 核心光照计算
unity·游戏引擎·shader
魔士于安17 小时前
Unity windows 同步 异步 打开文件文件夹工具
游戏·unity·游戏引擎·贴图·模型
笑虾17 小时前
cocos2d-x lua 加载 Cocos Studio 导出的 csb
游戏引擎·lua·cocos2d
魔士于安17 小时前
unity lowpoly 风格 城市 建筑 道路 交通标志
游戏·unity·游戏引擎·贴图·模型
mxwin17 小时前
Unity GPU Shader 性能优化指南
unity·游戏引擎·shader
董董女友1 天前
unity mcp 配置指南
unity·游戏引擎
垂葛酒肝汤1 天前
Unity的可视化网格和文字标签
unity·游戏引擎