在QT中使用OpenGL

参考资料:

主页 - LearnOpenGL CN

https://blog.csdn.net/qq_40120946/category_12566573.html

由于OpenGL的大多数实现都是由显卡厂商编写的,当产生一个bug时通常可以通过升级显卡驱动来解决。

OpenGL中的名词解释

OpenGL 上下文(Context)

  • 作用

    • OpenGL上下文就像是一个画家的工具箱,它包含了所有当前可用的工具(如画笔、颜料、画布等),它存储了OpenGL的所有状态(如当前颜色、线条粗细、是否启用混合等)。

    • 每个窗口/线程通常有一个独立的上下文,每个上下文是独立的,就像一个“沙盒”,不同上下文的资源默认不共享(除非显式设置共享)。

    • 上下文必须绑定到某个“窗口”或“绘图表面”(如HWNDQOpenGLWidget等),才能进行渲染。

为什么需要多个上下文?

多线程渲染(每个线程通常需要一个独立的上下文)。

不同窗口可能需要不同的OpenGL版本(如一个用OpenGL 2.1,另一个用OpenGL 4.6)。

  • 例子

    • 如果你有两个画家(两个OpenGL上下文),他们各自有自己的画笔和颜料,互不影响。

    • 当你切换上下文(比如从窗口A切换到窗口B),就像换了一个画家,他用的工具和之前的不一样。

OpenGL 状态机(State Machine)

OpenGL状态机决定了当前如何绘制图形,它由一系列可开关的设置组成,就像画家的当前工作模式

  • 作用

    • 控制OpenGL的绘制行为,比如:

      • 当前颜色(glColor3f(1.0, 0.0, 0.0) → 红色)

      • 是否启用深度测试(glEnable(GL_DEPTH_TEST)

      • 当前绑定的纹理(glBindTexture(GL_TEXTURE_2D, textureId)

    • 这些状态会一直保持,直到你手动改变它们。

  • 例子

    • 画家当前选择的是红色颜料glColor3f(1.0, 0.0, 0.0)),那么接下来他画的所有东西都是红色,直到他换颜色。

    • 画家决定是否使用尺子glEnable(GL_LINE_SMOOTH)),如果启用,画线会更平滑。

OpenGL (ObjectID)

对象ID(如VAOVBOTexture的ID)就像是工具箱里的每件工具的编号

  • 作用

    • OpenGL管理的资源(如缓冲区、纹理、着色器)都有一个唯一的GLuint类型的ID。

    • 你需要绑定(Bind)这些ID到OpenGL的某个目标(Target),才能使用它们。

  • 例子

    • 画家有3支画笔(3个VBO),编号分别是1、2、3。

    • 他必须拿起某支笔glBindBuffer(GL_ARRAY_BUFFER, vboId))才能用它画画。

    • 如果他不绑定任何笔(glBindBuffer(GL_ARRAY_BUFFER, 0)),就没法画。

着色器 —— 着色器 - LearnOpenGL CN

顶点着色器

核心作用:处理每个顶点的坐标变换和属性计算。

  • 坐标变换:将输入的顶点坐标(如模型空间坐标)转换为裁剪空间坐标(Clip Space),这是透视投影和视口变换的基础。
  • 属性传递:处理顶点属性(如位置、法线、纹理坐标、颜色),并将处理后的数据传递给后续阶段(如几何着色器或片段着色器)。
  • 应用场景
    • 实现模型的位移、旋转、缩放(通过矩阵变换)。
    • 计算顶点光照效果的初始值(如法线变换)。
    • 实现顶点动画(如骨骼动画、波浪效果)。

特点

  • 对每个顶点执行一次,并行计算效率高。
  • 必须输出裁剪空间坐标(gl_Position)。

// 顶点着色器示例(简化)
#version 330 core
layout (location = 0) in vec3 aPosition;  // 顶点位置
layout (location = 1) in vec3 aColor;     // 顶点颜色
out vec3 vColor;                          // 传递给片段着色器的颜色

uniform mat4 model;       // 模型矩阵
uniform mat4 view;        // 视图矩阵
uniform mat4 projection;  // 投影矩阵

void main() {
    // 坐标变换:模型空间 → 世界空间 → 视图空间 → 裁剪空间
    gl_Position = projection * view * model * vec4(aPosition, 1.0);
    vColor = aColor;      // 传递颜色属性
}

片段着色器

核心作用:计算每个片段(Fragment,可理解为潜在像素)的最终颜色。

  • 颜色计算:基于插值后的顶点属性(如颜色、纹理坐标)和外部数据(如光照、材质、纹理),计算像素的 RGBA 值。
  • 高级效果:实现光照模型(如 Phong、PBR)、阴影、纹理采样、透明度、后处理(如模糊、色调调整)。
  • 应用场景
    • 渲染物体材质和纹理。
    • 实现光照、反射、折射效果。
    • 创建特效(如雾效、发光、粒子)。

特点

  • 对每个光栅化后的片段执行一次,计算量通常比顶点着色器大。
  • 必须输出一个颜色值(out vec4 FragColor)。

#version 330 core
in vec3 vColor;           // 从顶点着色器接收的颜色
out vec4 FragColor;       // 输出的最终颜色

void main() {
    // 直接使用插值后的颜色
    FragColor = vec4(vColor, 1.0);
}

VBO(Vertex Buffer Object)—— 顶点缓冲区对象

VBO 是OpenGL中用于存储顶点数据(如位置、颜色、纹理坐标等)的缓冲区对象。它直接在GPU内存中分配空间,避免CPU到GPU的重复数据传输,提高渲染效率。

作用

  • 存储顶点属性数据(例如:float vertices[] = {x1,y1,z1, x2,y2,z2, ...})。

  • 通过glBindBuffer绑定后,OpenGL才知道从哪里读取数据。

类比

  • VBO = 颜料管

    • 每个颜料管(VBO)存储一种原始数据(如红色颜料管、蓝色颜料管)。

    • 颜料管本身不知道如何被使用,只是数据的容器。

VAO(Vertex Array Object)—— 顶点数组对象

VAO 是一个“配置容器”,用于记录:

  • 当前绑定的VBO。

  • 顶点属性的解析方式(如位置是3个float,颜色是4个float等)。

  • 顶点属性的启用状态(通过glEnableVertexAttribArray)。

作用

  • 避免重复配置:每次绘制时无需重新绑定VBO和设置属性格式。

  • 提高性能:OpenGL可以直接读取预定义的顶点数据布局。

类比

  • VAO = 调色板(或画笔套装)

    • 调色板(VAO)记录了:

      • 哪些颜料管(VBO)被挤到调色板上。

      • 每种颜料的用途(如红色用于轮廓,蓝色用于填充)。

    • 画家(OpenGL)拿起调色板后,直接知道如何作画。

VBO 和 VAO 的联系与区别

联系

  1. VAO 依赖 VBO

    • VAO本身不存储顶点数据,它只是记录“如何从VBO中读取数据”。

    • 必须先绑定VBO,再配置VAO(就像先挤颜料到调色板,再定义用途)。

区别

特性VBOVAO
存储内容原始顶点数据(如位置、颜色)顶点属性的配置(如何读数据)
是否直接参与绘制是(数据源)否(只是数据格式的封装)
绑定目标GL_ARRAY_BUFFER无目标(直接绑定)
性能优化减少CPU-GPU数据传输减少绘制时的状态切换开销

一个VAO绑定多个VBO吗?——可以

VAO可以关联多个VBO(例如:一个VBO存位置,另一个存颜色)。
只需在绑定VAO后,依次绑定不同VBO并配置属性:

glBindVertexArray(vaoId);
// 绑定位置VBO
glBindBuffer(GL_ARRAY_BUFFER, vboPos);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
// 绑定颜色VBO
glBindBuffer(GL_ARRAY_BUFFER, vboColor);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, NULL);

基础光照

环境光照(Ambient Lighting):

即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。

漫反射光照(Diffuse Lighting):

模拟光源对物体的方向性影响(Directional Impact)。它是风氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。

镜面光照(Specular Lighting):

模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。

法向量

法向量是一个垂直于顶点表面的(单位)向量。由于顶点本身并没有表面(它只是空间中一个独立的点),我们利用它周围的顶点来计算出这个顶点的表面。我们能够使用一个小技巧,使用叉乘对立方体所有的顶点计算法向量,但是由于3D立方体不是一个复杂的形状,所以我们可以简单地把法线数据手工添加到顶点数据中。更新后的顶点数据数组可以在这里找到。试着去想象一下,这些法向量真的是垂直于立方体各个平面的表面的(一个立方体由6个平面组成)。

计算漫反射光照需要什么?

  • 法向量:一个垂直于顶点表面的向量。
  • 定向的光线:作为光源的位置与片段的位置之间向量差的方向向量。为了计算这个光线,我们需要光的位置向量和片段的位置向量。

OpenGL 图形渲染管线全流程解析

OpenGL 状态机与对象管理基础
  • 状态机特性:OpenGL 通过上下文(Context)维护运行状态,通过设置选项、操作缓冲修改状态,以当前上下文执行渲染。
  • 对象引用机制:对象通过整数 ID(objectId)绑定至上下文目标位置,存储选项配置,避免重复设置(如模型数据绑定)。
阶段像素位置相关像素颜色相关
顶点着色器转换 3D 坐标至裁剪空间,为投影做准备处理顶点颜色等属性(可传递给片段着色器)
几何着色器(可选)修改图元形状(如生成更多顶点)可输出顶点颜色属性
图元装配定义几何形状的轮廓无直接颜色处理
光栅化确定像素的屏幕坐标(x, y)传递片段位置给片段着色器
片段着色器无直接位置处理计算像素的 RGBA 颜色值
Alpha 测试与混合基于深度判断像素可见性混合颜色值,确定最终显示的颜色

数据流

一、像素位置的确定:3D 到 2D 坐标转换与光栅化阶段

1. 顶点着色器(Vertex Shader):初步坐标变换
  • 作用:将输入的 3D 顶点坐标(如模型本地坐标)转换为裁剪空间坐标(Clip Space),并完成顶点属性(如位置、法线)的基础处理。
  • 与像素位置的关系:此阶段将顶点从模型空间映射到裁剪空间,为后续投影到 2D 屏幕做准备,但尚未直接确定像素位置。
2. 图元装配(Primitive Assembly):几何形状定义
  • 作用:将顶点按指定图元类型(如三角形、线段)装配成几何形状,确定渲染的基本单元(如一个三角形由 3 个顶点组成)。
  • 与像素位置的关系:明确了 3D 空间中几何图形的轮廓,但仍处于抽象的几何阶段。
3. 光栅化(Rasterization):像素位置生成
  • 作用:将图元(如三角形)映射到屏幕的 2D 像素网格,计算每个图元覆盖的像素坐标,并生成对应的片段(Fragment)
  • 关键细节
    • 此阶段通过插值计算图元在屏幕上的覆盖范围,确定每个像素的位置(x, y 坐标)。
    • 裁切(Clipping)会丢弃视图外的像素,减少无效计算。
  • 结论光栅化阶段直接确定了像素的屏幕位置

二、像素颜色的计算:片段处理与最终输出阶段

1. 片段着色器(Fragment Shader):颜色值计算
  • 作用:接收光栅化生成的片段(包含位置、纹理坐标等信息),结合 3D 场景数据(如光照、阴影、材质属性、纹理采样),计算每个像素的最终颜色值(RGBA)。
  • 关键细节
    • 可通过光照模型(如兰伯特、Phong)计算光照对颜色的影响。
    • 支持纹理采样,将纹理贴图的颜色映射到像素。
  • 结论片段着色器是像素颜色计算的核心阶段
2. Alpha 测试与混合(Alpha Test & Blending):颜色最终确定
  • 作用
    • 深度测试:比较当前片段与已渲染像素的深度值,决定是否保留当前像素(近物覆盖远物)。
    • Alpha 混合:根据透明度(Alpha 值)混合当前像素与背景像素的颜色,实现半透明效果(如玻璃、烟雾)。
  • 与颜色的关系:此阶段不直接计算颜色,而是基于深度和 Alpha 值对片段着色器输出的颜色进行筛选或混合,最终确定屏幕上显示的像素颜色。
    图形渲染管线核心流程拆解
    1. 3D 到 2D 坐标转换阶段

      • 顶点着色器(Vertex Shader):输入单个顶点,将 3D 坐标转换为特定空间坐标(如裁剪空间),并处理顶点属性(如位置、颜色)。
      • 几何着色器(Geometry Shader)(可选):输入顶点组(图元),通过生成新顶点扩展或修改图元形状(如从单个三角形生成两个三角形)。
    2. 图元装配与光栅化阶段

      • 图元装配(Primitive Assembly):将顶点按指定图元类型(如三角形、点)装配为几何形状,确定渲染基本单元。
      • 光栅化(Rasterization):将图元映射为屏幕像素,生成片段(Fragment);裁切(Clipping)丢弃视图外像素,提升效率。
    3. 片段处理与最终输出阶段

      • 片段着色器(Fragment Shader):计算像素最终颜色,结合 3D 场景数据(光照、阴影、材质等)生成颜色值。
      • Alpha 测试与混合(Alpha Test & Blending):通过深度 / 模板测试判断像素可见性,基于 Alpha 值实现透明度混合,确定最终渲染结果。
    管线核心逻辑总结

    “状态机管理对象状态 → 管线各阶段逐级处理顶点与图元 → 从 3D 坐标映射至 2D 像素并渲染”,这一流程构成了 OpenGL 将几何数据转化为屏幕图像的完整技术链路。

    完整OpenGL绘图流程

    OpenGL步骤Qt (QOpenGLWidget)画家类比
    1. 初始化OpenGL上下文

    QOpenGLWidget 构造函数自动创建OpenGL上下文

    initializeOpenGLFunctions()加载OpenGL函数,初始化Qt的OpenGL函数绑定

    画家准备好画布、工具箱(上下文=工具箱+画布)。
    2. 定义顶点数据initializeGL()中定义数组(如float vertices[]画家决定画什么(如“画一个三角形,左下红、右下绿、顶部蓝”)。
    3. 创建VBOglGenBuffers() + glBufferData() 在initializeGL()中完成把颜料挤到调色盘上(VBO=颜料管,存储原始颜色和位置数据)。
    4. 创建VAOglGenVertexArrays() + 配置属性(glVertexAttribPointer)在initializeGL()中完成

    调色盘(VAO)记录:

    - 红色颜料用于轮廓

    - 蓝色颜料用于填充。

    5. 清空屏幕paintGL()中调用 glClear()画家擦干净画布
    6. 绑定VAOpaintGL()中调用 glBindVertexArray(VAO)画家拿起调色盘(绑定VAO后,OpenGL知道如何读取VBO数据)。
    7. 绘制调用paintGL()中调用 glDrawArrays()画家用调色盘上的颜料开始作画
    8. 解绑VAO可调用 glBindVertexArray(0),但Qt通常省略画家放下调色盘
    9.调整画布大小重写 resizeGL(int w, int h),自动调用画家根据画布大小调整画笔范围。

    10.清理资源

    QOpenGLWidget 析构函数自动释放VAO/VBO画家收工,清理调色盘和颜料。

     原生OpenGL对比Qt绘图流程关键区别总结

    特性Qt (QOpenGLWidget)原生OpenGL (GLFW)
    上下文管理自动创建和管理OpenGL上下文需手动初始化(如GLFW/GLEW)
    窗口集成直接嵌入Qt窗口体系需手动处理窗口事件(如GLFW)
    函数调用通过 QOpenGLFunctions 调用OpenGL API直接调用OpenGL API(如 glDrawArrays
    生命周期自动调用 initializeGL()paintGL()需手动编写渲染循环
    适用场景Qt应用程序中嵌入3D绘图跨平台游戏/独立图形应用

    Qt 的 QOpenGLWidget 绘图完整代码——制一个三色三角形

    1.1 创建自定义 QOpenGLWidget 子类
    // MyGLWidget.h
    #include <QOpenGLWidget>
    #include <QOpenGLFunctions>class MyGLWidget : public QOpenGLWidget, protected QOpenGLFunctions {
    public:MyGLWidget(QWidget* parent = nullptr) : QOpenGLWidget(parent) {}protected:void initializeGL() override;  // 初始化OpenGLvoid paintGL() override;       // 绘制void resizeGL(int w, int h) override; // 窗口大小变化时调整private:GLuint VAO, VBO;  // OpenGL对象
    };
    1.2 实现 initializeGL(初始化阶段)
    // MyGLWidget.cpp
    void MyGLWidget::initializeGL() {initializeOpenGLFunctions();  // 初始化Qt的OpenGL函数绑定// 定义顶点数据(位置 + 颜色)float vertices[] = {// 位置          // 颜色-0.5f, -0.5f, 0.0f,  1.0f, 0.0f, 0.0f, // 左下(红)0.5f, -0.5f, 0.0f,  0.0f, 1.0f, 0.0f, // 右下(绿)0.0f,  0.5f, 0.0f,  0.0f, 0.0f, 1.0f  // 顶部(蓝)};// 创建并绑定VBOglGenBuffers(1, &VBO);glBindBuffer(GL_ARRAY_BUFFER, VBO);glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);// 创建并绑定VAOglGenVertexArrays(1, &VAO);glBindVertexArray(VAO);// 配置位置属性(前3个float)glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0);glEnableVertexAttribArray(0);// 配置颜色属性(后3个float,偏移量=3*sizeof(float))glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float)));glEnableVertexAttribArray(1);// 解绑(非必须,但安全)glBindVertexArray(0);glBindBuffer(GL_ARRAY_BUFFER, 0);
    }
    1.3 实现 paintGL(渲染阶段)
    void MyGLWidget::paintGL() {glClearColor(0.2f, 0.3f, 0.3f, 1.0f);  // 设置清屏颜色(深绿色)glClear(GL_COLOR_BUFFER_BIT);          // 清空颜色缓冲glBindVertexArray(VAO);                // 绑定VAO(自动关联VBO和属性)glDrawArrays(GL_TRIANGLES, 0, 3);      // 绘制三角形
    }
    1.4 实现 resizeGL(窗口调整)
    void MyGLWidget::resizeGL(int w, int h) {glViewport(0, 0, w, h);  // 调整视口大小
    }
    1.5 在Qt窗口中使用 MyGLWidget
    // main.cpp
    #include <QApplication>
    #include "MyGLWidget.h"int main(int argc, char** argv) {QApplication app(argc, argv);MyGLWidget widget;widget.show();return app.exec();
    }

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

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

    相关文章

    Qt::QueuedConnection详解

    在多线程编程中&#xff0c;线程间的通信是一个关键问题。Qt框架提供了强大的信号和槽机制来处理线程通信&#xff0c;其中Qt::QueuedConnection是一种非常有用的连接类型。本文将深入探讨Qt::QueuedConnection的原理、使用场景及注意事项。 一、基本概念 Qt::QueuedConnecti…

    X86 OpenHarmony5.1.0系统移植与安装

    近期在研究X86鸿蒙,通过一段时间的研究终于成功了,在X86机器上成功启动了openharmony系统了.下面做个总结和分享 1. 下载源码 获取OpenHarmony标准系统源码 repo init -u https://gitee.com/openharmony/manifest.git -b refs/tags/OpenHarmony-v5.1.0-Release --no-repo-ve…

    如何诊断服务器硬盘故障?出现硬盘故障如何处理比较好?

    当服务器硬盘出现故障时&#xff0c;及时诊断问题并采取正确的处理方法至关重要。硬盘故障可能导致数据丢失和系统不稳定&#xff0c;影响服务器的正常运行。以下是诊断服务器硬盘故障并处理的最佳实践&#xff1a; 诊断服务器硬盘故障的步骤 1. 监控警报 硬盘监控工具&#…

    vue3提供的hook和通常的函数有什么区别

    Vue 3 提供的 hook&#xff08;组合式函数&#xff09; 和普通函数在使用场景、功能和设计目的上有明显区别&#xff0c;它们是 Vue 3 组合式 API 的核心概念。下面从几个关键维度分析它们的差异&#xff1a; 1. 设计目的不同 Hook&#xff08;组合式函数&#xff09; 专为 Vu…

    Spark提交流程

    bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn ./examples/jars/spark-examples_2.12-3.3.1.jar 10 这一句命令实际上是 启动一个Java程序 java org.apache.spark.deploy.SparkSubmit 并将命令行参数解析到这个类的对应属性上 因为master给…

    Microsoft Copilot Studio - 尝试一下Agent

    1.简单介绍 Microsoft Copilot Studio以前的名字是Power Virtual Agent(简称PVA)。Power Virutal Agent是2019年出现的&#xff0c;是低代码平台Power Platform的一部分。当时Generative AI还没有出现&#xff0c;但是基于已有的Conversation AI技术&#xff0c;即Microsoft L…

    【源码剖析】2-搭建kafka源码环境

    在上篇文章kafka核心概念中&#xff0c;解释了kafka的核心概念&#xff0c;下面开始进行kafka源码编译。为什么学习源码需要进行源码编译呢&#xff0c;我认为主要有两点&#xff1a; 可以进行debug&#xff0c;跟踪代码执行逻辑可以对源码改动&#xff0c;强化学习学习效果 …

    小红书视频图文提取:采集+CV的实战手记

    项目说明&#xff1a;这波视频&#xff0c;值不值得采&#xff1f; 你有没有遇到过这样的场景&#xff1f;老板说&#xff1a;“我们得看看最近小红书上关于‘旅行’的视频都说了些什么。”团队做数据分析的&#xff0c;立马傻眼&#xff1a;官网打不开、接口抓不着、视频不能…

    Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级

    在互联网的快速发展中&#xff0c;高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司&#xff0c;近期做出了一个重大技术决策&#xff1a;弃用长期使用的 Nginx&#xff0c;转而采用其内部开发…

    从编辑到安全设置: 如何满足专业文档PDF处理需求

    随着数字化办公的发展&#xff0c;PDF 已成为跨平台文档交互的标准格式。无论是在日常办公、学术研究&#xff0c;还是项目协作中&#xff0c;对 PDF 文件进行高效编辑与管理的需求日益增长。功能全面、操作流畅且无额外负担的 PDF 编辑工具&#xff0c;它是一款在功能上可与 A…

    Kafka消费者组位移重设指南

    #作者&#xff1a;张桐瑞 文章目录 一、Kafka 与传统消息引擎的核心差异二、重设消费者组位移的核心原因三、重设位移的两大维度与七种策略四、重设位移的实现方式&#xff08;一&#xff09;Java API 方式&#xff08;二&#xff09;命令行脚本方式&#xff08;Kafka 0.11&am…

    分类模型:逻辑回归

    1、针对设计&#xff1a;二分类 Logistic 回归最初是为二分类问题设计的&#xff0c; Logistic 回归基于概率&#xff0c;通过 Sigmoid 函数转换输入特征的线性组合&#xff0c;将任意实数映射到 [0, 1] 区间内。 通过引入一个决策规则&#xff08;通常是概率的阈值&#xff…

    CppCon 2015 学习:C++ WAT

    这段代码展示了 C 中的一些有趣和令人困惑的特性&#xff0c;尤其是涉及数组访问和某些语法的巧妙之处。让我们逐个分析&#xff1a; 1. assert(map[“Hello world!”] e;) 这一行看起来很不寻常&#xff0c;因为 map 在这里被用作数组下标访问器&#xff0c;但是在前面没有…

    vscode自定义主题语法及流程

    vscode c/c 主题 DIY 启用自己的主题(最后步骤) 重启生效 文件–>首选项–>主题–>颜色主题: 也可以在插件里找到哈 手把手教你制作 在C:\Users\jlh.vscode\extensions下自己创建一个文件夹 里面有两个文件和一个文件夹 具体内容: package.json: {"name&…

    前端传递日期范围(开始时间和结束时间),后端解析及查询

    前端技术&#xff1a;Vue3 TypeScript Element Plus 后端技术&#xff1a;Java Spring Boot MyBatis 应用效果&#xff1a; 原来方案 1、前端日期控件使用 el-date-picker&#xff0c;日期显示格式和日期值返回格式都为&#xff1a;YYYY-MM-DD <el-form :model"…

    零基础设计模式——行为型模式 - 命令模式

    第四部分&#xff1a;行为型模式 - 命令模式 (Command Pattern) 接下来&#xff0c;我们学习行为型模式中的命令模式。这个模式能将“请求”封装成一个对象&#xff0c;从而让你能够参数化客户端对象&#xff0c;将请求排队或记录请求日志&#xff0c;以及支持可撤销的操作。 …

    禁止 Windows 更新后自动重启

    Windows 默认会在安装重要更新后自动重启&#xff0c;但你可以调整设置来避免这种情况&#xff1a; ​​方法 1&#xff1a;通过组策略&#xff08;适用于 Windows 专业版/企业版&#xff09;​​ 按 Win R&#xff0c;输入 gpedit.msc 打开 ​​本地组策略编辑器​​。导航…

    GoldenDB简述

    GoldenDB是国产的分布式数据库。它彻底解决了事务一致性&#xff0c;数据实时一致性的问题。采用的是Shared Nothing&#xff08;分片式存储&#xff09;的分布式架构。就是不共享数据&#xff0c;各自节点持有各自的数据。对比不共享的&#xff0c;还有其他两种分布式架构&…

    训练过程中的 Loss ?

    文章目录 在我们训练的过程中&#xff0c;设置好这个epochs也就是训练的轮次&#xff0c;然后计算这个损失函数&#xff0c;我们可以知道这个具体的训练的情况&#xff0c;那么在训练的过程中&#xff0c;这个损失函数的变化有哪些情况&#xff1f;对应的一个解释情况是怎么样的…

    S2B2B农产品供应链交易多平台开发有哪些发展前景?如何维护?

    一、S2B2B农产品供应链交易多平台开发的未来发展前景 本文将由小编为您介绍关于S2B2B农产品供应链交易多平台开发的内容&#xff0c;希望能够帮助大家。在数字化时代&#xff0c;农产品供应链的数字化转型成为了一种必然趋势。S2B2B(Supplier to Business to Business)模式通过…