这篇教程将教大家如何创建一个真实的模拟LCD显示器外观和感觉的着色器效果。游戏《Slime Rancher》中有一个奇妙的化妆品特效就是用特殊的LCD着色器做成的,而且当接近监视器的时候,看起来就是像素化的效果。
054053fhha6wdjhwdbyfat.png

值得注意的是,这并不是像素化图片以达到LCD显示效果的最好方法。变量_Pixels表示多少像素会显示在原始网格中,而忽略了真实世界的大小。如果缩放了包含上图纹理的四边形,像素的尺寸依旧不会改变。这与我们希望实现的效果不一致。但只要不调整监视器的尺寸,就没问题。

第二步 LCD渲染

LCD渲染看起来是个非常复杂的部分,但实际上却很简单。为了达到这个效果,我们需要用一些LCD像素纹理来替换图像的每个像素。谷歌搜索“LCD pixels”就可以找到Monomi Park实现该效果用到的原图。

054056f2pu6aaw262pcn2f.jpg

从理论上来说,我们只需要单一的RGB单元。为了避免重复,可以使用包含多个单元的一个纹理;这也能让着色器表现得更具多样性。
[C#] 纯文本查看 复制代码// Properties _LCDTex(LCD (RGB), 2D) = white {} _LCDPixels(LCD pixels, Vector) = (3,3,0,0) // Surf function float2 uv_lcd = IN.uv_MainTex * _Pixels.xy / _LCDPixels; fixed4 d = tex2D(_LCDTex, uv_lcd);

通过将UV乘以_Pixels可以确保采样的LCD纹理匹配所有像素点。变量_LCDPixels表示有多少RGB单元出现在图片中。

下面要做的就是混合两张图像:
[C#] 纯文本查看 复制代码o.Albedo = a * d; o.Alpha = 1;
054057vqe5ciwgi85wtw79.png

你会发现放大的效果很差,这将在下面的步骤中改善。

第三步 放大效果

当我们靠近监视器的时候应该就能看见LCD特效。远处的观众只能看到像素化的版本。更严谨来讲,如果与相机的距离较近为_DistanceOne,就可以看到完全的LCD效果,如果与相机的距离较远为_DistanceZero,就只能看到像素化效果。所有值都是这两个效果之间的线性插值。

为了实现这个效果,我们还需要两个附加信息:相机的位置和当前绘制片段的位置。后者可以通过改变输入结构体来获取:
[C#] 纯文本查看 复制代码struct Input { float2 uv_MainTex; float3 worldPos; };

相机位置则始终可以从内置变量_WorldSpaceCameraPos中获取。

下面的代码计算对象与相机间的距离,将其正规化在0和1之间,并用它作为混合系数。
[C#] 纯文本查看 复制代码// Properties _DistanceOne (Distance of full effect, Float) = 0.5 // In metres _DistanceZero (Distance of zero effect, Float) = 1 // In metres // Surf function float dist = distance(_WorldSpaceCameraPos, IN.worldPos); float alpha = saturate ( (dist - _DistanceOne) / (_DistanceZero-_DistanceOne) ); // [_DistanceOne, _DistanceZero] > [0, 1] // Mixing o.Albedo = lerp(a * d, a, alpha);

最终效果如下:
054104pldcggjlflllcsuo.gif

结论

本教程为使用着色器来实现现实中LCD显示器的效果打开了良好的思路。如你所见,它与游戏《Slime Rancher》中的效果根本没有可比性。当涉及到着色器时,细节决定成败是不变的真理。很多东西都能显著改善其效果。例如,非线性的缩放曲线,不同的颜色混合函数,增加一些噪声让颜色振荡,等等。如果有什么想法,欢迎来下方评论区分享。


原文链接:http://www.alanzucconi.com/2016/05/04/lcd-shader/
原文作者:Alan Zucconi
感谢Unity官方中文社区翻译组成员:“yangtze0621” 对本文翻译所做的贡献。
转载请注明来源:Unity官方中文社区 (forum.china.unity3d.com)。请勿私自更改任何版权说明信息。


Unity, Shader, LCD, 着色器锐亚教育

锐亚教育 锐亚科技 unity unity教程