escena de iluminación OpenGL

1. Introducción

El color que vemos de un objeto en la vida real no es el color que realmente tiene, sino el color que refleja. En otras palabras, aquellos colores que no pueden ser absorbidos por el objeto son los colores del objeto que podemos percibir.

Por ejemplo, la luz blanca que puede ver la luz del sol es en realidad una combinación de muchos colores diferentes. Si proyectamos luz blanca sobre un juguete azul, el juguete azul absorbe todos los subcolores de la luz blanca excepto el azul, y la luz azul no absorbida se refleja de nuevo en nuestros ojos, haciendo que el juguete parezca azul.

La siguiente imagen muestra un juguete de color rojo coral que refleja varios colores con distintas intensidades.

Cuando creamos una fuente de luz en OpenGL, queremos darle un color a la fuente de luz, configuramos la fuente de luz en blanco. Cuando multiplicamos el color de la fuente de luz por el valor de color del objeto, lo que obtenemos es el color reflejado por el objeto (es decir, el color que percibimos). Multiplicamos estos dos vectores de color como componentes y el resultado es el vector de color final:

glm::vec3 lightColor(1.0f, 1.0f, 1.0f);
glm::vec3 toyColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = lightColor * toyColor; // = (1.0f, 0.5f, 0.31f);

2. Ejemplo

Crear una escena de iluminación

En primer lugar, necesitamos un objeto como el objeto a moldear, usamos el cuadro de cubo frontal. También necesitamos un objeto para representar la posición de la fuente de luz en la escena 3D.

#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);

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>


float vertices[] = {
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
     0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
     0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
    -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
    -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,

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

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

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

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

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

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

//物体顶点着色器语言
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(position,1.0);\n"
"}\n\0";

//物体片段着色器语言
const GLchar* fragmentShaderSource = "#version 330 core\n"
"out vec4 color;\n"
"uniform vec3 objColor;\n"
"uniform vec3 lightColor;\n"
"void main()\n"
"{\n"
"color = vec4(objColor * lightColor,1.0f);\n"
"}\n\0";

//光源顶点着色器语言
const GLchar* vertexShaderSourceLight = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
"gl_Position = projection * view * model * vec4(position,1.0);\n"
"}\n\0";

//光源片段着色器语言
const GLchar* fragmentShaderSourceLight = "#version 330 core\n"
"out vec4 color;\n"
"uniform vec3 lightColor;\n"
"void main()\n"
"{\n"
"color = vec4(lightColor,1.0f);\n"
"}\n\0";

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;

QVector<QVector3D> cubePositions = {
  QVector3D( 0.0f,  0.0f,  0.0f),
  QVector3D( 2.0f,  5.0f, -15.0f),
  QVector3D(-1.5f, -2.2f, -2.5f),
  QVector3D(-3.8f, -2.0f, -12.3f),
  QVector3D( 2.4f, -0.4f, -3.5f),
  QVector3D(-1.7f,  3.0f, -7.5f),
  QVector3D( 1.3f, -2.0f, -2.5f),
  QVector3D( 1.5f,  2.0f, -2.5f),
  QVector3D( 1.5f,  0.2f, -1.5f),
  QVector3D(-1.3f,  1.0f, -1.5f)
};

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);
}

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

    //物体的着色器程序
    m_program = new QOpenGLShaderProgram();
    m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSource);
    m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSource);
    m_program->link();

    //光源着色器程序
    m_lightProgram = new QOpenGLShaderProgram();
    m_lightProgram->addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderSourceLight);
    m_lightProgram->addShaderFromSourceCode(QOpenGLShader::Fragment,fragmentShaderSourceLight);
    m_lightProgram->link();

    //物体VAO VBO
    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, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

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

    glBindVertexArray(0);//解绑VAO

    //光源VAO VBO
    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, 5 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindVertexArray(0);//解绑VAO

    //设置物体和光照颜色
    m_program->bind();
    m_program->setUniformValue("objColor",objectColor);
    m_program->setUniformValue("lightColor",lightColor);

    //设置光照颜色
    m_lightProgram->bind();
    m_lightProgram->setUniformValue("lightColor",lightColor);
}

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

    glBindVertexArray(0);

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

    glBindVertexArray(0);
}

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();
}

Supongo que te gusta

Origin blog.csdn.net/wzz953200463/article/details/131138971
Recomendado
Clasificación