实现CD-ROM或DVD上那种彩虹反射效果 VR资源

492899250 2017-09-27 17:15:56
本文会引导你创建一个着色器,实现CD-ROM或DVD上那种彩虹反射效果。这篇教程是物理彩虹效果系列中的一篇。
 
 
你可以从下面的链接找到这个系列的所有文章。
 
 
· Part 1. The Nature of Light
· Part 2. Improving the Rainbow (Part 1)
· Part 3. Improving the Rainbow (Part 2)
· Part 4. Understanding Diffraction Grating
· Part 5. The Mathematics of Diffraction Grating
· Part 6. CD-ROM Shader: Diffraction Grating (Part 1)
· Part 7. CD-ROM Shader: Diffraction Grating (Part 2)
· Part 8. Iridescence on Mobile
· Part 9. The Mathematics of Thin-Film Interference
· Part 10. Car Paint Shader: Thin-Film Interference
 
 
在页面的底部,有本系列中用到的Unity工程下载链接
 
 
介绍
 
在之前的教程中,衍射光栅的数学原理TheMathematics of Diffraction Grating),我们推导了反应彩虹反射原理的方程。晕彩效应会出现在具有重复图案的材质上,图案的尺寸符合它们所反射的光的波长。
 
 
我们想要实现的视觉效果,最终取决于3个因素:光源和表面法线的角度(光源方向),观察者的角度(观察方向),以及重复间隙的距离。
 
 
 
我们想要着色器,在标准材质附带的普通效果上,添加彩虹反射。所以,我们要扩展标准表面着色器(Standard Surface shader)光照函数。如果你对步骤还不熟悉,在 物理渲染和光照模型(Physically Based Rendering and Lighting Models 一文中有详细的介绍。
 
 
创建一个表面着色器(Surface Shader)
 
首先创建一个新的着色器。如果想要扩展一个已经支持物理光照的着色器,应该从标准表面着色器(Standard SurfaceShader开始。
 
 
 
 
 
新创建的CD-ROM着色器需要一个新的属性(property):距离file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps9BBC.tmp.jpg,用于光栅衍射方程中。先添加一个的Properties块,代码如下:
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
Properties
 
{
 
_Color ("Color", Color) = (1,1,1,1)
 
_MainTex ("Albedo (RGB)", 2D) = "white" {}
 
_Glossiness ("Smoothness", Range(0,1)) = 0.5
 
_Metallic ("Metallic", Range(0,1)) = 0.0
 
[/color] [color=Black]
 
_Distance ("Grating distance", Range(0,10000)) = 1600 // nm
 
}
 
这会在材质监视器(Material Inspector)中创建一个新的滑块。不过_Distance属性,还是需要在CGPROGRAM中有对应的变量。
 
float _Distance;
 
现在准备开始了。
 
 
自定义光照函数
 
首先需要把CD-ROM着色器的光照函数替换为我们自己的。可以将#pragma指令从
 
#pragma surface surf Standard fullforwardshadows
 
改为
 
#pragma surface surf Diffraction fullforwardshadows
 
这会强制Unity将光照计算委托给一个名为LightingDiffraction的函数。需要注意的是,我们是要扩展表面着色器(Surface shader)的行为,而不是重写它。因此,新的光照函数起初只是简单的调用了Unity的标准物理渲染(Standard PBR)函数。
 
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
#include "UnityPBSLighting.cginc"
 
inline fixed4 LightingDiffraction(SurfaceOutputStandard s, fixed3 viewDir, UnityGI gi)
 
{
 
// Original colour
 
fixed4 pbr = LightingStandard(s, viewDir, gi);
 
// <diffraction grating code here>
 
return pbr;
 
}
 
从以上代码片段可以看出,新的LightingDiffraction 只是简单调用了LightingStandard ,并返回了它的值。如果现在编译着色器,它渲染出的材质和之前是一样的。
 
 
在继续之前,还需要创建一些其他函数,来处理全局光照(Global Illumination)。因为我们并不需要改变它的行为,所以新的全局光照函数,也只是调用了Unity的标准物理渲染(Standard PBR)的函数。
 
 
1
2
3
4
5
6
void LightingDiffraction_GI(SurfaceOutputStandard s, UnityGIInput data, inout UnityGI gi)
 
{
 
LightingStandard_GI(s, data, gi);
 
}
 
最后需要注意的是,我们直接使用了LightingStandard 和LightingDiffraction_GI,所以需要在着色器中包含UnityPBSLighting.cginc
 
 
实现衍射光栅
 
下面是着色器的核心部分。我们最终用来实现衍射光栅的方程,可以参考 衍射光栅的数学原理(The Mathematics of Diffraction Grating)。在那篇文章里,我得出的结论是:观察者想要看见彩虹反射,那么所有的波长file:///C:\Users\ADMINI~1\AppData\Local\Temp\ksohtml\wps9BBE.tmp.jpg,要满足光栅方程:
 
其中n是一个大于θ的正数。

对于给定像素, θL(由光的入射方向决定),θV(由观察方向决定),d(间隔距离)都是已知的。w和n是未知变量。最简便的做法是循环遍历n的所有值,找到满足光栅方程的波长。
 
当找到了适合最终彩虹反射的波长,我们计算出它们相关的颜色,然后叠加。在 改进彩虹(Improving the Rainbow)中介绍了几种方法,可以将可见的光谱转换为颜色。这篇教程中,我们将会使用spectral_zucconi6算法,因为它能用最低的开销,达到最好的近似效果。
 
 
让我们来看看可能的实现过程:
 
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
inline fixed4 LightingDiffraction(SurfaceOutputStandard s, fixed3 viewDir, UnityGI gi)
{
// Original colour
fixed4 pbr = LightingStandard(s, viewDir, gi);
  
// Calculates the reflection color
fixed3 color = 0;
for (int n = 1; n <= 8; n++)
{
float wavelength = abs(sin_thetaL - sin_thetaV) * d / n;
color += spectral_zucconi6(wavelength);
}
color = saturate(color);
  
// Adds the refelection to the material colour
pbr.rgb += color;
return pbr;
}
在上面的代码中,我为使用的n最大为8,如果想要更好的效果,你还可以增大它,但是这已经占了彩虹反射的很大一部分了。
 
现在还剩下一件事要做。计算sinθLsinθV。这需要引入另一个概念:切线矢量(tangent vector)。它的计算方法,会在教程的后半部分介绍。
结论
 
你可以从下面的链接找到这个系列的所有文章:
 
· Part 1. The Nature of Light
· Part 2. Improving the Rainbow (Part 1)
· Part 3. Improving the Rainbow (Part 2)
· Part 4. Understanding Diffraction Grating
· Part 5. The Mathematics of Diffraction Grating
· Part 6. CD-ROM Shader: Diffraction Grating (Part 1)
· Part 7. CD-ROM Shader: Diffraction Grating (Part 2)
· Part 8. Iridescence on Mobile
· Part 9. The Mathematics of Thin-Film Interference
· Part 10. Car Paint Shader: Thin-Film Interference
 
你可以从Patreon下载CD-ROM shader的Unity包。
99VR视界二维码
热门推荐
Hot Recommended
在线客服