计算机图形学(OPENGL):基础光照

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机图形学(OPENGL):基础光照相关的知识,希望对你有一定的参考价值。

参考技术A 本文同时发布在我的个人博客上: https://dragon_boy.gitee.io

  光往往不来源于单一的光源,而是多个光源将光线散射到我们周围。光线可以散射和四处反射,这样会直接或间接影响物体的颜色。基于这种理论的算法是全局光照算法,但这里我们暂时将环境光模型考虑为单一的颜色,并降低它的光照强度来显得更为真实。比如我们在待渲染的立方体的片元着色器中这么定义:

  运行程序之后,结果如下:

  现在立方体有了一个基础的环境光颜色。

  环境光照的细节并不丰富,但添加漫反射光照后,物体的颜色信息就丰富了起来。我们想象一束直射光线:

  由于我们定义的是顶点,那么这里的法线就是顶点法线,可以通过与周围的顶点找出一个平面来计算该顶点处的顶点法线。由于立方体并不复杂,这里我们就简单地给出顶点的法线属性:

  修改顶点着色器:

  同时记得修改顶点属性指针。(灯光立方体我们不使用法线属性)

  我们需要在片元着色器中定义灯光的位置:

  接着在渲染循环中赋值:

  接下来我们需要片元的位置,这个可以在顶点着色器中计算(通过将顶点的位置和model矩阵相乘):

  接着需要在片元着色其中计算漫反射光照对颜色的影响,首先要输入FragPos;

  接着标准化法线,并通过lightPos和FragPos相减来获得灯光的方向,并标准化:

  之后计算灯光方向和法线的点积来获得漫反射光照的影响度,当然不能小于0,即光线和法线的角度不能大于90度,我们通过max函数来限制大小:

  最后,我们可以在结果颜色中添加漫反射光照的影响了:

  运行结果如下:

  可以看到立方体的显示更为真实了。

之前我们将法线直接从顶点着色器传入了片元着色器,但由于片元着色器的光照计算在世界空间中,那么我们应该将model矩阵作用于法线来进行一些转换,但这里有一些问题。首先法线仅仅代表方向,并不代表确切的位置。其次,法线是三维向量,并没有w组件,所以model矩阵的平移将不会影响法线,也就是说我们要先舍弃model的第四个维度再与法线向量相乘。然后就是model矩阵中会包含非全局缩放,如果这样的话,法线与model矩阵相乘后将可能不再垂直于平面:

  针对这些问题的解决方式是专门为法线定义model矩阵,做法是将原model矩阵的逆矩阵转置后降至3维:

  注意,在着色器中计算逆矩阵开销很大,最好能后在CPU中计算好再送往着色器。

  类似于漫反射光照,高光的计算基于光线的方向和片段的法线,其次,还要加入视线的方向。高光的实际计算和反射光线、视线方向有关:

  我们通过光线的方向和法线计算反射光线的方向,接着与视线方向作点积来计算高光影响。视线方向通过摄像机位置和片段位置作减法运算得到。(我们这里选择在世界空间中计算高光,当然也可以在视图空间中计算高光,在视图空间中计算的好处是摄像机的位置即观察者的位置永远在原点。)
  我们在片元着色器中添加观察位置:

  并将摄像机的位置赋予这个变量:

  接着定义一个控制高光强度的参数:

  接着计算观察方向和反射光线方向(通过内建reflect函数计算):

  reflect函数要求第一个参数指向片段,所以我们反向灯光方向。
  接下来计算高光对颜色的影响:

  pow方法中的32是反光度,用来控制高光的大小和范围:下面是一些不同反光度的效果:

  可以看到反光度越高,高光越亮,同时高光的范围更小。
  最后,我们加上高光的颜色影响:

  运行结果如下:

以上是关于计算机图形学(OPENGL):基础光照的主要内容,如果未能解决你的问题,请参考以下文章

图形学计算机图形学知识点提纲10

计算机图形学常用术语整理

计算机图形学_图元的属性_1_OpenGL状态变量

计算机图形学_图元的属性_1_OpenGL状态变量

计算机图形学(OPENGL):帧缓冲

计算机图形学(OPENGL):法线贴图