OpenGL 材质实现

news2024/11/17 10:01:04

1.简介

在现实世界里,每个物体会对光产生不同的反应。比如,钢制物体看起来通常会比陶土花瓶更闪闪发光,一个木头箱子也不会与一个钢制箱子反射同样程度的光。有些物体反射光的时候不会有太多的散射,因而产生较小的高光点,而有些物体则会散射很多,产生一个有着更大半径的高光点。如果我们想要在OpenGL中模拟多种类型的物体,我们必须针对每种表面定义不同的材质(Material)属性。

当描述一个表面时,我们可以分别为三个光照分量定义一个材质颜色(Material Color):

  • 环境光照(Ambient Lighting)
  • 漫反射光照(Diffuse Lighting)
  • 镜面光照(Specular Lighting)

通过为每个分量指定一个颜色,我们就能够对表面的颜色输出有细粒度的控制了。

#version 330 core
struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
}; 

uniform Material material;
  • ambient材质向量定义了在环境光照下这个表面反射的是什么颜色,通常与表面的颜色相同。
  • diffuse材质向量定义了在漫反射光照下表面的颜色。漫反射颜色(和环境光照一样)也被设置为我们期望的物体颜色。
  • specular材质向量设置的是表面上镜面高光的颜色(或者甚至可能反映一个特定表面的颜色)。
  • shininess影响镜面高光的散射/半径。

下图展示了几组现实世界的材质参数值对我们的立方体的影响:

2.设置材质

我们在片段着色器中创建了一个材质结构体的uniform,我们希望修改一下光照的计算来遵从新的材质属性。由于所有材质变量都储存在一个结构体中,我们可以从uniform变量material中访问它们:

void main()
{    
    // 环境光
    vec3 ambient = lightColor * material.ambient;

    // 漫反射 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = lightColor * (diff * material.diffuse);

    // 镜面光
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = lightColor * (spec * material.specular);  

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}

我们现在可以通过设置适当的uniform来设置应用中物体的材质了。

    m_program->setUniformValue("material.ambient", 1.0f, 0.5f, 0.31f);
    m_program->setUniformValue("material.diffuse",  1.0f, 0.5f, 0.31f);
    m_program->setUniformValue("material.specular", 0.5f, 0.5f, 0.5f);
    m_program->setUniformValue("material.shininess", 32.0f);

3.示例

源码:

#version 330 core

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};

uniform Material material;


out vec4 color;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;

in vec3 outNormal;
in vec3 FragPos;

void main()
{
    // 环境光
    vec3 ambient = lightColor * material.ambient;

    // 漫反射
    vec3 norm = normalize(outNormal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = lightColor * (diff * material.diffuse);

    // 镜面光
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = lightColor * (spec * material.specular);

    vec3 result = ambient + diffuse + specular;
    color = vec4(result, 1.0);
};
#ifndef MYOPENGLWIDGET_H
#define MYOPENGLWIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions_3_3_Core>
#include <QImage>
#include <QOpenGLShaderProgram>
#include <QVector3D>
#include <QVector>
#include <QKeyEvent>

class MyOpenGLWidget : public QOpenGLWidget,public QOpenGLFunctions_3_3_Core
{
public:
    MyOpenGLWidget(QWidget *parent = nullptr);

protected:
    virtual void initializeGL();
    virtual void paintGL();
    virtual void resizeGL(int w, int h);

    void keyPressEvent(QKeyEvent *event);

    void mouseMoveEvent(QMouseEvent *event);

    void wheelEvent(QWheelEvent *event);


private:
    QOpenGLShaderProgram *m_program;

    QOpenGLShaderProgram *m_lightProgram;

    QVector3D cameraPos;
    QVector3D cameraTarget;
    QVector3D cameraDirection;
    QVector3D up;
    QVector3D cameraRight;
    QVector3D cameraUp;
    QVector3D cameraFront;
    float cameraSpeed;
};

#endif // MYOPENGLWIDGET_H



#include "myopenglwidget.h"
#include <QMatrix4x4>
#include <QTime>
#include <QTimer>
#include <math.h>
#include <QDebug>

float vertices[] = {
    //位置                 //法向量
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
     0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
     0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
     0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f,  0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f,  0.0f, -1.0f,

    -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
    -0.5f,  0.5f,  0.5f,  0.0f,  0.0f, 1.0f,
    -0.5f, -0.5f,  0.5f,  0.0f,  0.0f, 1.0f,

    -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f,  0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f, -0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f, -0.5f,  0.5f, -1.0f,  0.0f,  0.0f,
    -0.5f,  0.5f,  0.5f, -1.0f,  0.0f,  0.0f,

     0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
     0.5f,  0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  1.0f,  0.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  1.0f,  0.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  1.0f,  0.0f,  0.0f,

    -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
     0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    -0.5f, -0.5f,  0.5f,  0.0f, -1.0f,  0.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, -1.0f,  0.0f,

    -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
     0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    -0.5f,  0.5f,  0.5f,  0.0f,  1.0f,  0.0f,
    -0.5f,  0.5f, -0.5f,  0.0f,  1.0f,  0.0f
};

GLuint indices[] = {
    0, 1, 3,
    1, 2, 3
};


GLuint VBO,VAO,EBO,lightVAO;
GLuint shaderProgram;

QVector3D lightPos(1.2f,1.0f,2.0f);
QVector3D lightColor(1.0f,1.0f,1.0f);
QVector3D objectColor(1.0f,0.5f,0.31f);

QTimer *timer;
QTime gtime;

float fov = 45.0f;

MyOpenGLWidget::MyOpenGLWidget(QWidget *parent)
    : QOpenGLWidget(parent)
{
    cameraPos = QVector3D( 0.0f,  0.0f,  5.0f);//摄像机位置
    cameraTarget = QVector3D( 0.0f,  0.0f,  0.0f);//摄像机看到的位置
    cameraDirection = QVector3D(cameraPos - cameraTarget);//摄像机的方向
    cameraDirection.normalize();

    up = QVector3D(0.0f,  1.0f,  0.0f);
    cameraRight = QVector3D::crossProduct(up,cameraDirection);//两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量
    cameraRight.normalize();

    cameraUp = QVector3D::crossProduct(cameraDirection,cameraRight);
    cameraFront = QVector3D( 0.0f,  0.0f,  -1.0f);

    timer = new QTimer();
    timer->start(50);
    gtime.start();
    connect(timer,&QTimer::timeout,[=]{
        update();
    });

    setFocusPolicy(Qt::StrongFocus);
    //setMouseTracking(true);
}

void MyOpenGLWidget::initializeGL()
{
    initializeOpenGLFunctions();

    m_program = new QOpenGLShaderProgram();
    m_program->addShaderFromSourceFile(QOpenGLShader::Vertex,":/shapes.vert");
    m_program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shapes.frag");
    m_program->link();
    qDebug()<<m_program->log();

    m_lightProgram = new QOpenGLShaderProgram();
    m_lightProgram->addShaderFromSourceFile(QOpenGLShader::Vertex,":/light.vert");
    m_lightProgram->addShaderFromSourceFile(QOpenGLShader::Fragment,":/light.frag");
    m_lightProgram->link();


    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &VBO);

    glBindVertexArray(VAO);//绑定VAO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把顶点数据复制到缓冲的内存中GL_STATIC_DRAW :数据不会或几乎不会改变。

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat)));
    glEnableVertexAttribArray(0);

    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);


    glGenVertexArrays(1, &lightVAO);
    glBindVertexArray(lightVAO);//绑定VAO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//顶点缓冲对象的缓冲类型是GL_ARRAY_BUFFER
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);//把顶点数据复制到缓冲的内存中GL_STATIC_DRAW :数据不会或几乎不会改变。

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);

    m_program->bind();
    m_program->setUniformValue("lightPos",lightPos);
    m_program->setUniformValue("viewPos",cameraPos);
    m_program->setUniformValue("lightColor",lightColor);
    m_program->setUniformValue("material.ambient", 1.0f, 0.5f, 0.31f);
    m_program->setUniformValue("material.diffuse",  1.0f, 0.5f, 0.31f);
    m_program->setUniformValue("material.specular", 0.5f, 0.5f, 0.5f);
    m_program->setUniformValue("material.shininess", 32.0f);

    m_lightProgram->bind();
    m_lightProgram->setUniformValue("lightColor",lightColor);

    glBindVertexArray(0);//解绑VAO
}

void MyOpenGLWidget::paintGL()
{
    glClearColor(0.2f,0.3f,0.3f,1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 model;
    QMatrix4x4 view;
    float time = gtime.elapsed()/50.0;

    QMatrix4x4 projection;
    projection.perspective(fov,(float)( width())/(height()),0.1,100);

    view.lookAt(cameraPos,cameraPos + cameraFront,up);

    m_program->bind();
    m_program->setUniformValue("projection",projection);
    m_program->setUniformValue("view",view); 

    glBindVertexArray(VAO);//绑定VAO

    model.rotate(time,1.0f,5.0f,0.5f);
    m_program->setUniformValue("model",model);
    glDrawArrays(GL_TRIANGLES,0,36);

    m_lightProgram->bind();
    m_lightProgram->setUniformValue("projection",projection);
    m_lightProgram->setUniformValue("view",view);

    model.setToIdentity();
    model.translate(lightPos);
    model.rotate(1.0f,1.0f,5.0f,0.5f);
    model.scale(0.2);
    m_lightProgram->setUniformValue("model",model);
    glBindVertexArray(lightVAO);//绑定VAO
    glDrawArrays(GL_TRIANGLES,0,36);
}

void MyOpenGLWidget::resizeGL(int w, int h)
{

}

void MyOpenGLWidget::keyPressEvent(QKeyEvent *event)
{
    qDebug()<<event->key();
    cameraSpeed = 2.5 * 100 / 1000.0;
    switch (event->key()) {
    case Qt::Key_W:{
        cameraPos += cameraSpeed * cameraFront;
    }
        break;
    case Qt::Key_S:{
        cameraPos -= cameraSpeed * cameraFront;
    }
        break;
    case Qt::Key_A:{
        cameraPos -= cameraSpeed * cameraRight;
    }
        break;
    case Qt::Key_D:{
        cameraPos += cameraSpeed * cameraRight;
    }
        break;
    default:
        break;

    }
    update();
}
float PI = 3.1415926;
QPoint deltaPos;
void MyOpenGLWidget::mouseMoveEvent(QMouseEvent *event)
{
//    static float yaw = -90;
//    static float pitch = 0;
//    static QPoint lastPos(width()/2,height()/2);
//    auto currentPos = event->pos();
//    deltaPos = currentPos-lastPos;
//    lastPos=currentPos;
//    float sensitivity = 0.1f;
//    deltaPos *= sensitivity;
//    yaw += deltaPos.x();
//    pitch -= deltaPos.y();
//    if(pitch > 89.0f) pitch = 89.0f;
//    if(pitch < -89.0f) pitch = -89.0f;
//    cameraFront.setX(cos(yaw*PI/180.0) * cos(pitch *PI/180));
//    cameraFront.setY(sin(pitch*PI/180));
//    cameraFront.setZ(sin(yaw*PI/180) * cos(pitch *PI/180));
//    cameraFront.normalize();
//    update();
}

void MyOpenGLWidget::wheelEvent(QWheelEvent *event)
{
    if(fov >= 1.0f && fov <= 75.0f)
        fov -= event->angleDelta().y()/120;
    if(fov <= 1.0f)
        fov = 1.0f;
    if(fov >= 75.0f)
        fov = 75.0f;

    update();
}

这个物体太亮了。物体过亮的原因是环境光、漫反射和镜面光这三个颜色对任何一个光源都全力反射。

我们可以用同样的方式影响光源的漫反射和镜面光强度。我们希望为光照属性创建类似材质结构体的东西:

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Light light;

和材质uniform一样,我们需要更新片段着色器:

vec3 ambient  = light.ambient * material.ambient;
vec3 diffuse  = light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);

我们接下来在应用中设置光照强度:

    m_program->setUniformValue("light.ambient",  QVector3D(0.2f, 0.2f, 0.2f));
    m_program->setUniformValue("light.diffuse",  QVector3D(0.5f, 0.5f, 0.5f));
    m_program->setUniformValue("light.specular", QVector3D(1.0,1.0,1.0));

结果如下:

4.不同颜色的光

设置一个随时间改变的光的颜色。

    lightColor.setX(sin(time/100 * 2.0f));
    lightColor.setY(sin(time/100 * 0.7f));
    lightColor.setZ(sin(time/100 * 1.3f));

    QVector3D diffuseColor = lightColor   * QVector3D(0.5f,0.5f,0.5f); // 降低影响
    QVector3D ambientColor = diffuseColor * QVector3D(0.2f,0.2f,0.2f); // 很低的影响

    m_program->setUniformValue("material.ambient", ambientColor);
    m_program->setUniformValue("material.diffuse",  diffuseColor);

 

5.完整源码

https://download.csdn.net/download/wzz953200463/87893740icon-default.png?t=N4P3https://download.csdn.net/download/wzz953200463/87893740

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

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

相关文章

35岁被淘汰?软件测试工程师职业生涯规划,从技术到管理...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 入门阶段&#xf…

Parallel Desktop中按照的centos在切换root用户时,密码正确,但一直切换不成功,显示su: Authentication failure

目录 一、出现问题二、分析问题三、解决问题四、参考资料 一、出现问题 我的密码明明是输入正确的&#xff0c;但又一直给我报下面的错误 二、分析问题 我怀疑是我密码记错了&#xff0c;所以我点击Log Out&#xff0c;重新去输入了一下密码&#xff0c;发现是正确的我确认…

[学习笔记] [机器学习] 9. 朴素贝叶斯(概率基础、联合概率、条件概率、贝叶斯公式、情感分析)

视频链接数据集下载地址&#xff1a;无需下载 学习目标&#xff1a; 4. 说明条件概率与联合概率 5. 说明贝叶斯公式、以及特征独立的关系 6. 记忆贝叶斯公式 7. 知道拉普拉斯平滑系数 8. 应用贝叶斯公式实现概率的计算 9. 会使用朴素贝叶斯对商品评论进行情感分析 1. 朴素贝叶…

对象进阶-继承、原型-原型链

工厂方法创建对象 我们之前已经学习了如何创建一个对象&#xff0c;那我们要是想要创建多个对象又该怎么办&#xff1f;聪明的同学可能会说&#xff0c;直接在写几个对象不就好了吗&#xff1f;比如下边的代码&#xff1a; var person1 {name: "孙悟空",age: 18,s…

APP自动化测试,Appium+PO模式+Pytest框架实战—项目案例

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 PO模式&#xff1…

如何解决GEE导出影像的Nodata值在ArcGIS中无法正常显示?

目录 01 ArcGIS对于GEE掩膜影像的Nodata值的说明 02 处理方法 2.1 方法1-GEE修改掩膜值 Arguments: Returns: Image 2.2 方法2-ArcGIS重新赋值Nodata&#xff08;推荐&#xff09; 01 ArcGIS对于GEE掩膜影像的Nodata值的说明 当在GEE中进行掩膜后&#xff0c;将影像在Ar…

打造极简风格动效 —— 5 分钟轻松实现惊艳、震撼人心的视觉效果

前期回顾 是不是在为 API 烦恼 &#xff1f;好用免费的api接口大全呼之欲出_免流接口api_彩色之外的博客-CSDN博客APi、常用框架、UI、文档—— 整理合并https://blog.csdn.net/m0_57904695/article/details/130459417?spm1001.2014.3001.5501 &#x1f44d; 本文专栏&…

20道嵌入式经典面试题(附答案)

1.嵌入式系统中经常要用到无限循环&#xff0c;如何用C编写死循环 答&#xff1a;while(1){} 或者 for(;;) 2.程序的局部变量存在于哪里&#xff0c;全局变量存在于哪里&#xff0c;动态申请数据存在于哪里。 答&#xff1a;程序的局部变量存在于栈区&#xff1b;全局变量存在…

【Linux】浅谈文件原理与操作

目录 问题引入 浅谈文件原理 文件操作 文件的打开与关闭 open close write与read 再谈C库文件操作 问题引入 &#x1f338;以前我们学过C语言的文件操作&#xff0c;而不同语言的文件操作都是不一样的&#xff0c;我们该如何理解这一现象&#xff0c;能不能用一种统一…

有关 string 类的练习(下)

目录 一、反转字符串 II 二、反转字符串中的单词 III 三、找出字符串中第一个只出现一次的字符 四、字符串相乘 五、把字符串转换成整数 一、反转字符串 II 给定一个字符串 s 和一个整数 k&#xff0c;从字符串开头算起&#xff0c;每计数至 2k 个字符&#xff0c;就反转…

Spring,注解开发

Spring是一个轻量级的控制反转&#xff08;IOC&#xff09;和面向切面编程&#xff08;AOP&#xff09;的框架 1、组成 spring七大模块详解 2、IOC理论推导 传统的开发 (pojo层、DAO层和业务层&#xff09; &#xff08;1&#xff09;UserDao &#xff08;2) UserDaoImpl (3)…

天狼星-大熊座 Ursa Major SIRIUS

大熊座 Ursa Major SIRIUS 键盘说明 客制化键盘&#xff1a; 大熊座 Ursa Major SIRIUS 配列&#xff1a; 75 键帽&#xff1a;KCA-HelloWorld-Black 双模&#xff1a; 蓝牙-分裂方案 驱动配置&#xff1a;Link Lab 驱动设置软件 键盘操作 键盘说明参考&#xff1a;键位配…

利用WinDbg查看堆栈中方法入参的值4(C#)

由于作者水平有限&#xff0c;如有写得不对的地方&#xff0c;请指正。 使用WinDbg的过程中&#xff0c;坑特别的多&#xff0c;对版本要求比较严格&#xff0c;如&#xff1a; 1 32位应用程序导出的Dump文件要用32位的WinDbg打开&#xff0c;想要没有那么多的问题&#xf…

海底光缆位置探测技术的应用概述

1. 概述 海底光缆运行在地质环境复杂的海洋环境中&#xff0c;地震、海床塌陷、滑坡、洋流变化、海洋生物及船只抛锚都有可能造成光缆断裂、破损&#xff0c;影响光缆的安全运行。海底光缆一旦遭受损坏&#xff0c;其造成的经济损失无法估量。因此在海洋开发工程实施前&#xf…

Web转化为APP——YonBIP(APICloud迁移版)

目录 平台注册 平台使用 设计封面&#xff08;端设置&#xff09; APP证书 代码上传 移动打包 运营管理和移动插件 众所周知&#xff0c;APP开发是一件非常麻烦的事&#xff0c;很多擅长Web开发的人未必擅长APP开发。那么作为一个Web开发者&#xff0c;可不可以有很方便…

基于prefix tuning + Bert的标题党分类器

文章目录 背景一、Prefix-Tuning介绍二、分类三、效果四、参阅 背景 近期, CSDN博客推荐流的标题党博客又多了起来, 先前的基于TextCNN版本的分类模型在语义理解上能力有限, 于是, 便使用的更大的模型来优化, 最终准确率达到了93.7%, 还不错吧. 一、Prefix-Tuning介绍 传统的…

Redis之Redisson原理详解

文章目录 1 Redisson1.1 简介1.2 与其他客户端比较1.3 操作使用1.3.1 pom.xml1.3.2 配置1.3.3 启用分布式锁 1.4 大致操作原理1.5 RLock1.5.1 RLock如何加锁1.5.2 解锁消息1.5.3 锁续约1.5.4 流程概括 1.6 公平锁1.6.1 java中公平锁1.6.2 RedissonFairLock1.6.3 公平锁加锁步骤…

50 Projects 50 Days - Form Input Wave 学习记录

项目地址 Form Input Wave 展示效果 Form Input Wave 实现思路 简单的登陆界面结构&#xff0c;只是在输入框聚焦时标题提示文字会有一个字母逐渐向上跳动的动画效果&#xff0c;这需要针对每个字符单独设置变换的延时&#xff0c;可以考虑在JavaScript中处理这部分逻辑&am…

2017~2018学年《信息安全》考试试题(A1卷)

北京信息科技大学 2017 ~2018 学年第二学期《信息安全》考试试题 (A 卷) 课程所在学院:计算机学院 适用专业班级:计科 1504-6、重修 考试形式:闭卷 一、单选题(本题满分 20 分&#xff0c;共含 10 道小题&#xff0c;每小题 2 分) 网络安全是指网络系统的硬件、软件及( C )的…

【头歌-Python】Python第九章作业(初级)第5关

第5关&#xff1a;绘制程序设计语言饼图 任务描述 列表labels和sizes中的数据分别是目前主流程序设计语言及其热度数据&#xff08;百分比&#xff09;&#xff0c;请根据这些数据绘制饼图&#xff0c;并将Python程序设计语言所在区域突出0.1显示。 labels [C语言, Python…