OpenGL基础18:光照基础

真实的光照非常的复杂,所以有关光照的算法和论文也有不少,想要模拟出更真实的光照往往需要很强的实力,很牛的算法以及很高的数学/物理水平,与此相关的技术到现在为止也只是在发展中(包括目前比较火的“光线追踪”),当然,还是要从最简单的入手,尽可能以最低的门槛,做出个大致的样子来

一、光照模型与光源

之所以说光照比较复杂,主要是在物理和数学专业上的难度,光通常都不是来自于同一光源,而是来自散落于我们周围的很多光源,即使它们可能并不是那么显而易见,光的一个属性是,它可以向很多方向发散和反弹,又或是多次反射,所以光最后到达的地点可能并不是它所临近的直射方向;

光能够像这样反射(Reflect)到其他表面,一个物体的光照可能受到来自一个非直射的光源影响

一种基础光照模型:冯氏光照模型(Phong)的主要结构由3个元素组成

  • 环境(Ambient)光:即使在黑暗的情况下,世界上也仍然有一些光亮(月亮、一个来自远处的光),所以物体永远不会是完全黑暗的,只要你在室外
  • 漫反射(Diffuse):模拟一个发光物对物体的方向性影响(Directional Impact),它是冯氏光照模型最显著的组成部分,面向光源的一面比其他面会更亮
  • 镜面(Specular)光照:模拟有光泽物体上面出现的亮点,镜面光照的颜色相比于物体的颜色更倾向于光的颜色

几种常见光源:

  • 环境光:一种低强度的光,没有位置的概念,由光线经过周围环境表面多次反射后形成的,可以用环境光可以描述一块区域的亮度,通常是常量(对应光照模型中的环境光)
  • 太阳光:定向光源,在无穷远出发射光线,光线是平行的,强度不会随着距离衰减(一般场景中只有至多一个)
  • 点光源:在有限空间内某个点上发出的光线,光线强度会随着距离衰减(最常见光源)
  • 聚光灯(SpotLight):一种具有锥形效果的光源,该光源拥有产生光的方向和角度,有主照射方向,光线强度会随着距离,延着中心向外衰减(例如手电筒,舞台灯)

阴影(Shadow)

  • 软阴影:阴影边界柔和,渐变,没有锯齿,常见而又普通
  • 硬阴影:边界锐利,通常出现在在和物体的交替处或者是光打下来离物体比较近的地方

二、环境光照

考虑环境光的性质,实现环境光照出乎意料的简单,如下修改物体的片段着色器:我们只需要用光的颜色乘以一个很小的常量环境因子,再乘以物体的颜色就ok了,这也是最基础的算法

#version 330 core
out vec4 color;
uniform vec3 objectColor;
uniform vec3 lightColor;
in vec2 texIn;
uniform sampler2D texOutA;
void main()
{
    float ambientStrength = 0.1f;
    vec3 ambient = ambientStrength * lightColor;
    vec3 result = ambient * objectColor;
    color = vec4(result, 1.0f);
}

为了能看出效果,把背景换成黑色:

如果你觉得这过于简单,可以去尝试学习全局照明(Global Illumination)算法

三、漫反射和镜面反射

再回到初高中物理,漫反射和镜面反射的区别可以用一张图表示:

为了简化问题,我们当然不可能去尝试计算每条光线的反射角和反射结果,我们只需要知道:漫反射是一个“混沌”的过程,也就是说,无论在什么方向上观察物体,从物体反射到我们眼中的光线强度和方向(总量)都是大致相似的,我们只需要考虑光与物体之间的关系,而对于镜面反射,我们就需要考虑到我们的观察视角,换句话说:

  • 对于漫反射:我们简单考虑入射光与物体表面法向量的夹角,夹角越大则越亮
  • 对于镜面反射:我们简单考虑反射光与视线方向的夹角,夹角越大则越亮

入射光和反射光关于物体反射点法向量对称

对于实现可以参考后面的文章

参考文献:https://learnopengl.com/Lighting/Basic-Lighting

猜你喜欢

转载自blog.csdn.net/Jaihk662/article/details/106624451