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

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,//1

          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,//2


          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,//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,//4


           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,//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 0
       0,  1 , 3, //triangle1
       2,  0,  3, //triangle2
       //Face 1
       4,  5,  7, //triangle3
       6,  4,  7, //triangle4
       //Face 2
       8,  9,  11, //triangle5
       10,  8,  11, //triangle6
       //Face 3
       12,  13,  15, //triangle7
       14,  12,  15, //triangle8
       //Face 4
       16,  17,  19, //triangle9
       18,  16,  19, //triangle10
       //Face 5
       20,  21,  23, //triangle11
       22,  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_OBJECT

public:
    //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 = aNormal;
}

修改片段着色器

#version 330 core

out 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;

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

    // specular
    float 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 左边 -x


        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,//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 左边 -x


        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,   //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,//1

       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,//2


       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,//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,//4


        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,//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 triangle
        1, 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。


http://www.kler.cn/a/546326.html

相关文章:

  • 08模拟法 + 技巧 + 数学 + 缓存(D3_数学)
  • LLM:BERT or BART 之BART
  • 微信小程序 - 模版语法
  • Elastic Cloud Serverless 现已在 Microsoft Azure 上提供技术预览版
  • Spring生态体系深度解析:现代Java开发的核心架构
  • 苹果转型独立AR眼镜:一场技术与创新的深度探索
  • 【鸿蒙开发】第三十章 应用稳定性-检测、分析、优化、运维汇总
  • 图形渲染(一)——Skia、OpenGL、Mesa 和 Vulkan简介
  • Spring Boot中使用Flyway进行数据库迁移
  • 网络安全——网络安全基础、常用网络命令
  • 如何动态修改第三方组件库的内部样式
  • 伯克利 CS61A 课堂笔记 07 —— Lists
  • 服务器,交换机和路由器的一些笔记
  • 天芒传奇Ⅱ·前传-特殊武器
  • 深入理解 ABA 问题与退让策略:Go 语言实现与优化
  • ArcGIS Pro显示缓存空间不足导致编辑或加载数据显示不完全
  • spring 学习 (注解)
  • Deepseek R1 模型本地部署(ollama+cherry studio)详细指南! 个人知识库搭建与使用
  • TDengine 性能测试工具 taosBenchmark
  • 【1min 快速上手 Unity 基本使用方法】外部模型使用