翻译自Android课程二:环境光和漫反射光
世界没有光就会什么也看不到,我们将无法感知这个世界活着物体。
在真实的世界里,光是由无数的光子聚合在一起形成的,它从一个光源出发,经过无数时间,最后传递到了我们的眼睛里
我们应该如何用计算机图像模拟光呢,现在有2种热门技术可以实现:光线跟踪和栅格化。光线跟踪通过数学计算跟踪真实的光线,能给出十分准确和真实的结果,但是不足之处是模拟所有的光线十分消耗计算资源,并且实时渲染速度很慢。由于这个限制,大多数的实时计算机图像使用的是栅格化技术,通过接近结果模拟光线。
我们可以抽象出光工作的方式形成三种基本的光线类型
环境光环境光是一种基础的光线,它遍布整个场景,它没有表现出来自任何其他的光源,因为它在到达你之前经过了无数的反射。这种光能阴天的户外,或是许多不同光源累积影响的室内。没有分别计算所有独立的光,我们可以为对象或场景设置一个基本的光照等级。
漫反射光这种光在到达教你的眼睛里经过了物体之间反射。物体的光照等级随它与光线的角度不同而变化。直面它的时候更加明亮。同样我们感知物体时无论我们相对物体的位置在哪里,亮点都是相同的。这种现象也叫兰伯特余弦定律(Lambert’s cosine law),漫反射和兰伯特反射在生活中是很常见的。
高光和漫反射不同,高光随我们和物体的位置不同而不同,它让物体发亮和更加光滑
与在3D场景中的光有3种一样,光源也有3种:直接光源、Point lighting、Spot lighting。
学习来自一个点光源的环境光和漫反射光
环境光其实是漫反射光的一种,但是它也能被看作是充满整个场景的低级光。这样想的话,它会很容易计算
final color = material color * ambient light color例如,有个物体是红色的,我们的环境光是灰白的。让我们假定将颜色存储为有3个颜色的数组红、绿、蓝,使用RGB 颜色模型:
final color = { 1 , 0 , 0 } * { 0.1 , 0.1 , 0.1 } = { 0.1 , 0.0 , 0.0 }最终物体的颜色会是淡红色。基础的场景光就是这样的,除非你想要更加高级的视觉技术
对漫反射光,我们需要增加衰减和光的位置。光的位置会用来计算光和表面的角度,它会影响表面的光照的整个等级。它还用来计算光和表面的距离,并决定了那个点的光照强度。
步骤一: 计算兰伯特因子
我们需要的第一个主要的计算是计算出表明和光的角度。直面光线的表层会处于光照的最大强度。计算出这个属性的合适的方式是使用兰伯特余弦定理。如果我们有2个向量,一个是从光线到表面的一个点,第二个是曲面法线,我们可以计算出余弦值:先将各个向量归一化,因此有它们的长度为1,然后计算出2个向量的点积。这个操作能通过OpenGL ES的两个着色器轻松完成。
我们声明lambert因子,它的范围是0到1
1.
light vector = light position - obejct position cosine = dot product(object normal,normalize(light vector)) lambert factor = max(cosine,0)首先我们通过对象位置减去光线位置计算出光线的向量,然后我们获取物体的法线和光线向量的点积,就得到了这个余弦了。归一化光线向量的意思就是改变它的长度为1。因为点积德范围是-1到1,我们把它固定到(0,1)。
这是一个例子:有个光滑的平面,表面的法线笔直的指向天。光线的位置为「0,10,-10」,或是向上10个单位,向前10个单位,我们要计算出原地的光
light vector = { 0, 10, -10} - {0, 0, 0} = {0, 10, -10} obejct normal = {0, 1, 0}用平白的语言来说,如果我们沿着光线向量出发移动,到达光线的位置。要归一化这个向量,我们让向量的每一个标量处以向量的长度:
light vector length = square root( 0*0 + 10*10 + -10*-10) = square root(200) = 14.14 normalized light vector = {0/14.14, 10/14.14, -10/14.14} = {0, 0.707, -0.707}然后我们计算点积
dot product({0,1,0},{0,0.707, -0.707}) = 0*0 + 1*0.707 + 0*-0.707 = 0.707 lambert factor = max(0.707,0) = 0.707OpenGL ES 2的着色器语言已经内置了一些这种函数,所以我们不需要手动做所有的数学,但是这对我们的理解仍然有帮助。
步骤二:计算衰减因子
接着,我们需要计算衰减,真实的点光源的光线衰减遵从平方反比定律,它可以表述为: luminosity = 1 / (distance* distance) 回到我们的例子,我们知道了一个距离为14.14,所以最后我们的亮度看起来是: luminosity = 1/ (14.14*14.14) = 0.005 你可以看到,平方反比定律在距离上会导致剧烈的衰减。这就是光在真实世界中从点光源出发是怎么回事,但是我们的图像显示有限制范围,因此抑制衰减因子,我们能得到更加真实的光照而不会使物体看起来太暗了。
步骤三:计算最后的颜色
现在我们同时有了余弦和衰减因子,我们能计算出最终的光照等级:
final color = meterial color * (light color * lambert factor * luminosity)回到之前一个例子,我们有红色的材料和全白的光源,最终的计算:
final color = {1, 0, 0} *({1,1,1}*0.707*0.005) = {1,0,0}*{0.0035,0.0035,0.0035} = {0.0035,0,0}简单的总结一下,对漫反射光我们需要使用表面和光线的角度,还有表面和光线的距离来最终计算出整个漫反射照明等级。下面是步骤:
//one light vector = light position - object position cosine = dot product(object normal,normalize(light vector)) lambert factor = max(cosine,0) //two luminosity = 1/(distance*distance) //three final color = material color * (light color*lambert factor * luminosity)有一个新的属性叫gl_PointSize是点在空间中的大小为多少个像素。
