QT+OpenGL光照

QT+OpenGL光照

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

颜色

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

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

在这里插入图片描述

颜色的数据化的由红色,绿色和蓝色三个分量组成,他们通常被缩写为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();
}

效果展示

在这里插入图片描述

冯氏光照模型

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

  • 环境光(ambient)
    • 即使在黑暗情况下,通常也仍然有一些光亮
  • 漫反射(diffuse)
    • 模拟光源对物体的方向性影响
  • 镜面反射(specular)
    • 模拟有光泽物体表面上出现的亮点

I p h o n g = k a ⋅ I a m b i e n t + ∑ i = 1 n u m L i g h t s I i ⋅ ( k d ( L ^ i ⋅ N ^ ) + k s ⋅ ( R ^ i ⋅ V ^ ) n s h i n y ) I_{phong} = k_a\cdot I_{ambient} + \sum_{i = 1}^{numLights}I_i\cdot (k_d(\hat L_i\cdot \hat N) + k_s\cdot (\hat R_i \cdot \hat V)^{n^{shiny}}) Iphong=kaIambient+i=1numLightsIi(kd(L^iN^)+ks(R^iV^)nshiny)

其中 k a k d k s k_a k_d k_s kakdks是系数

环境光代码:

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

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

在这里插入图片描述

漫反射代码:

计算漫反射光照需要:

  • 法向量:一个垂直于顶点表面的向量
  • 定向的光线:作为光源的位置与片段的位置之间的向量差的方向向量;为了计算这个光线,我们需要光的位置向量和片段的位置向量

片段着色器:

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

在这里插入图片描述

镜面反射代码:

片段着色器:

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

在这里插入图片描述

法向量

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

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

Normal = mat3(transpose(inverse(model))) * aNormal;
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

turbolove

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值