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

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

前置:

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就不改了,随便一测试画出来个矩形就对了

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Electron桌面应用实战:Element UI 导航栏橙色轮廓之谜与Bootstrap样式冲突解决方案

目录 引言 问题现象及排查过程 描述问题 深入探索 查明原因 解决方案与策略探讨 重写样式 禁用 Bootstrap 样式片段 深度定制 Element UI 组件 隔离样式作用域 结语 引言 在基于 Electron 开发桌面应用的过程中&#xff0c;我们可能时常遇到各种意想不到的问题…

存储技术架构演进

一. 演进过程 存储技术架构的演进主要是从集中式到分布式的一种呈现&#xff0c;集中式存储模式凭借其在稳定性和可靠性方面的优势成为许多业务数据库的数据存储首选&#xff0c;顾名思义&#xff0c;集中式存储主要体现在集中性&#xff0c;一套集中式管理的存储系统&#xff…

day35WEB 攻防-通用漏洞XSS 跨站反射存储DOMBeef-XSS

目录 一&#xff0c;XSS 跨站-原理&分类&手法&探针 1、原理 2、分类 3、危害 二&#xff0c;反射型XSS 1&#xff0c;案例演示 三&#xff0c;存储型XSS 1&#xff0c;案例演示 四&#xff0c;DOM 型XSS 五&#xff0c;XSS 利用环境-XSS 平台&Beef-XS…

【Linux】压缩脚本、报警脚本

一、压缩搅拌 要求&#xff1a; 写一个脚本&#xff0c;完成如下功能 传递一个参数给脚本&#xff0c;此参数为gzip、bzip2或者xz三者之一&#xff1b; (1) 如果参数1的值为gzip&#xff0c;则使用tar和gzip归档压缩/etc目录至/backups目录中&#xff0c;并命名为/backups/etc…

美国将限制中国,使用Azure、AWS等云,训练AI大模型

1月29日&#xff0c;美国商务部在Federal Register&#xff08;联邦公报&#xff09;正式公布了&#xff0c;《采取额外措施应对与重大恶意网络行为相关的国家紧急状态》提案。 该提案明确要求美国IaaS&#xff08;云服务&#xff09;厂商在提供云服务时&#xff0c;要验证外国…

前端框架---Vue2学习教程(上)

从HTML到现在一路跟过来的小伙伴们&#xff0c;坚持固然不容易&#xff0c;但我相信大家已经学到了不少&#xff0c;那么我们开始马不停蹄的进入前端的框架吧&#xff0c;下面讲的是Vue2&#xff0c;大家继续加油鸭&#xff01;&#xff01;&#xff01;&#xff01; Vue2 Vu…

记录一次腾讯云服务器部署宝塔

一、查看是否安装 宝塔面板 bt 14 1 已安装会列出宝塔登录地址&#xff1b; 否则-bash: bt: command not found&#xff1b; 下载及安装命令&#xff08;这条是目前最新的宝塔安装命令&#xff09; yum install -y wget && wget -O install.sh http://download.bt.cn/…

关于在Tkinter + Pillow图片叠加中出现的问题

这段时间我一直在尝试对多图层图片进行一个叠加的操作&#xff0c;想用tkinter实现出来&#xff0c;先看错误 这里我其实已经选择了图片&#xff0c;但是发现是ValueError&#xff0c;我尝试断点检测但是也无动于衷&#xff0c;因为设置变量检测的时候发现变量并没有错误&…

粒子群算法求解港口泊位调度问题(MATLAB代码)

粒子群算法&#xff08;Particle Swarm Optimization&#xff0c;PSO&#xff09;是一种基于群体智能的优化算法&#xff0c;它通过模拟鸟群或鱼群的行为来寻找最优解。在泊位调度问题中&#xff0c;目标是最小化所有船只在港时间的总和&#xff0c;而PSO算法可以帮助我们找到一…

腾讯云Linux(OpenCloudOS)安装tomcat9(9.0.85)

腾讯云Linux(OpenCloudOS)安装tomcat9 下载并上传 tomcat官网 https://tomcat.apache.org/download-90.cgi 下载完成后上传至自己想要放置的目录下 解压文件 输入tar -xzvf apache-tomcat-9.0.85.tar.gz解压文件&#xff0c;建议将解压后的文件重新命名为tomcat,方便后期进…

跟着pink老师前端入门教程-day13

品优购案例 一、品优购项目规划 1. 品优购项目整体介绍 项目名称&#xff1a;品优购 项目描述&#xff1a;品优购是一个电商网站&#xff0c;我们要完成 PC 端首页、列表页、注册页面的制作 2. 品优购项目学习目的 1. 电商类网站比较综合&#xff0c;里面需要大量的布…

com.alicp.jetcache.support.CacheEncodeException: Java Encode error 报错解决

目录 一、报错截图&#xff1a;二、报错原因三、解决方式 一、报错截图&#xff1a; Spring boot 整合 JetCache 使用Cached。报错如下&#xff1a; 二、报错原因 带有Cached注解的方法返回值对象没有实现序列化接口&#xff0c;如下图所示 三、解决方式 带有Cached注解的…

【docker】Docker-compose单机容器集群编排

一、Compose的相关知识 1. Compose的相关概念 Compose是单机编排容器集群或者是分布式服务容器的应用工具。通过Compose&#xff0c;可以使用YAML文件来配置应用程序的服务。然后&#xff0c;使用一个命令&#xff0c;就可以从配置中创建并启动所有服务。 Docker-Compose是一…

【AI_Design】Midjourney学习笔记

目录 后缀解析Promot合格使用prompt关键词描述 关键词化合作用关键词网站推荐 联合Chatgpt 后缀解析 –ar&#xff1a;宽高比设置–c&#xff1a;多样性设置&#xff08;数值0-100&#xff0c;默认值0&#xff09;–s&#xff1a;风格化设置&#xff08;数值0-1000&#xff0c…

promethues基础概念

promethues是一个开源的系统监控以及报警系统&#xff0c;整个zabbix的功能&#xff0c;系统&#xff0c;网络&#xff0c;设备 promethues可以兼容网络和设置被&#xff0c;容器监控&#xff0c;告警系统&#xff0c;因为他和k8s是一个项目基金开发的产品&#xff0c;天生匹配…

大专生能不能学习鸿蒙开发?

目前安卓有2,000万的开发者。本科及以上学历占比为35%&#xff1b;iOS有2,400万开发者&#xff0c;本科及以上学历占比为40% 绝大多数的前端开发者都是大专及以下学历&#xff0c;在2023年华为开发者大会上余承东透露华为的开发者目前有200万&#xff0c;但鸿蒙开发者统计的数据…

ARCGIS PRO SDK 数据库属性域设置与获取

一、数据库创建属性域。 sdk3.1 以下的开发版本不支持&#xff0c;不能使用 Pro SDK 向域添加新的编码值&#xff0c;可以使用地理处理工具&#xff1a; 创建属性域 Dim va As IReadOnlyList(Of String) Dim gpResult As ArcGIS.Desktop.Core.Geoprocessing.IGPResult Dim env…

【深度学习:目标检测】深度学习中目标检测模型、用例和示例

【深度学习&#xff1a;目标检测】深度学习中目标检测模型、用例和示例 什么是物体检测&#xff1f;物体检测与图像分类物体检测与图像分割 计算机视觉中的目标检测物体检测的优点物体检测的缺点深度学习和目标检测人员检测 物体检测如何工作&#xff1f;一阶段与两阶段深度学习…

Kotlin快速入门系列6

Kotlin的接口与扩展 接口 与Java类似&#xff0c;Kotlin使用interface关键字定义接口&#xff0c;同时允许方法有默认实现&#xff1a; interface KtInterfaceTest {fun method()fun methodGo(){println("上面方法未实现&#xff0c;此方法已实现")} } 接口实现 …

npm ERR! path E:node_modules\node-sass

分析报错发现有关 python2 环境相关报错 解决办法&#xff1a;需要再电脑中安装python 2.X版本的环境 因为我本地电脑有python 3.9的环境&#xff0c;所以我使用 Anaconda安装python环境 1、安装 python 2.7 conda create -n py2 python2.72、激活虚拟环境 conda activate…