ShaderLab

Pixel-Perfect Outline Shaders for Unity

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 原文地址 How outline shaders work 我第一次在电子游戏中看到3D物体的 轮廓线(outline) 是2003年育碧的《XIII》。这是我听说过的第一个具有 cel-shaded风格的 3D 游戏。(它基于一本图画小说。) 一旦我看到它,我必须知道它是如何完成的。《XIII》是一款使用虚幻2引擎的研发的游戏,我能够打开我信赖的 UnrealEd 并四处看看。 虚幻2引擎使用了固定功能的图形管道,这意味着XIII厚实的 墨水状轮廓(thick, ink-like outlines) 没有涉及着色器魔法。轮廓实际上是每个网格的一部分:外壳,悬停在角色的表面,具有倒置的面法线,因此只有内部可见,覆盖着黑色纹理。 自 2003 年和固定功能的图形管道以来,我们已经取得了长足的进步,但我们处理轮廓的方式几乎没有改变。最大的变化是轮廓不再需要成为网格的一部分;我们可以在单独的通道中使用顶点着色器来渲染网格的略微肥大的版本,并剔除正面(front face culled)。 换句话说,在我们的outline pass中,我们将取顶点的法线,乘以一个小数(我们不想增肥一个完整的单位!)得到一个偏移值,并将在变换顶点到裁剪空间之前,其此偏移值添加到顶点之前的位置。 这正是XIII在 2003 年在没有任何着色器的情况下完成的结果,但现在我们使用GPU自动地执行轮廓线绘制操作,来简化我们的创作工作流程。但我们可以做得更好。 Limitations of the classic technique 对于XIII受图形小说启发的美学而言,这些墨色轮廓恰到好处。但就像任何 15 年前的预着色技术一样,它们也有局限性,这使得它们作为通用轮廓解决方案的用处不大: 根据形状和视角,轮廓在对象表面上的厚度会有所不同。 当物体远离相机时,轮廓会被缩短(使用透视投影时) 轮廓宽度以对象空间单位指定,而不是以像素为单位。 请注意,这些是限制(limition),不一定是问题(problems)。在某些情况下,它们中的一些或全部可能是可取的。但他们每个人都应该在我们的控制之下。 我专注于技术,电脑艺术的。当我们作为艺术家以高水平的技术进行操作时,我们正在对我们制作的艺术——即我们代码的输出——施加精确的控制。 例如,我们可能希望将物体轮廓作为用户界面的一部分,以表明该物体已被选中。我们可能希望这些元素具有稳定的屏幕空间宽度。 或者我们可能正在模仿矢量或像素艺术风格,或者将 3D 网格与矢量或像素艺术精灵混合。我们需要能够以像素为单位匹配我们的轮廓宽度。 在本教程的过程中,我们将探索经典技术,然后对其进行改进,特别关注我们如何变换顶点位置,以更适应我们的需求,并为我们提供对最终外观的更多艺术控制。 Building the classic outline shader 下面是作为现代 Unity 着色器的经典XIII风格轮廓的代码。 Shader "Tutorial/Outline" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) _Glossiness ("Smoothness", Range(0, 1)) = 0.

Unity3D Shader的内建multi_compile开关所涵盖的多样体

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com multi_compile_fwdbase 在Unity3D 2018.4.18f1版本下实测到,如果不做其他特别的指定,一个multi_compile_fwdbase编译指令,包含了以下 9 个内建的keyword: DIRECTIONAL DIRLIGHTMAP_COMBINED DYNAMICLIGHTMAP_ON LIGHTMAP_ON LIGHTMAP_SHADOW_MIXING LIGHTPROBE_SH SHADOWS_SCREEN SHADOWS_SHADOWMASK VERTEXLIGHT_ON 如果不做特别的指定的话,默认地启用了其中的 4 个内建keyword,分别是:DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN VERTEXLIGHT_ON组成了 8 个多样体,如下: 多样体(变体) DIRECTIONAL DIRECTIONAL LIGHTPROBE_SH DIRECTIONAL SHADOWS_SCREEN DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN DIRECTIONAL VERTEXLIGHT_ON DIRECTIONAL LIGHTPROBE_SH VERTEXLIGHT_ON DIRECTIONAL SHADOWS_SCREEN VERTEXLIGHT_ON DIRECTIONAL LIGHTPROBE_SH SHADOWS_SCREEN VERTEXLIGHT_ON multi_compile_fwdadd 在Unity3D 2018.4.18f1版本下实测到,如果不做其他特别的指定,一个multi_compile_fwdadd编译指令,包含了以下 5 个内建的keyword: DIRECTIONAL DIRECTIONAL_COOKIE POINT POINT_COOKIE SPOT 如果不做特别的指定的话,默认地启用了全部的 5 个内建keyword,组成了 8 个多样体,如下: keyword组成的多样体(变体) DIRECTIONAL DIRECTIONAL_COOKIE POINT POINT_COOKIE SPOT multi_compile_fwdadd_fullshadows 在Unity3D 2018.4.18f1版本下实测到,如果不做其他特别的指定,一个multi_compile_fwdadd_fullshadows编译指令,包含了以下 5 个内建的keyword:

Unity的multi_compile和shader_feature编译指示符、shader variant和asset bundle

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com multi_compile编译指示符 multi_compile编译指示符的文档在这里。假如有以下的shader示例语句: #pragma multi_compile _USE_SEMITRANSPARENT _USE_OPAQUE #pragma multi_compile _MULTI_RED _MULTI_GREEN _MULTI_BLU ... fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); #if _MULTI_RED col = col * fixed4(1,0,0,1); #elif _MULTI_GREEN col = col * fixed4(0,1,0,1); #elif _MULTI_BLUE col = col * fixed4(0,0,1,1); #endif #if _USE_SEMITRANSPARENT col.a = 0.5; #elif _USE_OPAQUE col.a = 1.0; #endif return col; } 那么根据排列组合,就会有 $ 2 \times 3 = 6 $ 种代码段的组合,即分别是 _USE_SEMITRANSPARENT与_MULTI_RED , _USE_SEMITRANSPARENT与_MULTI_GREEN , _USE_SEMITRANSPARENT与_MULTI_BLUE , _USE_OPAQUE与_MULTI_RED , _USE_OPAQUE与_MULTI_GREEN , _USE_OPAQUE与_MULTI_BLUE。总得来说,就是各种排列组合对应编译生成的变体, $\color{#FF0000}{无论有没有被使用上,都会被编译打包到游戏包或者资源包中}$ 。所以 在运行时 ,可以使用 Material.

Unity3D shader优化技巧集合

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 一些优化的tips,基于2019.3版本 只做需要的计算,比如一直在shader设置某个固定颜色,就等于白做计算 能给vs做的,就不要给fs做,能在脚本设置的,就不要在shader里做,比如在shader代码里面用 if-else ,就不如在脚本中用 keyword 优化surface shader:启用 approxview 编译指示符,在光照计算时,在vs中而不是在fs中做视线向量的规格化 优化surface shader:启用 halfasview 编译指示符,在光照计算时,使用半角向量做光照计算,且半角向量的计算在vs中执行 优化surface shader:启用 noforwardadd 编译指示符,确保在 Forward rendering 模式中, 只使用一个有向平行光光源 在fs中执行光照计算,其他的实时光源都只在vs中进行计算,此指示符确保只在一个pass中执行渲染操作 优化surface shader:编译指令 noambient 禁用着色器上的环境照明和球谐光。这样可以使性能稍快一些。 数据精度的优化:世界坐标系下的坐标值,纹理映射坐标值,用 float 数据精度的优化:除了HDR颜色之外的数据,使用 half 数据精度的优化:纹理数据的相关的一些简单操作用 fixed 各种GPU的区别: 桌面GPU ,内部都会统一用 float 计算 各种GPU的区别: 移动GPU 内部能真正支持half精度,大胆地使用它 各种GPU的区别: 老旧的GPU 才内部实现了 fixed , OpenGL ES3 及后续的都内部把 fixed 处理为 half 了 Alpha Testing :在iOS等等使用了PowerVR芯片的平台,表现不佳。 ColorMask :在某些平台上(大多数是在iOS和Android设备的移动GPU),使用 ColorMask 忽略某些通道(例如 ColorMask RGB )可能会占用大量资源,因此仅在确实需要时才使用它。 参考网页: https://docs.unity3d.com/Manual/SL-ShaderPerformance.html https://www.cnblogs.com/sifenkesi/p/4716791.html