赞
踩
使用shader graph过程中,想要实现一些多pass效果,虽然使用render feature能够一定程度上解决需求,但我认为render feature始终是一个在特定阶段做一些简单操作的实用工具,在实现多pass效果的时候总会有一些不如意,所以总结了unity官网上的CG/HLSL规范,也是下一步准备浏览大佬作品的前置条件。如果连基本规则都不懂,即使是看到一些简单操作也会一头雾水。
- Shader "URPShaderTest"
- {
- Properties
- {
- //Color(4,线性SRGB)、Vector(4)、Float、2D(texture)、Cube(cubmap)、Integer、Range、2DArray、3D、CubeArray
- //对应下面声明fixed4、float4、float、sampler2D、samplerCUBE
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- _MainTex("Texture", 2D) = "white" {}
- [Toggle(Switch)]
- _Switch("Switch", Integer) = 0
- _OffsetUnitScale("OffsetUnitScale", Integer) = 0
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //特性
- /*
- [Gamma] 指示浮点或矢量特性使用sRGB值
- [HDR] 指示纹理或颜色特性使用高动态范围(HDR)值
- [HideInInspector] 藏
- [MainTexture] 设置材质的主纹理,可以使用Material.mainTexture访问该材质。默认名称为_MainTex的纹理为主纹理
- [MainColor] 设置材质的主颜色,可以使用Material.color访问该材质。默认名称为_color的颜色为主颜色
- [NoScaleOffset] 为该纹理属性隐藏平铺和偏移字段
- [Normal] 指示法线贴图纹理
- [PerRendererData] 指示纹理特性将来自MaterialPropertyBlock,inspector将显示为只读
- */
- //MaterialProperty类 https://docs.unity3d.com/2021.3/Documentation/ScriptReference/MaterialProperty.html Material.GetFloat, Material.SetFloat等等
- //编辑器扩展MaterialPropertyDrawer、MaterialEditor、MaterialProperty、ShaderGUI https://docs.unity3d.com/2021.3/Documentation/Manual/SL-CustomEditor.html
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //保留名称
- //_TransparencyLM ("Transmissive Texture", 2D) = "white" {} //在光照贴图过程中启用自定义RGB透明度
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- // Cg/HLSL 可以接受uniform值 https://docs.unity3d.com/2021.3/Documentation/Manual/SL-PropertiesInPrograms.html 矩阵和数组只能作为非序列化的运行时属性存在(因为无法在properties块中定义它们)
-
- }
- SubShader
- {
- //SubShaderTags
- //RenderPipeline:UniversalRenderPipeline/HighDefinitionRenderPipeline 主要控制渲染用的管线
- //Queue:Background(1000)Geometry(default)(2000)AlphaTest(2450)Transparent(3000)Overlay(4000) 或者可以写具体值1300或者Background+300等等 主要控制渲染顺序
- //RenderType 没有默认值 替换材质时可以使用这个值作标识:Camera.SetReplacementShader(ShaderType,“ReplaceMePlease”);平时不必使用 貌似也用作深度图生成?
- //ForceNoShadowCasting true false 是否阻止阴影投射,有时也阻止接收
- //DisableBatching True False默认 LODFading当Lod值非0时阻止,反之不阻止 阻止unity对使用这个SubShader的几何体应用动态批处理 动态批处理会将所有几何体转换为世界空间,着色器程序无法再访问对象空间。可以避免依赖对象空间的着色器程序无法正确渲染的问题
- //IgnoreProjector True False默认 不希望任何投影类型材质或者贴图,影响我们的物体或者着色器 UI上用的多
- //PreviewType Sphere Plane Skybox 检视预览用什么方式展示
- //CanUseSpriteAtlas 警告用户着色器依赖于原始纹理坐标,因此不应将其纹理打包到图集中 多用于使用Legacy Sprite Packer的项目中
- Tags {"RenderPipeline" = "UniversalRenderPipeline" "Queue" = "Geometry+100" "RenderType" = "ReplaceMePlease" "ForceNoShadowCasting" = "True" "DisableBatching" = "False" "IgnoreProjector" = "False" "PreviewType" = "Sphere"}
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //这个值和与相机的距离没有关系,Unity不会自动计算着色器LOD,必须手动设置最大着色器LOD,表示它在计算上的要求有多高
- // 当有多个subshader时,LOD必须按降序排列,这是因为Unity查找选择第一个有效的SubShader,所以如果它首先找到一个LOD较低的子着色器,它将始终使用它。看来是值越高计算要求越高
- LOD 200
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //为了支持SRP Batcher,Shader中要将所有暴露出的参数(贴图除外)给包含到CBUFFER_START(UnityPerMaterial)与CBUFFER_END之间。并且为了保证之后的每个Pass都能拥有一样的CBUFFER
- //这一段代码需要写在SubShader之内,其它Pass之前。
- //CBUFFER_START(UnityPerMaterial)
- // float4 _MainTex_ST;
- // float _Switch;
- //CBUFFER_END
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //插入来自另一个着色器的命名Pass,减少Pass代码重复 这里插入的是自己的
- UsePass "URPShaderTest/URPShaderTestPass0"
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //抓取帧缓冲区纹理到这个命名纹理中去,可以在Pass中声明使用这张纹理。如果不写名称会抓到_GrabTexture中去,但是使用自定义命名可以减少屏幕抓取次数,故尽量使用自命名
- GrabPass
- {
- "_BackgroundTexture"
- }
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- Pass
- {
- // 某些着色器需要在不同的管线下运行,需要这个模块 这个模块必须在Pass或者subshader的最开始声明,看你想单独控制pass还是整个subshader
- // 这些版本必须和package manager里对应上,否则Pass或者subshader无法正常工作
- // 不同的写法有不同的行为https://docs.unity3d.com/Manual/SL-PackageRequirements.html
- PackageRequirements
- {
- "com.unity.render-pipelines.universal": "[13.0.1,14.0.7]"
- "com.unity.textmeshpro" : "3.0.6"
- }
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- Name "URPShaderTestPass0"
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //指令:也可以单独控制pass或整个subshader,但是subshader的会被pass覆盖
- //部分一:渲染状态
- //AlphaToMask On Off 根据片段着色器输出中的alpha值按比例修改multisample覆盖遮罩 在不使用MSAA的情况下启用结果可能是不可预测的
- AlphaToMask Off
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //Blend Off默认 这里要花多行讲解一下
- /*混合公式为:finalValue = sourceFactor * sourceValue operation destinationFactor * destinationValue *这里的operation是下面的BlendOp 默认是Add*
- Blend的签名分为三种,State、Render Target、Factor。
- 其中State(Off)和Render Target(0到7的整数)只会出现一次 【简单来讲,渲染目标(Render Target)就是一种可以在运行时写入的纹理。从引擎的角度讲,渲染目标会存储颜色、法线以及AO等信息】
- Factor总共有四个,出现顺序从左到右按此解读:<source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha>
- 比如Blend 1 One Zero, Zero One就会这么解读<Render Target> <source factor RGB> <destination factor RGB>, <source factor alpha> <destination factor alpha>
- 但是:任何指定渲染目标的签名都需要OpenGL 4.0+、GL_ARB_draw_buffers_blend或OpenGL ES 3.2。单独的RGB和alpha混合与高级OpenGL混合操作不兼容。*/
- /*One 值为1,使用此因子来让帧缓冲区源颜色或是目标颜色完全的通过。1
- Zero 值为0,使用此因子来删除帧缓冲区源颜色或目标颜色的值。0
- SrcColor 使用此因子为将当前值乘以帧缓冲区源颜色的值 A
- SrcAlpha 使用此因子为将当前值乘以帧缓冲区源颜色Alpha的值。A*alpha
- DstColor 使用此因子为将当前值乘以帧缓冲区目标颜色的值。B
- DstAlpha 使用此因子为将当前值乘以帧缓冲区目标颜色Alpha分量的值。B*alpha
- OneMinusSrcColor 使用此因子为将当前值乘以(1 -帧缓冲区源颜色值) 1- A
- OneMinusSrcAlpha 使用此因子为将当前值乘以(1 -帧缓冲区源颜色Alpha分量的值) 1-A*lpha
- OneMinusDstColor 使用此因子为将当前值乘以(1 –目标颜色值) 1-B
- OneMinusDstAlpha使用此因子为将当前值乘以(1 –目标Alpha分量的值) 1- B*alpha*/
- //src是这个通道渲染出来的颜色值,des是帧缓冲中已经存在的颜色值,跟当前pass的渲染时间有关系,如果这个pass是在最后渲染,那么帧缓冲则是屏幕上渲染完所有其他物体后的颜色值
- Blend Zero One // 这样就是舍弃这个通道产生的颜色值而使用帧缓冲中的颜色值,也就是把这个物体透过去了
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //*添加BlendOp要保证已经存在Blend指令,且并非所有设备都支持所有混合操作!!!要注意的如下*
- /*1、Min and Max require GL_EXT_blend_minmax on OpenGL ES 2.
- 2、Logical operations require DX 11.1+ or Vulkan.
- 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.*/
- BlendOp Max // 或者使用这样的混合操作标识 Add(默认), Sub, RevSub, Min, Max等等值非常多,甚至带逻辑运算,具体看这里吧,感觉不常用 https://docs.unity3d.com/Manual/SL-BlendOp.html
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //默认情况下,GPU会写入所有通道(RGBA)。对于某些效果,您可能希望不修改某些通道,这时就需要ColorMask
- //ColorMask <channels> <render target>
- //channels代表颜色通道,值有0、R、G、B、A或是任意组合如:RA、RGB *写哪个代表允许写入哪个通道,值0代表可以写入所有通道,和RGBA应该是一样的*
- //render target如上所说,值为0到7
- ColorMask RGBA
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //是否开启保守光栅化,GPU不考虑覆盖范围,只要有一部分被三角形覆盖的像素就进行光栅化,等于说生成的像素会变多
- //使用SystemInfo.supportsConservativeRaster API检查硬件是否支持,不支持会被忽略
- Conservative False
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //裁剪:Back(默认)、Front、Off
- Cull Back
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //深度偏移:调整深度偏移以强制GPU在相同深度的其他几何体之上绘制几何体,这个东西能防止z-fighting(相同深度面片渲染打架)
- //Offset <factor>, <units>
- //factor:缩放最大Z坡度(不平行于近剪裁平面和远剪裁平面的多边形具有Z坡度),范围【-1,1】
- //units:缩放最小可解析深度缓冲区值,以产生恒定的深度偏移,范围【-1,1】 负值表示GPU将多边形绘制得更靠近摄影机。正值表示GPU绘制的多边形离摄影机更远。
- Offset -1, -1 // 一般来说这样就可以有效防止z-fighting
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- Offset -1, [_OffsetUnitScale] // *想用属性往任意指令里面写值的话*
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //模版缓冲区为每个像素存储一个8位整数值,模板测试失败GPU将跳过该像素,可以执行两种操作---写入和测试,它们甚至可以在一条指令中同时执行
- //使用Ref、ReadMask和Comp参数来配置模版测试。使用Ref、WriteMask、Pass、Fail和ZFail参数来配置模版写入。
- //(ref & readMask) comparisonFunction (stencilBufferValue & readMask) 测试方程,写入的话只是(ref & readMask)在通过或失败情况下怎么做
- Stencil{
- Ref 2 //这是传进去的int值(默认0【0,255】注意这是二进制11111111),如果在测试就用这个值和模板值(如果没有写入过默认0)作比较,受readMask影响、如果在写入就是写入这个值,受writeMask影响
- ReadMask 255 //这是传进去的int值(默认0【0,255】注意这是二进制掩码11111111,与Ref的二进制相与)这个掩码应该是为了不让自己写入的值影响自己,所以一般两个掩码应该是不同的,一般有通道单独写模板值,所以读取通道掩码应和那个写入通道的掩码匹配
- WriteMask 155 //这是传进去的int值(默认0【0,255】注意这是二进制掩码11111111,与Ref的二进制相与)
- Comp Always //何时通过模板测试,这个和写入没有任何关系,还有CompBack和CompFront专门针对背面和正面,如果存在Comp则会覆盖他们,值为:Never、Less、Equal、LEqual、Greater、NotEqual、GEqual、Always
- Pass Replace //设置对通过模板测试的像素怎么处理,还有PassBack和PassFront专门针对背面和正面,如果存在Pass则会覆盖他们,值为:Keep(保持原值)、Zero(写入模板值0)、Replace(写入Ref值)、IncrSat(加上去但不超过255)、DecrSat(相减但不小于0)、Invert(所有位取反)、IncrWrap(加上去但超过255会从0重新开始)、DecrWrap(相减但小于0会从255重新开始)
- Fail Keep //设置对未通过模板测试的像素怎么处理,还有FailBack和FailFront专门针对背面和正面,如果存在Fail则会覆盖他们,值和Pass的相同
- ZFail Keep //当像素通过模板测试但未通过深度测试时怎么处理,还有ZFailBack和ZFailFront专门针对背面和正面,如果存在ZFail则会覆盖他们,值和Pass的相同
- }
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //是否开启深度裁剪 该模式确定GPU如何处理近平面和远平面之外的片段
- ZClip False //True(默认,直接切掉)、False(clamp操作,低于近平面设为近平面,远于远平面设为远平面)
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //设置深度测试通过规则 Less、LEqual(默认)、Equal、GEqual、Greater、NotEqual、Always
- ZTest LEqual
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //深度写入 On(默认)、Off
- ZWrite On
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //通道内的Tags只能配置一个LightMode
- //URP通道的LightMode可选值:
- //UniversalForward 正向渲染 计算灯光 根据所有光源照亮一个物体,之后再渲染下一个物体
- //UniversalForwardOnly 如果URP使用“延迟渲染”但某个Pass必须使用“正向渲染”渲染对象,请使用此值
- //UniversalGBuffer 延迟渲染 不计算灯光 先将所有物体都先绘制到屏幕空间的缓冲(G-buffer几何缓冲区),再逐光源对该缓冲进行着色的过程 将本来在物空 间(三维空间)进行光照计算放到了像空间(二维空间)进行处理。
- //Universal2D 2D渲染用,计算灯光
- //ShadowCaster 渲染阴影贴图使用
- //DepthOnly 渲染深度图使用
- //Meta 当选用此值时,unity仅在灯光烘焙阶段执行此Pass,而在构建时会忽略此Pass
- //SRPDefaultUnlit 默认值,多Pass时可以用它
- Tags {"LightMode" = "SRPDefaultUnlit"}
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- HLSLINCLUDE
- HLSL code that you want to share goes here
- ENDHLSL
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- HLSLPROGRAM
- #pragma enable_d3d11_debug_symbols // debug信息
- #pragma target 4.0 // 默认2.5 target的详细信息 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html
- //#pragma require [value] 添加某些支持 https://docs.unity3d.com/Manual/SL-ShaderCompileTargets.html
- #pragma vertex vert
- //#pragma hull hul // 曲面细分阶段 这两个都需要相当高的target5.0的Tessellation,应该还用不上
- //#pragma domain dom // 曲面细分阶段
- #pragma geometry geo // 几何阶段,需要target4.0
- #pragma fragment frag
- //声明关键字shader_feature、multi_compile、dynamic_branch,前两个都是编译时确定,有变体。shader_feature会自动剔除没有使用的。后面是实时的,没有变体,可以使用关键字更改着色器行为
- //全局关键字限制256个,unity已经用了六十几个,为了避免不够用可以使用本地关键字【声明】_local
- #pragma multi_compile_local MyShaderKeyWord1 MyShaderKeyWord2 //这里生成了两个关键字,如果都没有去激活则默认使用第一个,否则使用激活的那个
- //删除哪些不需要的关键字
- #pragma skip_variants SKIP1 SKIP2
- //只想为某些图形API编译某些着色器程序,或是在使用并非所有平台都支持的功能时可以使用这个
- #pragma only_renderers gles gles3 d3d11 glcore vulkan
- #pragma exclude_renderers metal ps4 xboxone ps5
- //For More #pragma https://docs.unity3d.com/Manual/SL-PragmaDirectives.html
- /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
- //https://github.com/Unity-Technologies/Graphics/tree/master/Packages/com.unity.render-pipelines.universal/ShaderLibrary
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
- struct appdata
- {
- //顶点着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
- float4 vertex : POSITION;
- float3 normal : NORMAL;
- float4 tan : TANGENT;
- float2 uv : TEXCOORD0;
- };
-
- struct v2f
- {
- //像素着色器语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
- float2 uv : TEXCOORD0;
- float4 vertex : SV_POSITION;
- float3 normal : NORMAL;
- };
- //从片段着色器的返回结构,SV_Target,SV_Depth等,不知道这两个之外还有能用的不。SV_Target可以从0到7,在多渲染目标(MRT)时很有用
- struct fragOutput {
- //语义 https://learn.microsoft.com/zh-cn/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics?redirectedfrom=MSDN
- float4 color1 : SV_Target;
- float4 color2 : SV_Target1;
- float depth : SV_Depth; //用自定义深度覆盖Z缓冲区值,不知道啥用,还会关闭深度缓冲的优化,能不开别开
- };
-
- //如果是纹理属性:
- //1.可以添加一个_ST标识平铺和偏移。xy为xy平铺值,zw为xy偏移值
- //2.可以添加_TexelSize(float4)获取大小信息。xy为1/宽、1/高,zw为宽高
- //3.纹理_HDR,如何解码潜在HDR的信息(例如RGBM编码的)纹理,这取决于所使用的颜色空间 见UnityCG.cginc着色器包含文件中的DecodeHDR函数
- sampler2D _MainTex;
- float4 _MainTex_ST;
- float4 _MainTex_TexelSize;
- float4 _MainTex_HDR;
-
- v2f vert(appdata v, uint vid : SV_VertexID) // 获取顶点 ID,必须为 uint
- {
- v2f o;
- o.vertex = TransformObjectToHClip(v.vertex);
- o.uv = TRANSFORM_TEX(v.uv, _MainTex);
- o.normal = v.normal;
- return o;
- }
-
- [maxvertexcount(3)]
- void geo(triangle v2f p[3], inout LineStream<v2f> istream)
- {
- for (int i = 0; i < 3; i++)
- {
- v2f o = (v2f)0;
- o.vertex = p[i].vertex;
- o.normal = p[i].normal;
- o.uv = p[i].uv;
- //将每个顶点添加到LineStream流里
- istream.Append(o);
- }
- }
- //https://docs.unity3d.com/cn/current/Manual/SL-ShaderSemantics.html
- //特殊:屏幕uv坐标screenPos(float2)、是否面向摄像机facing,大于0是面向,小于0是反向
- //UNITY_VPOS_TYPE screenPos : VPOS,屏幕空间像素位置,感觉用起来有弊端,SV_POSITION不能放在结构体
- fragOutput frag(v2f i, float facing : VFACE) : SV_Target
- {
- fragOutput o;
- o.color1 = tex2D(_MainTex, i.uv);
- o.color2 = float4(i.uv, 0, 0);
- o.depth = 50;
- return o;
- }
- ENDHLSL
- }
- }
- Fallback Off
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。