原文地址:Docs » Shading » Your first shader » Your first Spatial shader: part 2
现在,我们拥有了一个平滑的看起来像塑料的表面了。接下来我们需要考虑模拟一些水特有的特点了。有两个重要特点可以把这个古怪的塑料表面变成美丽的风格化的水。首先是镜面反射(specular reflection
),镜面反射是那些阳光直接反射到你的眼中而使你看到的亮斑。其次就是菲涅耳反射(fresnel reflectance
),菲涅耳反射即和视线的夹角越小反射越强。这就是为什么你低头垂直向下看水时,能够看到水底,而看遥远的水面时,看到的只是它在反射天空。
译者注:补充一个关于菲涅耳反射的百科
“菲涅尔”是一个人的名字,因为他发现了一个有关反射的光学现象,这个现象就用这个人的名字命名了。那么,是什么现象呢?
这就是反射/折射与视点角度之间的关系。
如右图所示,我们站在湖边的时候,低头看脚下的水,水是透明的,反射不是特别强烈;远处的湖面,你会发现水并不是透明的,并且反射非常强烈。这就是“菲涅尔效应”。
image简单的讲,就是视线垂直于表面时,反射较弱,而当视线非垂直表面时,夹角越小,反射越明显。如果你看向一个圆球,那圆球中心的反射较弱,靠近边缘较强。不过这种过度关系被折射率影响。
如果不使用“菲涅尔效应”的话,则反射是不考虑视点与表面之间的角度的。
为了能够增强镜面反射,我们需要做两件事。首先是将镜面反射的渲染模式改为卡通模式,因为卡通渲染模式有更大的镜面反射高光。
render_mode specular_toon;
image
接下来,我们添加一个轮廓光(Rim Lighting
),轮廓光可以增加在掠射角(glancing angle)的效果。它被经常用于模拟光穿过结构边缘的效果,我们在这里用它来帮助实现更好的水的效果。
void fragment() {
RIM = 0.2;
METALLIC = 0.0;
ROUGHNESS = 0.01;
ALBEDO = vec3(0.1, 0.3, 0.5);
}
image
为了实现菲涅耳反射,我们先要在片元函数中计算一下菲涅耳系数(fresnel term
)。我们并不是使用真正的菲涅耳系数,而是用NORMAL
和VIEW
的点积(dot product
)近似代替它。NORMAL
向量从一个表面指向远方,VIEW
向量从我们的双眼中心点指向表面。以下就是菲涅耳系数与NORMAL
以及VIEW
之间的关系。
float fresnel = sqrt(1.0 - dot(NORMAL, VIEW));
然后,把他们融合到ROUGHNESS
和 ALBEDO
。这就是ShaderMaterial
相对于SpatialMaterial
的优势,在SpatialMaterial
中,你只能用纹理或者常数对那些属性赋值。但是在ShaderMaterial
中你可以基于任何你能想到的数学函数对它们赋值。
void fragment() {
float fresnel = sqrt(1.0 - dot(NORMAL, VIEW));
RIM = 0.2;
METALLIC = 0.0;
ROUGHNESS = 0.01 * (1.0 - fresnel);
ALBEDO = vec3(0.1, 0.3, 0.5) + (0.1 * fresnel);
}
image
现在,仅仅用了5行代码,你可以实现一个看起来非常复杂的水面。 我们有光,水面看起来太亮,我们把它调暗一些。非常容易实现,把我们传给ALBEDO
的vec3
值调低一些就可以了,让我们把它设为vec3(0.01, 0.03, 0.05)
。
网友评论