diff --git "a/_posts/shader_book/2023-02-26-\347\247\273\345\212\250\350\256\276\345\244\207\347\235\200\350\211\262\345\231\250\351\200\202\351\205\215.md" "b/_posts/shader_book/2023-02-26-\347\247\273\345\212\250\350\256\276\345\244\207\347\235\200\350\211\262\345\231\250\351\200\202\351\205\215.md" index 5ffa5066733..b37253f958b 100644 --- "a/_posts/shader_book/2023-02-26-\347\247\273\345\212\250\350\256\276\345\244\207\347\235\200\350\211\262\345\231\250\351\200\202\351\205\215.md" +++ "b/_posts/shader_book/2023-02-26-\347\247\273\345\212\250\350\256\276\345\244\207\347\235\200\350\211\262\345\231\250\351\200\202\351\205\215.md" @@ -21,3 +21,101 @@ tags: [U3D, Shader,Cookbook,中文版] ## 什么是低成本着色器 我们首先问一个问题,什么是低成本的着色器,它回答起来可能有点困难因为有太多的元素可以可以让一个着色器变得更加高效了。它可以是你的变量使用的内存的大小。可以是你的着色器使用的纹理的大小。也可是一个工作良好的着色器,但是我们却只使用了相较之前一半的代码或者数据就获得了相同的视觉效果。我们将会在这个知识点中探索一些这样的技术并且会展示如何将这些技术结合起来从而让你的着色器更快更高效,并且不管是在移动设备还是在PC上都生成当今游戏中每个人都期望的高质量的视觉效果。 + + +*** +
+ +- **始前准备** + 在开始这个知识点之前,我们需要准备一些资源并且把它们放一块。所以让我们按照下面的几个任务来: + - 1.创建一个新的场景,并且在场景中添加一个球体和一个方向光。 + - 2.创建一个新的着色器和材质球,并且把着色器应用到材质上。 + - 3.然后把材质球应用到我们刚刚创建的球体。 + - 4.最后,我们修改我们之前创建的着色器让它能使用漫反射纹理和法线贴图,并且创建一个自定义的光线函数。下面的代码展示的是修改后的着色器代码: + + ``` c# + Shader "Custom/MSA" + { + Properties + { + _MainTex ("Albedo (RGB)", 2D) = "white" {} + _NormalMap ("Normal Map", 2D) = "bump" {} + } + SubShader + { + Tags { "RenderType"="Opaque" } + LOD 200 + + CGPROGRAM + + sampler2D _MainTex; + sampler2D _NormalMap; + #pragma surface surf SimpleLambert + + struct Input + { + float2 uv_MainTex; + float2 uv_NormalMap; + }; + + inline float4 LightingSimpleLambert(SurfaceOutput s, float3 lightDir, float atten) + { + float diff = max(0, dot(s.Normal, lightDir)); + float4 c; + c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2); + c.a = s.Alpha; + return c; + } + + void surf (Input IN, inout SurfaceOutput o) + { + // Albedo comes from a texture tinted by color + fixed4 c = tex2D (_MainTex, IN.uv_MainTex); + o.Albedo = c.rgb; + o.Alpha = c.a; + o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap)); + } + ENDCG + } + FallBack "Diffuse" + } + ``` + 现在你应该有如下图所示的一个设置。下面的这个设置将让我们初步了解一些在Unity中使用表面着色器进行优化的基本概念: + ![diagram](https://linkliu.github.io/game-tech-post/assets/img/shader_book/diagram73.png){: .shadow width = "90%" } + +*** +
+ +- **操作步骤** + 我们将构建一个简单的漫反射着色器用来了解几种常用的优化着色器的方法。 + 首先,我们将会优化变量类型从而可以让它们在处理数据的时候使用更少的内存: + 1. 让我们从着色器的 **输入结构体(struct Input)** 着手。当前我们的UV数据是保存在一个 **float2** 类型的变量中的。我们需要将它改成 **half2** + ``` c# + struct Input + { + half2 uv_MainTex; + half2 uv_NormalMap; + }; + ``` + 2. 接下来我们去修改光照函数,通过如下的变量类型的修改从而减少了变量的内存占用: + ``` c# + inline fixed4 LightingSimpleLambert(SurfaceOutput s, fixed3 lightDir, fixed atten) + { + fixed diff = max(0, dot(s.Normal, lightDir)); + fixed4 c; + c.rgb = s.Albedo * _LightColor0.rgb * (diff * atten * 2); + c.a = s.Alpha; + return c; + } + ``` + 3. 最后,我们来修改 **surf()** 函数中的变量类型,这样就完成了这次的优化。代码如下所示: + ``` c# + void surf (Input IN, inout SurfaceOutput o) + { + // Albedo comes from a texture tinted by color + fixed4 c = tex2D (_MainTex, IN.uv_MainTex); + o.Albedo = c.rgb; + o.Alpha = c.a; + o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap)); + } + ``` \ No newline at end of file diff --git a/assets/img/shader_book/diagram73.png b/assets/img/shader_book/diagram73.png new file mode 100644 index 00000000000..a5c869ecf0f Binary files /dev/null and b/assets/img/shader_book/diagram73.png differ