Haxel Engine learning 17 -- Vertex Array

Cherno 视频:https://www.youtube.com/watch?v=rkxrw8dNrvI&list=PLlrATfBNZ98dC-V-N3m0Go4deliWHPFwT&index=32

完整代码:https://github.com/DXT00/Hazel_study/tree/80b37eba735ebbd73d9131779e0200ccaeb11267/Hazel

 

VertexBuffer和IndexBuffer都是实际存在于内存中的,而VertexArray 并不包含数据!

VertexArray just contain [references] to VertexBuffer and to IndexBuffer

或者说VertexArray只是链接到 VertexBuffer 和 IndexBuffer

Vertex Array are state containing entity

 

两种部署方式:
1.多个VertexBuffer,每个VertexBuffer一种属性(Position,Normal,Color..)

		float vertices_pos[3 * 3] = {
			//Position          //Color
			-0.5f,-0.5f,0.0f,	1.0f,0.0f,0.0f,1.0f,
			 0.5f,-0.5f,0.0f,	0.0f,1.0f,0.0f,1.0f,
			 0.0f, 0.5f,0.0f,	0.0f,0.0f,1.0f,1.0f,

		};
	    float vertices_color[3 * 4] = {
			//Color
			1.0f,0.0f,0.0f,1.0f,
			0.0f,1.0f,0.0f,1.0f,
			0.0f,0.0f,1.0f,1.0f,

		};

2.一个VertexBuffer,包含所有属性

		float vertices[3 * 7] = {
			//Position          //Color
			-0.5f,-0.5f,0.0f,	1.0f,0.0f,0.0f,1.0f,
			 0.5f,-0.5f,0.0f,	0.0f,1.0f,0.0f,1.0f,
			 0.0f, 0.5f,0.0f,	0.0f,0.0f,1.0f,1.0f,

		};

 

you can tile together,like IndexBuffer,VertexBuffer,Layout into a VertexArray

我们采用第二种

把VertexArray抽象成类:

VertexArray.h --->抽象类,不包含任何数据

#pragma once
#include<memory>
#include "Hazel/Renderer/Buffer.h"
namespace Hazel {

	class VertexArray
	{
	public:
		virtual ~VertexArray() {};
		virtual void Bind() const = 0;
		virtual void UnBind() const = 0;

		virtual void AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBufer) = 0;
		virtual void SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer) = 0;

		virtual const std::vector<std::shared_ptr<VertexBuffer>>& GetVertexBufers()const = 0;
		virtual const std::shared_ptr<IndexBuffer>& GetIndexBuffer()const = 0;

		static VertexArray *Create();
	};


}

实现由 OpenGLVertexArray.h 来实现:

VertexArray是指向VertexBuffer和IndexBuffer,所以存储的只是指针!

    std::vector<std::shared_ptr<VertexBuffer>> m_VertexBuffers;
    std::shared_ptr<IndexBuffer> m_IndexBuffer;

#pragma once
#include "Hazel/Renderer/VertexArray.h"
#include <memory>
namespace Hazel {

	class OpenGLVertexArray : public VertexArray
	{
	public:

		OpenGLVertexArray();
		virtual ~OpenGLVertexArray();

		virtual void Bind() const override;
		virtual void UnBind() const override;

		virtual void AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBufer)override;
		virtual void SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer) override;
		virtual const std::vector<std::shared_ptr<VertexBuffer>>& GetVertexBufers()const { return m_VertexBuffers; }
		virtual const std::shared_ptr<IndexBuffer>& GetIndexBuffer()const { return m_IndexBuffer; }
	private:
		std::vector<std::shared_ptr<VertexBuffer>> m_VertexBuffers;
		std::shared_ptr<IndexBuffer> m_IndexBuffer;
		uint32_t m_RendereID;
	};

}

OpenGLVertexArray.cpp

#include "hzpch.h"
#include "OpenGLVertexArray.h"
#include <glad/glad.h>
namespace Hazel {
	static uint32_t ShaderDataTypeToBufferType(const ShaderDataType & type) {
		switch (type)
		{
		case ShaderDataType::Int:			return GL_INT;
		case ShaderDataType::Int2:			return GL_INT;
		case ShaderDataType::Int3:			return GL_INT;
		case ShaderDataType::Int4:			return GL_INT;
		case ShaderDataType::Float:			return GL_FLOAT;
		case ShaderDataType::Float2:		return GL_FLOAT;
		case ShaderDataType::Float3:		return GL_FLOAT;
		case ShaderDataType::Float4:		return GL_FLOAT;
		case ShaderDataType::Mat3:			return GL_FLOAT;
		case ShaderDataType::Mat4:			return GL_FLOAT;
		case ShaderDataType::False:			return GL_FALSE;
		case ShaderDataType::True:			return GL_TRUE;


		}
		HZ_CORE_ASSERT(false, "Unknown ShaderDataType!")
			return 0;
	}
	OpenGLVertexArray::OpenGLVertexArray()
	{
		glGenVertexArrays(1, &m_RendereID);
	//	glBindVertexArray(m_RendereID);
	}


	OpenGLVertexArray::~OpenGLVertexArray()
	{
		glDeleteVertexArrays(1, &m_RendereID);
	}

	void OpenGLVertexArray::Bind() const
	{
		glBindVertexArray(m_RendereID);

	}

	void OpenGLVertexArray::UnBind() const
	{
		glBindVertexArray(0);

	}

	void OpenGLVertexArray::AddVertexBuffer(const std::shared_ptr<VertexBuffer>& vertexBufer)
	{
		HZ_CORE_ASSERT(vertexBufer->GetLayout().GetElements().size(), "Vertex Buffer has no layout!!")

		glBindVertexArray(m_RendereID);
		vertexBufer->Bind();
		uint32_t index = 0;
		const auto& layout = vertexBufer->GetLayout();
		for (auto& element : layout)
		{
			glEnableVertexAttribArray(index);
			glVertexAttribPointer(index,
				element.GetElementCount(),
				ShaderDataTypeToBufferType(element.Type),
				element.Normalized ? GL_TRUE : GL_FALSE,
				layout.GetStride(),
				(void *)element.Offset);
			index++;
		}
		m_VertexBuffers.push_back(vertexBufer);
	}

	void OpenGLVertexArray::SetIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer)
	{
		glBindVertexArray(m_RendereID);
		indexBuffer->Bind();
		m_IndexBuffer = indexBuffer;
	}



}

画一个方形,一个三角形:

Application.cpp

#include "hzpch.h"
#include "Application.h"

#include "Hazel/Log.h"

#include <glad/glad.h>

#include "Input.h"
#include "Platform/OpenGL/OpenGLBuffer.h"
namespace Hazel {

#define BIND_EVENT_FN(x) std::bind(&Application::x, this, std::placeholders::_1)


	Application* Application::s_Instance = nullptr;

	Application::Application()
	{
		HZ_CORE_ASSERT(!s_Instance, "Application already exists!");
		s_Instance = this;

		m_Window = std::unique_ptr<Window>(Window::Create());
		m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));

		m_ImGuiLayer = new ImGuiLayer();
		PushOverLay(m_ImGuiLayer);

		float vertices[3 * 7] = {
			//Position          //Color
			-0.5f,-0.5f,0.0f,	1.0f,0.0f,0.0f,1.0f,
			 0.5f,-0.5f,0.0f,	0.0f,1.0f,0.0f,1.0f,
			 0.0f, 0.5f,0.0f,	0.0f,0.0f,1.0f,1.0f,

		};
		float squareVertices[3 * 4] = {
			//Position          //Color
			-0.5f,-0.5f, 0.0f,
			0.5f, -0.5f, 0.0f,
			 0.5f,0.5f, 0.0f,
			 -0.5f, 0.5f, 0.0f,

		};
		unsigned int indices[3] = { 0,1,2 };
		unsigned int squareIndices[6] = { 0,1,2,0,2,3 };

		m_VertexArray.reset(VertexArray::Create());
		m_VertexBuffer.reset(VertexBuffer::Create(vertices, sizeof(vertices)));
		m_IndexBuffer.reset(IndexBuffer::Create(indices, 3));


		BufferLayout layout = {
			{ ShaderDataType::Float3,"a_Position", false },
			{ ShaderDataType::Float4,"a_Color",    false },


		};
		BufferLayout squareLayout = {
			{ ShaderDataType::Float3,"a_Position", false },


		};
		m_VertexBuffer->SetLayout(layout);
		m_VertexArray->AddVertexBuffer(m_VertexBuffer);
		m_VertexArray->SetIndexBuffer(m_IndexBuffer);


		m_SqareVA.reset(VertexArray::Create());
		m_SqareVB.reset(VertexBuffer::Create(squareVertices, sizeof(squareVertices)));
		m_SqareIB.reset(IndexBuffer::Create(squareIndices, 6));

		m_SqareVB->SetLayout(squareLayout);
		m_SqareVA->AddVertexBuffer(m_SqareVB);
		m_SqareVA->SetIndexBuffer(m_SqareIB);

		/*	uint32_t index = 0;
			for (auto& element: m_VertexBuffer->GetLayout())
			{
				glEnableVertexAttribArray(index);
				glVertexAttribPointer(index,
					element.GetElementCount(),
					ShaderDataTypeToBufferType(element.Type),
					element.Normalized ? GL_TRUE : GL_FALSE,
					layout.GetStride(),
					(void *)element.Offset);
				index++;
			}*/
			/*glEnableVertexAttribArray(0);
			glEnableVertexAttribArray(1);

			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7 * sizeof(float), nullptr);
			glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7 * sizeof(float), (void*)12);
	*/

		const std::string vertexSrc = 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,1.0);

				}


				)";
		const std::string fragmentSrc = R"(
				#version 330 core
				
				layout(location = 0) out vec4 color;
				layout(location = 1) out vec4 color1;

				in vec3 v_Position;
				in vec4 v_Color;
				
				void main()
				{

					color = v_Color;//vec4(v_Position*0.5+0.5, 1.0);

				}
				)";

		const std::string squareVertexSrc = 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);

				}


				)";
		const std::string squareFragmentSrc = R"(
				#version 330 core
				
				layout(location = 0) out vec4 color;

				in vec3 v_Position;

				
				void main()
				{

					color =vec4(v_Position*0.5+0.5, 1.0);

				}
				)";
		//m_Shader = std::make_unique<Shader>(vertexSrc,fragmentSrc);
		m_Shader.reset(new Shader(vertexSrc, fragmentSrc));
		m_SqareShader.reset(new Shader(squareVertexSrc, squareFragmentSrc));

	}

	Application::~Application()
	{
	}

	void Application::PushLayer(Layer* layer)
	{
		m_LayerStack.PushLayer(layer);
		layer->OnAttach();
	}

	void Application::PushOverLay(Layer* layer)
	{
		m_LayerStack.PushOverLay(layer);
		layer->OnAttach();
	}

	void Application::OnEvent(Event& e)
	{
		EventDispatcher dispatcher(e);
		dispatcher.Dispatch<WindowCloseEvent>(BIND_EVENT_FN(OnWindowClose));

		for (auto it = m_LayerStack.end(); it != m_LayerStack.begin(); )
		{
			(*--it)->OnEvent(e);
			if (e.Handled)
				break;
		}
	}

	void Application::Run()
	{
		while (m_Running)
		{
			glClearColor(0.1f, 0.1f, 0.1f, 1);
			glClear(GL_COLOR_BUFFER_BIT);
			m_SqareShader->Bind();
			m_SqareVA->Bind();
			glDrawElements(GL_TRIANGLES, m_SqareVA->GetIndexBuffer()->GetCount(), GL_UNSIGNED_INT, nullptr);

			m_Shader->Bind();
			m_VertexArray->Bind();
			glDrawElements(GL_TRIANGLES, m_IndexBuffer->GetCount(), GL_UNSIGNED_INT, nullptr);



			for (Layer* layer : m_LayerStack)
				layer->OnUpdate();

			m_ImGuiLayer->Begin();
			for (Layer* layer : m_LayerStack)
				layer->OnImGuiRender();
			m_ImGuiLayer->End();

			m_Window->OnUpdate();
		}
	}

	bool Application::OnWindowClose(WindowCloseEvent& e)
	{
		m_Running = false;
		return true;
	}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值