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

techbrood 发表于 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(12) views5763 comments1

发送私信

最新评论

iefreer 2019-08-12 14:42:01

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


请先 登录 再评论.
相关文章
  • 谷歌ARCore技术特性简介

    谷歌美国时间2017.8.29号刚发布了ARCore预览版,这是一个类似于苹果ARKit的增强现实SDK,在此之前,谷歌虽然已投资AR平台Tango,但由于需要特定的硬件和传感器,...

  • CSS3属性选择器特性使用详解

    CSS3除了引入动画、滤镜(用于特效)以及新的布局技术外,在选择器(selector)方面也有增强。属性选择器根据元素的属性(attributes)来匹配。这可以是一个单独...

  • Web界面编程状态变化和JS开发框架(React/Angular/Ember)

    UI编程中的一个关键课题就是界面组件化(可复用)以及组件状态管理。稍早一些的windows程序员可能接触过MFC,其界面编程中有一个DDX(DoDataExchange)的机制,...

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

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

  • Three.js入门教程2 - 着色器(下)

    这是WebGL着色器教程的后半部分,如果你没看过前一篇,阅读这一篇教程可能会使你感到困惑,建议你翻阅前面的教程。

  • S3TC(S3 Texture Compression)纹理压缩格式详解

    使用S3TC格式存储的压缩纹理是以4X4的纹理单元块(texel blocks)为基本单位存储的,每纹理单元块(texel blocks)有64bit或者128bit的纹理单元数据(texel data)。这...

  • WebGL入门教程4 - 使用纹理贴图(Texture Map)

    3D建模和纹理贴图的关系就好比人体和皮肤(或着装)的关系,3D建模用来处理空间属性,而贴图适合用来处理细腻的表面属性。如果不使用贴图,而想在表面达到足够的...

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

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

  • WebGL入门教程1 - 3D绘图基础知识

    现代浏览器努力使得Web用户体验更为丰富,而WebGL正处于这样的技术生态系统的中心位置。其应用范围覆盖在线游戏、大数据可视化、计算机辅助设计、虚拟现实以及数...

  • 更多...