跟着cherno手搓游戏引擎【25】封装2DRenderer,封装shader传参,自定义Texture

封装2DRenderer:

Renderer.h:

cpp 复制代码
#include"ytpch.h"
#include"Renderer.h"
#include <Platform/OpenGL/OpenGLShader.h>
#include"Renderer2D.h"
namespace YOTO {
	Renderer::SceneData* Renderer::m_SceneData = new	Renderer::SceneData;
	void Renderer::Init()
	{
		RenderCommand::Init();
		Renderer2D::Init();
	}
	void Renderer::OnWindowResize(uint32_t width, uint32_t height)
	{
		RenderCommand::SetViewport(0, 0, width, height);
	}
	void Renderer::BeginScene(OrthographicCamera& camera)
	{
		m_SceneData->ViewProjectionMatrix = camera.GetViewProjectionMatrix();
	}
	void Renderer::EndScene()
	{
	}
	void Renderer::Submit(const Ref<Shader>& shader, const Ref<VertexArray>& vertexArray, const glm::mat4& transform)
	{
		shader->Bind();
		std::dynamic_pointer_cast<OpenGLShader>(shader)->UploadUniformMat4("u_ViewProjection", m_SceneData->ViewProjectionMatrix);
		std::dynamic_pointer_cast<OpenGLShader>(shader)->UploadUniformMat4("u_Transform", transform);
	/*	mi.Bind();*/

		vertexArray->Bind();
		RenderCommand::DrawIndexed(vertexArray);
	}
}

Renderer2D.h:专门渲染2D的类,负责"画什么"的问题

cpp 复制代码
#pragma once
#include "OrthographicCamera.h"
#include"Texture.h"
namespace YOTO {
	class Renderer2D
	{
	public:
		//为什么渲染器是静态的:
		static void Init();
		static void ShutDown();
		static void BeginScene(const OrthographicCamera& camera);
		static void EndScene();
		static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color);
		static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color);
		static void DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D> texture);
		static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref<Texture2D> texture);
	private:
	private:

	};
}

Renderer2D.cpp:

cpp 复制代码
#include "ytpch.h"
#include "Renderer2D.h"
#include"VertexArray.h"
#include"Shader.h"
//#include "Platform/OpenGL/OpenGLShader.h"
#include <glm/gtc/matrix_transform.hpp>
#include "RenderCommand.h"
namespace YOTO {
	struct  Renderer2DStorage {
		Ref<VertexArray> QuadVertexArray;
		//Ref<Shader> FlatColorShader;
		Ref<Shader> TextureShader;
		Ref<Texture2D> WhiteTexture;
	};
	static Renderer2DStorage* s_Data;
	void Renderer2D::Init()
	{
		s_Data = new  Renderer2DStorage();
		s_Data->QuadVertexArray = VertexArray::Create();

		float squareVertices[5 * 4] = {
			-0.5f,-0.5f,0.0f,0.0f,0.0f,
			0.5f,-0.5f,0.0f,1.0f,0.0f,
			0.5f,0.5f,0.0f,1.0f,1.0f,
			-0.5f,0.5f,0.0f,0.0f,1.0f,
		};
		Ref<VertexBuffer> squareVB;
		squareVB.reset(VertexBuffer::Create(squareVertices, sizeof(squareVertices)));
		squareVB->SetLayout({
			{ShaderDataType::Float3,"a_Position"},
				{ShaderDataType::Float2,"a_TexCoord"}
			});
		s_Data->QuadVertexArray->AddVertexBuffer(squareVB);
		uint32_t squareIndices[6] = { 0,1,2,2,3,0 };
		Ref<IndexBuffer> squareIB;

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

		s_Data->QuadVertexArray->AddIndexBuffer(squareIB);

		s_Data->WhiteTexture = Texture2D::Create(1, 1);
		uint32_t whiteTextureData = 0xffffffff;
		s_Data->WhiteTexture->SetData(&whiteTextureData,sizeof(uint32_t));

		//s_Data->FlatColorShader =Shader::Create("assets/shaders/FlatColor.glsl");
		s_Data->TextureShader= Shader::Create("assets/shaders/Texture.glsl");
		s_Data->TextureShader->Bind();
		s_Data->TextureShader->SetInt("u_Texture", 0);

	}
	void Renderer2D::ShutDown()
	{
		delete s_Data;
	}
	void Renderer2D::BeginScene(const OrthographicCamera& camera)
	{
		/*s_Data->FlatColorShader->Bind();
		s_Data->FlatColorShader->SetMat4("u_ViewProjection",camera.GetViewProjectionMatrix());*/
		s_Data->TextureShader->Bind();
		s_Data->TextureShader->SetMat4("u_ViewProjection", camera.GetViewProjectionMatrix());
	
	}
	void Renderer2D::EndScene()
	{
	}
	void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const glm::vec4& color)
	{
		DrawQuad({ position.x,position.y,0.0f }, size, color);
	}
	void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& color)
	{
		//s_Data->FlatColorShader->Bind();
		//s_Data->FlatColorShader->SetFloat4("u_Color", color);
		//s_Data->TextureShader->Bind();
		s_Data->TextureShader->SetFloat4("u_Color", color);
		s_Data->WhiteTexture->Bind();

		glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), {size.x,size.y,1.0f});
		s_Data->TextureShader->SetMat4("u_Transform", transform);
		s_Data->QuadVertexArray->Bind();
		RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
	}
	void Renderer2D::DrawQuad(const glm::vec2& position, const glm::vec2& size, const Ref<Texture2D> texture)
	{
		DrawQuad({ position.x,position.y,0.0f }, size, texture);
	}
	void Renderer2D::DrawQuad(const glm::vec3& position, const glm::vec2& size, const Ref<Texture2D> texture)
	{
		//s_Data->TextureShader->Bind();
		s_Data->TextureShader->SetFloat4("u_Color", {0.2f,0.3f,0.8f,0.5f});
		texture->Bind();


		glm::mat4 transform = glm::translate(glm::mat4(1.0f), position) /**rotation*/ * glm::scale(glm::mat4(1.0f), { size.x,size.y,1.0f });
		s_Data->TextureShader->SetMat4("u_Transform", transform);

		s_Data->QuadVertexArray->Bind();
		RenderCommand::DrawIndexed(s_Data->QuadVertexArray);
		
	}
}

封装Shader传参:

Shader.h:添加SetInt、SetFloat3...等等Set方法

cpp 复制代码
#pragma once
#include <string>
#include<glm/glm.hpp>
namespace YOTO {

	class Shader {

	public:
		virtual~Shader()=default;
		virtual void Bind()const=0;
		virtual void UnBind()const=0;

		virtual void SetInt(const std::string& name,int value) = 0;
		virtual void SetFloat3(const std::string& name, const glm::vec3& value) = 0;
		virtual void SetFloat4(const std::string& name, const glm::vec4& value) = 0;
		virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0;

		virtual const std::string& GetName()const = 0;

		static Ref<Shader> Create(const std::string& filepath);
		static Ref<Shader> Create(const std::string&name, const std::string& vertexSrc, const std::string& fragmentSrc);

	};
	class ShaderLibrary {
	public:
		void Add(const Ref<Shader>& shader);
		void Add(const std::string &name,const Ref<Shader>& shader);
		Ref<Shader> Load(const std::string filepath);
		Ref<Shader> Load(const std::string &name,const std::string filepath);
		Ref<Shader> Get(const std::string& name);
		bool Exists(const std::string& name);
	private:
		std::unordered_map<std::string,Ref<Shader>> m_Shaders;

	};
}

OpenGLShader.h:同Shader.h

cpp 复制代码
#pragma once
#include <string>
#include "YOTO/Renderer/Shader.h"
#include <glm/glm.hpp>
typedef unsigned int GLenum;
namespace YOTO {

	class OpenGLShader:public Shader {

	public:
		OpenGLShader(const std::string& filepath);
		OpenGLShader(const std::string &name,const std::string& vertexSrc, const std::string& fragmentSrc);
		~OpenGLShader();
		void Bind()const override;
		void UnBind()const override;

		virtual void SetInt(const std::string& name, int value) override;
		virtual void SetFloat3(const std::string& name, const glm::vec3& value) override;
		virtual void SetFloat4(const std::string& name, const glm::vec4& value)override;
		virtual void SetMat4(const std::string& name, const glm::mat4& value) override;

		virtual const std::string& GetName()const override { return m_Name; }
		void UploadUniformMat4(const std::string& name, const glm::mat4& matrix);
		void UploadUniformMat3(const std::string& name, const glm::mat3& matrix);

		void UploadUniformFloat4(const std::string& name, const glm::vec4& values);
		void UploadUniformFloat3(const std::string& name, const glm::vec3& values);
		void UploadUniformFloat2(const std::string& name, const glm::vec2& values);
		void UploadUniformFloat(const std::string& name, float values);

		void UploadUniformInt(const std::string& name, int values);
	private:
		std::string ReadFile(const std::string filepath);
		std::unordered_map<GLenum,std::string> PreProcess(const std::string& source);
		void Compile(const std::unordered_map<GLenum, std::string>& shaderSources);
	private:
		uint32_t m_RendererID;
		std::string m_Name;
	}
	;
} 

OpenGLShader.cpp:

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

#include <glad/glad.h>
#include<glm/gtc/type_ptr.hpp>
namespace YOTO {
	static GLenum ShaderTypeFromString(const std::string& type) {
		if (type == "vertex") {
			return GL_VERTEX_SHADER;
		}
		if (type == "fragment" || type == "pixel") {
			return GL_FRAGMENT_SHADER;
		}
		YT_CORE_ASSERT(false, "不知道的shader类型");
		return 0;
	}
	
	OpenGLShader::OpenGLShader(const std::string& filepath)
	{
		std::string source = ReadFile(filepath);
		YT_CORE_ASSERT(source.size(), "GLSL读取的字符串为空");
		auto shaderSources = PreProcess(source);
		Compile(shaderSources);


		auto lastSlash = filepath.find_last_of("/\\");
		lastSlash = lastSlash == std::string::npos ? 0 : lastSlash + 1;
		auto lastDot = filepath.rfind('.');
		auto count = lastDot == std::string::npos ? filepath.size() - lastSlash : lastDot - lastSlash;
		m_Name=filepath.substr(lastSlash, count);
	}
	OpenGLShader::OpenGLShader(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc)
	:m_Name(name){
		std::unordered_map<GLenum, std::string >sources;
		sources[GL_VERTEX_SHADER] = vertexSrc;
		sources[GL_FRAGMENT_SHADER] = fragmentSrc;
		Compile(sources);
	}
	OpenGLShader::~OpenGLShader()
	{
		glDeleteProgram(m_RendererID);
	}

	std::string OpenGLShader::ReadFile(const std::string filepath)
	{
		std::string result;
		std::ifstream in(filepath, std::ios::in | std::ios::binary);
		if (in) {
			in.seekg(0, std::ios::end);			// 将指针放在最后面
			result.resize(in.tellg());			// 初始化string的大小, in.tellg()返回位置
			in.seekg(0, std::ios::beg);			// in指回头部
			in.read(&result[0], result.size());	// in读入放在result指向的内存中
		}
		else {
			YT_CORE_ERROR("不能打开文件:{0}", filepath);
		}
		return result;
	}
	std::unordered_map<GLenum, std::string> OpenGLShader::PreProcess(const std::string& source)
	{
		std::unordered_map<GLenum, std::string> shaderSources;

		std::string typeToken = "#type";
		size_t typeTokenLen = typeToken.size();
		size_t findCurPos = source.find(typeToken, 0);
		size_t findNextPos = findCurPos;
		while (findNextPos != std::string::npos) {
			size_t curlineEndPos = source.find_first_of("\r\n", findCurPos);///r/n写错为/r/n
			YT_CORE_ASSERT(curlineEndPos != std::string::npos, "解析shader失败");
			size_t begin = findCurPos + typeTokenLen + 1;

			std::string type = source.substr(begin, curlineEndPos - begin);// 获取到是vertex还是fragment
			YT_CORE_ASSERT(ShaderTypeFromString(type), "无效的shader的类型	");

			size_t nextLinePos = source.find_first_not_of("\r\n", curlineEndPos);
			findNextPos = source.find(typeToken, nextLinePos);
			// 获取到具体的shader代码
			shaderSources[ShaderTypeFromString(type)] = source.substr(nextLinePos, findNextPos - (nextLinePos == std::string::npos ? source.size() - 1 : nextLinePos));

			findCurPos = findNextPos;
		}
		return shaderSources;
		/*
			用find,而不是find_firtst_of,因为
			find返回完全匹配的字符串的的位置;
			find_first_of返回被查匹配字符串中某个字符的第一次出现位置。

			std::string::npos是一个非常大的数
			source.substr(0, source.size() + 10000)截取到从头到末尾,不会报错
		*/
	}

	void OpenGLShader::Compile(const std::unordered_map<GLenum, std::string>& shaderSources)
	{
		GLuint program = glCreateProgram();
		YT_CORE_ASSERT(shaderSources.size()<=2,"OpenGLShader:shader只支持两种!")
		std::array<GLenum,2>glShaderIDs;
		int glShaderIDIndex=0;
		for (auto& kv : shaderSources) {
			GLenum type = kv.first;
			const std::string& source = kv.second;
			// Create an empty vertex shader handle
			GLuint shader = glCreateShader(type);
			// Send the vertex shader source code to GL
			// Note that std::string's .c_str is NULL character terminated.
			const GLchar* sourceCStr = source.c_str();
			glShaderSource(shader, 1, &sourceCStr, 0);
			// Compile the vertex shader
			glCompileShader(shader);
			GLint isCompiled = 0;
			glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
			if (isCompiled == GL_FALSE)
			{
				GLint maxLength = 0;
				glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
				// The maxLength includes the NULL character
				std::vector<GLchar> infoLog(maxLength);
				glGetShaderInfoLog(shader, maxLength, &maxLength, &infoLog[0]);
				// We don't need the shader anymore.
				glDeleteShader(shader);
				// Use the infoLog as you see fit.
				// In this simple program, we'll just leave
				YT_CORE_ERROR("{0} ", infoLog.data());
				YT_CORE_ASSERT(false, "shader 编译失败!");
				break;
			}
			// Attach our shaders to our program
			glAttachShader(program, shader);
			glShaderIDs[glShaderIDIndex++]=shader;
		}

		// Link our program
		glLinkProgram(program);
		// Note the different functions here: glGetProgram* instead of glGetShader*.
		GLint isLinked = 0;
		glGetProgramiv(program, GL_LINK_STATUS, (int*)&isLinked);
		if (isLinked == GL_FALSE)
		{
			GLint maxLength = 0;
			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
			// The maxLength includes the NULL character
			std::vector<GLchar> infoLog(maxLength);
			glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
			// We don't need the program anymore.
			glDeleteProgram(program);
			// Don't leak shaders either.
			for (auto id : glShaderIDs) {
				glDeleteShader(id);
			}
			// Use the infoLog as you see fit.
			// In this simple program, we'll just leave
			YT_CORE_ERROR("{0} ", infoLog.data());
			YT_CORE_ASSERT(false, "shader link failure!");
			return;
		}
		// Always detach shaders after a successful link.
		for (auto id : glShaderIDs) {
			glDetachShader(program, id);
		}
		m_RendererID = program;

	}

	void OpenGLShader::Bind() const
	{
		glUseProgram(m_RendererID);
	}
	void OpenGLShader::UnBind() const
	{
		glUseProgram(0);
	}
	void OpenGLShader::SetInt(const std::string& name, int value)
	{
		UploadUniformInt(name, value);
	}
	void OpenGLShader::SetFloat3(const std::string& name, const glm::vec3& value)
	{
		UploadUniformFloat3(name, value);
	}
	void OpenGLShader::SetFloat4(const std::string& name, const glm::vec4& value)
	{
		UploadUniformFloat4(name, value);
	}
	void OpenGLShader::SetMat4(const std::string& name, const glm::mat4& value)
	{
		UploadUniformMat4(name, value);
	}
	void OpenGLShader::UploadUniformMat4(const std::string& name, const glm::mat4& matrix)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniformMatrix4fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix));

	}
	void OpenGLShader::UploadUniformMat3(const std::string& name, const glm::mat3& matrix)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniformMatrix3fv(loacation, 1, GL_FALSE, glm::value_ptr(matrix)); 
	}
	void OpenGLShader::UploadUniformFloat4(const std::string& name, const glm::vec4& values)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniform4f(loacation, values.x, values.y, values.z, values.w);

	}
	void OpenGLShader::UploadUniformFloat3(const std::string& name, const glm::vec3& values)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniform3f(loacation, values.x, values.y, values.z);
	}
	void OpenGLShader::UploadUniformFloat2(const std::string& name, const glm::vec2& values)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniform2f(loacation, values.x, values.y);
	}
	void OpenGLShader::UploadUniformFloat(const std::string& name, float values)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniform1f(loacation, values);
	}
	void OpenGLShader::UploadUniformInt(const std::string& name, int values)
	{
		GLint loacation = glGetUniformLocation(m_RendererID, name.c_str());
		glUniform1i(loacation, values);
	}
	
}

添加自定义Texture方法:

Texture.h:添加新的Create方法:根据宽高添加

cpp 复制代码
#pragma once
namespace YOTO {
	class Texture
	{
	public:
		virtual ~Texture() = default;
		virtual uint32_t GetWidth()const = 0;
		virtual uint32_t GetHeight()const = 0;
		virtual void SetData(void* data, uint32_t size) = 0;
		virtual void Bind(uint32_t slot=0)const = 0;

	};
	class Texture2D :public Texture 
	{
	public:
		static Ref<Texture2D>Create(uint32_t width,uint32_t height);
		static Ref<Texture2D>Create(const std::string& path);
	};
}

Texture.cpp:

cpp 复制代码
#include "ytpch.h"
#include "Texture.h"
#include"Renderer.h"
#include "Platform/OpenGL/OpenGLTexture.h"
namespace YOTO {
	Ref<Texture2D> Texture2D::Create(uint32_t width, uint32_t height)
	{
		switch (Renderer::GetAPI())
		{
		case RendererAPI::API::None:
			YT_CORE_ASSERT(false, "Texture2D:API为None不支持");
			return nullptr;
		case RendererAPI::API::OpenGL:
			return  CreateRef<OpenGLTexture2D>(width,height);
		}
		YT_CORE_ASSERT(false, "Buffer:未知API");
		return nullptr;
	}
	Ref<Texture2D> Texture2D::Create(const std::string& path)
	{
		switch (Renderer::GetAPI())
		{
		case RendererAPI::API::None:
			YT_CORE_ASSERT(false, "Texture2D:API为None不支持");
			return nullptr;
		case RendererAPI::API::OpenGL:
			return  CreateRef<OpenGLTexture2D>(path);
		}
		YT_CORE_ASSERT(false, "Buffer:未知API");
		return nullptr;
	}
}

OpenGLTexture.h:同Texture.h相同,且添加设置texture数据的方法SetData:

cpp 复制代码
#pragma once
#include"YOTO/Renderer/Texture.h"
#include<glad/glad.h>
namespace YOTO {
	class OpenGLTexture2D:public Texture2D
	{
	public:
		OpenGLTexture2D(uint32_t width,uint32_t height);
		OpenGLTexture2D(const std::string path);
		virtual~OpenGLTexture2D();
		virtual uint32_t GetWidth()const override { return m_Width; }
		virtual uint32_t GetHeight()const override { return m_Height; }
	
		virtual void SetData(void* data, uint32_t size)override;

		virtual void Bind(uint32_t slot=0)const override;
	private:
		std::string m_Path;
		uint32_t m_Width, m_Height;
		uint32_t m_RendererID;
		GLenum m_InternalFormat, m_DataFormat;
	};
}

OpenGLTexture.cpp:

cpp 复制代码
#include "ytpch.h"
#include "OpenGLTexture.h"
#include<glad/glad.h>
#include"stb_image.h"
namespace YOTO {
	OpenGLTexture2D::OpenGLTexture2D(uint32_t width, uint32_t height)
		:m_Width(width),m_Height(height)
	{
		m_InternalFormat = GL_RGBA8;
		m_DataFormat = GL_RGBA;
		
	
			glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
		///告诉OpenGLm_RendererID的纹理存储的是rbg8位,宽高的缓冲区
		glTextureStorage2D(m_RendererID, 1, m_InternalFormat, m_Width, m_Height);
		//配置参数:纹理放大时用周围颜色的平均值过滤
		glTextureParameteri(m_RendererID, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);

	
	}
	OpenGLTexture2D::OpenGLTexture2D(const std::string path)
		:m_Path(path)
	{
		int width, height, channels;
		stbi_set_flip_vertically_on_load(1);//翻转
		stbi_uc*data=stbi_load(path.c_str(),&width,&height,&channels,0);
		YT_CORE_ASSERT(data, "图片加载错误");
		m_Width = width;
		m_Height = height;

		GLenum internalFormat = 0,dataFormat=0;
		if (channels == 4) {
			internalFormat = GL_RGBA8;
			dataFormat = GL_RGBA;
		}
		else if (channels==3) {
			internalFormat = GL_RGB8;
			dataFormat = GL_RGB;
		}

		m_InternalFormat = internalFormat;
		m_DataFormat = dataFormat;

		YT_CORE_ASSERT(internalFormat& dataFormat,"OpenGLTexture2D:不支持的颜色格式")
		//创建纹理
		glCreateTextures(GL_TEXTURE_2D, 1, &m_RendererID);
		///告诉OpenGLm_RendererID的纹理存储的是rbg8位,宽高的缓冲区
		glTextureStorage2D(m_RendererID, 1, internalFormat,m_Width,m_Height);
		//配置参数:纹理放大时用周围颜色的平均值过滤
		glTextureParameteri(m_RendererID,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
		glTextureParameteri(m_RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTextureParameteri(m_RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT);

		glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height, dataFormat,GL_UNSIGNED_BYTE,data);
		stbi_image_free(data);
	}
	OpenGLTexture2D::~OpenGLTexture2D()
	{
		glDeleteTextures(1,&m_RendererID);
	}
	void OpenGLTexture2D::SetData(void* data, uint32_t size)
	{
		uint32_t bpc = m_DataFormat == GL_RGBA ? 4 : 3;
		YT_CORE_ASSERT(size == m_Width * m_Height * bpc,"OpenGLTexture2D:数据必须是完整的!");
		glTextureSubImage2D(m_RendererID, 0, 0, 0, m_Width, m_Height,m_DataFormat, GL_UNSIGNED_BYTE,data);
	}
	void OpenGLTexture2D::Bind(uint32_t slot) const
	{
		glBindTextureUnit(slot, m_RendererID);
	}
}

Sandbox2D.h:添加m_CheckerboardTexture

cpp 复制代码
#pragma once
#include "YOTO.h"
class Sandbox2D :public YOTO::Layer
{public:
	Sandbox2D();
	virtual ~Sandbox2D() = default;
	virtual void OnAttach()override;
	virtual void OnDetach()override;

	void OnUpdate(YOTO::Timestep ts)override;
	virtual void OnImGuiRender() override;
	void OnEvent(YOTO::Event& e)override;
private:
	YOTO::OrthographicCameraController m_CameraController;

	YOTO::Ref<YOTO::Shader> m_FlatColorShader;
	YOTO::Ref<YOTO::VertexArray> m_SquareVA;
	YOTO::Ref<YOTO::Texture2D>m_CheckerboardTexture;
	glm::vec4 m_SquareColor = { 0.2f,0.3f,0.7f,1.0f };
};

化简Sandbox2D:

Sandbox2D.cpp:把传shader参数的代码注释掉 ,统一使用DrawQuad封装;负责"怎么画"的问题:

cpp 复制代码
#include "Sandbox2D.h"
#include <imgui/imgui.h>
#include <glm/gtc/matrix_transform.hpp>
//#include <Platform/OpenGL/OpenGLShader.h>
#include <glm/gtc/type_ptr.hpp>
Sandbox2D::Sandbox2D()
:Layer("Sandbox2D"), m_CameraController(1280.0f / 720.0f, true) 
{
}
void Sandbox2D::OnAttach()
{
	m_CheckerboardTexture = YOTO::Texture2D::Create("assets/textures/Checkerboard.png");

}
void Sandbox2D::OnDetach()
{
}

void Sandbox2D::OnUpdate(YOTO::Timestep ts)
{	//update
	m_CameraController.OnUpdate(ts);

	//Render
	YOTO::RenderCommand::SetClearColor({ 0.2f, 0.2f, 0.2f, 1.0f });
	YOTO::RenderCommand::Clear();

	YOTO::Renderer2D::BeginScene(m_CameraController.GetCamera());
	{
		static glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(0.1f));
		glm::vec4  redColor(0.8f, 0.3f, 0.3f, 1.0f);
		glm::vec4  blueColor(0.2f, 0.3f, 0.8f, 1.0f);


		/*std::dynamic_pointer_cast<YOTO::OpenGLShader>(m_FlatColorShader)->Bind();
		std::dynamic_pointer_cast<YOTO::OpenGLShader>(m_FlatColorShader)->UploadUniformFloat4("u_Color", m_SquareColor);
		YOTO::Renderer::Submit(m_FlatColorShader, m_SquareVA, glm::scale(glm::mat4(1.0f), glm::vec3(1.5f)));*/

		YOTO::Renderer2D::DrawQuad({ -1.0f,0.0f }, { 0.8f,0.8f }, {0.8f,0.2f,0.3f,1.0f});
		YOTO::Renderer2D::DrawQuad({ 0.5f,-0.5f }, { 0.5f,0.75f }, { 0.2f,0.3f,0.8f,1.0f });
		YOTO::Renderer2D::DrawQuad({ 0.0f,0.0f,-0.1f }, {10.0f,10.0f }, m_CheckerboardTexture);
		YOTO::Renderer2D::EndScene();
	}
}
void Sandbox2D::OnImGuiRender()
{
	ImGui::Begin("设置");
	ImGui::ColorEdit4("正方形颜色", glm::value_ptr(m_SquareColor));
	ImGui::End();
}

void Sandbox2D::OnEvent(YOTO::Event& e)
{
	m_CameraController.OnEvent(e);
}

小修改:

OpenGLRendererAPI.cpp:DrawIndexed中添加解绑Texture:

cpp 复制代码
#include "ytpch.h"
#include "OpenGLRendererAPI.h"
#include <glad/glad.h>
namespace YOTO {
	void OpenGLRendererAPI::Init()
	{
		//启用混合
		glEnable(GL_BLEND);
		//设置混合函数
		glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
		//深度测试
		glEnable(GL_DEPTH_TEST);
	}
	void OpenGLRendererAPI::SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height)
	{
		glViewport(x, y, width, height);
	}
	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 Ref<VertexArray>& vertexArray)
	{
		glDrawElements(GL_TRIANGLES, vertexArray->GetIndexBuffer()->GetCount(), GL_UNSIGNED_INT, nullptr);
		glBindTexture(GL_TEXTURE_2D, 0);
	}
}

flatColor.glsl:

cpp 复制代码
		#type vertex
		#version 330 core
		layout(location = 0) in vec3 a_Position;

		uniform mat4 u_ViewProjection;
		uniform mat4 u_Transform;
		


		void main(){
		gl_Position =u_ViewProjection*u_Transform*vec4( a_Position,1.0);
		}

		#type fragment
		#version 330 core
		layout(location = 0) out vec4 color;
	
		uniform vec4 u_Color ;
		void main(){
		color =u_Color;	
		}
		

Texture.glsl:

cpp 复制代码
		#type vertex
		#version 330 core
		layout(location = 0) in vec3 a_Position;
		layout(location = 1) in vec2 a_TexCoord;

		uniform mat4 u_ViewProjection;
		uniform mat4 u_Transform;
		
		out vec2 v_TexCoord;
		out vec3 v_Position;

		void main(){
		v_TexCoord=a_TexCoord;
		v_Position=a_Position;
		gl_Position =u_ViewProjection*u_Transform*vec4( a_Position,1.0);
		}

		#type fragment
		#version 330 core
		layout(location = 0) out vec4 color;
		in vec3 v_Position;
	
		in vec2 v_TexCoord;

		uniform vec4 u_Color ;
		uniform sampler2D u_Texture ;
		void main(){
		color = texture(u_Texture, v_TexCoord*10.0f)*u_Color;	
		}
		

YOTO.h:添加:

cpp 复制代码
#include"YOTO/Renderer/Renderer2D.h"

Core.h:

cpp 复制代码
#pragma once
#include<memory>
//用于dll的宏
#ifdef YT_PLATFORM_WINDOWS
#if YT_DYNAMIC_LINK
		#ifdef YT_BUILD_DLL
		#define YOTO_API __declspec(dllexport) 
		#else
		#define YOTO_API __declspec(dllimport) 

		#endif // DEBUG
#else
		#define YOTO_API
#endif
#else
#error YOTO_ONLY_SUPPORT_WINDOWS
#endif // YOTO_PLATFORM_WINDOWS

#ifdef YT_DEBUG
#define YT_ENABLE_ASSERTS
#endif

#ifdef YT_ENABLE_ASSERTS
#define YT_CLIENT_ASSERT(x,...) {if(!(x)){YT_CLIENT_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#define YT_CORE_ASSERT(x,...) {if(!(x)){YT_CORE_ERROR("断言错误:{0}",__VA_ARGS__);__debugbreak();}}
#else
#define YT_CLIENT_ASSERT(x,...)
#define YT_CORE_ASSERT(x,...)

#endif // YT_ENABLE_ASSERTS



#define BIT(x)(1<<x)
//绑定事件定义
#define YT_BIND_EVENT_FN(fn) std::bind(&fn, this, std::placeholders::_1)

namespace YOTO {
	template<typename T>
	using  Scope = std::unique_ptr<T>;
	template<typename T>
	using  Ref = std::shared_ptr<T>;

	template<typename T,typename ...Args>
	constexpr Scope<T> CreateScope(Args&&...args) {
		return std::make_shared<T>(std::forward<Args>(args)...);
	}
	template<typename T, typename ...Args>
	constexpr Ref<T> CreateRef(Args&&...args) {
		return std::make_shared<T>(std::forward<Args>(args)...);
	}

}

测试:

cool!

相关推荐
charon877816 小时前
UE ARPG | 虚幻引擎战斗系统
游戏引擎
小春熙子17 小时前
Unity图形学之Shader结构
unity·游戏引擎·技术美术
极梦网络无忧19 小时前
Unity中IK动画与布偶死亡动画切换的实现
unity·游戏引擎·lucene
_oP_i1 天前
Unity Addressables 系统处理 WebGL 打包本地资源的一种高效方式
unity·游戏引擎·webgl
代码盗圣1 天前
GODOT 4 不用scons编译cpp扩展的方法
游戏引擎·godot
Leoysq2 天前
【UGUI】实现点击注册按钮跳转游戏场景
游戏·unity·游戏引擎·ugui
PandaQue2 天前
《潜行者2切尔诺贝利之心》游戏引擎介绍
游戏引擎
_oP_i2 天前
unity中 骨骼、纹理和材质关系
unity·游戏引擎·材质
Padid2 天前
Unity SRP学习笔记(二)
笔记·学习·unity·游戏引擎·图形渲染·着色器
dangoxiba3 天前
[Unity Demo]从零开始制作空洞骑士Hollow Knight第十八集补充:制作空洞骑士独有的EventSystem和InputModule
游戏·unity·c#·游戏引擎·playmaker