Unity Shader原理和实战
文章平均质量分 86
专注Unity Shader 原理与实战应用。系统讲解 Unity 图形系统、Shader 编写与渲染机制,并结合真实项目案例解析实用 Shader 的实现与优化方法。
所有示例均经过项目验证,强调工程实用性、性能优化与可复用性。
n5
在信息时代客观障碍已不复存在,所谓障碍都是主观上的。如果你想研发什么新的技术,你不需要几百万美元的资金。你只需要在冰箱里放满比萨和可乐,再有一台便宜的计算机和与之献身的决心,你即可拥有任何你想拥有的编程境界- John Carmack
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
Unity Lightmap 场景下 Screen-Space Shadow 大面积错误阴影问题排查实战
本文给出了一次Unity Lightmap场景下Screen-Space Shadow错误阴影问题的分析和修复的实战记录。原创 2026-04-18 15:46:45 · 125 阅读 · 0 评论 -
Unity URP 中 GPU Instancing的使用
本文详细讨论了Unity URP中的GPU Instancing,Staic Batching 和 SRPBatcher,探讨它们的原理以及在场景中的优先级。讲解如何在自定义Shader中启用GPU Instancing,以及如何通过破坏SRPBatcher兼容性来启用GPU实例化。原创 2022-05-19 13:51:30 · 8689 阅读 · 1 评论 -
Unity内置管线Projector原理分析
Unity 内置管线的Projector功能Unity内置管理的Projector功能还是比较简单的。首先给投影体加一个 Projector组件:这个Projector定义了一个视锥体,可以是透视投影也可以是平行投影。场景中和这个视锥体相交的物体会绘制投影纹理。所以总的效果就是投影体镜头上的贴图(材质)被绘制在场景物体中,例如上图的两个Plane和一个Cube。投影纹理的原理这儿使用的技术叫做 Projective Texture Mapping,使用这个关键词可以搜索到一篇论文。基本原理是对于原创 2022-04-01 19:38:46 · 8484 阅读 · 0 评论 -
Unity UI HSV 调色 Shader 完整方案(图片复用 + 内存优化)
本文介绍了一种高效的Unity UI HSV调色方案,通过Shader实现单张图片复用多种颜色效果。核心思路是利用VertexColor传递HSV参数,在Shader中将RGB转为HSV空间进行调整后再转回RGB。相比传统Sprite Color乘法,HSV调色能灵活改变色相、饱和度和亮度,显著减少贴图资源占用。方案包含完整的Shader实现、Inspector控制脚本和工具类,支持UI合批和Mask等特性,可广泛应用于技能图标、品质框等需要多颜色版本的UI元素,有效优化包体和内存。原创 2026-03-12 14:34:53 · 117 阅读 · 0 评论 -
Unity UI 叠加特效 Shader 实现详解(AddTexture + Animator 驱动 UV)
UI特效叠加Shader与UV动画实现方案 本文完整介绍了一套UI特效解决方案,通过Shader与脚本配合实现纹理叠加和动态效果。系统包含以下核心组件: Effect_Add Shader:实现基础渲染逻辑,支持主纹理与叠加纹理的混合,包含颜色合成公式:FinalColor = (MainTex + AddTexture * AddColor * Mask) * VertexColor UV动画控制:通过脚本动态修改_AddTexture_ST参数(包含Tiling和Offset值)实现纹理流动效果原创 2026-03-12 14:00:10 · 185 阅读 · 0 评论 -
Unity UI 流光特效 Shader 实现详解(Flow + Mask + Noise)
本文详细介绍了Unity UI流光特效Shader的实现方法,主要包含以下内容: 效果原理:通过UV流动实现按钮流光、高亮扫光等视觉效果,比动画序列更节省资源且可调节性强。 核心实现: 基础UI Shader结构支持Mask、ClipRect等功能 通过UV滚动(UV Panner)实现流动效果 使用Mask控制流光显示区域 添加Noise扰动使效果更自然原创 2026-03-12 09:59:25 · 559 阅读 · 0 评论 -
移动端高效各向异性头发 Shader 实现指南
本文介绍了移动端游戏中实现逼真头发渲染的技术方案。核心采用Kajiya-Kay各向异性高光模型,该模型计算简单且适合移动端性能要求。关键实现包括: 发色渐变:通过梯度纹理控制发根到发梢的颜色过渡 切线空间处理:利用TBN矩阵转换法线贴图方向 Alpha Test:实现头发透明效果,避免排序问题 各向异性高光:基于发丝方向(T)计算特殊高光带效果 Shader通过顶点着色器准备TBN数据,片元着色器计算漫反射和各向异性高光,最终形成垂直于发丝方向的高光带而非传统圆形高光原创 2026-03-12 09:50:01 · 235 阅读 · 0 评论 -
Unity UI Default Shader分析
Unity ShaderLab的Properties一般用于将材质使用到的Shader参数暴露在材质的Inspector面板中以方便设置,并且编辑后的参数值可以和材质一起保存。另外材质使用到的渲染状态值,以及关键字也可以使用Properties进行编辑。Properties在上面的shader中,包含以上的属性。其中_MainTex, _Color是shader的参数,而_Stencil开头的这些和_ColorMask是渲染状态值,_UseUIAlphaClip则是关键字开关。原创 2025-02-06 23:05:11 · 922 阅读 · 0 评论 -
Unity shader中真的可以动态关闭Stencil Test吗?
由此可知,如果我上面的测试是正确的,UGUI的 UI/Default shader由于包含了Stencil,那么Stencil Test对于所有的UGUI Drawcall都是开启的。那么使用Mask似乎也不会额外影响性能了是吧,那还优化个啥呢。另外,如果Shader中根本不包含Stencil这段,则Stencil Eanble为false。但是我没有测试移动平台和DX12,但这应该是RHI无关的逻辑吧。可是Stencil这段没法动态关闭。原创 2025-01-12 20:02:59 · 1028 阅读 · 2 评论 -
深入URP之Shader篇16: UNITY_BRANCH和UNITY_FLATTEN
实际上,编译器会进行优化,以及处理成多种不同的情况。比如编译器会将if和else展开,分别执行其中的代码,然后根据测试条件选择一个结果,这被称为Flatten。或者编译器会真的编译出if指令,真正的动态分支。这取决于平台是否支持。比如在老的OpenGL ES 2.0平台,编译器总是进行Flatten,所以if分支才被视作性能杀手。当然即便是没有Flatten,真正的动态分支由于会让同一个Warp中的线程不能同步执行而互相等待,也会造成性能问题。在DX11中,编译器支持[branch]和[flatten]原创 2024-05-31 17:24:03 · 2201 阅读 · 0 评论 -
深入URP之Shader篇15: Shader关键字和变体
每种关键字的组合对应的shader版本就是一个shader变体。所谓变体,就是同一份shader源码,由于启用了不同的关键字组合,经过编译器预处理就得到了最终不一样的shader代码。原创 2024-02-22 10:45:30 · 1887 阅读 · 0 评论 -
深入URP之Shader篇14: GPU Instancing
首先,定义PerMaterial Uniform block时,要使用INSTANCING相关的宏和。这些宏的作用是将Uniform block定义成数组。需要注意的是,只有当同一个材质下面的不同Instance存在逐Instance不同的属性时,才需要将UnityPerMaterial的CBuffer改成使用这些宏,否则是不需要的,因为这些宏只是为了将属性定义成数组,然后可以使用Instance索引去得到数组里面不同Instance各自的属性。原创 2023-08-27 17:58:14 · 1884 阅读 · 0 评论 -
深入URP之Shader篇13: SRP Batcher
首先对于Unity内置属性,比如要放在一个名字为的CBuffer中。其实我们写自定义shader都是直接include URP的Libraray的,其中已经做好了这个。在Packages\com.unity.render-pipelines.universal\ShaderLibrary\UnityInput.hlsl中我们看到:这些属性被分为不同的block,虽然我们可能只使用一部分block,但是还是得按照这个布局来。材质自定义的属性要放在的CBuffer中。原创 2023-04-04 12:05:29 · 2691 阅读 · 1 评论 -
深入URP之Shader篇12: 深度值专题(3)
深度图的定义在本篇中分析了深度图的生成,定义和采样,结合软粒子效果看了一下深度图和线性深度的应用。原创 2023-02-13 17:15:46 · 2388 阅读 · 0 评论 -
深入URP之Shader篇11: 深度值专题(2)
本篇简单总结了URP Shader中使用线性深度以及重建世界坐标的方法。原创 2023-02-06 11:21:30 · 1282 阅读 · 0 评论 -
深入URP之Shader篇10: 深度值专题(1)
当平台使用翻转深度值方向时,Unity就会定义为1:在这些平台上,由于深度缓冲是翻转的,那么的范围也是1(near)到0(far)。同时clip space的z值范围是[near,0]。在shader中就要使用区分出这种情况做相应的处理。例如,当我们要从#endif而如果我们要手动操作clip space Z值时,也要多加注意了,比如下面这个情况。原创 2023-01-14 11:31:42 · 1580 阅读 · 0 评论 -
深入URP之Shader篇9: SimpleLit Shader分析(5)
在前两篇中,FS的数据已经全部准备好了,本篇就重点看怎么计算光照的,这个Simple Lit有多Simple。另外本篇的另一个重点就是Unity的GI的使用,包括BakedGI和RealtimeGI,这些在这个Simple Lit里面都有用到。计算光照的核心函数就是,传入的参数除了InputData,还有之前计算出来的diffuse, specular, smoothness, emission和alpha。之后使用MixFog将光照计算出来的颜色和雾的颜色进行混合,最后使用计算最终的alpha值。原创 2023-01-03 17:51:13 · 1540 阅读 · 3 评论 -
深入URP之Shader篇8: SimpleLit Shader分析(4)
URP ShaderLibrary的Input.hlsl这个结构体包含了光照计算所需要的所有输入参数,有些参数是直接从Varying获取,有些是进一步计算得到。这个结构体大量用于URP的各个Shader中。而的作用就是设置这个结构体的各个成员值,这个函数名也是URP的一个惯例,很多shader中都会有这个函数,当然函数参数可能不一样,但是作用是一样的。我们看下SimpleLit Shader的这个函数吧。原创 2022-12-09 10:37:41 · 1168 阅读 · 0 评论 -
深入URP之Shader篇7: SimpleLit Shader分析(3)
上篇中分析了Simple Lit Forward Pass的Vertex Shader都计算和输出了什么数据,本篇就看看在Fragment shader中是怎么使用这些数据计算最终的光照颜色的。由于代码较短,就都贴出来方便查看:首先进行的是Alpha Test之前在分析Depth Only Pass的时候就看过alpha test的处理,和这儿有些类似,但是由于Depth only pass更加通用,所以会在使用albedo贴图alpha的时候做一些判断,在某些情况下这个贴图的alpha是不用来做al原创 2022-12-07 10:44:37 · 1368 阅读 · 0 评论 -
深入URP之Shader篇6: SimpleLit Shader分析(2) Vertex Shader
看看在顶点shader中都计算了什么其中,函数位于SPR Core的中:这里面的却又位于URP的中:回到中,首先计算world space的法线和切线没啥问题,只不过变换法线需要用逆转置矩阵因此使用一个特定的函数,而变换切线使用普通的变换向量的函数即可,这两个函数自己写shader也经常用。而计算副切线是使用法线和切线的叉积,但是其结果需要校正符号。而这个符号是Object space切线的w和返回值的乘积。这个我暂时没弄清楚,按照之前掌握的知识,Object space切线的w的正负,是由DCC工原创 2022-12-06 11:03:40 · 2071 阅读 · 3 评论 -
深入URP之Shader篇5: SimpleLit Shader分析(1)
本篇开始分析simple lit shader。我们通过分析unlit shader了解了URP shader的结构,以及一些基础功能。而simple lit shader包含了更多的内容。本篇开始,就不会特别仔细的逐行去分析shader文件了,只会针对pass的功能中比较有意思且之前没看到过的内容进行分析。名字为的pass,它的Tags为:根据URP的文档:说明这是一个前向渲染路径的pass,虽然URP(至少是10.8.1版本)还没有正式支持Deferred Rendering,但URP已经为它打了很多原创 2022-12-05 11:21:37 · 1857 阅读 · 0 评论 -
深入URP之Shader篇4: Depth Only Pass
unlit shader中包含了一个Depth Only Pass,这个pass的代码在中。这是一个公共pass,几乎所有的URP shader都会包含这个pass。本篇说一说这个pass的作用以及实现细节。Depth only pass的作用是生成一张场景的深度图,一般是在渲染不透明物体之前,对所有包含该pass的材质对应的物体执行这个pass,当所有物体执行完毕后,就得到了深度图。这个pass执行的前提是URP判断需要深度图,比如URP assets中配置了:或者camera开启了后处理。使用深度图,游原创 2022-12-04 13:31:28 · 3779 阅读 · 0 评论 -
深入URP之Shader篇3: Unlit Shader分析[下]
上篇中我们分析了Unlit shader的Properties在ShaderGUI中的处理,接下来看Sub Shader。unlit shader以及其他URP shader包含两个SubShader,分别是针对ShaderModel4.5和2.0。由于unlit shader本身很简单,这两个SubShader几乎一样,唯一的差别是ShaderModel 4.5的SubShader会定义,这个可参考dots-instancing-shaders,本文中先忽略它。总之这儿的要点是URP会针对比较强大的设备使原创 2022-12-03 09:44:48 · 1818 阅读 · 1 评论 -
深入URP之Shader篇2: 目录结构和Unlit Shader分析[上]
我使用的Unity版本为2020.3.33f1,对应的URP和SRP Core版本为10.8.1。阅读URP源码建议把package从Library/PackageCache中拷贝到Packages目录,也就是自定义package的方式,然后推荐使用VS code打开工程,这样可以很方便的跳转代码阅读。原创 2022-12-02 18:23:11 · 2323 阅读 · 0 评论 -
深入URP之Shader篇1: URP Shader概述
我们知道,URP和HDRP都是基于SRP的,尽管现在可以使用Shader Graph编写Shader,但是手写Shader仍然是有一定的优势,特别是在性能方面,手写Shader可以更极致的优化,因此我们在项目中前期都是直接使用Shader Graph编写Shader,项目后期会改成手写Shader来提高性能。而在SRP中手写Shader,我们仍然使用的是Shader Lab,这个结构并没有太大的变化,但是SRP Shader中使用Shader Lab语言还是有几点不同。原创 2022-12-01 22:30:02 · 4594 阅读 · 0 评论 -
Unity解决同材质物体重叠产生Z-Fighting的问题
在Unity中绘制多个可能部分或全部重叠的物体,这些物体可能是使用同一个材质,此时大概率会产生Z-FightingZ-Fighting的原因是片段计算出的深度值太接近了,从而不能确定哪一个离相机更近,互相竞争导致闪烁。那么解决思路就是让他们的Z值稍微有点区别。比较常见的解决方案是Polgon Offset,即Unity Shader Lab的Offset属性。但是对于使用同一个材质的物体,这个方法无效。因为这种物体互相重叠时即便在材质上设置了Offset,由于是同一个材质,计算出来的depth还是一样的,并原创 2022-07-12 16:32:34 · 4070 阅读 · 0 评论 -
Unity使用shader渲染时的操作顺序
确定Active SubShaderSubShader列表Unity在使用一个Shader Object之前,会创建一个SubShader列表,将该Shader Object中所有的SubShader加入该列表中。并且也会把fallback shader object的所有SubShader加入到这个列表中。Active SubShader选择当第一次使用这个Shader object渲染几何体时,或者当shader LOD value改变时,又或者当前激活的render pipleline改变时,原创 2022-04-14 12:43:36 · 3650 阅读 · 0 评论
分享