当前位置: 首页 > news >正文

LearnOpenGL-光照-5.投光物

本人刚学OpenGL不久且自学,文中定有代码、术语等错误,欢迎指正

我写的项目地址:https://github.com/liujianjie/LearnOpenGLProject

文章目录

  • 投光物
  • 平行光
  • 点光源
  • 聚光
    • 不平滑的例子
    • 平滑例子

投光物

  • 前面几节使用的光照都来自于空间中的一个点

    即把光源当做一个点

    但现实世界中,我们有很多种类的光照,每种的表现都不同。

  • 投光物

    将光投射(Cast)到物体的光源叫做投光物

  • 小结

    我做个小总结,与前面几节把光源当做一个点的区别

    • 平行光

      • 与一个点做光源不一样

        点光源需要位置

        平行光需要方向

        所以在实现计算光源对片段的漫反射、镜面光影响,要得到光源的方向方式会不一样

    • 点光源

      • 与一个点做光源一样需要位置

        在实现计算光源对片段的漫反射、镜面光影响,要得到光源的方向方式会一样

      • 点光源会衰减,前面的点光不会

    • 聚光灯

      • 与一个点做光源一样需要位置

        在实现计算光源对片段的漫反射、镜面光影响,要得到光源的方向方式会一样

      • 聚光灯照射一个特点方向的范围,前面的点光没有范围且四周散射

平行光

这里需要定义平行光的方向向下,才符合太阳的光照照射(指向)方向,所以计算漫反射和镜面光强度的时候需要取反得到光源的方向向量。

  • 简介

    当我们使用一个假设光源处于无限远处的模型时,它就被称为定向光,因为它的所有光线都有着相同的方向,它与光源的位置是没有关系的。

  • 图示

    计算漫反射和镜面光分量时光源的方向

  • 特点

    因为所有的光线都是平行的,所以物体与光源的相对位置是不重要的,因为对场景中每一个物体光的方向都是一致的。

  • 例子

    定义一个光线方向向量而不是位置向量来模拟一个定向光。

    这个光线方向是从光源指向像素点的方向,若要模仿太阳光从上往下照射,各个分量值应该为

    cpp

    lightingShader.setVec3("light.direction", -0.2f, -1.0f, -0.3f);// 太阳光向下
    

    glsl

    #version 330 core
    out vec4 FragColor;in vec3 Normal;
    in vec3 FragPos;
    in vec2 TexCoords;// 纹理坐标uniform vec3 viewPos;struct Material {sampler2D diffuse;  // 纹理单元sampler2D specular;//  镜面光照颜色分量从纹理采样float shininess;
    }; 
    uniform Material material;// 光照强度
    struct Light {// vec3 position; // 使用平行光就不再需要位置了vec3 direction; // 从光源出发到全局的方向vec3 ambient;vec3 diffuse;vec3 specular;
    };uniform Light light;
    void main()
    {// 取负变为光源的方向向量,用在计算漫反射和镜面光分量时vec3 lightDir = normalize(-light.direction);// 环境光光照分量float ambientStrength = 0.1;// 从漫反射纹理读取颜色分量vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); // 漫反射光照分量vec3 norm = normalize(Normal);// vec3 lightDir = normalize(light.position - FragPos);// 一个点做光源才需要这样相减计算片段到光源的方向向量float diff = max(dot(norm, lightDir), 0.0);             // 得到光源对当前片段实际的漫反射影响vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));// 从漫反射纹理读取颜色分量// 镜面光照分量float specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);            // 是观察者方向,不是观察者看向的方向vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// 光源对当前片段的镜面光影响// vec3 specular = light.specular * (spec * material.specular); // 改变在这里// 采样镜面光纹理颜色作为镜面光照颜色分量vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); vec3 result = (ambient + diffuse + specular) ;FragColor = vec4(result, 1.0);
    }
    
    • 说明

      依旧是冯氏光照模型

      vec3 lightDir = normalize(-light.direction);

      因为direction是光源指向像素点,加了负号以后成为像素点指向光源(光源的方向),这样才能与前面小节相符,正确计算光源对片段的漫反射和镜面光影响。

      对应开头的小结

      在实现计算光源对片段的漫反射、镜面光影响,要得到光源的方向方式会不一样

      // vec3 lightDir = normalize(light.position - FragPos);// 一个点做光源才需要这样相减计算片段到光源的方向向量
      // 取负变为光源的方向向量,用在计算漫反射和镜面光分量时
      vec3 lightDir = normalize(-light.direction);
      float diff = max(dot(norm, lightDir), 0.0);             // 得到光源对当前片段实际的漫反射影响
      

点光源

这里算距离与衰减,无论是光源的方向还是光源的指向方向都可以,但是计算漫反射和镜面光强度还是依旧用光的方向向量。

  • 介绍

    处于世界中某一个位置的光源,它会朝着所有方向发光,但光线会随着距离逐渐衰减

  • 计算漫反射和镜面光分量时光源的方向图就不用画了,就是片段指向灯泡

  • 重点在于如何定义衰减,即距离与衰减系数关系

    • 若用线性

      • 距离的增长线性地减少光的强度,从而让远处的物体更暗

      • 这样的线性方程通常会看起来比较

    • 用以下公式才是稍好的选择

      定义3个(可配置的)项:常数项Kc、一次项Kl和二次项Kq。

      • 解读

        • 常数项Kc通常保持为1.0,它的主要作用是保证分母永远不会比1小,否则的话在某些距离上它反而会增加强度,这肯定不是我们想要的效果。

        • 一次项Kl会与距离值相乘,以线性的方式减少强度。

        • 二次项Kq会与距离的平方相乘,让光源以二次递减的方式减少强度。

          二次项在距离比较小的时候影响会比一次项小很多,但当距离值比较大的时候它就会比一次项更大了。

      • 效果

        光在近距离时亮度很高、随着距离变远亮度迅速降低、最后会以更慢的速度减少亮度

        匹配

        现实:灯在近处通常会非常亮、随着距离的增加光源的亮度一开始会下降非常快、但在远处时剩余的光强度就会下降的非常缓慢

      • 选择正确的值

        距离常数项一次项二次项
        71.00.71.8
        131.00.350.44
        201.00.220.20
        321.00.140.07
        501.00.090.032
        651.00.070.017
        1001.00.0450.0075
        1601.00.0270.0028
        2001.00.0220.0019
        3251.00.0140.0007
        6001.00.0070.0002
        32501.00.00140.000007
  • 例子

    • glsl

      #version 330 core
      out vec4 FragColor;
      struct Material {sampler2D diffuse;  // 纹理单元sampler2D specular;//  镜面光照颜色分量从纹理采样float shininess;
      }; 
      // 点光源
      struct Light {vec3 position;  // 需要位置vec3 ambient;   vec3 diffuse;vec3 specular;float constant; // 常数float linear;   // 一次项float quadratic;// 二次项
      };in vec3 FragPos;
      in vec3 Normal;
      in vec2 TexCoords;// 纹理坐标uniform vec3 viewPos;
      uniform Material material;
      uniform Light light;
      void main()
      {// 环境光光照分量// 从漫反射纹理读取颜色分量vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); // 漫反射光照分量vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos); // 得到光源的方向,与一个点做光源一样float diff = max(dot(norm, lightDir), 0.0);         // 得到光源对当前片段实际的漫反射影响vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;// 从漫反射纹理读取颜色分量// 镜面光照分量vec3 viewDir = normalize(viewPos - FragPos);        // 是观察者方向,不是观察者看向的方向vec3 reflectDir = reflect(-lightDir, norm);         // reflect要求第一个参数是光源指向像素点的向量float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// 光源对当前片段的镜面光影响// 采样镜面光纹理颜色作为镜面光照颜色分量//vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); // 这句也行vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; // 计算衰减float distance  = length(light.position - FragPos);                // 得到光源到片段长度float attenuation = 1.0 / (light.constant + light.linear * distance // 根据公式+ light.quadratic * distance * distance);// 光照分量随距离衰减ambient *= attenuation;diffuse *= attenuation;specular *= attenuation;vec3 result = (ambient + diffuse + specular) ;FragColor = vec4(result, 1.0);
      }
      
      • 说明

        与一个点做光源一样,用光源的位置减去片段位置得到光源的方向

        vec3 lightDir = normalize(light.position - FragPos); // 得到光源的方向,与一个点做光源一样
        

      cpp

      lightingShader.setFloat("light.constant",  1.0f);
      lightingShader.setFloat("light.linear",    0.09f);
      lightingShader.setFloat("light.quadratic", 0.032f);
      
    • 重要bug

      箱子发生旋转,法线也要跟随着变换,不然法线不再垂直顶点,会导致如下不正确效果

      所以需要在vs阶段需计算发生变换后的法线

      #version 330 core
      layout (location = 0) in vec3 aPos;
      layout (location = 1) in vec3 aNormal;
      layout (location = 2) in vec2 aTexCoords;uniform mat4 view;
      uniform mat4 projection;
      uniform mat4 model;out vec3 FragPos;  
      out vec3 Normal;
      out vec2 TexCoords;
      void main()
      {gl_Position = projection * view * model * vec4(aPos, 1.0);FragPos = vec3(model * vec4(aPos, 1.0));// Normal = aNormal;// 只有顶点只发生位移时才可以保持不变Normal = mat3(transpose(inverse(model))) * aNormal;TexCoords = aTexCoords;
      }
      

      以下正确结果

聚光

这里定义光源的位置为摄像机的位置向量,计算漫反射和镜面光反射,得摄像机的位置减去像素点的位置就成光的方向向量。

  • 简介

    位于环境中某个位置的光源,它只朝一个特定方向而不是所有方向照射光线。

    这样的结果就是只有在聚光方向的特定半径内的物体才会被照亮,其它的物体都会保持黑暗。

    聚光很好的例子就是路灯或手电筒

  • opengl上表示

    OpenGL中聚光是用一个世界空间位置、一个方向和一个切光角来表示,切光角指定了聚光的半径

  • 实现思路

    对于每个片段,我们会计算片段是否位于聚光的切光方向之间(也就是在锥形内),如果是的话,我们就会相应地照亮片段

  • 图示

    • LightDir:从片段指向光源的向量。
    • SpotDir:聚光所指向的方向。(但实际计算时,取反方向)
    • Phiϕ:指定了聚光半径的切光角。落在这个角度之外的物体都不会被这个聚光所照亮。
    • Thetaθ:LightDir向量和SpotDir向量之间的夹角。在聚光内部的话θ值应该比ϕ值小。

    要做的就是计算LightDir向量和SpotDir向量之间的点积,等于cosθ值,将cosθ值与切光角cosϕ值对比

不平滑的例子

  • 计算向量图示

    算theta时,为了与光的方向向量对应,dot(光的方向向量,取反光源照射前方向量)

  • 代码

    #version 330 core
    out vec4 FragColor;
    struct Material {sampler2D diffuse;  // 漫反射颜色分量从纹理采样sampler2D specular;//  镜面光照颜色分量从纹理采样float shininess;
    }; 
    // 聚光灯
    struct Light {vec3  position; // 需要位置vec3  direction;// 需要照射方向float cutOff;vec3 ambient;vec3 diffuse;vec3 specular;float constant; // 常数float linear;   // 一次项float quadratic;// 二次项
    };in vec3 FragPos;
    in vec3 Normal;
    in vec2 TexCoords;// 纹理坐标uniform vec3 viewPos;
    uniform Material material;
    uniform Light light;
    void main()
    {// 光源的方向向量:像素点指向光源vec3 lightDir = normalize(light.position - FragPos);// 算出theta,dot(像素点指向光源,光源照射的方向取反)float theta = dot(lightDir, normalize(-light.direction)); // float theta=dot(-lightDir, normalize(light.direction));// dot(光源指向像素点, 光源照射的方向)// 执行正常光照计算:由于theta是cos值,cutOff也是cos值,cos(0-90)递减,所以theta>,而不是<if(theta > light.cutOff){// 片段在切角内// 从漫反射纹理读取颜色分量vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); // 漫反射光照分量vec3 norm = normalize(Normal);vec3 lightDir = normalize(light.position - FragPos); // 得到光源的方向,与一个点做光源一样float diff = max(dot(norm, lightDir), 0.0);         // 得到光源对当前片段实际的漫反射影响vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;// 从漫反射纹理读取颜色分量// 镜面光照分量vec3 viewDir = normalize(viewPos - FragPos);       // 是观察者方向,不是观察者看向的方向vec3 reflectDir = reflect(-lightDir, norm);         // reflect要求第一个参数是光源指向像素点的向量float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// 光源对当前片段的镜面光影响// 采样镜面光纹理颜色作为镜面光照颜色分量//vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); // 这句也行vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; // 计算衰减float distance  = length(light.position - FragPos);                 // 得到光源到片段长度float attenuation = 1.0 / (light.constant + light.linear * distance // 根据公式+ light.quadratic * distance * distance);// 光照分量随距离衰减ambient *= attenuation;diffuse *= attenuation;specular *= attenuation;vec3 result = (ambient + diffuse + specular) ;FragColor = vec4(result, 1.0);}else{// 片段不在切角内:计算环境光,以免全黑FragColor = vec4(light.ambient * vec3(texture(material.diffuse, TexCoords)), 1.0) ;}
    }
    

    上传数据

    lightingShader.setVec3("light.position",  camera.Position);
    lightingShader.setVec3("light.direction", camera.Front);
    lightingShader.setFloat("light.cutOff",   glm::cos(glm::radians(12.5f)));
    
    • 说明

      算theta时,为了与光的方向向量对应,dot(像素点指向光源,光源照射的方向取反)

      float theta = dot(lightDir, normalize(-light.direction)); 
      

      与一个点做光源一样,用光源的位置减去片段位置得到光源的方向

      vec3 lightDir = normalize(light.position - FragPos); // 得到光源的方向,与一个点做光源一样
      
    • 注意点theta > light.cutOff

      因为上传给cutOff的是已经计算好了的cos值,且theta也是cosθ值(cosθ=dot(lightDir, normalize(-light.direction)))

      cos(0-90内)递减,所以theta >light.cutOff,代表当前夹角要比规定的范围角度要小,需要照亮

  • 效果

    • 疑问点

      为什么,计算cos角度要用弧度值

      lightingShader.setFloat("light.cutOff", glm::cos(glm::radians(12.5f)));
      

      glm::cos();接收的参数需要是弧度值

  • 测试点积两个向量的方向

    glm::vec3 lightDir = camera.Position;
    glm::vec3 lightdirection = camera.Front;
    float theta1 = glm::dot(lightDir, glm::normalize(-lightdirection));// 对应第一个图
    cout << "像素点指向光源:" << theta1 << endl;
    float theta2 = glm::dot(-lightDir, glm::normalize(lightdirection));// 对应第二个图
    cout << "光源指向像素点:" << theta2 << endl;
    

    方向一样,点积值一样

平滑例子

  • 引入

    如上一个例子,发现聚光灯的光圈边缘并不平滑

  • 解决方法

    我们可以将内圆锥设置为上一个例子聚光灯的圆锥,但我们也需要一个外圆锥,来让光从内圆锥逐渐减暗,直到外圆锥的边界。

  • 融入代码中

    为了创建一个外圆锥,我们只需要再定义一个余弦值来代表聚光灯方向向量和外圆锥向量(等于它的半径)的夹角

  • 边缘平滑且圆锥内正常思路

    如果一个片段处于内外圆锥之间,将会给它计算出一个0.0到1.0之间的强度值。

    如果片段在内圆锥之内,它的强度就是1.0。

    如果在外圆锥之外强度值就是0.0。

  • 公式来计算边缘平滑且圆锥内正常

    • 理解方式一

      θ = dot(像素点指向光源,光源照射的方向取反)= cos(它们之间的夹角)

      γ = cos(外圆角度)

      ϵ(Epsilon) = cos(内圆角度) - cos(外圆角度)

    • 结合下方图表理解

      θ = cos(θ(角度) = dot(像素点指向光源,光源照射的方向取反)= cos(它们之间的夹角)

      γ = cos(γ(角度))= γ(外光切)

      ϵ(Epsilon) = ϕ(内光切)- γ(外光切)

    θθ(角度)ϕ(内光切)ϕ(角度)γ(外光切)γ(角度)ϵI
    0.87300.91250.82350.91 - 0.82 = 0.090.87 - 0.82 / 0.09 = 0.56
    0.9260.91250.82350.91 - 0.82 = 0.090.9 - 0.82 / 0.09 = 0.89
    0.97140.91250.82350.91 - 0.82 = 0.090.97 - 0.82 / 0.09 = 1.67
    0.83340.91250.82350.91 - 0.82 = 0.090.83 - 0.82 / 0.09 = 0.11
    0.64500.91250.82350.91 - 0.82 = 0.090.64 - 0.82 / 0.09 = -2.0
    0.966150.997812.50.95317.50.9978 - 0.953 = 0.04480.966 - 0.953 / 0.0448 = 0.29
    • 个人发现图表有错(也许没错)

      最后一行:cos值计算错了

      cos(12.5)=0.976,而表中的0.9978是cos(12.5rad),把12.5当做弧度来计算cos值

  • 转换为代码

    glsl

    #version 330 core
    out vec4 FragColor;
    struct Material {sampler2D diffuse;  // 漫反射颜色分量从纹理采样sampler2D specular;//  镜面光照颜色分量从纹理采样float shininess;
    }; 
    // 聚光灯
    struct Light {vec3  position; // 需要位置vec3  direction;// 需要照射方向float cutOff;	// ϕ(内光切)float outerCutOff;// γ(外光切)vec3 ambient;vec3 diffuse;vec3 specular;float constant; // 常数float linear;   // 一次项float quadratic;// 二次项
    };
    in vec3 FragPos;
    in vec3 Normal;
    in vec2 TexCoords;// 纹理坐标uniform vec3 viewPos;
    uniform Material material;
    uniform Light light;
    void main()
    {// 光源的方向向量:像素点指向光源vec3 lightDir = normalize(light.position - FragPos);// 算出theta,dot(像素点指向光源,光源照射的方向取反)float theta = dot(lightDir, normalize(-light.direction));// float theta=dot(-lightDir, normalize(light.direction));// dot(光源指向像素点, 光源照射的方向)// 从漫反射纹理读取颜色分量vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords)); // 漫反射光照分量vec3 norm = normalize(Normal);// vec3 lightDir = normalize(light.position - FragPos); // 得到光源的方向float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;// 从漫反射纹理读取颜色分量// 镜面光照分量vec3 viewDir = normalize(viewPos - FragPos);            // 是观察者方向,不是观察者看向的方向vec3 reflectDir = reflect(-lightDir, norm);             // reflect要求第一个参数是光源指向像素点的向量float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);// 光源对当前片段的镜面光影响// 采样镜面光纹理颜色作为镜面光照颜色分量//vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords)); // 这句也行vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb; // 计算衰减float distance  = length(light.position - FragPos);                 // 得到光源到片段长度float attenuation = 1.0 / (light.constant + light.linear * distance // 根据公式+ light.quadratic * distance * distance);// 光照分量随距离衰减ambient *= attenuation;diffuse *= attenuation;specular *= attenuation;// 为了边缘平滑且圆锥内正常float epsilon = light.cutOff - light.outerCutOff;float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);// 将不对环境光做出影响,让它总是能有一点光diffuse *= intensity;specular *= intensity;// 聚光灯受影响vec3 result = (ambient + diffuse + specular) ;FragColor = vec4(result, 1.0);
    }
    
    lightingShader.use();
    lightingShader.setVec3("viewPos", camera.Position);
    lightingShader.setVec3("light.position", camera.Position);
    lightingShader.setVec3("light.direction", camera.Front);// direction是光照射方向
    lightingShader.setFloat("light.cutOff", glm::cos(glm::radians(12.5f)));		//ϕ(内光切)
    lightingShader.setFloat("light.outerCutOff", glm::cos(glm::radians(17.5f)));// γ(外光切)
    
  • 效果

    请添加图片描述

相关文章:

LearnOpenGL-光照-5.投光物

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录投光物平行光点光源聚光不平滑的例子平滑例子投光物 前面几节使用的光照都来自于空间中的一个点 即…...

【C语言】每日刷题 —— 牛客语法篇(1)

前言 大家好&#xff0c;今天带来一篇新的专栏c_牛客&#xff0c;不出意外的话每天更新十道题&#xff0c;难度也是从易到难&#xff0c;自己复习的同时也希望能帮助到大家&#xff0c;题目答案会根据我所学到的知识提供最优解。 &#x1f3e1;个人主页&#xff1a;悲伤的猪大…...

【深度学习】Subword Tokenization算法

在自然语言处理中&#xff0c;面临的首要问题是如何让模型认识我们的文本信息&#xff0c;词&#xff0c;是自然语言处理中基本单位&#xff0c;神经网络模型的训练和预测都需要借助词表来对句子进行表示。 1.构建词表的传统方法 在字词模型问世之前&#xff0c;做自然语言处理…...

五分钟了解支付、交易、清算、银行等专业名词的含义?

五分钟了解支付、交易、清算、银行等专业名词的含义&#xff1f;1. 支付类名词01 支付应用02 支付场景03 交易类型04 支付类型&#xff08;按通道类型&#xff09;05 支付类型&#xff08;按业务双方类型&#xff09;06 支付方式07 支付产品08 收银台类型09 支付通道10 通道类型…...

4个工具,让 ChatGPT 如虎添翼!

LightGBM中文文档 机器学习统计学,476页 机器学习圣经PRML中文版...

初识PO、VO、DAO、BO、DTO、POJO时

PO、VO、DAO、BO、DTO、POJO 区别分层领域模型规约DO(Data Object)DTO(Data Transfer Object)BO(Business Object)AO(ApplicationObject)VO(View Object)Query领域模型命名规约&#xff1a;一、PO :(persistant object )&#xff0c;持久对象二、VO :(value object) &#xff0…...

[2.2.4]进程管理——FCFS、SJF、HRRN调度算法

文章目录第二章 进程管理FCFS、SJF、HRRN调度算法&#xff08;一&#xff09;先来先服务&#xff08;FCFS, First Come First Serve&#xff09;&#xff08;二&#xff09;短作业优先&#xff08;SJF, Shortest Job First&#xff09;对FCFS和SJF两种算法的思考&#xff08;三…...

【代码随想录Day55】动态规划

583 两个字符串的删除操作 https://leetcode.cn/problems/delete-operation-for-two-strings/72 编辑距离https://leetcode.cn/problems/edit-distance/...

Java开发 - 消息队列前瞻

前言 学完了Redis&#xff0c;那你一定不能错过消息队列&#xff0c;要说他俩之间的关联&#xff1f;关联是有的&#xff0c;但也不见得很大&#xff0c;只是他们都是大数据领域常用的一种工具&#xff0c;一种用来提高程序运行效率的工具。常见于高并发&#xff0c;大数据&am…...

MySQL连接IDEA详细教程

使用IDEA的时候&#xff0c;需要连接Database&#xff0c;连接时遇到了一些小问题&#xff0c;下面记录一下操作流程以及遇到的问题的解决方法。 目录 MySQL连接IDEA详细教程 MySQL连接IDEA详细教程 打开idea&#xff0c;点击右侧的 Database 或者 选择 View --> Tool Wind…...

线程(操作系统408)

基本概念 我们说引入进程的目的是更好的使用多道程序并发执行&#xff0c;提高资源的利用率和系统吞吐量&#xff1b;而引入线程的目的则是减小程序在并发执行的时候所付出的时间开销&#xff0c;提高操作系统的并发性能。 线程可以理解成"轻量级进程"&#xff0c;…...

功耗降低99%,Panamorph超清VR光学架构解析

近期&#xff0c;投影仪变形镜头厂商Panamorph获得新型VR显示技术专利&#xff08;US11493773B2&#xff09;&#xff0c;该专利方案采用了紧凑的结构&#xff0c;结合了Pancake透镜和光波导显示模组&#xff0c;宣称比传统VR方案的功耗、发热减少99%以上&#xff0c;可显著提高…...

【数据结构】带你深入理解栈

一. 栈的基本概念&#x1f4ab;栈是一种特殊的线性表。其只允许在固定的一端进行插入和删除元素的操作&#xff0c;进行数据的插入和删除的一端称作栈顶&#xff0c;另外一端称作栈底。栈不支持随机访问&#xff0c;栈的数据元素遵循后进先出的原则&#xff0c;即LIFO&#xff…...

认识CSS之如何提高写前端代码的效率

&#x1f31f;所属专栏&#xff1a;前端只因变凤凰之路&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该系列将持续更新前端的相关学习笔记&#xff0c;欢迎和我一样的小白订阅&#xff0c;一起学习共同进步~&#x1f449;文章简…...

Vue中watch和computed

首先这里进行声明&#xff0c;这个讲的是vue2的内容&#xff0c;在vue3发生了什么变动与此无关 这里是官网&#xff1a; https://v2.cn.vuejs.org/v2/guide/installation.html computed > 计算属性 watch > 侦听器&#xff08;也叫监视器&#xff09; 其区别如下&…...

华为鲲鹏+银河麒麟v10 安装 docker-ce

设备&#xff1a;硬件&#xff1a;仅有ARM处理器&#xff0c;无GPU和NPU&#xff0c;操作系统麒麟银河V10&#xff0c;Kunpeng-920 #######参考原链接######### 华为鲲鹏银河麒麟v10 安装 docker-ce 踩坑 - akiyaの博客 在 arm64(aarch64) 架构服务器上基于国产化操作系统安…...

Lambda,Stream,响应式编程从入门到放弃

Lambda表达式 Java8新引入的语法糖 Lambda表达式*&#xff08;关于lambda表达式是否属于语法糖存在很多争议&#xff0c;有人说他并不是语法糖&#xff0c;这里我们不纠结于字面表述&#xff09;*。Lambda表达式是一种用于取代匿名类&#xff0c;把函数行为表述为函数式编程风…...

C语言枚举使用技巧

什么是C语言枚举 C语言枚举是一种用户自定义数据类型&#xff0c;它允许程序员定义一个变量&#xff0c;并将其限制为一组预定义的常量。这些常量被称为“枚举值”&#xff0c;并且可以通过名称进行引用。 在C语言中&#xff0c;枚举值是整数类型&#xff0c;它们的值默认从0…...

保姆级使用PyTorch训练与评估自己的EfficientNetV2网络教程

文章目录前言0. 环境搭建&快速开始1. 数据集制作1.1 标签文件制作1.2 数据集划分1.3 数据集信息文件制作2. 修改参数文件3. 训练4. 评估5. 其他教程前言 项目地址&#xff1a;https://github.com/Fafa-DL/Awesome-Backbones 操作教程&#xff1a;https://www.bilibili.co…...

【9】基础语法篇 - VL9 使用子模块实现三输入数的大小比较

VL9 使用子模块实现三输入数的大小比较 【报错】官方平台得背锅 官方平台是真的会搞事情,总是出一些平台上的莫名其妙的错误。 当然如果官方平台是故意考察我们的细心程度,那就当我没有说!! 在这个程序里,仿真时一直在报错 错误:无法在“test”中绑定wire/reg/memory“t…...

成功的项目管理策略:减少成本,提高质量

项目管理是一项具有挑战性的任务&#xff0c;项目团队需要合理的规划和策略&#xff0c;以确保项目的成功和达成预期。为了实现项目的成功&#xff0c;项目经理必须采用正确的策略&#xff0c;才能以最大限度地减少成本并提高项目质量。本文将探讨成功的项目管理策略&#xff0…...

centos 7下JDK8安装

下载安装包https://www.oracle.com/java/technologies/downloads/#java8-linux上传路径 /usr/local&#xff08;替换为自己需要安装的路径&#xff09;解压tar -zxvf jdk-8u131-linux-x64.tar.gz配置环境变量[rootlocalhost java]# vi /etc/profile添加如下配置在配置文件最后&…...

datatables.js中文项目使用案例

官方下载地址https://datatables.net/download/中文官网&#xff1a;http://datatables.club/资源引用<link href"~/datatables/datatables.min.css" rel"stylesheet" /> <script src"~/jquery.min.js" type"text/javascript"…...

Hadoop小结

Hadoop是什么Hadoop是一 个由Apache基金 会所开发的分布式系统基础架构。主要解决,海量数据的存储和海量数据的分析计算问题。广义上来说&#xff0c;Hadoop通 常是指一个更广泛的概念一Hadoop 生态圈。Hadoop优势Hadoop组成HDFS架构Hadoop Distributed File System&#xff0c…...

经典卷积模型回顾14—vgg16实现图像分类(tensorflow)

VGG16是由牛津大学计算机视觉小组&#xff08;Visual Geometry Group&#xff09;开发的深度卷积神经网络模型。其结构由16层组成&#xff0c;其中13层是卷积层&#xff0c;3层是全连接层。 VGG16被广泛应用于各种计算机视觉任务&#xff0c;如图像分类、目标检测和人脸识别等。…...

#Vue2篇:keep-alive的属性和方法

定义 keep-alive 组件是 Vue.js 内置的一个高阶组件&#xff0c;用于缓存其子组件&#xff0c;以提高组件的性能和响应速度。 除了基本用法之外&#xff0c;它还提供了一些属性和方法&#xff0c;以便更好地控制缓存的组件。 属性 include属性用于指定哪些组件应该被缓存&a…...

webpack指南(项目篇)——webpack在项目中的运用

系列文章目录 webpack指南&#xff08;基础篇&#xff09;——手把手教你配置webpack webpack指南&#xff08;优化篇&#xff09;——webpack项目优化 文章目录系列文章目录前言一、配置拆分二、修改启动命令三、定义环境变量四、配置路径别名总结前言 前面我们对webpack的基…...

unicode字符集与utf-8编码的区别,unicode转中文工具、中文转unicode工具(汉字)

在cw上报的报警信息中&#xff0c;有一个name字段的值是\u4eba\u4f53 不知道是啥&#xff0c;查了一下&#xff0c;是unicode编码&#xff0c;用下面工具转换成汉字就是“人体” 参考文章&#xff1a;https://tool.chinaz.com/tools/unicode.aspx 那么我很好奇&#xff0c;uni…...

3D数学系列之——再谈特卡洛积分和重要性采样

目录一、前篇文章回顾二、积分的黎曼和形式三、积分的概率形式&#xff08;蒙特卡洛积分&#xff09;四、误差五、蒙特卡洛积分计算与收敛速度六、重要性采样七、重要性采样方法和过程八、重要性采样的优缺点一、前篇文章回顾 在前一篇文章3D数学系列之——从“蒙的挺准”到“蒙…...

Python错误 TypeError: ‘NoneType‘ object is not subscriptable解决方案汇总

目录前言一、引发错误来源二、解决方案2-1、解决方案一&#xff08;检查变量&#xff09;2-2、解决方案二&#xff08;使用 [] 而不是 None&#xff09;2-3、解决方案三&#xff08;设置默认值&#xff09;2-4、解决方案四&#xff08;使用异常处理&#xff09;2-5、解决方案五…...

VMware空间不足又无法删除快照的解决办法

如果因为快照删除半路取消或者失败&#xff0c;快照管理器就不再显示这个快照&#xff0c;但是其占用的空间还在&#xff0c;最终导致硬盘不足。 可以百度到解决方案&#xff0c;就是在快照管理器&#xff0c;先新建一个&#xff0c;再点删除&#xff0c;等待删除完成就可以将…...

类和对象(一)

类和对象&#xff08;一&#xff09; C并不是纯面向对象语言 C是面向过程和面向对象语言的&#xff01; 面向过程和面向对象初步认识&#xff1a; C语言是面向过程的&#xff0c;关注的是过程&#xff0c;分析出求解问题的步骤&#xff0c;通过函数调用逐步解决问题。 C是基…...

Java 不同路径

不同路径中等一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。问总共有多少条不同的路径&#xff1f…...

【SAP PO】X-DOC:SAP PO 接口配置 REST 服务对接填坑记

X-DOC&#xff1a;SAP PO 接口配置 REST 服务对接填坑记1、背景2、PO SLD配置3、PO https证书导入1、背景 &#xff08;1&#xff09;需求背景&#xff1a; SAP中BOM频繁变更&#xff0c;技术人员在对BOM进行变更后&#xff0c;希望及时通知到相关使用人员 &#xff08;2&…...

最新研究!美国爱荷华州立大学利用量子计算模拟原子核

爱荷华州立大学物理学和天文学教授James Vary&#xff08;图片来源&#xff1a;网络&#xff09;美国爱荷华州立大学物理学和天文学教授James Vary和来自爱荷华州立大学、马萨诸塞州塔夫茨大学&#xff0c;以及美国能源部加利福尼亚州劳伦斯伯克利国家实验室的研究人员&#xf…...

零入门kubernetes网络实战-22->基于tun设备实现在用户空间可以ping通外部节点(golang版本)

《零入门kubernetes网络实战》视频专栏地址 https://www.ixigua.com/7193641905282875942 本篇文章视频地址(稍后上传) 本篇文章主要是想做一个测试&#xff1a; 实现的目的是 希望在宿主机-1上&#xff0c;在用户空间里使用ping命令发起ping请求&#xff0c;产生的icmp类型的…...

web安全——Mybatis防止SQL注入 ssrf漏洞利用 DNS污染同源策略

目录 0x01 Mybatis防止SQL注入 0x02 sqlmap中报错注入判断 0x03 ssrf漏洞利用 0x04 SSRF重绑定 0x05 DNS污染...

smp_init过程解析

当你看到这样的log&#xff0c;会不会很慌张&#xff1f;竟然由CPU没有启动成功&#xff0c;除了什么故障&#xff1f;本文将结合我遇到的一个问题&#xff0c;将启动过程中bringup secondary cpu的过程分析一下。smp_init代码如下&#xff1a;602 void __init smp_init(void) …...

判断推理之逻辑判断

考点一翻译推理&#xff08;一&#xff09;题目特征题干或选项中出现多组“逻辑关联词”&#xff0c;如&#xff1a;“如果……那么……”、“只要……就……”、“只有……才……”、“所有”、“有些”、“……且……”、“ ……或……”等典型逻辑关联词。&#xff08;二&am…...

2023金三银四常见Handler面试总结,附带答案

以下的Handler的面试题都是在面试过程中总结出来比较常见的面试题&#xff0c;现在分享给大家&#xff0c;希望可以帮助你们&#xff01;1.Handler的实现原理从四个方面看Handler、Message、MessageQueue 和 Looper Handler:负责消息的发送和处理 Message:消息对象&#xff0c;…...

为什么机器人操作系统ROS1、ROS2这么难学

AI回复&#xff1a;ROS1、ROS2是机器人操作系统&#xff0c;涉及到很多复杂的概念和技术&#xff0c;需要有一定的编程和机器人知识基础才能学习。此外&#xff0c;ROS1和ROS2的架构和设计也有很大的不同&#xff0c;需要花费一定的时间和精力去学习和适应。但是&#xff0c;一…...

day01

授课老师 &#xff1a;陶国荣 联系方式 &#xff1a; taogrtedu.cn 授课阶段 &#xff1a; Web前端基础 授课内容 &#xff1a; HTML CSS JavaScript 文章目录一、讲师和课程介绍二、Web前端介绍1. 什么是网页2. 网页的组成3. 网页的优势4. 开发前的准备三、 HTML语法介绍…...

第四十章 linux-并发解决方法五(顺序锁seqlock)

第四十章 linux-并发解决方法四&#xff08;顺序锁seqlock&#xff09; 文章目录第四十章 linux-并发解决方法四&#xff08;顺序锁seqlock&#xff09;顺序锁的设计思想是&#xff0c;对某一共享数据读取时不加锁&#xff0c;写的时候加锁。为了保证读取的过程中不会因为写入名…...

【SPSS】交叉设计方差分析和协方差分析详细操作教程(附案例实战)

🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 目录 方差分析概述 交叉设计方差分析...

playwright--核心概念和Selector定位

文章目录前言一、浏览器二、浏览器上下文三、页面和框架四、Selectors1、data-test-id selector2、CSS and XPath selector3、text 文本selector4、id定位selector5、Selector 组合定位五、内置Selector前言 Playwright提供了一组API可自动化操作Chromium&#xff0c;Firefox和…...

响应式操作实战案例

Project Reactor 框架 在Spring Boot 项目 Maven 中添加依赖管理。 <dependency><groupId>io.projectreactor</groupId><artifactId>reactor-core</artifactId> </dependency><dependency><groupId>io.projectreactor</g…...

NetApp AFF A900:针对任务关键型应用程序的解决方案

NetApp AFF A900&#xff1a;适用于数据中心的解决方案 AFF A 系列中的 AFF A900 高端 NVMe 闪存存储功能强大、安全可靠、具有故障恢复能力&#xff0c;提供您为任务关键型企业级应用程序提供动力并保持数据始终可用且安全所需的一切。 AFF A900&#xff1a;针对任务关键型应…...

使用Houdini输出四面体网格并输出tetgen格式

我们的目标是从houdini输出生成的四面体&#xff0c;希望是tetgen格式的。 众所周知&#xff0c;houdini是不能直接输出四面体的。 有三方案去解决&#xff1a; 输出点云ply文件&#xff0c;然后利用tetgen生成网格。输出Hounidi内置的.geo格式文件&#xff0c;然后写个脚本…...

组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比

组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比 目录 组合预测 | MATLAB实现EMD-KPCA-LSTM、EMD-LSTM、LSTM多输入单输出回归预测对比预测效果基本介绍模型描述程序设计参考资料预测效果 基本介绍 MATLAB实现EMD-KP...

【C语言】操作符详解总结(万字)

操作符详解1. 操作符分类2. 算术操作符3. 移位操作符3.1 整数的二进制是怎么形成的3.2 左移操作符3.3 右移操作符4. 位操作符5. 赋值操作符6. 单目操作符6.1 单目操作符介绍6.2 sizeof 和 数组7. 关系操作符8. 逻辑操作符9. 条件操作符9.1 练习19.2 练习210. 逗号表达式11. 下标…...