• Learn OpenGL光照(二)


    基础光照

    • 冯氏光照模型(Phong Lighting Model):主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。
    1. 环境光照(Ambient Lighting):即使在黑暗的情况下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不会是完全黑暗的。为了模拟这个,我们会使用一个环境光照常量,它永远会给物体一些颜色。
    2. 漫反射光照(Diffuse Lighting):模拟光源对物体的方向性影响(Directional Impact)。它是冯氏光照模型中视觉上最显著的分量。物体的某一部分越是正对着光源,它就会越亮。(光照分量和表面点的法向量点乘的值 再乘于光的颜色,越垂直光照就越亮)
    3. 镜面光照(Specular Lighting):模拟有光泽物体上面出现的亮点。镜面光照的颜色相比于物体的颜色会更倾向于光的颜色。

    • 漫反射:
    1. 光的方向向量是光源位置向量与片段位置向量之间的向量差。
    2. 求法向量:vec3 norm = normalize(Normal); vec3 lightDir = normalize(lightPos - FragPos);
    3. 漫反射击:float diff = max(dot(norm, lightDir), 0.0); vec3 diffuse = diff * lightColor;
    4. 最终颜色:vec3 result = (ambient + diffuse) * objectColor; FragColor = vec4(result, 1.0);
    • 镜面光照:

    1. 计算反射向量视线方向的角度差,如果夹角越小,那么镜面光的影响就会越大。它的作用效果就是,当我们去看光被物体所反射的那个方向的时候,我们会看到一个高光。
    2. 计算镜面光强度,用它乘以光源的颜色,再将它加上环境光漫反射分量
    3. 观察者的世界空间坐标,我们简单地使用摄像机对象的位置坐标代替
    4. 求镜面光照float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32); vec3 specular = specularStrength * spec * lightColor;
    5. 最终颜色:vec3 result = (ambient + diffuse + specular) * objectColor; FragColor = vec4(result, 1.0);

    • 材质:

    当描述一个物体的时候,我们可以用这三个分量来定义一个材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)。

    1. ambient材质向量定义了在环境光照下这个物体反射得是什么颜色,通常这是和物体颜色相同的颜色。
    2. diffuse材质向量定义了在漫反射光照下物体的颜色。(和环境光照一样)漫反射颜色也要设置为我们需要的物体颜色。
    3. specular材质向量设置的是镜面光照对物体的颜色影响(或者甚至可能反射一个物体特定的镜面高光颜色)。
    4. shininess影响镜面高光的散射/半径。

    材质光照定义成一个整体:
    struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
    };
    uniform Material material;

    struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    };

    uniform Light light;

    • 光照贴图:

    现实世界中的物体通常并不只包含有一种材质,而是由多种材质所组成。想想一辆汽车:它的外壳非常有光泽,车窗会部分反射周围的环境,轮胎不会那么有光泽,所以它没有镜面高光,轮毂非常闪亮(如果你洗车了的话)。汽车同样会有漫反射和环境光颜色,它们在整个物体上也不会是一样的,汽车有着许多种不同的环境光/漫反射颜色。总之,这样的物体在不同的部件上都有不同的材质属性。
    引入漫反射和镜面光贴图(Map),允许我们对物体的漫反射分量(以及间接地对环境光分量,它们几乎总是一样的)和镜面光分量有着更精确的控制。

    • 将漫反射和环境光由一个vec3替换成一张贴图,由贴图来反映材质漫反射的强度。

    struct Material {
    sampler2D diffuse;
    vec3 specular;
    float shininess;
    };
    ...
    in vec2 TexCoords;

    • 镜面光贴图:

    将镜面光由一个vec3替换成一张贴图,由贴图来反映材质镜面光的强度。
    struct Material {
    sampler2D diffuse;
    sampler2D specular;
    float shininess;
    };

    通过使用漫反射和镜面光贴图,我们可以给相对简单的物体添加大量的细节。我们甚至可以使用法线/凹凸贴图(Normal/Bump Map)或者反射贴图(Reflection Map)给物体添加更多的细节

    添加一个叫做放射光贴图(Emission Map)的东西,它是一个储存了每个片段的发光值(Emission Value)的贴图。发光值是一个包含(假设)光源的物体发光(Emit)时可能显现的颜色,这样的话物体就能够忽略光照条件进行发光(Glow)。游戏中某个物体在发光的时候,你通常看到的就是放射光贴图(比如 机器人的眼,或是箱子上的灯带)。

    • 平行光:将直接使用光的direction向量而不是通过direction来计算lightDir向量,平行光对于照亮整个场景的全局光源是非常棒的。

    旧OpenGL(固定函数式)决定光源是定向光还是位置光源(Positional Light Source)的方法,是根据w分量是0和1来判断,0判断是定向光照,1判断是点光源位置计算方向。

    • 点光源:处于世界中某一个位置的光源,它会朝着所有方向发光,但光线会随着距离逐渐衰减。
    • 衰减:随着光线传播距离的增长逐渐削减光的强度通常叫做衰减(Attenuation)

    常数项KcKc在所有的情况下都是1.0。一次项KlKl为了覆盖更远的距离通常都很小,二次项KqKq甚至更小。

     

    • 聚光:是位于环境中某个位置的光源,它只朝一个特定方向而不是所有方向照射光线。(路灯或手电筒),基本上说,手电筒就是普通的聚光,但它的位置和方向会随着玩家的位置和朝向不断更新。
    • 平滑/软化边缘:为了创建一种看起来边缘平滑的聚光,我们需要模拟聚光有一个内圆锥(Inner Cone)和一个外圆锥(Outer Cone)。我们可以将内圆锥设置为上一部分中的那个圆锥,但我们也需要一个外圆锥,来让光从内圆锥逐渐减暗,直到外圆锥的边界。
    • 平滑公式:

    • 多光源:我们需要有一个单独的颜色向量代表片段的输出颜色。对于每一个光源,它对片段的贡献颜色将会加到片段的输出颜色向量上。所以场景中的每个光源都会计算它们各自对片段的影响,并结合为一个最终的输出颜色。

  • 相关阅读:
    hdu 1176 免费馅饼
    http://codeforces.com/contest/741/problem/B B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    瞎搞题
    1D1D决策单调性dp
    整体二分(POJ2104 静态第k大查询)
    B
    http://codeforces.com/contest/776/problem/G
    http://codeforces.com/contest/776/problem/D 2-sat
    bzoj1492(cdq分治 && 平衡树维护dp)
    F. Bear and Bowling 4(斜率优化)
  • 原文地址:https://www.cnblogs.com/wwhhgg/p/12653933.html
Copyright © 2020-2023  润新知