本节先把代码粘上,后续会慢慢把注释都给加上,先看代码了解个大概(待更新)

前置:

RendererAPI.h:

#pragma once

namespace YOTO {

enum class RendererAPI {

None = 0,

OpenGL=1

};

class Renderer {

public:

inline static RendererAPI GetAPI() {

return s_RendererAPI;

}

static RendererAPI s_RendererAPI;

};

}

 RendererAPI.cpp:

#include"ytpch.h"

#include"Renderer.h"

namespace YOTO {

RendererAPI Renderer::s_RendererAPI = RendererAPI::OpenGL;

}

抽象:

buffer.h:

#pragma once

#include

namespace YOTO {

enum class ShaderDataType{

None=0,

Float,Float2,Float3,Float4,

Mat3,Mat4,

Int,Int2,Int3,Int4,

Bool,

};

static uint32_t ShaderDataTypeSize(ShaderDataType type) {

switch (type)

{

case YOTO::ShaderDataType::Float:

return 4;

break;

case YOTO::ShaderDataType::Float2:

return 4*2;

break;

case YOTO::ShaderDataType::Float3:

return 4*3;

break;

case YOTO::ShaderDataType::Float4:

return 4*4;

break;

case YOTO::ShaderDataType::Mat3:

return 4*3*3;

break;

case YOTO::ShaderDataType::Mat4:

return 4*4*4;

break;

case YOTO::ShaderDataType::Int:

return 4;

break;

case YOTO::ShaderDataType::Int2:

return 4*2;

break;

case YOTO::ShaderDataType::Int3:

return 4*3;

break;

case YOTO::ShaderDataType::Int4:

return 4*4;

break;

case YOTO::ShaderDataType::Bool:

return 1;

break;

}

YT_CORE_ASSERT(false, "未知的ShaderDataType!");

return 0;

}

struct BufferElement {

std::string Name;

ShaderDataType Type;

uint32_t Size;

uint32_t Offset;

bool Normalized;

BufferElement(){}

BufferElement(ShaderDataType type, const std::string& name,bool normalized=false)

:Name(name), Type(type), Size(ShaderDataTypeSize(type)), Offset(0), Normalized(normalized){}

uint32_t GetComponentCount() const{

switch (Type)

{

case YOTO::ShaderDataType::Float:

return 1;

break;

case YOTO::ShaderDataType::Float2:

return 2;

break;

case YOTO::ShaderDataType::Float3:

return 3;

break;

case YOTO::ShaderDataType::Float4:

return 4;

break;

case YOTO::ShaderDataType::Mat3:

return 3*3;

break;

case YOTO::ShaderDataType::Mat4:

return 4*4;

break;

case YOTO::ShaderDataType::Int:

return 1;

break;

case YOTO::ShaderDataType::Int2:

return 2;

break;

case YOTO::ShaderDataType::Int3:

return 3;

break;

case YOTO::ShaderDataType::Int4:

return 4;

break;

case YOTO::ShaderDataType::Bool:

return 1;

break;

default:

break;

}

YT_CORE_ASSERT(false, "未知的ShaderDataType!");

return 0;

}

};

class BufferLayout {

public:

BufferLayout(){}

BufferLayout(const std::initializer_listelements)

:m_Elements(elements)

{

CalculateOffsetAndStride();

}

inline uint32_t GetStride()const { return m_Stride; }

inline const std::vector& GetElements()const {

return m_Elements;

}

std::vector::iterator begin() { return m_Elements.begin(); }

std::vector::iterator end() { return m_Elements.end(); }

std::vector::const_iterator begin() const { return m_Elements.begin(); }

std::vector::const_iterator end() const { return m_Elements.end(); }

private:

void CalculateOffsetAndStride() {

uint32_t offset = 0;

m_Stride = 0;

for (auto& element : m_Elements) {

element.Offset = offset;

offset += element.Size;

m_Stride += element.Size;

}

}

private:

std::vector m_Elements;

uint32_t m_Stride = 0;

};

class VertexBuffer {

public:

virtual~VertexBuffer() {}

virtual void Bind() const = 0;

virtual void UnBind() const = 0;

virtual void SetLayout(const BufferLayout& layout) = 0;

virtual const BufferLayout& GetLayout()const = 0;

static VertexBuffer* Create(float* vertices, uint32_t size);

};

class IndexBuffer {

public:

virtual~IndexBuffer(){}

virtual void Bind() const = 0;

virtual void UnBind() const = 0;

virtual uint32_t GetCount() const = 0;

static IndexBuffer* Create(uint32_t* indices, uint32_t size);

};

}

buffer.cpp:

#include"ytpch.h"

#include"Buffer.h"

#include "Renderer.h"

#include "Platform/OpenGL/OpenGLBuffer.h"

namespace YOTO {

VertexBuffer* VertexBuffer::Create(float* vertices, uint32_t size)

{

switch (Renderer::GetAPI())

{

case RendererAPI::None:

YT_CORE_ASSERT(false,"Buffer:API为None不支持");

return nullptr;

case RendererAPI::OpenGL:

return new OpenGLVertexBuffer(vertices,size);

}

YT_CORE_ASSERT(false,"Buffer:未知API");

return nullptr;

}

IndexBuffer* IndexBuffer::Create(uint32_t* indices, uint32_t size)

{

switch (Renderer::GetAPI())

{

case RendererAPI::None:

YT_CORE_ASSERT(false, "Buffer:API为None不支持");

return nullptr;

case RendererAPI::OpenGL:

return new OpenGLIndexBuffer(indices, size);

}

YT_CORE_ASSERT(false, "Buffer:未知API");

return nullptr;

}

}

 VertexArray.h:

#pragma once

#include"YOTO/Renderer/Buffer.h"

namespace YOTO {

class VertexArray {

public:

virtual~VertexArray() {}

virtual void Bind() const = 0;

virtual void UnBind() const = 0;

virtual void AddVertexBuffer(const std::shared_ptr&vertexBuffer) = 0;

virtual void AddIndexBuffer(const std::shared_ptr& indexBuffer) = 0;

virtual const std::vector>& GetVertexBuffers()const = 0;

virtual const std::shared_ptr& GetIndexBuffer()const = 0;

static VertexArray* Create();

};

}

 VertexArray.cpp:

#include "ytpch.h"

#include "VertexArray.h"

#include"Renderer.h"

#include "Platform/OpenGL/OpenGLVertexArray.h"

namespace YOTO {

VertexArray* VertexArray::Create()

{

switch (Renderer::GetAPI())

{

case RendererAPI::None:

YT_CORE_ASSERT(false, "Buffer:API为None不支持");

return nullptr;

case RendererAPI::OpenGL:

return new OpenGLVertexArray();

}

YT_CORE_ASSERT(false, "Buffer:未知API");

return nullptr;

}

}

实现:

OpenGLBuffer.h:

#pragma once

#include "YOTO/Renderer/Buffer.h"

namespace YOTO {

class OpenGLVertexBuffer : public VertexBuffer {

public:

OpenGLVertexBuffer(float* vertices, uint32_t size);

virtual~OpenGLVertexBuffer();

virtual void Bind()const override;

virtual void UnBind()const override;

virtual void SetLayout(const BufferLayout& layout) override {

m_Layout = layout;

}

virtual const BufferLayout& GetLayout()const override {

return m_Layout;

}

private:

uint32_t m_RendererID;

BufferLayout m_Layout;

};

class OpenGLIndexBuffer : public IndexBuffer {

public:

OpenGLIndexBuffer(uint32_t* indices, uint32_t count);

virtual~OpenGLIndexBuffer();

virtual void Bind()const;

virtual void UnBind()const;

virtual uint32_t GetCount() const {

return m_Count;

};

private:

uint32_t m_RendererID;

uint32_t m_Count;

};

}

 OpenGLBuffer.cpp:

#include"ytpch.h"

#include"OpenGLBuffer.h"

#include

namespace YOTO {

// VertexBuffer

OpenGLVertexBuffer::OpenGLVertexBuffer(float* vertices, uint32_t size)

{

glCreateBuffers(1, &m_RendererID);

glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);

glBufferData(GL_ARRAY_BUFFER, size, vertices, GL_STATIC_DRAW);

}

OpenGLVertexBuffer::~OpenGLVertexBuffer()

{

glDeleteBuffers(1, &m_RendererID);

}

void OpenGLVertexBuffer::Bind() const

{

glBindBuffer(GL_ARRAY_BUFFER, m_RendererID);

}

void OpenGLVertexBuffer::UnBind() const

{

glBindBuffer(GL_ARRAY_BUFFER, 0);

}

// IndexBuffer /

OpenGLIndexBuffer::OpenGLIndexBuffer(uint32_t* indices, uint32_t count)

:m_Count(count)

{

glCreateBuffers(1, &m_RendererID);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID);

glBufferData(GL_ELEMENT_ARRAY_BUFFER, count*sizeof(uint32_t), indices, GL_STATIC_DRAW);

}

OpenGLIndexBuffer::~OpenGLIndexBuffer()

{

glDeleteBuffers(1, &m_RendererID);

}

void OpenGLIndexBuffer::Bind() const

{

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID);

}

void OpenGLIndexBuffer::UnBind() const

{

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

}

}

 OpenGLVertexArray.h:

#pragma once

#include"YOTO/Renderer/VertexArray.h"

namespace YOTO {

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)override;

virtual void AddIndexBuffer(const std::shared_ptr& indexBuffer)override;

virtual const std::vector>& GetVertexBuffers()const {

return m_VertexBuffers;

}

virtual const std::shared_ptr& GetIndexBuffer()const {

return m_IndexBuffers;

}

private:

uint32_t m_RendererID;

std::vector> m_VertexBuffers;

std::shared_ptr m_IndexBuffers;

};

}

  OpenGLVertexArray.cpp:

#include "ytpch.h"

#include "OpenGLVertexArray.h"

#include

namespace YOTO {

static GLenum ShaderDataTypeToOpenGLBaseType(ShaderDataType type) {

switch (type)

{

case YOTO::ShaderDataType::Float:

return GL_FLOAT;

case YOTO::ShaderDataType::Float2:

return GL_FLOAT;

case YOTO::ShaderDataType::Float3:

return GL_FLOAT;

case YOTO::ShaderDataType::Float4:

return GL_FLOAT;

case YOTO::ShaderDataType::Mat3:

return GL_FLOAT;

case YOTO::ShaderDataType::Mat4:

return GL_FLOAT;

case YOTO::ShaderDataType::Int:

return GL_INT;

case YOTO::ShaderDataType::Int2:

return GL_INT;

case YOTO::ShaderDataType::Int3:

return GL_INT;

case YOTO::ShaderDataType::Int4:

return GL_INT;

case YOTO::ShaderDataType::Bool:

return GL_BOOL;

}

return 0;

}

OpenGLVertexArray::OpenGLVertexArray()

{

glCreateVertexArrays(1, &m_RendererID);

}

OpenGLVertexArray::~OpenGLVertexArray()

{

glDeleteVertexArrays(1, &m_RendererID);

}

void OpenGLVertexArray::Bind() const

{

glBindVertexArray(m_RendererID);

}

void OpenGLVertexArray::UnBind() const

{

glBindVertexArray(0);

}

void OpenGLVertexArray::AddVertexBuffer(const std::shared_ptr& vertexBuffer)

{

YT_CORE_ASSERT(vertexBuffer->GetLayout().GetElements().size(), "OpenGLVertexArray:VertexBuffer没有布局(Layout)")

glBindVertexArray(m_RendererID);

vertexBuffer->Bind();

uint32_t index = 0;

const auto& layout = vertexBuffer->GetLayout();

for (const auto& element : layout) {

glEnableVertexAttribArray(index);

//设置缓冲区数据格式:缓冲区序号、顶点属性的大小、什么数据类型、会不会被归一化、

glVertexAttribPointer(index,

element.GetComponentCount(),

ShaderDataTypeToOpenGLBaseType(element.Type),

element.Normalized ? GL_TRUE : GL_FALSE,

layout.GetStride(),

(const void*)element.Offset);

index++;

}

m_VertexBuffers.push_back(vertexBuffer);

}

void OpenGLVertexArray::AddIndexBuffer(const std::shared_ptr& indexBuffer)

{

glBindVertexArray(m_RendererID);

indexBuffer->Bind();

m_IndexBuffers = indexBuffer;

}

}

调用:

Application.h:

#pragma once

#include"Core.h"

#include"Event/Event.h"

#include"Event/ApplicationEvent.h"

#include "YOTO/Window.h"

#include"YOTO/LayerStack.h"

#include"YOTO/ImGui/ImGuiLayer.h"

#include

#include

#include

namespace YOTO {

class YOTO_API Application

{

public:

Application();

virtual ~Application();

void Run();

void OnEvent(Event &e);

void PushLayer(Layer* layer);

void PushOverlay(Layer* layer);

inline static Application& Get() {return * s_Instance;}

inline Window& GetWindow() { return *m_Window; }

private:

bool OnWindowClosed(WindowCloseEvent& e);

std::unique_ptr m_Window;

ImGuiLayer * m_ImGuiLayer;

bool m_Running = true;

LayerStack m_LayerStack;

//unsigned int m_VertexArray;

std::shared_ptr m_Shader;

std::shared_ptr m_VertexArray;

std::shared_ptr m_BlueShader;

std::shared_ptr m_SquareVA;

static Application* s_Instance;

};

//在客户端定义

Application* CreateApplication();

}

 Application.cpp:

#include"ytpch.h"

#include "Application.h"

#include"Log.h"

#include

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

//顶点数组:

//glGenVertexArrays(1, &m_VertexArray);

//glBindVertexArray(m_VertexArray);

//顶点缓冲区

//glGenBuffers(1, &m_VertexBuffer);

//glBindBuffer(GL_ARRAY_BUFFER,m_VertexBuffer);

//把数据传送给gpu,GL_STATIC_DRAW不断的用新数据刷新数组。告诉opengl这个缓冲区的数据布局

//glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

std::shared_ptr m_VertexBuffer;

m_VertexBuffer.reset(VertexBuffer::Create(vertices, sizeof(vertices)));

//启用数据的索引0

//glEnableVertexAttribArray(0);

//设置缓冲区数据格式:缓冲区序号、顶点属性的大小、什么数据类型、会不会被归一化、

//glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float),nullptr);

{

BufferLayout setlayout = {

{ShaderDataType::Float3,"a_Position"},

{ShaderDataType::Float4,"a_Color"}

};

m_VertexBuffer->SetLayout(setlayout);

}

//uint32_t index = 0;

//const auto& layout = m_VertexBuffer->GetLayout();

//for (const auto& element : layout) {

// glEnableVertexAttribArray(index);

// //设置缓冲区数据格式:缓冲区序号、顶点属性的大小、什么数据类型、会不会被归一化、

// glVertexAttribPointer(index,

// element.GetComponentCount(),

// ShaderDataTypeToOpenGLBaseType(element.Type),

// element.Normalized?GL_TRUE:GL_FALSE,

// layout.GetStride() ,

// (const void *)element.Offset);

// index++;

//}

m_VertexArray->AddVertexBuffer(m_VertexBuffer);

//创建索引缓冲区

//glGenBuffers(1, &m_IndexBuffer);

//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IndexBuffer);

//设置缓冲区格式

//glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

std::shared_ptrm_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 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 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));

//shader

}

Application::~Application() {

}

///

/// 所有的Window事件都会在这触发,作为参数e

///

///

void Application::OnEvent(Event& e) {

//根据事件类型绑定对应事件

EventDispatcher dispatcher(e);

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

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

}

}

 测试:

shader就不改了,随便一测试画出来个矩形就对了

推荐阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。