OpenGL原理与实践——核心模式(一):VBO、VAO等原理解析及项目初始设置

news2024/11/15 15:45:21

目录

序言——OpenGL在是什么?为什么?做什么?

OpenGL实现了什么

OpenGL内模型数据的本质——顶点数据 

我们需要研究什么——三角形,一个图形基元

MVP变换

OpenGL渲染流程的关键——摄像机变换

OpenGL渲染管线概览

准备——项目配置

项目初始代码框架及注释

初识——三角形绘制 

OpenGL中的顶点数据格式——float数组

OpenGL中shader如何从CPU中获取数据——layout(锚点)

Shader

VBO:Vertex Buffer Object

VAO:解决锚点问题,记录了VBO的锚点信息

编译shader

设定VAO并进行渲染

整体源码


序言——OpenGL在是什么?为什么?做什么?

OpenGL实现了什么

将三维物体映射到视线方向上的一个裁剪空间(屏幕)上 

OpenGL内模型数据的本质——顶点数据 

我们需要研究什么——三角形,一个图形基元

MVP变换

OpenGL渲染流程的关键——摄像机变换

OpenGL渲染管线概览

准备——项目配置

GLFW

Download | GLFW

GLAD

https://glad.dav1d.de

 下载后,进行相应配置。

项目初始代码框架及注释

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		glfwSetWindowShouldClose(window, true);
	}
}

int main() {
	//初始化OpenGL上下文环境,OpenGL是一个状态机,会保存当前状态下的渲染状态以及管线的状态
	glfwInit(); 
	//,3版本以上
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//用OpenGL核心开发模式
	glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

	//创建窗体
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGl Core", nullptr, nullptr);
	if (window == nullptr) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	//把当前上下文绑定至当前窗口
	glfwMakeContextCurrent(window);

	//通过glad绑定各种函数指针
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//视口:需要渲染的东西在哪里
	glViewport(0, 0, 800, 600);
	//当Frame大小变动,调用回调函数调整视口大小
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	//防止窗口结束退出
	while (!glfwWindowShouldClose(window)) {
		processInput(window);

		//擦除画布,用定义的颜色填充
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		//双缓冲
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	//结束,释放资源
	glfwTerminate();
	return 0;

}

运行结果如下:

初识——三角形绘制 

OpenGL中的顶点数据格式——float数组

看向-Z方向

OpenGL中shader如何从CPU中获取数据——layout(锚点)

  • CPU将float顶点数据数组传入GPU
  • CPU告诉GPU如何解析这个数组
  • 调用渲染指令进行绘制

GPU显存中的布局:layout;可以理解为“锚点”,指明在这一锚点代表的区域,存放了什么样的数据。

Shader

直白来说,Shader就是跑在GPU上的一种语言,用来操作GPU。

我们先写好两个shader的内容,先大致了解一番:

vertexShader:

#version 330 core

//在layout=0,这块区域放置了一个vec3
layout (location = 0 ) in vec3 aPos;

//操作
void main()
{
	gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
}
  • vertexShader中的数据gl_Position,会自动流入下一个阶段中,也就是fragmentShader 
  • vertexShader会被调用多少次?有多少顶点就会调用多少次

 fragmentShader:

#version 330 core
out vec4 FragColor;
void main(){
	FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}
  • fragmentShader的目的是为了输出一个数据,这里是vec4 FragColor,被定义为out类型,会被输出到下一个管线流程中。
  • fragmentShader会被调用多少次?简单来说有多少像素就会调用多少次

流程:

  • 将顶点数据转入到vertexShader,进行空间变换等操作(注意是并行的
  • 数据从vertexShader传入到fragmentShader,进行像素插值等操作(处理一堆像素点)

VBO:Vertex Buffer Object

在上面那个图中,其中的“GPU shader”就是所谓的VBO,也就是我们开辟的一块区域。

在开辟的这块空间,存储顶点数据。

那么在OpenGL中如何做这件事?

  • 获取VBO的index(由OpenGL状态机分配的index
  • 绑定VBO的index
  • 给VBO分配显存空间,并传输数据
  • 告诉shader数据的解析方式
  • 激活锚点,按照解析方式取读取数据

具体代码如下,我们在mian.cpp中添加如下函数:

//构建模型数据:VBO,
void initModel() {
	float vertices[] = {
		-0.5f, -0.5f, 0.0f,
		0.5f, -0.5f, 0.0f,
		0.0f, 0.5f, 0.0f
	};

	glGenBuffers(1, &VBO);
	//绑定哪一种buffer, 
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//分配显存:分配哪种buffer,分配显存大小,分配地址,使用数据的方式
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	//打开锚点:激活
	glEnableVertexAttribArray(0);

	//解绑
	glBindBuffer(GL_ARRAY_BUFFER, 0);
}

每个函数的作用和参数意义,这里我用注释详细标明。方便后时查阅复习。

VAO:解决锚点问题,记录了VBO的锚点信息

编译shader

VAO是与shader密切相关的一个内容,所以在此之前需要进行shader的一系列操作:

首先声明一个全局变量:

unsigned int shaderProgram = 0;

初始化Shader,并进行编译链接。 

void initShader(const char* _vertexPath, const char* _fragPath) {
	//shader的代码读取
	std::string _vertexCode("");
	std::string _fragCode("");

	std::ifstream _vShaderFile;
	std::ifstream _fShaderFile;

	_vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	_fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try {
		_vShaderFile.open(_vertexPath);
		_fShaderFile.open(_fragPath);

		std::stringstream _vShaderStream, _fShaderStream;
		_vShaderStream << _vShaderFile.rdbuf();
		_fShaderStream << _fShaderFile.rdbuf();

		_vertexCode = _vShaderStream.str();
		_fragCode = _fShaderStream.str();
	}
	catch(std::ifstream::failure e) {
		std::string errStr = "read shader fail";
		std::cout << errStr << ": " << e.what() << std::endl;
	}

	const char* _vShaderStr = _vertexCode.c_str();
	const char* _fShaderStr = _fragCode.c_str();

	//shader的编译链接
	unsigned int _vertexID = 0, _fragID = 0;
	char _infoLog[512];
	int _successFlag = 0;

	//编译

	_vertexID = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(_vertexID, 1, &_vShaderStr, nullptr);
	glCompileShader(_vertexID);

	//捕捉编译过程中的状态信息
	glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(_vertexID, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	_fragID = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(_fragID, 1, &_vShaderStr, nullptr);
	glCompileShader(_fragID);

	//捕捉编译过程中的状态信息
	glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(_fragID, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	//链接
	//创建一个程序
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, _vertexID);
	glAttachShader(shaderProgram, _fragID);
	glLinkProgram(shaderProgram);

	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(shaderProgram, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	//删除中间文件
	glDeleteShader(_vertexID);
	glDeleteShader(_fragID);

}

设定VAO并进行渲染

//构建模型数据:VBO,VAO
void initModel() {
	float vertices[] = {
		-0.5f, -0.5f, 0.0f,
		0.5f, -0.5f, 0.0f,
		0.0f, 0.5f, 0.0f
	};

	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	//之后的VBO便属于了VAO的管理范围
	glGenBuffers(1, &VBO);
	//绑定哪一种buffer, 
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//分配显存:分配哪种buffer,分配显存大小,分配地址,使用数据的方式
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	//打开锚点:激活
	glEnableVertexAttribArray(0);

	//解绑
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

}
//渲染
void render() {
	glBindVertexArray(VAO);
	glUseProgram(shaderProgram);
	//以三角形模式绘制,从第0个顶点开始,起作用的有3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glUseProgram(0);
}

渲染结果:

 

整体源码

main.cpp

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>


void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow* window);
void initModel();
void initShader(const char* _vertexPath, const char* _fragPath);
void render();

unsigned int VBO = 0;
unsigned int VAO = 0;
unsigned int shaderProgram = 0;

int main() {
	//初始化OpenGL上下文环境,OpenGL是一个状态机,会保存当前状态下的渲染状态以及管线的状态
	glfwInit(); 
	//,3版本以上
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	//用OpenGL核心开发模式
	glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

	//创建窗体
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGl Core", nullptr, nullptr);
	if (window == nullptr) {
		std::cout << "Failed to create GLFW window" << std::endl;
		glfwTerminate();
		return -1;
	}
	//把当前上下文绑定至当前窗口
	glfwMakeContextCurrent(window);

	//通过glad绑定各种函数指针
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		std::cout << "Failed to initialize GLAD" << std::endl;
		return -1;
	}

	//视口:需要渲染的东西在哪里
	glViewport(0, 0, 800, 600);
	//当Frame大小变动,调用回调函数调整视口大小
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	initModel();
	initShader("vertexShader.glsl", "fragmentShader.glsl");

	//防止窗口结束退出
	while (!glfwWindowShouldClose(window)) {
		processInput(window);

		//擦除画布,用定义的颜色填充
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		render();

		//双缓冲
		glfwSwapBuffers(window);
		glfwPollEvents();
	}

	//结束,释放资源
	glfwTerminate();
	return 0;

}

void framebuffer_size_callback(GLFWwindow* window, int width, int height) {
	glViewport(0, 0, width, height);
}

void processInput(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) {
		glfwSetWindowShouldClose(window, true);
	}
}

//渲染
void render() {
	glBindVertexArray(VAO);
	glUseProgram(shaderProgram);
	//以三角形模式绘制,从第0个顶点开始,起作用的有3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glUseProgram(0);
}

//构建模型数据:VBO,VAO
void initModel() {
	float vertices[] = {
		-0.5f, -0.5f, 0.0f,
		0.5f, -0.5f, 0.0f,
		0.0f, 0.5f, 0.0f
	};

	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);

	//之后的VBO便属于了VAO的管理范围
	glGenBuffers(1, &VBO);
	//绑定哪一种buffer, 
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//分配显存:分配哪种buffer,分配显存大小,分配地址,使用数据的方式
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	//对哪个锚点进行操作:layout=0的锚点,读3个顶点,类型为float,不需要归一化,每次步长为3个float大小,从0处开始读
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	//打开锚点:激活
	glEnableVertexAttribArray(0);

	//解绑
	//glBindBuffer(GL_ARRAY_BUFFER, 0);
	glBindVertexArray(0);

}

//
void initShader(const char* _vertexPath, const char* _fragPath) {
	//shader的代码读取
	std::string _vertexCode("");
	std::string _fragCode("");

	std::ifstream _vShaderFile;
	std::ifstream _fShaderFile;

	_vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
	_fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);

	try {
		_vShaderFile.open(_vertexPath);
		_fShaderFile.open(_fragPath);

		std::stringstream _vShaderStream, _fShaderStream;
		_vShaderStream << _vShaderFile.rdbuf();
		_fShaderStream << _fShaderFile.rdbuf();

		_vShaderFile.close();
		_fShaderFile.close();

		_vertexCode = _vShaderStream.str();
		_fragCode = _fShaderStream.str();
	}
	catch(std::ifstream::failure e) {
		std::string errStr = "read shader fail";
		std::cout << errStr << ": " << e.what() << std::endl;
	}

	const char* _vShaderStr = _vertexCode.c_str();
	const char* _fShaderStr = _fragCode.c_str();

	//shader的编译链接
	unsigned int _vertexID = 0, _fragID = 0;
	char _infoLog[512];
	int _successFlag = 0;

	//编译
	_vertexID = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(_vertexID, 1, &_vShaderStr, nullptr);
	glCompileShader(_vertexID);

	//捕捉编译过程中的状态信息
	glGetShaderiv(_vertexID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(_vertexID, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	_fragID = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(_fragID, 1, &_fShaderStr, nullptr);
	glCompileShader(_fragID);

	//捕捉编译过程中的状态信息
	glGetShaderiv(_fragID, GL_COMPILE_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(_fragID, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	//链接
	//创建一个程序
	shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, _vertexID);
	glAttachShader(shaderProgram, _fragID);
	glLinkProgram(shaderProgram);

	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &_successFlag);
	if (!_successFlag) {
		glGetShaderInfoLog(shaderProgram, 512, nullptr, _infoLog);
		std::string errStr(_infoLog);
		std::cout << errStr << std::endl;
	}

	//删除中间文件
	glDeleteShader(_vertexID);
	glDeleteShader(_fragID);

}

vertexShader.glsl 

#version 330 core
layout (location = 0) in vec3 aPos;
void main()
{
   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
};

fragmentShader.glsl 

#version 330 core
out vec4 FragColor;
void main()
{
    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);
};

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

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

相关文章

dpdk结合sriov测试vpp ipsec性能

目的 测试vpp ipsec转发性能&#xff0c;想当作openstack VPNaas的一种driver&#xff0c;提高ipsec网关的转发能力。 环境 测试资源很有限&#xff0c;没有测试仪&#xff0c;物理机之外的交换机不受控制。 只有两台物理机&#xff0c;各有一张测试网卡&#xff0c;网卡有…

分布式存储之 etcd 的集群管理

在分布式文件存储中&#xff0c;我们通常会面临集群选主&#xff0c;配置共享和节点状态监控的问题。通过 etcd&#xff08;基于 Raft 协议)&#xff09;可以实现超大规模集群的管理&#xff0c;以及多节点的服务可靠性。今天&#xff0c;我们就聊聊 etcd 在分布式存储中的具体…

作业-11.24

1、多线程并发服务器 #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <string.h> #include <pthread.h> #include <stdlib.h> #include <…

MCE | 间歇性禁食增强抗癌疗效

越来越多的研究表明&#xff0c;“禁食”不仅与免疫系统调控 、血糖调节有关&#xff0c;还对多种疾病的治疗有改善效果&#xff0c;如心血管疾病和癌症等。这里的“禁食”与节食不同&#xff0c;一般指的是间歇性禁食&#xff0c;包括多种方案&#xff0c;例如 FMD (Fasting-m…

LeetCode135. 分发糖果(贪心算法)

1 题目描述 n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。 你需要按照以下要求&#xff0c;给这些孩子分发糖果&#xff1a; 每个孩子至少分配到 1 个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。 请你给每个孩子分发糖果&#xff0c;计算并返回…

pyinstaller打包教程(pycharm)

PyInstaller简介 PyInstaller是一个跨平台的Python应用打包工具&#xff0c;支持 Windows/Linux/MacOS三大主流平台&#xff0c;能够把 Python 脚本及其所在的 Python 解释器打包成可执行文件&#xff0c;从而允许最终用户在无需安装 Python 的情况下执行应用程序。 PyInstalle…

IOS安全测试学习-DVIA-v2

前言 为学习IOS知识并加深理解&#xff0c;故通过IOS漏洞靶场来直接体现IOS环境中的常见漏洞。 环境准备 iPhone X ios 13.4.1 已越狱 MacOS Big Sur 11.0 Bate 虚拟机 DVIA-v2 IOS 漏洞靶场app grapefruit、objection #pip3 install frida、pip3 install frida-tools、sudo …

【App自动化测试】(五)移动端自动化常用的元素定位工具——Uiautomatorviewer、 ATX WEditor、Appium Inspector

目录1. uiautomatorviewer1.1 uiautomatorviewer 的安装1.2 uiautomatorviewer 工具功能介绍1.3 uiautomatorviewer 的使用方法2. ATX WEditor2.1 ATX WEditor的安装2.2 ATX WEditor 功能介绍2.3 ATX WEditor 的使用3. Appium Inspector3.1 Appium Inspector安装与运行3.2 Appi…

【AWS系列】第八讲:AWS Serverless之S3

目录 序言 1.基础介绍 1.1 概念介绍 1.2 原理介绍 1.3 应用场景 1.3.1 构建数据湖 1.3.2 备份和还原关键数据 1.3.3 以最低成本存档数据 1.3.4 运行云原生应用程序 1.4 S3 的功能 1.4.1 存储类 1.4.2 存储管理 1.4.3 访问管理 2 使用方法 2.1 创建存储桶 ​2.2…

用DIV+CSS技术设计的网页与实现制作【体育文化】dreamweaver学生网页设计

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

day074:XML、XML的解析

目录 一、XML 1.什么是XML 2.XML作用 3.XML语法规则 4.XML文件代码示例 二、解析XML文件 1.解析XML 2.常用的解析思想 &#xff08;1&#xff09;DOM思想 &#xff08;2&#xff09;图解 3.XML解析工具 一、XML 1.什么是XML XML&#xff08;EXtensible Markup Lan…

【已解决】CentOS7等linux系统时区时间不对显示误差8小时

文章目录问题解决处理时区问题date查看时间、时区timedatectl查看时间、时区查看localtime设置时区处理时间问题问题 中国使用的是东八区上海时间&#xff0c;而linux服务器&#xff0c;一般默认是0时区UTC&#xff0c;所以需要将时区改为东八区CST将时区改为东八区后&#xf…

机器学习-决策树算法

机器学习-基础知识 机器学习-线性回归 机器学习-逻辑回归 机器学习-聚类算法 机器学习-决策树算法 机器学习-集成算法 机器学习-SVM算法 文章目录1. 决策树算法1.1. 什么是决策树/判定树1.2. 决策树归纳算法1.3. 熵概念1.4. 具体算法1.5. 决策树剪枝1.6. 连续值与缺失值处理1.6…

MCE | 正确认识阿尔茨海默病

什么是阿尔茨海默病 (Alzheimer Disease, AD)&#xff1f; 1907 年德国神经病理学家阿尔茨海默 (Alois Alzheimer) 仔细描述了一名具有进行性痴呆表现的 51 岁妇女 (Auguste Deter) 的症状&#xff1a; “她的记忆力严重受损。如果向她显示了对象&#xff0c;她会正确地命名它…

还在调API写所谓的AI“女友”,唠了唠了,教你基于python咱们“new”一个(深度学习)

文章目录前言停用词闲聊语料基础知识词的表示表达one-hot编码词嵌入大致原理实现简单版复杂版如何训练转换后的形状RNN循环网络RNNRNN投影图RNN是三维立体的LSTM&GRU构建数据配置数据集准备分词划分数据集加载模型搭建基本概念Encoder搭建DecoderAttention机制decoder与bea…

赫夫曼树赫夫曼编码的创建

目录基础知识点最优二叉树如何构造赫夫曼树赫夫曼编码编码与压缩文件代码结构体设计创建赫夫曼树创建构建赫夫曼编码基础知识点 赫夫曼树又称为最优树&#xff0c;是一种带权路径长短最短的树&#xff0c;有着广泛的应用。 最优二叉树 我们给出路径和路径长度的概念。从树的…

盘点面试常见的设计类算法问题

设计问题也是一种很重要的考察类型&#xff0c;特征是整体难度不大&#xff0c;但是要求结构合理、复用性好、考虑周全&#xff0c;代码规范等等。有些面试官不喜欢烧脑的动态规划等问题&#xff0c;就喜欢设计题&#xff0c;笔者曾经在面试微博和猿辅导都遇到过类似的问题。这…

【操作系统】2.1 进程与线程总结

2.1.1 操作系统之进程的定义、特征、组成、组织 2.1.1 操作系统之进程的定义、特征、组成、组织_StudyWinter的博客-CSDN博客 进程由程序段、数据段、进程控制块&#xff08;PCB&#xff09;三部分组成。 进程是进程实体的运行过程&#xff0c;是系统进行资源分配和资源调度的…

隆化的大米排之首 国稻种芯·中国水稻节:河北承德十大特产

隆化的大米排之首 国稻种芯中国水稻节&#xff1a;河北承德十大特产 中新网河北新闻10月8日电 (张桂芹 王思明) 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 中国农民丰收节国际贸易促进会 国稻种芯中国水稻节 中国三农智库网-功能性农业农业大健康大会报道&#xf…

python基础项目实战-俄罗斯方块

一、俄罗斯方块游戏设计分析: 俄罗斯方块是一款风靡全球,从一开始到现在都一直经久不衰的电脑、手机、掌上游戏机产品,是一款游戏规则简单,但又不缺乏乐趣的简单经典小游戏,上手容易,适用范围广泛,人所共知。俄罗斯方块游戏基本规则是油4个小方块组成的7种不同的规则图形…