Unity中Shader LOD控制
发表于2016-09-08
这一部分算是比较简单的内容,与其说是技术相关,不如说是新项目美术前期规划方面的准备。前期地基打的越牢,后面的工作越轻松。
Shader Level of Detail (LOD),翻译过来是什么“着色器的细节层次效果”。听着好高端的样子,这种夸张的翻译也就只能放在那些作者自己都不知道写的是什么的软文里面。对于TA来说,Shader LOD其实就是根据设备性能的不同编译不同版本的Shader。
这种编译方式最早是为了适应不同时代的显卡而准备的。主机端本来就不存在这个问题,而现在在PC端上想找到上古级别的显卡也不太容易。所以目前这玩意儿最大的用途也就是为了适配高低配置不同的手机(以上为个人意见)。
使用Shader LOD,要编写多个SubShader,格式大致如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | Shader "YY/Cube" { Properties { _Color ( "Color" , Color) = (1,1,1,1) _MainTex ( "Albedo (RGB)" , 2D) = "white" {} _Glossiness ( "Smoothness" , Range(0,1)) = 0.5 _Metallic ( "Metallic" , Range(0,1)) = 0.0 } SubShader { Tags { "RenderType" = "Opaque" } LOD 200 CGPROGRAM // Physically based Standard lighting model, and enable shadows on all light types #pragma surface surf Standard fullforwardshadows // Use shader model 3.0 target, to get nicer looking lighting #pragma target 3.0 sampler2D _MainTex; struct Input { float2 uv_MainTex; }; half _Glossiness; half _Metallic; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { // Albedo comes from a texture tinted by color fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; o.Albedo = c.rgb; // Metallic and smoothness come from slider variables o.Metallic = _Metallic; o.Smoothness = _Glossiness; o.Alpha = c.a; } ENDCG } SubShader { Tags { "RenderType" = "Opaque" "IgnoreProjector" = "True" } LOD 100 UsePass "YY/BasicShaders/UNLIGHT" } SubShader { Tags { "RenderType" = "Opaque" "IgnoreProjector" = "True" } LOD 50 UsePass "YY/BasicShaders/UNLIGHTNOFOG" } FallBack "Diffuse" } |
在脚本中给Shader.globalMaximumLOD赋值就可以改变Shader。个人推荐最好在初始化的时候做这一步。
小技巧就是给Pass的Name属性赋值。这样可以在LOD控制的时候做到代码复用,非常方便。比如说上面代码中UsePass "YY/BasicShaders/UNLIGHT" 和 UsePass "YY/BasicShaders/UNLIGHTNOFOG"。其源代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | Shader "YY/BasicShaders" { Properties { _MainTex ( "Texture" , 2D) = "white" {} } SubShader { Tags { "RenderType" = "Opaque" } Pass { //注意Name要写在CGPROGRAM外面 //注意Name所有的字母必须大写 Name "UNLIGHTNOFOG" CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { fixed4 vertex : POSITION; fixed2 uv : TEXCOORD0; }; struct v2f { fixed2 uv : TEXCOORD0; fixed4 vertex : SV_POSITION; }; sampler2D _MainTex; fixed4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); return o; } fixed4 frag (v2f i) : SV_Target { fixed4 col = tex2D(_MainTex, i.uv); return col; } ENDCG } Pass { Name "UNLIGHT" CGPROGRAM #pragma vertex vert #pragma fragment frag // make fog work #pragma multi_compile_fog #include "UnityCG.cginc" struct appdata { fixed4 vertex : POSITION; fixed2 uv : TEXCOORD0; }; struct v2f { fixed2 uv : TEXCOORD0; UNITY_FOG_COORDS(1) fixed4 vertex : SV_POSITION; }; sampler2D _MainTex; fixed4 _MainTex_ST; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = TRANSFORM_TEX(v.uv, _MainTex); UNITY_TRANSFER_FOG(o,o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { // sample the texture fixed4 col = tex2D(_MainTex, i.uv); // apply fog UNITY_APPLY_FOG(i.fogCoord, col); return col; } ENDCG } } } |
Name所有的字母必须大写!Name所有的字母必须大写!Name所有的字母必须大写!重要的事儿要说三遍!
另外需要注意的是默认的Standered材质本身也是有LOD层级的,修改的时候小心别把Standerd效果给改动了。以下是Built-in shader LOD的使用方法:
Built-in shaders in Unity have their LODs set up this way:
· VertexLit kind of shaders = 100
· Decal, Reflective VertexLit = 150
· Diffuse = 200
· Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped ·VertexLit = 250
· Bumped, Specular = 300
· Bumped Specular = 400
· Parallax = 500
· Parallax Specular = 600
Unity中编译多版本Shader还可以使用multi_compile。具体可自行百度"使用multi_compile编译Shader的多个版本"。这种方法可以全局设置也可以针对单独的材质,可以和LOD配合使用。