跟着cherno手搓游戏引擎【14】封装opengl

news2024/11/16 7:40:07

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

前置:

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 <YOTO/Log.h>
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_list<BufferElement>elements)
			:m_Elements(elements) 
		{
			CalculateOffsetAndStride();
		} 
		inline uint32_t GetStride()const { return m_Stride; }
		inline const std::vector<BufferElement>& GetElements()const {
			return m_Elements;
		}
		std::vector<BufferElement>::iterator begin() { return m_Elements.begin(); }
		std::vector<BufferElement>::iterator end() { return m_Elements.end(); }
		std::vector<BufferElement>::const_iterator begin() const { return m_Elements.begin(); }
		std::vector<BufferElement>::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<BufferElement> 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>&vertexBuffer) = 0;
		virtual void AddIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer) = 0;
		virtual const  std::vector<std::shared_ptr<VertexBuffer>>& GetVertexBuffers()const = 0;
		virtual const std::shared_ptr<IndexBuffer>& 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 <glad/glad.h>
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>& vertexBuffer)override;
		virtual void AddIndexBuffer(const std::shared_ptr<IndexBuffer>& indexBuffer)override;

		virtual const std::vector<std::shared_ptr<VertexBuffer>>& GetVertexBuffers()const {
			return m_VertexBuffers;
		}
		virtual const std::shared_ptr<IndexBuffer>& GetIndexBuffer()const {
			return m_IndexBuffers;
		}
	private:
		uint32_t m_RendererID;
		std::vector<std::shared_ptr<VertexBuffer>> m_VertexBuffers;
		std::shared_ptr<IndexBuffer> m_IndexBuffers;
	};

}


  OpenGLVertexArray.cpp:

#include "ytpch.h"
#include "OpenGLVertexArray.h"
#include <glad/glad.h>
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>& 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>& 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 <YOTO/Renderer/Shader.h>
#include <YOTO/Renderer/Buffer.h>
#include <YOTO/Renderer/VertexArray.h>
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<Window>  m_Window;
		ImGuiLayer *  m_ImGuiLayer;
		bool m_Running = true;
		LayerStack m_LayerStack;
		
		//unsigned int m_VertexArray;
		std::shared_ptr<Shader> m_Shader;
		std::shared_ptr<VertexArray> m_VertexArray;


		std::shared_ptr<Shader> m_BlueShader;
		std::shared_ptr<VertexArray> m_SquareVA;



		static Application* s_Instance;
	};
	//在客户端定义
	Application* CreateApplication();
}

 Application.cpp:

#include"ytpch.h"
#include "Application.h"

#include"Log.h"
#include<glad/glad.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());


		//顶点数组:
		//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<VertexBuffer> 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_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));
		
		//shader
	}
	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);
			
			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就不改了,随便一测试画出来个矩形就对了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1420173.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

交换排序(快排)

当当当当&#xff01;终于来到了令人激动人心的环节&#xff1a;交换排序&#xff01;在这里&#xff0c;我们将会学习到一个大家经常听到过的名词&#xff1a;快速排序&#xff0c;而我希望通过这篇文章的学习&#xff0c;大家也能够真正的学会快排&#xff01; 交换排序 基本…

SkyWalking+es部署与使用

第一步下载skywalking :http://skywalking.apache.org/downloads/ 第二步下载es:https://www.elastic.co/cn/downloads/elasticsearch 注&#xff1a;skywalking 和es要版本对应&#xff0c;可从下面连接查看版本对应关系&#xff0c;8.5.0为skywalking 版本号 Index of /di…

Scala入门01

Spark入门 1.入门 spark采用Scala语言开发 Spark是用来计算的 Scala掌握&#xff1a;特性&#xff0c;基本操作&#xff0c;集合操作&#xff0c;函数&#xff0c;模式匹配&#xff0c;trait&#xff0c;样例类&#xff0c;actor等内容。 2.内容讲解 2.1 Scala简介 在http…

idea报错(建一个数据库和里面的表)

//报错1 2024-01-30 11:36:50.652 ERROR 21136 --- [nio-9090-exec-5] c.e.exception.GlobalExceptionHandler : 异常信息&#xff1a; 前端没有传数据就会报这个错 //报错2 Caused by: java.sql.SQLException: Access denied for user rootlocalhost (using password: YES…

【UEFI实战】Redfish的BIOS实现——生成EDK数据

生成Redfish文件 Redfish数据的表示形式&#xff0c;最常用的是JSON。将JSON表示的数据转换成C语言可以操作的结构体&#xff0c;是必不可少的步骤。当然如果手动转换的话&#xff0c;需要浪费大量的时间&#xff0c;因此DMTF组织开发了一个工具&#xff0c;用于将JSON数据快速…

redis-4 集群

应用场景 为什么需要redis集群&#xff1f; 当主备复制场景&#xff0c;无法满足主机的单点故障时&#xff0c;需要引入集群配置。 一般数据库要处理的读请求远大于写请求 &#xff0c;针对这种情况&#xff0c;我们优化数据库可以采用读写分离的策略。我们可以部 署一台主服…

论文笔记:多任务学习模型:渐进式分层提取(PLE)含pytorch实现

整理了RecSys2020 Progressive Layered Extraction : A Novel Multi-Task Learning Model for Personalized Recommendations&#xff09;论文的阅读笔记 背景模型代码 论文地址&#xff1a;PLE 背景 多任务学习&#xff08;multi-task learning&#xff0c;MTL&#xff09;&a…

【C/C++ 01】初级排序算法

排序算法通常是针对数组或链表进行排序&#xff0c;在C语言中&#xff0c;需要手写排序算法完成对数据的排序&#xff0c;排序规则通常为升序或降序&#xff08;本文默认为升序&#xff09;&#xff0c;在C中&#xff0c;<algorithm>头文件中已经封装了基于快排算法的 st…

Leetcode3015. 按距离统计房屋对数目 I

Every day a Leetcode 题目来源&#xff1a;3015. 按距离统计房屋对数目 I 解法1&#xff1a;暴力 暴力枚举每一个房屋对 (i, j) 的 3 种路径&#xff1a; i->j&#xff1a;长度为 len1 j-i&#xff1b;i->x->y->j&#xff1a;长度为 len2 abs(i - x) 1 a…

解决Linux环境下gdal报错:ERROR 4: `/xxx.hdf‘ not recognized as a supported file format.

网上查了一堆资料&#xff0c;五花八门&#xff0c;总结了一下可能的原因&#xff1a; ① gdal不支持该格式 使用命令“gdalinfo --formats” 即可查看当前环境中的gdal所能支持的数据格式。如下图&#xff08;没截完整&#xff0c;下面还有一大串&#xff09;。 这个是很常见…

Java代码混淆加密之ClassFinal

一:介绍 ClassFinal是一款java class文件安全加密工具,支持直接加密jar包或war包,无需修改任何项目代码,兼容spring-framework;可避免源码泄漏或字节码被反编译。 二:功能特性 无需修改原项目代码,只要把编译好的jar/war包用本工具加密即可。运行加密项目时,无需求修…

iText操作pdf

最近有个任务是动态的创建pdf根据获取到的内容&#xff0c;百度到的知识点都比较零散&#xff0c;官方文档想必大家也不容易看懂。下文是我做出的汇总 public class CreatePdfUtils {public static void create(){//准备File file new File("C:\\code\\base-project-back…

STM32矩形(矩阵)按键(键盘)输入控制LED灯 ——4*4矩阵按键源码解析

本文基于标准函数库的工程实现stm32F103C8T6使用4*4的矩阵按键控制LED灯的亮灭及闪烁等功能。 程序源码&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1_MPhvMduKCTP0MPG-Gtw3A?pwd2syk 提取码&#xff1a;2syk 文章目录 一、矩形键盘介绍 1、硬件电路基本原理 …

Sketch 英文转中文:轻松搞定

Sketch版本的转换一直是每个人的关键问题。现在UI设计领域有很多UI设计软件&#xff0c;但大部分都是英文版。对于国内英语基础差的设计师来说&#xff0c;使用这样的软件无形中增加了工作量&#xff0c;往往需要在设计编辑的同时查阅翻译。中文Sketch版本替代即时设计详细介绍…

动手学RAG:汽车知识问答

原文&#xff1a;动手学RAG&#xff1a;汽车知识问答 - 知乎 Part1 内容介绍 在自然语言处理领域&#xff0c;大型语言模型&#xff08;LLM&#xff09;如GPT-3、BERT等已经取得了显著的进展&#xff0c;它们能够生成连贯、自然的文本&#xff0c;回答问题&#xff0c;并执行…

常用网址备份

阿里git下载镜像 (npmmirror.com 主页有其他资源)https://registry.npmmirror.com/binary.html?pathgit-for-windows/

【Java】Spring的APO及事务

今日目标 能够理解AOP的作用 能够完成AOP的入门案例 能够理解AOP的工作流程 能够说出AOP的五种通知类型 能够完成"测量业务层接口万次执行效率"案例 能够掌握Spring事务配置 一、AOP 1 AOP简介 问题导入 问题1&#xff1a;AOP的作用是什么&#xff1f; 问题2&am…

Phoncent博客,探索Rie Kudan的GPT创作之举

近日&#xff0c;大家都在谈论日本作家Rie Kudan&#xff0c;她凭借其小说《东京共鸣塔》&#xff08;"Tokyo-to Dojo-to"&#xff09;荣获了日本极具声望的芥川奖。这本小说引起了广泛的讨论和思考&#xff0c;因为令人惊讶的是&#xff0c;Kudan在其中直接引用了人…

Python(19)Excel表格操作Ⅰ

目录 导包 读取EXCEL文件 1、获取worksheet名称 2、设定当前工作表 3、输出目标单元格数据 4、工作表.rows&#xff08;行&#xff09; 5、工作表.columns&#xff08;列&#xff09; 小结 导包 要想使用 python 操作 Excel 文件&#xff0c;应当导入 openpyxl 包。在…

Java 面试题之 IO(二)

字符流 文章目录 字符流Reader&#xff08;字符输入流&#xff09;Writer&#xff08;字符输出流&#xff09; 文章来自Java Guide 用于学习如有侵权&#xff0c;立即删除 不管是文件读写还是网络发送接收&#xff0c;信息的最小存储单元都是字节。 那为什么 I/O 流操作要分为字…