qt + opengl 给立方体增加阴影
在前几篇文章里面学会了通过opengl实现一个立方体,那么这篇我们来学习光照。
风氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子:
1 环境光照(Ambient Lighting):即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
2 漫反射光照(Diffuse Lighting):模拟光源对物体的方向性影响(Directional Impact)。它是风氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。
3 镜面光照(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。
我们运行下结果如下:
1 我们设置顶点着色器
#version 330 core
//顶点着色器uniform mat4 mvp_matrix;
uniform mat4 model_matrix;layout (location = 0) in vec3 a_position; //空间坐标
layout (location = 1) in vec3 aColor; //颜色
layout (location = 2) in vec2 a_texcoord; //纹理out vec3 FragPos;
out vec2 outtexcoord;
out vec3 outclolor;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
out vec3 Normal;void main()
{gl_Position = projection*view* model * vec4(a_position, 1.0);outtexcoord = a_texcoord;outclolor = aColor;
}
在设置片段着色器
#version 330 core
//像素着色器
in vec2 outtexcoord;
in vec3 outclolor;
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
uniform sampler2D texture;void main()
{//ambient 环境光照float ambientStrength = 0.1; //环境因子vec3 ambient = ambientStrength * lightColor;//环境因子*光照颜色vec3 result = ambient * objectColor;//环境因子*光照位置*物体颜色FragColor = vec4(result, 1.0);}
上立方体代码
#include "widget.h"
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QMouseEvent>
#include <QDateTime>
#include <QtMath>
#include "ui_widget.h"#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QMouseEvent>//GLfloat light_ambient[4]={0.5, 0.5, 0.5, 1.0};
//GLfloat light_diffuse[4]={1.0, 1.0, 1.0, 1.0};
//GLfloat light_position[4]={0.0, 0.0, 2.0, 0.0};GLfloat LightAmbient[4] = {0.5f, 0.5f, 0.5f, 1.0f}; //环境光参数
GLfloat LightDiffuse[4] = {1.0f, 1.0f, 1.0f, 1.0f}; //漫散光参数
GLfloat LightPosition[4] = {0.0f, 0.0f, 2.0f, 1.0f}; //光源位置
//模型主动刷新帧率
#define ACTION_FPS 60
#define LIGHT_COLOR QVector3D(1.2f, 1.0f, 2.0f)
#define EYE_CENTER QVector3D(0.0, 0.0, 3.0)
#define LIGHT_POS QVector3D(2.5f, 2.0f, -1.0f)static const char *vertexShaderSource ="#version 330\n""layout (location = 0) in vec4 vertex;\n""layout (location = 1) in vec4 texCoord;\n""out vec4 texc;\n""out vec3 ourColor;\n""uniform mat4 model;\n""void main(void)\n""{\n"" gl_Position = model * vertex;\n"" texc = texCoord;\n""}\n";static const char *fragmentShaderSource ="#version 330\n""uniform sampler2D texture;\n""in vec3 ourColor;\n""in vec4 texc;\n""void main(void)\n""{\n"" gl_FragColor = texture2D(texture, texc.st)* vec4(1.0f, 0.5f, 0.5f, 1.0);\n""}\n";static const char *vertex1ShaderSource ="#version 330\n""layout (location = 0) in vec4 aPos;\n""layout (location = 1) in vec4 aColor;\n""uniform mat4 model;\n""uniform mat4 view;\n""uniform mat4 projection;\n""out vec4 FragPos;\n""out vec4 Normal;\n""void main(void)\n""{\n"//" FragPos = vec3(model * vec4(aPos, 1.0));\n"// " Normal = mat3(transpose(inverse(model))) * aNormal;\n"" gl_Position = projection * view * model * aPos;\n""}\n";
static const char *vertex2ShaderSource ="#version 330\n""layout (location = 0) in vec4 aPos;\n""out vec3 result;\n""uniform mat4 model;\n""uniform mat4 view;\n""uniform mat4 projection;\n""uniform vec3 objectColor;\n""uniform vec3 lightColor;\n""uniform float ambientStrength;\n""void main(void)\n""{\n"" gl_Position = projection * view * model * aPos;\n"" vec3 ambient = ambientStrength * lightColor;\n"" result = ( ambient ) * objectColor;\n""}\n";
static const char *fragment1ShaderSource ="#version 330\n""in vec3 FragPos;\n""in vec3 Normal;\n""uniform vec3 lightPos;\n""uniform vec3 viewPos;\n""uniform vec3 objectColor;\n""uniform vec3 lightColor;\n""void main(void)\n""{\n"// ambient" float ambientStrength = 0.1;\n"" vec3 ambient = ambientStrength * lightColor;\n"// diffuse" vec3 norm = normalize(Normal);\n"" vec3 lightDir = normalize(lightPos - FragPos);\n"" float diff = max(dot(norm, lightDir), 0.0);\n"" vec3 diffuse = diff * lightColor; \n"// specular" float specularStrength = 0.5;\n"" vec3 viewDir = normalize(viewPos - FragPos);\n"" vec3 reflectDir = reflect(-lightDir, norm);\n"" float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);\n"" vec3 specular = specularStrength * spec * lightColor;\n"" vec3 result = (ambient + diffuse + specular) * objectColor;\n"" gl_FragColor = vec4(result, 1.0);\n""}\n";
static const char *vertexLight1Source ="#version 330\n""layout (location = 0) in vec4 aPos;\n""layout (location = 1) in vec4 aColor;\n""uniform mat4 matrix;\n""uniform mat4 view;\n""uniform mat4 projection;\n""void main(void)\n""{\n"" gl_Position = projection * view * matrix * aPos;\n""}\n";// " gl_FragColor = texture2D(texture, texc.st) *vec4(1.0f, 0.5f, 0.5f, 1.0);\n"
static const char *fragmentLight1Source ="#version 330\n""out vec4 FragColor;\n""void main(void)\n""{\n""FragColor = vec4(1.0);\n""}\n";//static const char *vertexLightSource =
// "#version 330\n"
// "layout (location = 0) in vec4 aPos;\n"
// "layout (location = 1) in vec4 aTexCord;\n"
// "uniform mat4 matrix;\n"
// "uniform mat4 view;\n"
// "uniform mat4 projection;\n"
// "out vec4 texc;\n"
// "void main(void)\n"
// "{\n"
// " gl_Position = projection * view * matrix * aPos;\n"
// " texc = aTexCord;\n"
// "}\n";" gl_FragColor = texture2D(texture, texc.st) *vec4(1.0f, 0.5f, 0.5f, 1.0);\n"
//static const char *fragmentLightSource =
// "#version 330\n"
// "out vec4 FragColor;\n"
// "uniform sampler2D texture;\n"
// "in vec4 texc;\n"
// "uniform vec3 objectColor;\n"
// "uniform vec3 lightColor;\n"
// "void main(void)\n"
// "{\n"
// "gl_FragColor = vec4(lightColor * objectColor, 1.0);\n"
// "}\n";Widget::Widget():QOpenGLWidget(),m_xRos(0),m_yRos(0)
{cam = QVector3D(m_xRos, m_yRos, m_zRos);cameraPos = QVector3D(0, 0, 3);timer = new QTimer;timer->setInterval(20);connect(timer,&QTimer::timeout,this,[=]{qDebug()<<"timeout";// m_xRos+=30;// m_yRos+=30;//rotateBy(2 * 16, +2 * 16, -1 * 16);rotateBy(10 * 16, +10 * 16, -1 * 16);});timer->start();
}
Widget::~Widget()
{makeCurrent();vbo.destroy();for (int i = 0; i < 6; ++i)delete textures[i];delete program;doneCurrent();
}QSize Widget::minimumSizeHint() const
{return QSize(400, 400);
}QSize Widget::sizeHint() const
{return QSize(400, 400);
}void Widget::rotateBy(int xAngle, int yAngle, int zAngle)
{xRot += xAngle;yRot += yAngle;zRot += zAngle;update();timer->stop();
}void Widget::setClearColor(const QColor &color)
{clearColor = color;update();
}void Widget::initializeGL()
{/*vertices = {// ---- 位置---- - 纹理坐标 - ---- 颜色 ----0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,};*/vertices = {// ---- 位置---- - 纹理坐标 - ---- 颜色 ----0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//10.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//20.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//3-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//40.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//5-0.5f, -0.5f, 0.5f,1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f,0.0f, 0.0f, 1.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,};GLushort indices[36] ={/*** 每两个三角形渲染一个面* 注意节点顺序,因为开启了遮挡剔除(glEnable(GL_CULL_FACE)),opengl是根据顶点顺序决定三角形法线方向的,顺时针顺序算出来* 三角形是朝里的就不画了,所以 0 3 1 会导致该三角形不显示,后面的三角形同样的道理注意顶点顺序*///Face 00, 1 , 3, //triangle12, 0, 3, //triangle2//Face 14, 5, 7, //triangle36, 4, 7, //triangle4//Face 28, 9, 11, //triangle510, 8, 11, //triangle6//Face 312, 13, 15, //triangle714, 12, 15, //triangle8//Face 416, 17, 19, //triangle918, 16, 19, //triangle10//Face 520, 21, 23, //triangle1122, 20, 23, //triangle12};initializeOpenGLFunctions();// makeObject();//#define PROGRAM_VERTEX_ATTRIBUTE 0//#define PROGRAM_TEXCOORD_ATTRIBUTE 1// lightinhProgram = new QOpenGLShaderProgram;
// lightinhProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Diffuse.vs");
// lightinhProgram->addShaderFromSourceFile(QOpenGLShader::Fragment,":/Diffuse.fs");
// lightinhProgram->link();
// lightinhProgram->bind();//激活Program对象program = new QOpenGLShaderProgram;program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader.vs");program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader.fs");program->link();program->bind();//激活Program对象vbo.create();vbo.bind(); //绑定到当前的OpenGL上下文,vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));//初始化VAO,设置顶点数据状态(顶点,法线,纹理坐标等)vao.create();vao.bind();// indexBuf.create();
// indexBuf.bind();
// indexBuf.allocate(indices, 36 * sizeof(GLushort));for (int j = 0; j < 6; ++j){textures[j] = new QOpenGLTexture(QImage(QString(":/cube%1.png").arg(j+1)).mirrored());textures[j]->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);textures[j]->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);textures[j]->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);}program->setAttributeBuffer(0, GL_FLOAT, 0, 3, 8 * sizeof(float)); //设置aPos顶点属性program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 3, 8 * sizeof(float)); //设置aColor顶点颜色program->setAttributeBuffer(2, GL_FLOAT, 6 * sizeof(float), 2, 8 * sizeof(float)); //设置aColor顶点颜色program->enableAttributeArray(0); //使能aPos顶点属性program->enableAttributeArray(1); //使能aColor顶点颜色program->enableAttributeArray(2); //使能aColor顶点颜色program->setUniformValue("texture", 0);// lightinhProgram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 8 * sizeof(float)); //设置aPos顶点属性
// lightinhProgram->enableAttributeArray(0); //使能aPos顶点属性projection.setToIdentity();projection.perspective(45,(float)width()/height(),2.0,45.0);//构建透视矩阵,这个可以是固定写法//projection.perspective(45,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法program->setUniformValue("projection", projection);//program1->setUniformValue("projection", projection);//program->setUniformValue("texture", 0);// vao.release();// vbo.release();
}void Widget::paintGL()
{glClearColor(0.1f, 0.1f, 0.1f, 1.0f); //设置清屏颜色// glClearColor(0.1f,0.5f,0.7f,1.0f); //设置清屏颜色glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//开启深度测试glEnable(GL_DEPTH_TEST);//开启遮挡剔除glEnable(GL_CULL_FACE);QMatrix4x4 m;m.translate(0.0f, 0.0f, 0.0f);m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);m.scale(0.5);QMatrix4x4 modelmatrix;//平移至左下角modelmatrix.translate(0.0f, 0.0f, 0.0f);//鼠标滚动旋转角度modelmatrix.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);modelmatrix.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);modelmatrix.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);//滚轮缩放modelmatrix.scale(0.5);program->setUniformValue("model", modelmatrix);QMatrix4x4 view;view.lookAt(EYE_CENTER, QVector3D(0, 0, -20), QVector3D(0, 1, 0));program->setUniformValue("view", view);program->setUniformValue("lightColor", QVector3D(1.0f, 1.0f, 1.0f));//灯光颜色program->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.3f));//物体颜色for (int i = 0; i < 6; ++i) {textures[i]->bind();glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);}
}
void Widget::resizeGL(int width, int height)
{this->glViewport(0,0,width,height); //定义视口区域
}void Widget::mousePressEvent(QMouseEvent *event)
{lastPos = event->pos();
}void Widget::mouseMoveEvent(QMouseEvent *event)
{int dx = event->x() - lastPos.x();int dy = event->y() - lastPos.y();if (event->buttons() & Qt::LeftButton) {rotateBy(8 * dy, 8 * dx, 0);} else if (event->buttons() & Qt::RightButton) {rotateBy(8 * dy, 0, 8 * dx);}lastPos = event->pos();
}void Widget::mouseReleaseEvent(QMouseEvent * /* event */)
{// emit clicked();
}
#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QTimer>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QTimer>namespace Ui {
class Widget;
}QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)class Widget : public QOpenGLWidget, protected QOpenGLFunctions
{Q_OBJECTpublic://using QOpenGLWidget::QOpenGLWidget;Widget();~Widget();QSize minimumSizeHint() const override;QSize sizeHint() const override;void rotateBy(int xAngle, int yAngle, int zAngle);void setClearColor(const QColor &color);void drawLight();signals:// void clicked();protected:void initializeGL() override;void paintGL() override;void resizeGL(int width, int height) override;void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;private:Ui::Widget *ui;QColor clearColor = Qt::black;QPoint lastPos;int xRot = 0;int yRot = 0;int zRot = 0;QOpenGLTexture *textures[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};QOpenGLShaderProgram *program = nullptr;QOpenGLShaderProgram *lightinhProgram = nullptr;QOpenGLBuffer vbo;QVector<float> vertices;QOpenGLVertexArrayObject vao;QOpenGLVertexArrayObject vao1;QTimer* timer;float m_xRos = 0.0f;float m_yRos = 0.0f;float m_zRos = 3.0f;QVector3D cam;int nCount=0;QVector3D cameraPos;QVector3D cameraTarget;QVector3D cameraDirection;float m_viewAngle=0.0f;float radius = 10.0f;float camX= 10.0f;float camZ= 10.0f;QVector3D _cameraPos = {0.0f, 0.0f, 3.0f};QVector3D _cameraFront = {0.0f, 0.0f, -1.0f};QVector3D _cameraUp = {0.0f, 1.0f, 0.0f};float ambientStrength = 0.0;//关照强度QMatrix4x4 projection;QOpenGLTexture *texture;QOpenGLBuffer indexBuf;
};#endif // WIDGET_H
运行下结果如下:
我们可以看到物体并全黑,还是可以看到物体的轮廓,为什么变黑呢?变黑的原因:1.无光源2无
法线。
二 漫反射
环境光照本身不能提供最有趣的结果,但是漫反射光照就能开始对物体产生显著的视觉影响了。漫反射光照使物体上与光线方向越接近的片段能从光源处获得更多的亮度。为了能够更好的理解漫反射光照,请看下图:
图左上方有一个光源,它所发出的光线落在物体的一个片段上。我们需要测量这个光线是以什么角度接触到这个片段的。如果光线垂直于物体表面,这束光对物体的影响会最大化(更亮)。为了测量光线和片段的角度,我们使用一个叫做法向量(Normal Vector)的东西,它是垂直于片段表面的一个向量(这里以黄色箭头表示),我们在后面再讲这个东西。这两个向量之间的角度很容易就能够通过点乘计算出来。
法向量是一个垂直于顶点表面的(单位)向量。由于顶点本身并没有表面(它只是空间中一个独立的点),我们利用它周围的顶点来计算出这个顶点的表面。我们能够使用一个小技巧,使用叉乘对立方体所有的顶点计算法向量,但是由于3D立方体不是一个复杂的形状,所以我们可以简单地把法线数据手工添加到顶点数据中。更新后的顶点数据数组可以在这里找到。试着去想象一下,这些法向量真的是垂直于立方体各个平面的表面的(一个立方体由6个平面组成)。
(修改顶点着色器)
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;out vec3 Normal;
out vec3 FragPos;
out vec4 OutTextcord;void main()
{gl_Position = projection * view * model * vec4(aPos, 1.0);FragPos = vec3(model*vec4(aPos,1.0));Normal = mat3(transpose(inverse(model))) * aNormal;}
修改片段着色器
#version 330 coreout vec4 FragColor;in vec3 Normal;
in vec3 FragPos;
in vec4 OutTextcord;uniform vec3 viewPos;
uniform vec3 lightPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
uniform sampler2D texture;void main()
{float ambientStrength = 0.1;vec3 ambient = ambientStrength * lightColor;// diffusevec3 norm = normalize(Normal);vec3 lightDir = normalize(lightPos - FragPos);float diff = max(dot(norm, lightDir), 0.0);vec3 diffuse = diff * lightColor;// specularfloat specularStrength = 0.5;vec3 viewDir = normalize(viewPos - FragPos);vec3 reflectDir = reflect(-lightDir, norm);float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);vec3 specular = specularStrength * spec * lightColor;vec3 result = (ambient + diffuse + specular) * objectColor;FragColor = vec4(result, 1.0);}
#include "testshadewidget.h"
#define EYE_CENTER QVector3D(0.0, 0.0, 3.0)testshadeWidget::testshadeWidget():QOpenGLWidget(),m_xRos(0),m_yRos(0),m_zRos(0),lightPos(1.0, 1.0, 0.0),m_verticalAngle(45)
{cam = QVector3D(m_xRos, m_yRos, m_zRos);cameraPos = QVector3D(0, 0, 3);timer = new QTimer;timer->setInterval(100);connect(timer,&QTimer::timeout,this,[=]{qDebug()<<"timeout";// m_xRos+=30;// m_yRos+=30;//rotateBy(2 * 16, +2 * 16, -1 * 16);/*if(nDerection==0) //RIGHT{m_xRos += 0.05f;m_yRos = 0;m_zRos = 0;if(m_xRos>=1.0f){m_xRos = 0.0f;timer->stop();}}else if(nDerection==1)//LEFT{m_xRos -= 0.05f;m_yRos = 0;m_zRos = 0;if(m_xRos<=-1.0f){m_xRos = 0.0f;timer->stop();}}else if(nDerection==2)//DOWN{m_xRos = 0;m_yRos -= 0.05f;m_zRos = 0;if(m_yRos<=-1.0f){m_yRos = 0.0f;timer->stop();}}else if(nDerection==3)//UP{m_xRos = 0;m_yRos += 0.05f;m_zRos = 0;if(m_yRos>=1.0f){m_yRos = 0.0f;timer->stop();}}update();// offsetBy(10 * 16, +10 * 16, -1 * 16);*/rotateBy(10 * 16, +10 * 16, -1 * 16);});timer->start();
}testshadeWidget::~testshadeWidget()
{}void testshadeWidget::initializeGL()
{float vertices22[] = { // ---- 顶点 ---- - 法向量 -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,//1 正面 -z垂直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,//2上面 垂直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,//3右边 x-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,//4 左边 -x0.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,//5 后面 z-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,//6下面-y};float vertices11[] = {// ---- 顶点 ---- - 法向量 -// ---- 顶点 ---- - 法向量 - - 纹理 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f,0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f,0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f,0.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f,1.0f, //1 正面 -z垂直0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f,0.0f,-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f,0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f,1.0f, //2上面 垂直0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f,0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f,1.0f, //3右边 x-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f,0.0f,-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f,0.0f,-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f,0.0f,-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f,1.0f, //4 左边 -x0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,0.0f,-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f,0.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,0.0f,0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, //5 后面 z-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f,0.0f,0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f,0.0f,0.5f, 0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f,0.0f,-0.5f, 0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f,1.0f, //6下面-y};vertices = {// ---- 位置---- - 纹理坐标 - ---- 颜色 ----0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//10.5f, 0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//20.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.5f, -0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//3-0.5f, -0.5f, -0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//40.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,-0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//5-0.5f, -0.5f, 0.5f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,0.5f, -0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,-0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f,//6};//绑定OpenGL函数指针?类似GLAD库的作用?initializeOpenGLFunctions();//开启深度测试glEnable(GL_DEPTH_TEST);lightprogram = new QOpenGLShaderProgram;lightprogram->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/base_lighting.vs");lightprogram->addShaderFromSourceFile(QOpenGLShader::Fragment,":/base_lighting.fs");lightprogram->link();lightprogram->bind();//激活Program对象program = new QOpenGLShaderProgram;
// program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/shader.vs");
// program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/shader.fs");program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/Diffuse.vs");program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/Diffuse.fs");program->link();program->bind();//激活Program对象unsigned int indices[] = {0, 1, 3, // first triangle1, 2, 3 // second triangle};vbo.create();vbo.bind(); //绑定到当前的OpenGL上下文,vbo.setUsagePattern(QOpenGLBuffer::StaticDraw);vbo.allocate(vertices22, sizeof(vertices22));//vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));vao.create();vao.bind();// _ebo = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
// _ebo->create();
// if(!_ebo->bind()){
// qDebug() << "ebo绑定失败!";
// }
// _ebo->allocate(indices, sizeof(indices));for (int j = 0; j < 6; ++j){textures[j] = new QOpenGLTexture(QImage(QString(":/cube%1.png").arg(j+1)).mirrored());textures[j]->setMinMagFilters(QOpenGLTexture::LinearMipMapLinear,QOpenGLTexture::Linear);textures[j]->setWrapMode(QOpenGLTexture::DirectionS, QOpenGLTexture::ClampToEdge);textures[j]->setWrapMode(QOpenGLTexture::DirectionT, QOpenGLTexture::ClampToEdge);}program->setAttributeBuffer(0, GL_FLOAT, 0, 3, 6 * sizeof(float)); //设置aPos顶点属性program->setAttributeBuffer(1, GL_FLOAT, 3 * sizeof(float), 3, 6 * sizeof(float)); //设置aColor顶点颜色// program->setAttributeBuffer(2, GL_FLOAT, 6 * sizeof(float), 2, 8 * sizeof(float)); //设置aColor顶点颜色program->enableAttributeArray(0); //使能aPos顶点属性program->enableAttributeArray(1); //使能aColor顶点颜色// program->enableAttributeArray(2); //使能aColor顶点颜色//program->setUniformValue("texture", 0);lightVao.create();lightVao.bind();lightprogram->setAttributeBuffer(0, GL_FLOAT, 0, 3, 6 * sizeof(float));lightprogram->enableAttributeArray(0); // 使能 location = 0的顶点属性aPos
}
void testshadeWidget::rotateBy(int xAngle, int yAngle, int zAngle)
{xRot += xAngle;yRot += yAngle;zRot += zAngle;update();//timer->stop();
}void testshadeWidget::offsetBy(int xPos, int yPos, int zPos)
{m_xRos += xPos;m_yRos += yPos;m_zRos += zPos;update();
}void testshadeWidget::mouseMoveEvent(QMouseEvent *event)
{
// if(event->x() == m_cursorPos.x() && m_cursorPos.y() == event->y())
// return;// QPoint MovePos = QCursor::pos();
// QPoint currentPos = mapFromGlobal(MovePos);
// int xoffset = 0;
// int yoffset = 0;
// xoffset = currentPos.x() - m_cursorPos.x();
// yoffset = currentPos.y() - m_cursorPos.y();// qDebug()<<"1111111111"<<m_xRos;
// if(xoffset>0 )
// {
// m_xRos += 0.1;
// m_yRos = 0;
// if(m_xRos>=1.0f)
// {
// m_xRos = 0.0f;
// m_yRos = 0.0f;
// }
// }
// else if(xoffset<0 )
// {
// m_xRos -= 0.1;
// m_yRos = 0;
// if(m_xRos<=-1.0f)
// {
// m_xRos = 0.0f;
// m_yRos = 0.0f;
// }
// }
// else if(yoffset>0)
// {
// m_xRos = 0;
// m_yRos -= 0.1;
// if(m_yRos<=-1.0f)
// {
// m_xRos = 0.0f;
// m_yRos = 0.0f;
// }
// }
// else if(yoffset<0)
// {
// m_xRos = 0;
// m_yRos += 0.1;
// if(m_yRos>=1.0f)
// {
// m_xRos = 0.0f;
// m_yRos = 0.0f;
// }
// }
// update();
// m_cursorPos = currentPos;//timer->start();//m_yRos += yPos;//update();//m_yRos += yoffset;//qDebug()<<"mouseMoveEvent"<<xoffset<<yoffset<<m_xRos<<m_yRos<<xPos<<yPos;//qDebug()<<"m_cursorPos"<<(m_xRos==1.0);//m_cursorPos = QPoint(event->x(),event->y());}void testshadeWidget::mouseReleaseEvent(QMouseEvent *event)
{if(event->x() == m_cursorPos.x() && m_cursorPos.y() == event->y())return;QPoint MovePos = QCursor::pos();QPoint currentPos = mapFromGlobal(MovePos);int xoffset = 0;int yoffset = 0;xoffset = currentPos.x() - m_cursorPos.x();yoffset = currentPos.y() - m_cursorPos.y();if( xoffset>0 && (yoffset>=-15 && yoffset<=15)){nDerection = 0;}else if(xoffset<0 && (yoffset>=-15 && yoffset<=15)){nDerection = 1;}else if(yoffset>0 && (xoffset>=-15 && xoffset<=15))//down{nDerection = 2;}else if(yoffset<0 && (xoffset>=-15 && xoffset<=15))//up{nDerection = 3;}qDebug()<<"1111111111"<<m_xRos<<nDerection<<xoffset<<yoffset;timer->start();
}void testshadeWidget::mousePressEvent(QMouseEvent *event)
{if(event->button() == Qt::LeftButton){m_cursorGlobalPos = QCursor::pos();m_cursorPos = mapFromGlobal(m_cursorGlobalPos);}
}void testshadeWidget::paintGL()
{glClearColor(0.1f, 0.1f, 0.1f, 1.0f); //设置清屏颜色glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// //开启深度测试//glEnable(GL_DEPTH_TEST);
// //开启遮挡剔除// glEnable(GL_CULL_FACE);QMatrix4x4 m;m.translate(m_xRos, m_yRos, m_zRos);m.rotate(xRot / 16.0f, 1.0f, 0.0f, 0.0f);m.rotate(yRot / 16.0f, 0.0f, 1.0f, 0.0f);m.rotate(zRot / 16.0f, 0.0f, 0.0f, 1.0f);m.scale(0.5);program->bind();QMatrix4x4 view;view.lookAt(QVector3D(0,0,3), QVector3D(0,0,3)+QVector3D(0,0,-1), QVector3D(0,1,0));QMatrix4x4 projection;projection.perspective(45.0f,float(this->width())/float(this->height()),0.1f,100.0f);program->setUniformValue("model", m);program->setUniformValue("view", view);program->setUniformValue("projection", projection);program->setUniformValue("objectColor", QVector3D(1.0f, 0.5f, 0.3f));//物体颜色program->setUniformValue("lightColor", QVector3D( 1.0f, 1.0f, 1.0f));program->setUniformValue("lightPos", QVector3D(1.2f, 1.0f, 2.0f));//光位置for(int i=0;i<6;i++){glDrawArrays(GL_TRIANGLE_FAN, i*4, 4);}vao.bind(); lightprogram->bind();QMatrix4x4 model;model.translate(0.5f, 0.5f, 0.5f);model.scale(0.2);lightprogram->setUniformValue("view", view);lightprogram->setUniformValue("model", model);lightprogram->setUniformValue("projection", projection);lightVao.bind();//glDrawArrays(GL_TRIANGLES, 0, 36);for(int i=0;i<6;i++){glDrawArrays(GL_TRIANGLE_FAN, i*4, 4);}}void testshadeWidget::resizeGL(int width, int height)
{
// QMatrix4x4 projection;
// projection.perspective(m_verticalAngle, width/height, 0.01, 100);
// // m_verticalAngle: 设置垂直角度(值越大,那么物体越小)
// // width()/height(): 设置宽高比
// // 0.1 100: 设置近远平面距离
// glUseProgram(program->programId());
// program->setUniformValue("projection", projection);this->glViewport(0,0,width,height); //定义视口区域this->update();
}
#ifndef TESTSHADEWIDGET_H
#define TESTSHADEWIDGET_H#include <QWidget>
#include <QOpenGLWidget>
#include <QOpenGLExtraFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLShaderProgram>
#include <QOpenGLVertexArrayObject>
#include <QTimer>
#include <QOpenGLTexture>
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QOpenGLBuffer>
#include <QOpenGLVertexArrayObject>
#include <QTimer>
#include <QMouseEvent>QT_FORWARD_DECLARE_CLASS(QOpenGLShaderProgram);
QT_FORWARD_DECLARE_CLASS(QOpenGLTexture)
class testshadeWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
public:testshadeWidget();~testshadeWidget();
protected:void initializeGL() override;void paintGL() override;void resizeGL(int width, int height) override;void rotateBy(int xAngle, int yAngle, int zAngle);void mouseMoveEvent(QMouseEvent *event) override;void mouseReleaseEvent(QMouseEvent *event) override;void mousePressEvent(QMouseEvent *event) override;void offsetBy(int xPos, int yPos, int zPos);
private:QOpenGLTexture *textures[6] = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};QOpenGLShaderProgram *program = nullptr;QOpenGLBuffer vbo;QVector<float> vertices;QOpenGLVertexArrayObject vao;QTimer* timer;float m_xRos = 0.0f;float m_yRos = 0.0f;float m_zRos = 0.0f;QVector3D cameraPos;QVector3D cameraTarget;QVector3D cameraDirection;QOpenGLTexture *texture;QMatrix4x4 projection;QVector3D cam;int xRot = 0;int yRot = 0;int zRot = 0;QPoint m_cursorPos;QPoint m_cursorGlobalPos;int nDerection=0;QVector3D lightPos;float m_verticalAngle; // 视角缩放QOpenGLShaderProgram *lightprogram = nullptr;QOpenGLVertexArrayObject lightVao;QOpenGLBuffer *_ebo;};#endif // TESTSHADEWIDGET_H
我们运行下
这里是不是有阴影和光照了。
我们来解释下方向量的定义。
我们看下正面这个面,垂直于这个面的是不是Z轴,那就是z轴是1,其他是0,在看垂直于这个面的是不是Z轴反方向,所以是-1,所以法向量是0,0,-1。
相关文章:

qt + opengl 给立方体增加阴影
在前几篇文章里面学会了通过opengl实现一个立方体,那么这篇我们来学习光照。 风氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。下面这张图展示了这些光照分量看起来的样子: 1 环境光照(Ambient …...
Webpack,Vite打包的理解
Webpack 和 Vite 都是现代前端开发中常用的构建工具,用于打包和优化项目代码。尽管它们的目标相似,但在设计理念、工作方式和适用场景上存在显著差异。 Webpack Webpack 是一个模块打包工具,主要用于将多个模块(如 JavaScript、…...
Vue 3 30天精进之旅:Day 25 - PWA支持
一、引言 在前面的24天中,我们已经深入探讨了Vue 3的许多核心概念和高级特性。今天,我们将进入一个全新的领域——PWA(Progressive Web App)。PWA是一种现代Web应用程序的开发模式,它结合了Web和原生应用的优点&#…...

机器学习-生命周期
假如一个用户向银行申请贷款,银行该如何对这个用户进行评估?很明显,银行首先需要调查清楚该用户的资金储备情况和信用历史等,然后再决定是否向其放款。 整个机器学习生命周期如下图所示: 1、定义问题 在使用机器学习中的术语表…...

大道至简 少字全意 易经的方式看 缓存 mybatis缓存 rendis缓存场景 案例
目录 介绍 mybatis缓存 一级缓存 1.是什么 2.特点 3.场景 mybatis 二级缓存 1.是什么 2.特点 3.配置步骤 注意 一级缓存问题 二级缓存问题 扩展 1.MyBatis集成 Redis 2.直接使用Redis redis 缓存 一、String 字符串 二、Llst 列表 三、Hash 哈希 四、Set…...
如何使用 Flutter DevTools 和 PerformanceOverlay 监控性能瓶颈
使用 Flutter DevTools 和 PerformanceOverlay 监控性能瓶颈:详细分析与实战 在开发 Flutter 应用时,性能问题可能会导致用户体验下降,比如页面卡顿、掉帧、内存泄漏等。为了定位和解决这些问题,Flutter 提供了强大的性能监控工具…...
TS中Any和Unknown有什么区别
在 TypeScript 中,any 和 unknown 都是顶级类型(top types),表示可以是任何类型的值。但它们在使用和行为上有显著区别,主要体现在类型安全性和使用方式上。 1. any 类型 特点: any 是 TypeScript 中最宽松…...

【Mpx】-环境搭建项目创建(一)
一.概述 官方文档:https://mpxjs.cn/guide/basic/start.html mpxjs/cli文档: https://github.com/mpx-ecology/mpx-cli 二.脚手架安装&创建项目 2.1项目创建 //脚手架安装 npm i -g mpxjs/cli //创建Mpx项目 mpx create mpx-demo(项目名称) //安装依赖 np…...

PyQt加载UI文件
1.动态加载 import sys from PySide6 import QtCore,QtWidgets from PySide6.QtWidgets import * from PySide6.QtUiTools import QUiLoaderclass readfile(QWidget):def __init__(self):super().__init__()self.uiQUiLoader().load("test.ui",self) self.__c…...

Java面试第二山!《计算机网络》!
在 Java 面试里,计算机网络知识是高频考点,今天就来盘点那些最容易被问到的计算机网络面试题,帮你轻松应对面试,也方便和朋友们一起探讨学习。 一、HTTP 和 HTTPS 的区别 1. 面试题呈现 HTTP 和 HTTPS 有什么区别?在…...

Mysql基础语句
一、 MySQL语句 在熟悉安装及访问 MySQL 数据库以后, 接下来将学习使用 MySQL 数据库的基本操作,这也是在服务器运维工作中不可或缺的知识。 本节中的所有数据库语句均在“MySQL>”操作环境中执行 MySQL 是一套数据库管理系统,在每台 MySQ…...

连接池Java导包
目录 一、Java导包 二、 数据库连接池 1. 概述 2. 常见参数 3. 常见连接池 4. Druid连接池(重点) 核心功能: 使用方法: 导入依赖 配置连接池: 代码配置: 配置文件: 获取连接&#…...
一些耳朵起茧子的名词解释
1 web应用 1.1 web应用的概念 Web应用(Web Application) 是一种通过浏览器访问的软件程序,它运行在服务器上,用户通过网络(如互联网或内网)与它进行交互。与传统网站(主要提供静态内容&#x…...
HBuilderX中,VUE生成随机数字,vue调用随机数函数
Vue 中可以使用JavaScript的Math.random() 函数生成随机数,它会返回 0 到 1 之间的浮点数, 如果需要0到1000之前的随机数,可以对生成的随机数乘以1000,再用js的向下取整函数Math.floor() 。 let randNum Math.random(); // 生成…...
C#发送邮件
基础调用类: public class EmailHelper{/// <summary>/// 发件人名称/// </summary>public string MailName { get; set; }/// <summary>/// 收件人/// </summary>public string MailTo { get; set; }/// <summary>/// 密送/// <…...
2025-2-19学习笔记 : this关键字,constructor结构体,class类
1、This关键字 在 JavaScript 中,this 是一个关键字,其指向取决于函数的调用方式。理解 this 的指向对于编写正确的代码至关重要。以下是 this 在不同情况下的指向规则: 1. 全局函数调用 当函数在全局作用域中被调用时,this 指向…...

避坑:过早的文件结束符(EOF):解决“git clone龙蜥OS源码失败”的失败过程
避坑:过早的文件结束符(EOF):解决“git clone龙蜥OS源码失败”的失败过程 安装Anolis OS 8.9 下载AnolisOS-8.9-x86_64-dvd.iso并安装。 使用uname -a查看内核版本为5.10.134-18.an8.x86_64。 [rootlocalhost cloud-kernel]# c…...

【Quest开发】全身跟踪
软件:Unity 2022.3.51f1c1、vscode、Meta XR All in One SDK V72 硬件:Meta Quest3 最终效果:能像meta的操作室沉浸场景一样根据头盔移动来推断用户姿势,实现走路、蹲下、手势匹配等功能 需要借助UnityMovement这个包 GitHub …...

通过BingAPI爬取Bing半个月内壁纸
通过BingAPI爬取Bing半个月内壁纸 一、前言二、爬虫代码三、代码说明 一、前言 爬取Bing搜索网站首页壁纸的方式主要有两种,第一种为间接爬取,即并不直接对Bing网站发起请求,而是对那些收集汇总了Bing壁纸的网站发起请求,爬取图片…...
Linux升级Anacodna并配置jupyterLab
在使用 Anaconda 的过程中,随着项目和需求的发展,可能需要升级 Anaconda 的 Base 环境中的 Python 版本。本文将详细介绍如何安全地进行升级,包括步骤、代码示例与最终流程图。 升级 Python 一、环境准备 在进行任何升级之前,建…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式
点一下关注吧!!!非常感谢!!持续更新!!! 🚀 AI篇持续更新中!(长期更新) 目前2025年06月05日更新到: AI炼丹日志-28 - Aud…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...

从“安全密码”到测试体系:Gitee Test 赋能关键领域软件质量保障
关键领域软件测试的"安全密码":Gitee Test如何破解行业痛点 在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的"神经中枢"。从国防军工到能源电力,从金融交易到交通管控,这些关乎国计民生的关键领域…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...