(十三)MipMap

MipMap概念

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

滤波

在这里插入图片描述

采样

在这里插入图片描述
在这里插入图片描述

mipmap级别判定

问题:opengl如何判定应该使用下一级的mipmap呢?
通过glsl中的求偏导函数计算变化量决定
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

手动实现mipmap原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
1、生成mipmap的各个级别
2、修改vertexShader使得三角形随着时间变小
**** 需要更改Filter才能够在变小的时候使用mipmap *****

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}GLuint program = 0;
GLuint vao = 0;
void prepareVAO()
{//positionsfloat positions[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f,  0.5f, 0.0f,};//颜色float colors[] = {1.0f, 0.0f,0.0f,0.0f, 1.0f,0.0f,0.0f, 0.0f,1.0f,};//索引unsigned int indices[] = {0, 1, 2,};//uv坐标float uvs[] = {0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f,};//2 VBO创建GLuint posVbo = 0;GLuint colorVbo = 0;GLuint uvVbo = 0;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &colorVbo);glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO创建GLuint ebo = 0;glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO创建vao = 0;glGenVertexArrays(1, &vao);glBindVertexArray(vao);//5 绑定vbo ebo 加入属性描述信息//5.1 加入位置属性描述信息glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.2 加入颜色属性描述信息glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.3 加入uv属性描述数据glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);//5.2 加入ebo到当前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBindVertexArray(0);
}
void prepareShader() {//1 完成vs与fs的源代码,并且装入字符串const char* vertexShaderSource ="#version 330 core\n""layout (location = 0) in vec3 aPos;\n""layout (location = 1) in vec3 aColor;\n""layout (location = 2) in vec2 aUV;\n""out vec3 color;\n""out vec2 uv;\n""uniform float time;\n""void main()\n""{\n""   float scale = 1.0/time;\n""   vec3 sPos = aPos * scale;\n""   gl_Position = vec4(sPos, 1.0);\n""   color = aColor;\n""   uv = aUV;\n""}\0";const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""in vec3 color;\n""in vec2 uv;\n""uniform sampler2D sampler;\n""void main()\n""{\n""  FragColor = texture(sampler, uv);\n""}\n\0";//2 创建Shader程序(vs、fs)GLuint vertex, fragment;vertex = glCreateShader(GL_VERTEX_SHADER);fragment = glCreateShader(GL_FRAGMENT_SHADER);//3 为shader程序输入shader代码glShaderSource(vertex, 1, &vertexShaderSource, NULL);glShaderSource(fragment, 1, &fragmentShaderSource, NULL);int success = 0;char infoLog[1024];//4 执行shader代码编译 glCompileShader(vertex);//检查vertex编译结果glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;}glCompileShader(fragment);//检查fragment编译结果glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;}//5 创建一个Program壳子program = glCreateProgram();//6 将vs与fs编译好的结果放到program这个壳子里glAttachShader(program, vertex);glAttachShader(program, fragment);//7 执行program的链接操作,形成最终可执行shader程序glLinkProgram(program);//检查链接错误glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(program, 1024, NULL, infoLog);std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;}//清理glDeleteShader(vertex);glDeleteShader(fragment);
}
GLuint genTexture(const char* picPath, int unitTexturt)
{//1 stbImage 读取图片int width, height, channels;//--反转y轴stbi_set_flip_vertically_on_load(true);unsigned char* data = stbi_load(picPath, &width, &height, &channels, STBI_rgb_alpha);//2 生成纹理并且激活单元绑定GLuint texture = 0;glGenTextures(1, &texture);//--激活纹理单元--glActiveTexture(GL_TEXTURE0 + unitTexturt);//--绑定纹理对象--glBindTexture(GL_TEXTURE_2D, texture);int tmepWidth = width, tempHeight = height;//3 传输纹理数据,开辟显存//glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//遍历每个mipmap的层级,为每个级别的mipmap填充图片数据for (int level = 0; true; ++level){//1 将当前级别的mipmap对应的数据发往gpu端glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, tmepWidth, tempHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//2 判断是否退出循环if (tmepWidth == 1 && tempHeight == 1)break;//3 计算下一次循环的宽度/高度,除以2tmepWidth = tmepWidth > 1 ? tmepWidth / 2 : 1;tempHeight = tempHeight > 1 ? tempHeight / 2 : 1;}//***释放数据stbi_image_free(data);//4 设置纹理的过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//*****重要*****////GL_NEAREST:在单个mipmap上采用最邻近采样//GL_LINEAR   //MIPMAP_LINEAR:在两层mipmap之间采用线性插值//MIPMAP_NEARESTglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);//5 设置纹理的包裹方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//uglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//vreturn texture;
}
void prepareTextrue()
{//GLuint grassTexture = genTexture("grass.jpg", 0);//GLuint landTexture = genTexture("land.jpg", 1);//GLuint noiseTexture = genTexture("noise.jpg", 2);GLuint wallTexture = genTexture("goku.jpg", 0);
}void render()
{//执行opengl画布清理操作glClear(GL_COLOR_BUFFER_BIT);//1.绑定当前的programglUseProgram(program);//2 更新Uniform的时候,一定要先UserProgram//2.1 通过名称拿到Uniform变量的位置Location//2.2 通过Location更新Uniform变量的值GLint time = glGetUniformLocation(program, "time");int i = glfwGetTime();glUniform1f(time, glfwGetTime());GLint sampler = glGetUniformLocation(program, "sampler");glUniform1i(sampler, 0);//3 绑定当前的vaoglBindVertexArray(vao);//4 发出绘制指令//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}int main()
{//初始化glfw环境glfwInit();//设置opengl主版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//设置opengl次版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置opengl启用核心模式glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//创建窗体对象GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);//设置当前窗体对象为opengl的绘制舞台glfwMakeContextCurrent(window);//窗体大小回调glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);//键盘相应回调glfwSetKeyCallback(window, glfwKeyCallback);//使用glad加载所有当前版本opengl的函数if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "初始化glad失败" << std::endl;return -1;};//设置opengl视口大小和清理颜色glViewport(0, 0, 800, 600);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//shaderprepareShader();//vaoprepareVAO();//textureprepareTextrue();//执行窗体循环while (!glfwWindowShouldClose(window)){//接受并分发窗体消息//检查消息队列是否有需要处理的鼠标、键盘等消息//如果有的话就将消息批量处理,清空队列glfwPollEvents();//渲染操作render();//切换双缓存glfwSwapBuffers(window);}//推出程序前做相关清理glfwTerminate();return 0;
}

上述代码即可实现随着时间的变化,不同层级的图片贴到三角形中的效果。
还可以不在代码中设置层级间的采样方式 即注释掉

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);

在fs中,实现根据像素对应图素的数量多少,决定采样哪个层级的mipmap

#version 330 core
out vec4 FragColor;
in vec3 color;
in vec2 uv;
uniform sampler2D sampler;
uniform float width;
uniform float height;
void main()
{//FragColor = texture(sampler, uv);//1 获取当前像素对应的纹理上的纹素具体位置vec2 location = uv * vec2(width, height);//2 计算当前像素对应纹素具体位置在xy方向上的变化量vec2 dx = dFdx(location);vec2 dy = dFdy(location);//3 选择最大的delta,求log2(delta)float maxDelta = sqrt(max(dot(dx, dx), dot(dy,dy)));float L = log2(maxDelta);//4 计算出mipmap的采样级别int level = max(int(L + 0.5), 0);FragColor = textureLod(sampler, uv, level);
}

fs的glsl设置以上字符串,渲染时设置图片的宽度和高度即可达到同样的效果。

opengl自动生成mipmap

在这里插入图片描述

#include <glad/glad.h>//glad必须在glfw头文件之前包含
#include <GLFW/glfw3.h>
#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
void frameBufferSizeCallbakc(GLFWwindow* window, int width, int height)
{glViewport(0, 0, width, height);
}
void glfwKeyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
}GLuint program = 0;
GLuint vao = 0;
void prepareVAO()
{//positionsfloat positions[] = {-0.5f, -0.5f, 0.0f,0.5f, -0.5f, 0.0f,0.0f,  0.5f, 0.0f,};//颜色float colors[] = {1.0f, 0.0f,0.0f,0.0f, 1.0f,0.0f,0.0f, 0.0f,1.0f,};//索引unsigned int indices[] = {0, 1, 2,};//uv坐标float uvs[] = {0.0f, 0.0f,1.0f, 0.0f,0.5f, 1.0f,};//2 VBO创建GLuint posVbo = 0;GLuint colorVbo = 0;GLuint uvVbo = 0;glGenBuffers(1, &posVbo);glBindBuffer(GL_ARRAY_BUFFER, posVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(positions), positions, GL_STATIC_DRAW);glGenBuffers(1, &colorVbo);glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW);glGenBuffers(1, &uvVbo);glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glBufferData(GL_ARRAY_BUFFER, sizeof(uvs), uvs, GL_STATIC_DRAW);//3 EBO创建GLuint ebo = 0;glGenBuffers(1, &ebo);glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);//4 VAO创建vao = 0;glGenVertexArrays(1, &vao);glBindVertexArray(vao);//5 绑定vbo ebo 加入属性描述信息//5.1 加入位置属性描述信息glBindBuffer(GL_ARRAY_BUFFER, posVbo);glEnableVertexAttribArray(0);glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.2 加入颜色属性描述信息glBindBuffer(GL_ARRAY_BUFFER, colorVbo);glEnableVertexAttribArray(1);glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);//5.3 加入uv属性描述数据glBindBuffer(GL_ARRAY_BUFFER, uvVbo);glEnableVertexAttribArray(2);glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0);//5.2 加入ebo到当前的vaoglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);glBindVertexArray(0);
}
void prepareShader() {//1 完成vs与fs的源代码,并且装入字符串const char* vertexShaderSource ="#version 330 core\n""layout (location = 0) in vec3 aPos;\n""layout (location = 1) in vec3 aColor;\n""layout (location = 2) in vec2 aUV;\n""out vec3 color;\n""out vec2 uv;\n""uniform float time;\n""void main()\n""{\n""   float scale = 1.0/time;\n""   vec3 sPos = aPos * scale;\n""   gl_Position = vec4(sPos, 1.0);\n""   color = aColor;\n""   uv = aUV;\n""}\0";const char* fragmentShaderSource ="#version 330 core\n""out vec4 FragColor;\n""in vec3 color;\n""in vec2 uv;\n""uniform sampler2D sampler;\n""void main()\n""{\n""  FragColor = texture(sampler, uv);\n""}\n\0";//2 创建Shader程序(vs、fs)GLuint vertex, fragment;vertex = glCreateShader(GL_VERTEX_SHADER);fragment = glCreateShader(GL_FRAGMENT_SHADER);//3 为shader程序输入shader代码glShaderSource(vertex, 1, &vertexShaderSource, NULL);glShaderSource(fragment, 1, &fragmentShaderSource, NULL);int success = 0;char infoLog[1024];//4 执行shader代码编译 glCompileShader(vertex);//检查vertex编译结果glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(vertex, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --VERTEX" << "\n" << infoLog << std::endl;}glCompileShader(fragment);//检查fragment编译结果glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);if (!success) {glGetShaderInfoLog(fragment, 1024, NULL, infoLog);std::cout << "Error: SHADER COMPILE ERROR --FRAGMENT" << "\n" << infoLog << std::endl;}//5 创建一个Program壳子program = glCreateProgram();//6 将vs与fs编译好的结果放到program这个壳子里glAttachShader(program, vertex);glAttachShader(program, fragment);//7 执行program的链接操作,形成最终可执行shader程序glLinkProgram(program);//检查链接错误glGetProgramiv(program, GL_LINK_STATUS, &success);if (!success) {glGetProgramInfoLog(program, 1024, NULL, infoLog);std::cout << "Error: SHADER LINK ERROR " << "\n" << infoLog << std::endl;}//清理glDeleteShader(vertex);glDeleteShader(fragment);
}
GLuint genTexture(const char* picPath, int unitTexturt)
{//1 stbImage 读取图片int width, height, channels;//--反转y轴stbi_set_flip_vertically_on_load(true);unsigned char* data = stbi_load(picPath, &width, &height, &channels, STBI_rgb_alpha);//2 生成纹理并且激活单元绑定GLuint texture = 0;glGenTextures(1, &texture);//--激活纹理单元--glActiveTexture(GL_TEXTURE0 + unitTexturt);//--绑定纹理对象--glBindTexture(GL_TEXTURE_2D, texture);//3 传输纹理数据,开辟显存glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);//为当前纹理对象生成mipmapglGenerateMipmap(GL_TEXTURE_2D);//***释放数据stbi_image_free(data);//4 设置纹理的过滤方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//*****重要*****////GL_NEAREST:在单个mipmap上采用最邻近采样//GL_LINEAR   //MIPMAP_LINEAR:在两层mipmap之间采用线性插值//MIPMAP_NEARESTglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);//5 设置纹理的包裹方式glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);//uglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);//vreturn texture;
}
void prepareTextrue()
{//GLuint grassTexture = genTexture("grass.jpg", 0);//GLuint landTexture = genTexture("land.jpg", 1);//GLuint noiseTexture = genTexture("noise.jpg", 2);GLuint wallTexture = genTexture("goku.jpg", 0);
}void render()
{//执行opengl画布清理操作glClear(GL_COLOR_BUFFER_BIT);//1.绑定当前的programglUseProgram(program);//2 更新Uniform的时候,一定要先UserProgram//2.1 通过名称拿到Uniform变量的位置Location//2.2 通过Location更新Uniform变量的值GLint time = glGetUniformLocation(program, "time");int i = glfwGetTime();glUniform1f(time, glfwGetTime());GLint sampler = glGetUniformLocation(program, "sampler");glUniform1i(sampler, 0);//3 绑定当前的vaoglBindVertexArray(vao);//4 发出绘制指令//glDrawArrays(GL_TRIANGLE_STRIP, 0, 6);glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_INT, 0);
}int main()
{//初始化glfw环境glfwInit();//设置opengl主版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//设置opengl次版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置opengl启用核心模式glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//创建窗体对象GLFWwindow* window = glfwCreateWindow(800, 600, "lenarnOpenGL", nullptr, nullptr);//设置当前窗体对象为opengl的绘制舞台glfwMakeContextCurrent(window);//窗体大小回调glfwSetFramebufferSizeCallback(window, frameBufferSizeCallbakc);//键盘相应回调glfwSetKeyCallback(window, glfwKeyCallback);//使用glad加载所有当前版本opengl的函数if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)){std::cout << "初始化glad失败" << std::endl;return -1;};//设置opengl视口大小和清理颜色glViewport(0, 0, 800, 600);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//shaderprepareShader();//vaoprepareVAO();//textureprepareTextrue();//执行窗体循环while (!glfwWindowShouldClose(window)){//接受并分发窗体消息//检查消息队列是否有需要处理的鼠标、键盘等消息//如果有的话就将消息批量处理,清空队列glfwPollEvents();//渲染操作render();//切换双缓存glfwSwapBuffers(window);}//推出程序前做相关清理glfwTerminate();return 0;
}

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

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

相关文章

事务底层与高可用原理

1.事务底层与高可用原理 事务的基础知识 mysql的事务分为显式事务和隐式事务 默认的事务是隐式事务 显式事务由我们自己控制事务的开启&#xff0c;提交&#xff0c;回滚等操作 show variables like autocommit; 事务基本语法 事务开始 1、begin 2、START TRANSACTION&…

透过 Go 语言探索 Linux 网络通信的本质

大家好&#xff0c;我是码农先森。 前言 各种编程语言百花齐放、百家争鸣&#xff0c;但是 “万变不离其中”。对于网络通信而言&#xff0c;每一种编程语言的实现方式都不一样&#xff1b;但其实&#xff0c;调用的底层逻辑都是一样的。linux 系统底层向上提供了统一的 Sock…

三菱PLC标签使用(I/O的映射)与内容

今天&#xff0c;小编继续开始三菱PLC的学习&#xff0c;今天的内容是标签及其标签的内容说明&#xff0c;如果对你有帮助&#xff0c;欢迎评论收藏。 标签的种类&#xff0c;等级&#xff0c;定义 种类 三菱3U的PLC的种类分别为二种&#xff1a;全局标签与局部标签 全局标签…

操作审计(一)

操作审计&#xff08;一&#xff09; 前言一、快速查询事件二、高级查询事件总结 前言 这里主要记录操作审计的过程&#xff0c;操作审计其实就是监控并记录阿里云账号的活动&#xff0c;可以使用阿里云的操作审计服务来审计最近90天阿里云账号下的操作&#xff0c;从而确保云…

Java AI 编程助手

Java AI 编程助手是指利用人工智能技术来增强和优化Java开发过程中的各种任务和活动。它可以涵盖从代码生成和分析到测试和优化的多个方面&#xff0c;帮助开发人员提高生产效率、降低错误率&#xff0c;并优化代码质量和性能。 ### 功能和特点 1. **智能代码生成和建议**&am…

如何在 SCSS 中实现复杂的嵌套选择器并确保代码的可维护性?

在 SCSS 中实现复杂的嵌套选择器时&#xff0c;可以遵循以下几个原则以确保代码的可维护性&#xff1a; 限制嵌套层级&#xff1a;避免层级过深的嵌套&#xff0c;最好不要超过三级。过多的嵌套会增加代码的复杂性和选择器的特异性&#xff0c;降低代码的可读性和维护性。 使用…

等保2.0是否强制要求所有物联网设备都必须支持自动更新?

等保2.0对物联网设备自动更新的要求 等保2.0&#xff08;网络安全等级保护2.0&#xff09;是中国政府为了加强网络安全而推出的一套标准和要求。在物联网设备的安全管理方面&#xff0c;等保2.0确实提出了一系列措施&#xff0c;以确保设备的软件安全更新。这些措施包括&#…

RKNN3588——YOLOv8的PT模型转RKNN模型

一&#xff1a;PT转ONNX 1. 首先克隆rknn修改后的ultralytics版本项目到本地 https://github.com/airockchip/ultralytics_yolov8 cd ultralytics-main pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple pip install -e . 主要是修改了源码的ul…

如何使用find查找命令

Linux查找命令是类Unix操作系统中最重要且最常用的命令行实用程序之一。查找命令可以根据你设定的参数匹配的文件指定的条件来搜索和查找文件或目录的列表。 查找可以在多种条件下使用&#xff0c;例如可以按权限&#xff0c;用户&#xff0c;组&#xff0c;文件类型&#xff…

JAVA声明数组

一、声明并初始化数组 直接初始化&#xff1a;在声明数组的同时为其分配空间并初始化元素。 int[] numbers {1, 2, 3, 4, 5}; 动态初始化&#xff1a;先声明数组&#xff0c;再为每个元素分配初始值。 double[] decimals;decimals new double[5]; // 分配空间&#xff0c;但…

PhpStorm 2024 for Mac PHP集成开发工具

Mac分享吧 文章目录 效果一、下载软件二、开始安装1、双击运行软件&#xff08;适合自己的M芯片版或Intel芯片版&#xff09;&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕2、应用程序显示软件图标&#xff0c;表示安装成功3、打开访达&#xff0c;点击【文…

锁之Syncronized(java面经)

在Java中&#xff0c;锁机制是用于管理多线程环境下的资源访问&#xff0c;以确保数据的一致性和完整性。Java提供了多种锁的实现方式&#xff0c;包括但不限于&#xff1a; 锁从宏观上分类&#xff0c;分为悲观锁与乐观锁。 乐观锁: 即读多写少 , 并发的可能性小 , 一般只有…

大数据面试题之Flink(1)

目录 Flink架构 Flink的窗口了解哪些&#xff0c;都有什么区别&#xff0c;有哪几种?如何定义? Flink窗口函数&#xff0c;时间语义相关的问题 介绍下Flink的watermark(水位线)&#xff0c;watermark需要实现哪个实现类&#xff0c;在何处定义?有什么作用? Flink的…

如何在TikTok上获得更多观看量:12个流量秘诀

TikTok作为热门海外社媒&#xff0c;在跨境出海行业中成为新兴的推广渠道&#xff0c;但你知道如何让你的TikTok赢得更多关注次数吗&#xff1f;如果您正在寻找增加 TikTok 观看次数的方法&#xff0c;接下来这12种策略&#xff0c;你需要一一做好&#xff01; 1. 在内容中添加…

HQ-SAM

不建议复现

鸿蒙开发设备管理:【@ohos.update (升级)】

升级 说明&#xff1a; 本模块首批接口从API version 6开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 升级范围&…

argparse大坑之parser

parser.add_argument(--rate,help"--rate 0.5 means that there is a 50% probability;",typefloat,default0.5)此时用-h输出usage会报错如下&#xff1a; 最后发现是因为parser的help里面出现了%&#xff0c;改了之后就好了。真坑啊&#xff01;

[AI Kimi] Context Caching 正式公测,推动长文本模型降本 90%

Kimi 的上下文缓存&#xff08;Context Caching&#xff09;技术&#xff0c;开启了公测。我们一起来看下。 介绍 上下文缓存&#xff08;Context Caching&#xff09;是一种高效的数据管理技术&#xff0c;它允许系统预先存储那些可能会被频繁请求的大量数据或信息。这样&am…

BeautifulSoup 类通过查找方法选取节点

BeautifulSoup 类提供了一些基于 HTML 或 XML 节点树选取节点的方法&#xff0c;其中比较主流 的两个方法是 find() 方法和 find_all() 方法。 find() 方法用于查找符合条件的第一个节点&#xff1b; find_all() 方法用于查找所有符合条件的节点&#xff0c;并以列表的…

深入Spring Boot启动过程:揭秘设计模式与代码优化秘籍

Spring Boot作为一个强大的框架&#xff0c;其简化的配置和快速启动特性深受开发者喜爱。在本篇博客中&#xff0c;我们将深入探讨Spring Boot的启动过程&#xff0c;并分享一些在日常开发中可以参考的实例&#xff0c;包括工厂类的使用、设计模式的应用以及代码优化的技巧。 …