当前位置:   article > 正文

Unity URP CG/HLSL精简规范总结_unity hlsl clamp

unity hlsl clamp

使用shader graph过程中,想要实现一些多pass效果,虽然使用render feature能够一定程度上解决需求,但我认为render feature始终是一个在特定阶段做一些简单操作的实用工具,在实现多pass效果的时候总会有一些不如意,所以总结了unity官网上的CG/HLSL规范,也是下一步准备浏览大佬作品的前置条件。如果连基本规则都不懂,即使是看到一些简单操作也会一头雾水。

  1. Shader "URPShaderTest"
  2. {
  3. Properties
  4. {
  5. //Color(4,线性SRGB)、Vector(4)、Float、2D(texture)、Cube(cubmap)、Integer、Range、2DArray、3D、CubeArray
  6. //对应下面声明fixed4、float4、float、sampler2D、samplerCUBE
  7. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  8. _MainTex("Texture", 2D) = "white" {}
  9. [Toggle(Switch)]
  10. _Switch("Switch", Integer) = 0
  11. _OffsetUnitScale("OffsetUnitScale", Integer) = 0
  12. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  13. //特性
  14. /*
  15. [Gamma] 指示浮点或矢量特性使用sRGB值
  16. [HDR] 指示纹理或颜色特性使用高动态范围(HDR)值
  17. [HideInInspector] 藏
  18. [MainTexture] 设置材质的主纹理,可以使用Material.mainTexture访问该材质。默认名称为_MainTex的纹理为主纹理
  19. [MainColor] 设置材质的主颜色,可以使用Material.color访问该材质。默认名称为_color的颜色为主颜色
  20. [NoScaleOffset] 为该纹理属性隐藏平铺和偏移字段
  21. [Normal] 指示法线贴图纹理
  22. [PerRendererData] 指示纹理特性将来自MaterialPropertyBlock,inspector将显示为只读
  23. */
  24. //MaterialProperty类 https://docs.unity3d.com/2021.3/Documentation/ScriptReference/MaterialProperty.html Material.GetFloat, Material.SetFloat等等
  25. //编辑器扩展MaterialPropertyDrawer、MaterialEditor、MaterialProperty、ShaderGUI https://docs.unity3d.com/2021.3/Documentation/Manual/SL-CustomEditor.html
  26. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  27. //保留名称
  28. //_TransparencyLM ("Transmissive Texture", 2D) = "white" {} //在光照贴图过程中启用自定义RGB透明度
  29. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  30. // Cg/HLSL 可以接受uniform值 https://docs.unity3d.com/2021.3/Documentation/Manual/SL-PropertiesInPrograms.html 矩阵和数组只能作为非序列化的运行时属性存在(因为无法在properties块中定义它们)
  31. }
  32. SubShader
  33. {
  34. //SubShaderTags
  35. //RenderPipeline:UniversalRenderPipeline/HighDefinitionRenderPipeline 主要控制渲染用的管线
  36. //Queue:Background(1000)Geometry(default)(2000)AlphaTest(2450)Transparent(3000)Overlay(4000) 或者可以写具体值1300或者Background+300等等 主要控制渲染顺序
  37. //RenderType 没有默认值 替换材质时可以使用这个值作标识:Camera.SetReplacementShader(ShaderType,“ReplaceMePlease”);平时不必使用 貌似也用作深度图生成?
  38. //ForceNoShadowCasting true false 是否阻止阴影投射,有时也阻止接收
  39. //DisableBatching True False默认 LODFading当Lod值非0时阻止,反之不阻止 阻止unity对使用这个SubShader的几何体应用动态批处理 动态批处理会将所有几何体转换为世界空间,着色器程序无法再访问对象空间。可以避免依赖对象空间的着色器程序无法正确渲染的问题
  40. //IgnoreProjector True False默认 不希望任何投影类型材质或者贴图,影响我们的物体或者着色器 UI上用的多
  41. //PreviewType Sphere Plane Skybox 检视预览用什么方式展示
  42. //CanUseSpriteAtlas 警告用户着色器依赖于原始纹理坐标,因此不应将其纹理打包到图集中 多用于使用Legacy Sprite Packer的项目中
  43. Tags {"RenderPipeline" = "UniversalRenderPipeline" "Queue" = "Geometry+100" "RenderType" = "ReplaceMePlease" "ForceNoShadowCasting" = "True" "DisableBatching" = "False" "IgnoreProjector" = "False" "PreviewType" = "Sphere"}
  44. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  45. //这个值和与相机的距离没有关系,Unity不会自动计算着色器LOD,必须手动设置最大着色器LOD,表示它在计算上的要求有多高
  46. // 当有多个subshader时,LOD必须按降序排列,这是因为Unity查找选择第一个有效的SubShader,所以如果它首先找到一个LOD较低的子着色器,它将始终使用它。看来是值越高计算要求越高
  47. LOD 200
  48. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  49. //为了支持SRP Batcher,Shader中要将所有暴露出的参数(贴图除外)给包含到CBUFFER_START(UnityPerMaterial)与CBUFFER_END之间。并且为了保证之后的每个Pass都能拥有一样的CBUFFER
  50. //这一段代码需要写在SubShader之内,其它Pass之前。
  51. //CBUFFER_START(UnityPerMaterial)
  52. // float4 _MainTex_ST;
  53. // float _Switch;
  54. //CBUFFER_END
  55. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  56. //插入来自另一个着色器的命名Pass,减少Pass代码重复 这里插入的是自己的
  57. UsePass "URPShaderTest/URPShaderTestPass0"
  58. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  59. //抓取帧缓冲区纹理到这个命名纹理中去,可以在Pass中声明使用这张纹理。如果不写名称会抓到_GrabTexture中去,但是使用自定义命名可以减少屏幕抓取次数,故尽量使用自命名
  60. GrabPass
  61. {
  62. "_BackgroundTexture"
  63. }
  64. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  65. Pass
  66. {
  67. // 某些着色器需要在不同的管线下运行,需要这个模块 这个模块必须在Pass或者subshader的最开始声明,看你想单独控制pass还是整个subshader
  68. // 这些版本必须和package manager里对应上,否则Pass或者subshader无法正常工作
  69. // 不同的写法有不同的行为https://docs.unity3d.com/Manual/SL-PackageRequirements.html
  70. PackageRequirements
  71. {
  72. "com.unity.render-pipelines.universal": "[13.0.1,14.0.7]"
  73. "com.unity.textmeshpro" : "3.0.6"
  74. }
  75. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  76. Name "URPShaderTestPass0"
  77. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  78. //指令:也可以单独控制pass或整个subshader,但是subshader的会被pass覆盖
  79. //部分一:渲染状态
  80. //AlphaToMask On Off 根据片段着色器输出中的alpha值按比例修改multisample覆盖遮罩 在不使用MSAA的情况下启用结果可能是不可预测的
  81. AlphaToMask Off
  82. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  83. //Blend Off默认 这里要花多行讲解一下
  84. /*混合公式为:finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue *这里的operation是下面的BlendOp 默认是Add*
  85. Blend的签名分为三种,State、Render Target、Factor。
  86. 其中State(Off)和Render Target(07的整数)只会出现一次 【简单来讲,渲染目标(Render Target)就是一种可以在运行时写入的纹理。从引擎的角度讲,渲染目标会存储颜色、法线以及AO等信息】
  87. Factor总共有四个,出现顺序从左到右按此解读:<source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha>
  88. 比如Blend 1 One Zero, Zero One就会这么解读<Render Target> <source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha>
  89. 但是:任何指定渲染目标的签名都需要OpenGL 4.0+、GL_ARB_draw_buffers_blend或OpenGL ES 3.2。单独的RGB和alpha混合与高级OpenGL混合操作不兼容。*/
  90. /*One 值为1,使用此因子来让帧缓冲区源颜色或是目标颜色完全的通过。1
  91. Zero 值为0,使用此因子来删除帧缓冲区源颜色或目标颜色的值。0
  92. SrcColor 使用此因子为将当前值乘以帧缓冲区源颜色的值 A
  93. SrcAlpha 使用此因子为将当前值乘以帧缓冲区源颜色Alpha的值。A*alpha
  94. DstColor 使用此因子为将当前值乘以帧缓冲区目标颜色的值。B
  95. DstAlpha 使用此因子为将当前值乘以帧缓冲区目标颜色Alpha分量的值。B*alpha
  96. OneMinusSrcColor 使用此因子为将当前值乘以(1 -帧缓冲区源颜色值) 1- A
  97. OneMinusSrcAlpha 使用此因子为将当前值乘以(1 -帧缓冲区源颜色Alpha分量的值) 1-A*lpha
  98. OneMinusDstColor 使用此因子为将当前值乘以(1 –目标颜色值) 1-B
  99. OneMinusDstAlpha使用此因子为将当前值乘以(1 –目标Alpha分量的值) 1- B*alpha*/
  100. //src是这个通道渲染出来的颜色值,des是帧缓冲中已经存在的颜色值,跟当前pass的渲染时间有关系,如果这个pass是在最后渲染,那么帧缓冲则是屏幕上渲染完所有其他物体后的颜色值
  101. Blend Zero One // 这样就是舍弃这个通道产生的颜色值而使用帧缓冲中的颜色值,也就是把这个物体透过去了
  102. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  103. //*添加BlendOp要保证已经存在Blend指令,且并非所有设备都支持所有混合操作!!!要注意的如下*
  104. /*1、Min and Max require GL_EXT_blend_minmax on OpenGL ES 2.
  105. 2、Logical operations require DX 11.1+ or Vulkan.
  106. 3、Advanced OpenGL blending operations require GLES3.1 AEP+, GL_KHR_blend_equation_advanced, or GL_NV_blend_equation_advanced. They can only be used with standard RGBA blending; they are not compatible with separate RGB and alpha blending.*/
  107. BlendOp Max // 或者使用这样的混合操作标识 Add(默认), Sub, RevSub, Min, Max等等值非常多,甚至带逻辑运算,具体看这里吧,感觉不常用 https://docs.unity3d.com/Manual/SL-BlendOp.html
  108. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  109. //默认情况下,GPU会写入所有通道(RGBA)。对于某些效果,您可能希望不修改某些通道,这时就需要ColorMask
  110. //ColorMask <channels> <render target>
  111. //channels代表颜色通道,值有0、R、G、B、A或是任意组合如:RA、RGB *写哪个代表允许写入哪个通道,值0代表可以写入所有通道,和RGBA应该是一样的*
  112. //render target如上所说,值为07
  113. ColorMask RGBA
  114. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  115. //是否开启保守光栅化,GPU不考虑覆盖范围,只要有一部分被三角形覆盖的像素就进行光栅化,等于说生成的像素会变多
  116. //使用SystemInfo.supportsConservativeRaster API检查硬件是否支持,不支持会被忽略
  117. Conservative False
  118. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  119. //裁剪:Back(默认)、Front、Off
  120. Cull Back
  121. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  122. //深度偏移:调整深度偏移以强制GPU在相同深度的其他几何体之上绘制几何体,这个东西能防止z-fighting(相同深度面片渲染打架)
  123. //Offset <factor>, <units>
  124. //factor:缩放最大Z坡度(不平行于近剪裁平面和远剪裁平面的多边形具有Z坡度),范围【-11
  125. //units:缩放最小可解析深度缓冲区值,以产生恒定的深度偏移,范围【-11】 负值表示GPU将多边形绘制得更靠近摄影机。正值表示GPU绘制的多边形离摄影机更远。
  126. Offset -1, -1 // 一般来说这样就可以有效防止z-fighting
  127. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  128. Offset -1, [_OffsetUnitScale] // *想用属性往任意指令里面写值的话*
  129. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  130. //模版缓冲区为每个像素存储一个8位整数值,模板测试失败GPU将跳过该像素,可以执行两种操作---写入和测试,它们甚至可以在一条指令中同时执行
  131. //使用Ref、ReadMask和Comp参数来配置模版测试。使用Ref、WriteMask、Pass、Fail和ZFail参数来配置模版写入。
  132. //(ref & readMask) comparisonFunction (stencilBufferValue & readMask) 测试方程,写入的话只是(ref & readMask)在通过或失败情况下怎么做
  133. Stencil{
  134. Ref 2 //这是传进去的int值(默认00255】注意这是二进制11111111),如果在测试就用这个值和模板值(如果没有写入过默认0)作比较,受readMask影响、如果在写入就是写入这个值,受writeMask影响
  135. ReadMask 255 //这是传进去的int值(默认00255】注意这是二进制掩码11111111,与Ref的二进制相与)这个掩码应该是为了不让自己写入的值影响自己,所以一般两个掩码应该是不同的,一般有通道单独写模板值,所以读取通道掩码应和那个写入通道的掩码匹配
  136. WriteMask 155 //这是传进去的int值(默认00255】注意这是二进制掩码11111111,与Ref的二进制相与)
  137. Comp Always //何时通过模板测试,这个和写入没有任何关系,还有CompBack和CompFront专门针对背面和正面,如果存在Comp则会覆盖他们,值为:Never、LessEqual、LEqual、Greater、NotEqual、GEqual、Always
  138. Pass Replace //设置对通过模板测试的像素怎么处理,还有PassBack和PassFront专门针对背面和正面,如果存在Pass则会覆盖他们,值为:Keep(保持原值)、Zero(写入模板值0)、Replace(写入Ref值)、IncrSat(加上去但不超过255)、DecrSat(相减但不小于0)、Invert(所有位取反)、IncrWrap(加上去但超过255会从0重新开始)、DecrWrap(相减但小于0会从255重新开始)
  139. Fail Keep //设置对未通过模板测试的像素怎么处理,还有FailBack和FailFront专门针对背面和正面,如果存在Fail则会覆盖他们,值和Pass的相同
  140. ZFail Keep //当像素通过模板测试但未通过深度测试时怎么处理,还有ZFailBack和ZFailFront专门针对背面和正面,如果存在ZFail则会覆盖他们,值和Pass的相同
  141. }
  142. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  143. //是否开启深度裁剪 该模式确定GPU如何处理近平面和远平面之外的片段
  144. ZClip False //True(默认,直接切掉)、False(clamp操作,低于近平面设为近平面,远于远平面设为远平面)
  145. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  146. //设置深度测试通过规则 Less、LEqual(默认)、Equal、GEqual、Greater、NotEqual、Always
  147. ZTest LEqual
  148. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  149. //深度写入 On(默认)、Off
  150. ZWrite On
  151. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  152. //通道内的Tags只能配置一个LightMode
  153. //URP通道的LightMode可选值:
  154. //UniversalForward 正向渲染 计算灯光 根据所有光源照亮一个物体,之后再渲染下一个物体
  155. //UniversalForwardOnly 如果URP使用“延迟渲染”但某个Pass必须使用“正向渲染”渲染对象,请使用此值
  156. //UniversalGBuffer 延迟渲染 不计算灯光 先将所有物体都先绘制到屏幕空间的缓冲(G-buffer几何缓冲区),再逐光源对该缓冲进行着色的过程 将本来在物空 间(三维空间)进行光照计算放到了像空间(二维空间)进行处理。
  157. //Universal2D 2D渲染用,计算灯光
  158. //ShadowCaster 渲染阴影贴图使用
  159. //DepthOnly 渲染深度图使用
  160. //Meta 当选用此值时,unity仅在灯光烘焙阶段执行此Pass,而在构建时会忽略此Pass
  161. //SRPDefaultUnlit 默认值,多Pass时可以用它
  162. Tags {"LightMode" = "SRPDefaultUnlit"}
  163. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  164. HLSLINCLUDE
  165. HLSL code that you want to share goes here
  166. ENDHLSL
  167. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  168. HLSLPROGRAM
  169. #pragma enable_d3d11_debug_symbols // debug信息
  170. #pragma target 4.0 // 默认2.5 target的详细信息 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html
  171. //#pragma require [value] 添加某些支持 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html
  172. #pragma vertex vert
  173. //#pragma hull hul // 曲面细分阶段 这两个都需要相当高的target5.0的Tessellation,应该还用不上
  174. //#pragma domain dom // 曲面细分阶段
  175. #pragma geometry geo // 几何阶段,需要target4.0
  176. #pragma fragment frag
  177. //声明关键字shader_feature、multi_compile、dynamic_branch,前两个都是编译时确定,有变体。shader_feature会自动剔除没有使用的。后面是实时的,没有变体,可以使用关键字更改着色器行为
  178. //全局关键字限制256个,unity已经用了六十几个,为了避免不够用可以使用本地关键字【声明】_local
  179. #pragma multi_compile_local MyShaderKeyWord1 MyShaderKeyWord2 //这里生成了两个关键字,如果都没有去激活则默认使用第一个,否则使用激活的那个
  180. //删除哪些不需要的关键字
  181. #pragma skip_variants SKIP1 SKIP2
  182. //只想为某些图形API编译某些着色器程序,或是在使用并非所有平台都支持的功能时可以使用这个
  183. #pragma only_renderers gles gles3 d3d11 glcore vulkan
  184. #pragma exclude_renderers metal ps4 xboxone ps5
  185. //For More #pragma https://docs.unity3d.com/Manual/SL-PragmaDirectives.html
  186. /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
  187. //https://github.com/Unity-Technologies/Graphics/tree/master/Packages/com.unity.render-pipelines.universal/ShaderLibrary
  188. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  189. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  190. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
  191. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
  192. struct appdata
  193. {
  194. //顶点着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
  195. float4 vertex : POSITION;
  196. float3 normal : NORMAL;
  197. float4 tan : TANGENT;
  198. float2 uv : TEXCOORD0;
  199. };
  200. struct v2f
  201. {
  202. //像素着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
  203. float2 uv : TEXCOORD0;
  204. float4 vertex : SV_POSITION;
  205. float3 normal : NORMAL;
  206. };
  207. //从片段着色器的返回结构,SV_Target,SV_Depth等,不知道这两个之外还有能用的不。SV_Target可以从07,在多渲染目标(MRT)时很有用
  208. struct fragOutput {
  209. //语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
  210. float4 color1 : SV_Target;
  211. float4 color2 : SV_Target1;
  212. float depth : SV_Depth; //用自定义深度覆盖Z缓冲区值,不知道啥用,还会关闭深度缓冲的优化,能不开别开
  213. };
  214. //如果是纹理属性:
  215. //1.可以添加一个_ST标识平铺和偏移。xy为xy平铺值,zw为xy偏移值
  216. //2.可以添加_TexelSize(float4)获取大小信息。xy为1/宽、1/高,zw为宽高
  217. //3.纹理_HDR,如何解码潜在HDR的信息(例如RGBM编码的)纹理,这取决于所使用的颜色空间 见UnityCG.cginc着色器包含文件中的DecodeHDR函数
  218. sampler2D _MainTex;
  219. float4 _MainTex_ST;
  220. float4 _MainTex_TexelSize;
  221. float4 _MainTex_HDR;
  222. v2f vert(appdata v, uint vid : SV_VertexID) // 获取顶点 ID,必须为 uint
  223. {
  224. v2f o;
  225. o.vertex = TransformObjectToHClip(v.vertex);
  226. o.uv = TRANSFORM_TEX(v.uv, _MainTex);
  227. o.normal = v.normal;
  228. return o;
  229. }
  230. [maxvertexcount(3)]
  231. void geo(triangle v2f p[3], inout LineStream<v2f> istream)
  232. {
  233. for (int i = 0; i < 3; i++)
  234. {
  235. v2f o = (v2f)0;
  236. o.vertex = p[i].vertex;
  237. o.normal = p[i].normal;
  238. o.uv = p[i].uv;
  239. //将每个顶点添加到LineStream流里
  240. istream.Append(o);
  241. }
  242. }
  243. //https://docs.unity3d.com/cn/current/Manual/SL-ShaderSemantics.html
  244. //特殊:屏幕uv坐标screenPos(float2)、是否面向摄像机facing,大于0是面向,小于0是反向
  245. //UNITY_VPOS_TYPE screenPos : VPOS,屏幕空间像素位置,感觉用起来有弊端,SV_POSITION不能放在结构体
  246. fragOutput frag(v2f i, float facing : VFACE) : SV_Target
  247. {
  248. fragOutput o;
  249. o.color1 = tex2D(_MainTex, i.uv);
  250. o.color2 = float4(i.uv, 0, 0);
  251. o.depth = 50;
  252. return o;
  253. }
  254. ENDHLSL
  255. }
  256. }
  257. Fallback Off
  258. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/101235
推荐阅读
相关标签
  

闽ICP备14008679号