QT+OpenGL光照

简介: 现实生活中看到的物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色太阳光能被看见的白光是多找演的的组合

QT+OpenGL光照

本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主


颜色

现实生活中看到的物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色


太阳光能被看见的白光是多找演的的组合


7da19043116843a9852c0a1d62bf2c90.png


颜色的数据化的由红色,绿色和蓝色三个分量组成,他们通常被缩写为RGB


例如:珊瑚红色

QVector3D color(1.0f, 0.5f, 0.31f);

上图颜色的代码展示

// 灯光颜色
QVector3D lightColor(1.0f, 1.0f, 1.0f);
// 珊瑚红色
QVector3D toyColor(1.0f, 0.5f, 0.31f);
QVector3D result = lightColor * toyColor; // 分量相乘,不是点乘也不是叉乘

代码展示:


light.frag

#version 330 core
out vec4 FragColor;
uniform vec3 lightColor;
void main()
{
    FragColor = vec4(lightColor, 1.0);
}

light.vert

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aTexCord;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
}
void TurboOpenGLWidget::paintGL()
{
    QMatrix4x4 model;
    QMatrix4x4 view;
    float time = m_time.elapsed() / 50.0;
    model.rotate(time, 1.0f, 5.0f, 0.0f);
    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glEnable(GL_DEPTH_TEST);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    shader_program_.bind();
    glBindVertexArray(VAO);
    QMatrix4x4 projection;
    projection.perspective(camera_.getZoom(), float(width() / height()), 0.1, 100);
    shader_program_.setUniformValue("projection", projection);
    view = camera_.getViewMatrix();
    switch(shape_)
    {
        case Rect:
            shader_program_.setUniformValue("model", model);
            shader_program_.setUniformValue("view", view);
            for(const auto &item: cubePositions)
            {
                model.setToIdentity();
                model.translate(item);
                model.rotate(time, 1.0, 5.0, 0.5);
                shader_program_.setUniformValue("model", model);
                glDrawArrays(GL_TRIANGLES,0,36);
            }
            break;
    }
    glBindVertexArray(0);
    glBindVertexArray(lightVAO);
    light_shader_program_.bind();
    light_shader_program_.setUniformValue("projection", projection);
    light_shader_program_.setUniformValue("model", model);
    light_shader_program_.setUniformValue("view", view);
    model.setToIdentity();
    model.translate(lightPos);
    model.rotate(1.0, 1.0, 5.0, 0.5);
    model.scale(0.2);
    light_shader_program_.setUniformValue("model", model);
    glDrawArrays(GL_TRIANGLES,0,36);
    update();
}

效果展示

640586bdc3844cde9adeb8ba6b83a703.png

冯氏光照模型

冯氏光照模型的主要结构有三个:

  ●  环境光(ambient)

          ○  即使在黑暗情况下,通常也仍然有一些光亮

  ●  漫反射(diffuse)

          ○  模拟光源对物体的方向性影响

  ●  镜面反射(specular)

          ○  模拟有光泽物体表面上出现的亮点

屏幕截图 2023-08-03 152452.png


环境光代码:

#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
void main()
{
    float ambientStrength = 0.2;
    vec3 ambient = ambientStrength * lightColor;
    vec3 result = ambient * objectColor;
    FragColor = vec4(result, 1.0);
}

向上面代码,如果我们只有环境光,会是如下效果,并不是完全黑的。

7012fe3e6c33483aad0fbc20efeb0e43.png

漫反射代码:

计算漫反射光照需要:

●  法向量:一个垂直于顶点表面的向量

●  定向的光线:作为光源的位置与片段的位置之间的向量差的方向向量;为了计算这个光线,我们需要光的位置向量和片段的位置向量


片段着色器:

#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
in vec3 Normal;
in vec3 fragPos;
void main()
{
    // ambient
    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;
    vec3 result = (ambient + diffuse)  * objectColor;
    FragColor = vec4(result, 1.0);
}

108fe29863ff48518958619c2e825fdf.png

镜面反射代码:


片段着色器:

#version 330 core
out vec4 FragColor;
uniform vec3 objectColor;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
in vec3 Normal;
in vec3 fragPos;
void main()
{
    // ambient
    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);
}

b48f8c896a534b7c802575cfe94172f1.png

法向量

●  如果模型矩阵执行了不等比例的缩放,顶点的改变导致法向量不再垂直与表面。

●  修复这个行为的诀窍是使用一个为法向量专门定制的模型矩阵。这个矩阵称之为法线矩阵

Normal = mat3(transpose(inverse(model))) * aNormal;


目录
相关文章
|
4月前
QT4.7版本的OPENGL的3D旋转模型例子
QT4.7版本的OPENGL的3D旋转模型例子
|
2月前
|
Linux API iOS开发
【Qt 渲染引擎】一文带你了解qt的三种 渲染引擎,包括栅格引擎(Raster)、OpenGL 和本地绘图系统
【Qt 渲染引擎】一文带你了解qt的三种 渲染引擎,包括栅格引擎(Raster)、OpenGL 和本地绘图系统
37 0
|
2月前
|
机器学习/深度学习 API vr&ar
Qt, OpenCV与OpenGL协同作战:图像处理与三维图形界面的完美结合
Qt, OpenCV与OpenGL协同作战:图像处理与三维图形界面的完美结合
117 4
|
2月前
|
Linux Windows
imx6ull开发板之qt应用编程读取AP3216c(光照,距离)数据。
imx6ull开发板之qt应用编程读取AP3216c(光照,距离)数据。
21 0
|
2月前
Qt+OpenGL 打砖块游戏
Qt+OpenGL 打砖块游戏
21 0
|
3月前
|
数据可视化 API vr&ar
qt“五彩斑斓“ opengl
qt“五彩斑斓“ opengl
|
7月前
QT圆形进度条(QT桌面项目光照强度检测)
QT圆形进度条(QT桌面项目光照强度检测)
40 0
|
9月前
|
算法
QT+OpenGL高级光照 Blinn-Phong和Gamma校正
冯氏光照:视线与反射方向之间的夹角不小于90度,镜面光分量会变成0.0(不是很合理,会有清晰的分界线) Blinn-Phone模型采用了半程向量,即光线与视线夹角一般方向上的一个单位向量。当半程向量与法线向量越接近,镜面光分量就越大。
62 0
|
9月前
|
编解码 异构计算
QT+OpenGL实例化和抗锯齿
如果将数据一次性发送给GPU,然后使用一个绘制函数让OpenGL利用这些数据绘制多个物体,就会方便了。这就是实例化(Instancing)。
166 0
|
9月前
|
数据可视化
QT+OpenGL几何着色器
输入布局限定符可以从顶点着色器接收下列任何一个图元值: ● points:绘制GL_POINTS图元时 ● lines:绘制GL_LINES或GL_LINE_STRIP时 ● lines_adjacency:GL_ADJACENCY或GL_LINESTRIP_ADJACENCY ● triangles:GL_TRIANGLES、GL_TRIANGLE_STRIP或GL_TRIANGLE_FAN ● triangles_adjacency:GL_TRIANGLES_ADJACENCY或GL_TRIANGLE_STRIP_ADJACENCY
74 0