qt + opengl 给立方体增加阴影+纹理

在上一篇中,我们说了如何给立方体增加阴影和光照,那么我这篇在说下如何给在阴影上增加纹理。

这里我们需要在顶点和片段着色器里面增加纹理属性。

修改顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

out vec3 Normal;
out vec3 FragPos;
out vec2 texc;
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    FragPos = vec3(model*vec4(aPos,1.0));
    Normal = mat3(transpose(inverse(model))) * aNormal;
    texc = aTexCoord;
}

修改片段着色器

#version 330 core
out vec4 FragColor;

in vec3 Normal;
in vec3 FragPos;
in vec2 texc;

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;
    gl_FragColor = texture2D(texture, texc)*vec4(result,1.0f);
}

下面上代码

#include "testwidget.h"
#include 
#include 
#include 
#include 
#include 

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"
    "uniform  mat4 matrix;\n"
    "uniform  mat4 model;\n"
    "uniform  mat4 view;\n"
    "uniform  mat4 projection;\n"
    "void main(void)\n"
    "{\n"
    "    gl_Position =  projection*view* matrix * vertex;\n"
    "    texc = texCoord;\n"
    "}\n";

static const char *fragmentShaderSource =
      "#version 330\n"
      "uniform sampler2D texture;\n"
      "in vec4 texc;\n"
      "void main(void)\n"
      "{\n"
      "    gl_FragColor = texture2D(texture, texc.st);\n"
      "}\n";

testwidget::testwidget():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"<start();

}
testwidget::~testwidget()
{
    makeCurrent();
    vbo.destroy();
    for (int i = 0; i < 6; ++i)
        delete textures[i];
    delete program;
    doneCurrent();
}

QSize testwidget::minimumSizeHint() const
{
    return QSize(400, 400);
}

QSize testwidget::sizeHint() const
{
    return QSize(400, 400);
}

void testwidget::rotateBy(int xAngle, int yAngle, int zAngle)
{
    float cameraSpeed = 0.2;
    //cameraPos -= cameraSpeed * QVector3D(0, 0, -1);//由远到近
    //cameraPos += cameraSpeed * QVector3D(0, 0, -1);//由近到远

    xRot += xAngle;
    yRot += yAngle;
    zRot += zAngle;
    update();
}

void testwidget::setClearColor(const QColor &color)
{
    clearColor = color;
    update();
}

void testwidget::initializeGL()
{
    vertices = {
            // ---- 位置----   - 纹理坐标 -      ---- 颜色 ----

        0.5f, -0.5f, -0.5f,     0.0f, 0.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, -1.0f,                0.0f, 0.0f,
        0.5f, 0.5f, -0.5f,      0.0f, 0.0f, -1.0f,                1.0f, 0.0f,//1

        0.5f, 0.5f, -0.5f,      0.0f, 1.0f, 0.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, 1.0f, 0.0f,                 0.0f, 0.0f,
        0.5f, 0.5f, 0.5f,       0.0f, 1.0f, 0.0f,                 1.0f, 0.0f,//2


        0.5f, -0.5f, 0.5f,      1.0f, 0.0f, 0.0f,                 1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,     1.0f, 0.0f, 0.0f,                 0.0f, 1.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,//3



        -0.5f, -0.5f, -0.5f,    -1.0f, 0.0f, 0.0f,                 1.0f, 1.0f,
         -0.5f, -0.5f, 0.5f,    -1.0f, 0.0f, 0.0f,                 0.0f, 1.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,//4


         0.5f, -0.5f, 0.5f,     0.0f, 0.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, 1.0f,                 0.0f, 0.0f,
         0.5f, -0.5f, -0.5f,    0.0f, 0.0f, 1.0f,                 1.0f, 0.0f,//5

        -0.5f, -0.5f, 0.5f,     0.0f, -1.0f, 0.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, -1.0f, 0.0f,                 0.0f, 0.0f,
        -0.5f, 0.5f, 0.5f,      0.0f, -1.0f, 0.0f,                 1.0f, 0.0f,

    };
    initializeOpenGLFunctions();

   // makeObject();

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);

//#define PROGRAM_VERTEX_ATTRIBUTE 0
//#define PROGRAM_TEXCOORD_ATTRIBUTE 1

//    program = new QOpenGLShaderProgram;
//    program->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);
//    program->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);
//    program->link();
//    program->bind();//激活Program对象

    program = new QOpenGLShaderProgram;
    program->addShaderFromSourceFile(QOpenGLShader::Vertex, ":/light_cube.vert");
    program->addShaderFromSourceFile(QOpenGLShader::Fragment,":/light_cube.frag");
    program->link();
    program->bind();//激活Program对象

    vbo.create();
    vbo.bind();              //绑定到当前的OpenGL上下文,
    vbo.allocate(vertices.constData(), vertices.count() * sizeof(GLfloat));


    //初始化VAO,设置顶点数据状态(顶点,法线,纹理坐标等)
    vao.create();
    vao.bind();

    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);
    QMatrix4x4 projection;
    projection.perspective(60,(float)width()/height(),0.1,100);//构建透视矩阵,这个可以是固定写法
    program->setUniformValue("projection", projection);

//    vao.release();
//    vbo.release();
}

void testwidget::paintGL()
{
    //glClearColor(clearColor.redF(), clearColor.greenF(), clearColor.blueF(), clearColor.alphaF());
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.1f,0.5f,0.7f,1.0f);  //设置清屏颜色
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    QMatrix4x4 m;
    //m.ortho(-0.5f, +0.5f, +0.5f, -0.5f, 4.0f, 15.0f);
    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);
    program->setUniformValue("model", m);

//    QMatrix4x4 view;
//    view.translate(0.0f,0.0f,-3.0f);
//    program->setUniformValue("view", view);


    QMatrix4x4 view;
    view.lookAt(cameraPos, cameraPos+QVector3D(0,0,-1), QVector3D(0,1,0));
    program->setUniformValue("view", view);
    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) {
        textures[i]->bind();
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
    }
}
void testwidget::resizeGL(int width, int height)
{
    this->glViewport(0,0,width,height);                //定义视口区域
}

void testwidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
    timer->start();
}

void testwidget::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 testwidget::mouseReleaseEvent(QMouseEvent * /* event */)
{
    emit clicked();
}
#ifndef TESTWIDGET_H
#define TESTWIDGET_H

#include 
#include "camera.h"
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
class testwidget : public QOpenGLWidget,public QOpenGLExtraFunctions
{
    Q_OBJECT

public:
    testwidget();
    ~testwidget();
protected:
    QSize minimumSizeHint() const override;
    QSize sizeHint() const override;
    void rotateBy(int xAngle, int yAngle, int zAngle);
    void setClearColor(const QColor &color);

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:

    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;
    QOpenGLBuffer vbo;
    QVector vertices;
    QOpenGLVertexArrayObject vao;
    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;

};
#endif // TESTWIDGET_H

运行后结果:

qt + opengl 给立方体增加阴影+纹理_第1张图片

你可能感兴趣的:(qt,opengl,c++)