WebGL入门教程 - 高光计算模型

iefreer 发表于 2019-08-09 18:06:06

标签: webgl, tutorials, specular, light

- +

现实物体在光源的照射下,会出现吸收和反射。物体的颜色主要由漫反射决定,但局部高光效果则主要由镜面反射来决定。

从表面反射出的光线与入射角成相等但相反的角度,称为“镜面反射”。

如果镜面反射光线直接进入相机,就好像相机直接看到光源一样,即使它已经从物体上反弹出来。相机看到的是光源的光,而不是物体的颜色。如果你有一个白色光源,镜面反射将是白色的。如果您有一个红色光源,镜面反射将是红色的。因此,要对镜面反射进行建模,需要在照明模型中指定光源的颜色。

specular_angle.png

通常相机位置和反射光之间存在一个角度,如果角度很大,我们将看不到反射光,如果角度为0,那么在不考虑光线被吸收和衰减的情况下,我们看到了全部的反射光。可以用余弦函数来计算百分比,但是对于高聚焦的镜面反射来说,一般我们的直观体验是角度为0及其附近处光线陡然变亮,而超过某个角度后光线迅速变暗,因此普通余弦函数的曲线太平缓了,所以我们把余弦函数提高一个n次幂,曲线就会在边缘处(偏离角度较大处)快速下降。你可以自行测试下cos函数的指数函数的变化曲线,通过引入额外的指数参数,我们可以模拟在镜面反射矢量周围的各种光散射量。如果指数较大,例如100,则cos(a)exp将向y轴塌缩,只有非常小的角度才会返回一个有效的百分比值,即高光区域很小;而如果指数很小,如1.0,则会模拟反射光线周围的大量光线,即高光区域较大。

高光反射数学模型

如果我们用n表示片段法线(N)方向上的正规化向量(长度为1),如下图所示:

reflection_vectors2.png

在已知入射光位置、入射光L、片段点位置和片段点法向量的情况下,我们可以通过简单的几何计算推导反射光R如下:

R = N + P
=> R = n*dot_product(n,-L) + (L + N)
=> R = n*dot_product(n,-L) + (L + n*dot_product(n,-L))
=> R = 2*n*dot_product(n,-L) + L
其中L = fragment_position - light_position

得到反射光后,根据相机位置,我们可以进一步计算反射光和相机夹角,然后算上我们刚才提到的指数参数以及额外的一个高光强度调节参数,推导过程如下:

reflection = normalize( R );
to_camera = normalize( fragment_position - camera_position );
cos_angle = dot(reflection, to_camera);
cos_angle = clamp(cos_angle, 0.0, 1.0);
cos_angle = specular_factor*(pow(cos_angle, specular_gloss)); // 这里specular_gloss代表上面所提到的指数参数,表示shiness
specular_color = u_Light_color * cos_angle;

根据上面的公式,我们可以很容易的实现一个webgl shader程序。

possitive(3) negative(0) views668 comments1
私信 收藏 分享
分享到

发送私信

最新评论

iefreer 2019-08-12 14:42:01

一个参考实现:https://wow.techbrood.com/fiddle/53585


请先 登录 再评论.
相关文章
  • WebAssembly工作原理和JavaScript语言性能对比分析

    本文简单说明WebAssembly(简称wasm)工作原理和高性能的原由(和JavaScript相比)。不过需要提醒的是Wasm并非设计来完全替代JS,而是对JS的一个强大补充,JS中...

  • NodeJS、Java和PHP性能考量和若干参考结论

    首先需要说明的是,严格而言NodeJS和Java、PHP并非对等概念,NodeJS是基于JS的一个应用程序,而Java/PHP是语言。我们这里实际指的是分别使用node、java和php来实...

  • CSS3弹性布局弹性流(flex-flow)属性详解和实例

    弹性布局是CSS3引入的强大的布局方式,用来替代以前Web开发人员使用的一些复杂而易错hacks方法(如使用float进行类似流式布局)。其中flex-flow是flex-direction...

  • Three.js 对象局部坐标转换为世界坐标

    在Three.js中进行顶点几何计算时,一个需要注意的地方是,需要统一坐标系。比如你通过Three.js提供的API创建了一个球体网孔对象,那么默认情况下,各网孔顶点的...

  • 纹理基础知识和过滤模式详解

    1、 为什么在纹理采样时需要texture filter(纹理过滤)。
    我们的纹理是要贴到三维图形表面的,而三维图形上的pixel中心和纹理上的texel中心并不一至(pixe...

  • WebGL 纹理映射模式以及WRAP_S | WRAP_T参数详解

    我们在纹理滤镜一文中已经说明了2个重要的纹理参数,用来定义对象缩放时纹理的处理方式:GL_TEXTURE_MIN_FILTERGL_TEXTURE_MAG_FILTER本文讲解其余几个纹理参数...

  • Blender2.7 快捷键一览表

    通用操作
    停止当前操作:ESC
    快捷搜索:SPACE撤销:ctrl+z重做:ctrl+shift+z渲染:F12
    单选:鼠标右键(RMB)全选:A
    框选:B
    刷选:...

  • Three.js入门教程6 - 创建全景图和纹理

    全景图非常酷。使用Three.js做一个属于自己的全景图并不是那么困难。要做一个全景图,你需要一个软件用来做一张全景图片。我使用了iPhone上的Microsoft Photosyn...

  • WebGL入门教程6 - 光照效果和Phong光照模型

    正是因为有了光,世界才能被我们看见,在3D的世界里,光照给物体带来真实的视觉感受。当光照射在某一表面上时,它可能被吸收、反射或投射。其中入射到表面上的一...

  • 如何使用WebGL创建一个逼真的下雨动画

    之前写过文章来分别讲解如何使用CSS3和Canvas2D实现过雨滴和下雨动画。通过背景处理看起来也有视觉上的3D效果,但并非真正的3D场景,如果要加入用户交互,进行36...

  • 使用requestAnimationFrame和Canvas给按钮添加绕边动画

    要给按钮添加酷炫的绕边动画,可以使用Canvas来实现。基本的思路是创建一个和按钮大小相同的Canvas元素,内置在按钮元素中。然后在Canvas上实现边线环绕的动画。...

  • 如何使用CSS3实现书页(书本)卷角效果

    我们有时候想在页面显示一个公告或用户提示信息。一个常用设计是使用书签形状。我们可以给书签添加卷角效果,以使其更为逼真。所谓的“卷角”实际上可以用小角度...

  • 更多...