Shader

从半透明模型的描边到URP Multipass Rendering

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 卡通渲染技术中,描边的实现的有多种做法,有基于后处理实现,也有基于非后处理,通过多次绘制模型的方法实现。 通过多次绘制模型的实现,方法无非就是: 绘制模型本体,同时写入深度值。 让模型顶点沿着法线外扩一定的偏移量,即让模型膨胀一些 全用描边的颜色绘制膨胀过的模型,且,在绘制时,使用cull front,即只绘制模型的背向摄像机面。在第1步中因为绘制模型本体时已经写入深度值。在本步骤中只要不改变深度测试函数的方式,那么除了膨胀部分之外,是无法写入像素的,能写入的部分,便形成了边缘。 上述的方式,一般应用于不透明的材质上。如果是半透明的材质的话就有问题,因为在第1步绘制半透明材质时,一般是不写入深度值的。那么第3步在绘制膨胀模型时,模型背部的地方就会被绘制上去。 解决这个问题有很多,可以利用stencil test的方式。也可以在第一步绘制,不绘制任何颜色,只写入深度,然后再绘制模型,最后再绘制描边。后一种方法,如果用Unity内置管线,大约就是这个样子: Shader "Unlit/半透明" { Properties { _Diffuse("Diffuse",Color) = (1,1,1,1) // 漫反射 _MainTex("MainTex",2D) = "white"{} // 2D纹理贴图 _AlphaScale("Alpha Scale",Range(0,1)) = 1 // 控制Alpha参数 } SubShader { Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } //渲染顺序设置Transparent LOD 100 // 用两个pass通道来处理,防止出现渲染错误,第一个pass通道 // 每个pass通道都会渲染一次 Pass { ZWrite On // 注意这里:写入深度 为了确认渲染顺序 ColorMask 0 // 掩码遮罩代表这个pass通道不写入任何颜色值 } Pass // 第二个pass通道 { Tags{"LightMode" = "ForwardBase"} ZWrite Off // 注意这里:关闭ZWrite(深度写入) Blend SrcAlpha OneMinusSrcAlpha // 源颜色因子 正常透明混合 CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.

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.

An Introduction to shader derivative functions(翻译)

请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com 原文地址 Partial difference derivative functions (ddx and ddy in HLSL[a], dFdx and dFdy in GLSL[b]) (in the rest of this article I will use both terms according to the code examples I will provide) are fragment shader instructions wich can be used to compute the rate of variation of any value with respect to the screen-space coordinates. 偏导数函数(在HLSL中为ddx和ddy,GLSL中为dFdx和dFdy)。在本文的其余部分中,我将根据我将提供的代码示例使用这两个术语)都是可以使用的片元着色器指令,可用于计算任何数值相对于 屏幕空间坐标 的变化率。 Derivatives computation During triangles rasterization, GPUs run many instances of a fragment shader at a time organizing them in blocks of 2×2 pixels.

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

《Unity3D内建着色器源码剖析》

书籍信息 信息 详情 定价 89.00 出版社 人民邮电出版社 版次 1 出版时间 2019年08月 开本 16 装帧 平装 页数 334 ISBN编码 9787115507044 官方QQ群 群1号码:672523982 书籍配套代码 代码文件 MD5值 Unity3D内建着色器源代码 版本2017.2.0f3 MD5: 1737874a497c6fa04031af3c90ff2f99 第12章的代码工程 MD5:640938e9f1a259b7e693b1abe866f368 书中参考引用到的一些技术文章 微软网站上关于DXT及BC系列格式的详细介绍 微软MSDN上有介绍块状压缩的文章 nVidia开发者网站有一篇介绍单程立体渲染原理的文章。 Unity3D官网也有单程立体渲染的介绍 《Unity3D内建着色器源码剖析》勘误表 第1版第1刷 章节 页数 位置 错误内容 正确内容 1.2.2 正文第4页 第5段第5行 $$\left< p_1,p_2,p_3 \right>$$ 的排列顺序称为顺时针方向(clockwise,CW)。 $$ \left< p_1,p_3,p_2 \right> $$ 的排列顺序称为顺时针方向(clockwise,CW)。…… 1.2.2 正文第4页 第6段第2行 在图1-7(b)的左手坐标系下排列顺序改为 $$ \left< p_1,p_2,p_3 \right> $$ 在图1-7(b)的左手坐标系下排列顺序改为 $$ \left< p_1,p_3,p_2 \right> $$ 1.