[Unity shaders] mobile shader Adjustment -- what is an efficient shader?

Source: Internet
Author: User

This series mainly references the book "Unity shaders and effects cookbook" (thanks to the author of the original book) and adds a bit of personal understanding or expansion.

Here are all the illustrations in this book. Here is the code and resources required for this book (you can also download them from the official website ).

========================================================== ===================================================== =====



Preface


We have never considered the availability of various shader models on all platforms. Unity is a powerful cross-platform game engine, but it also determines that we need to consider more platform factors when writing code. If the shader is not optimized, it is likely that it cannot run on platforms with high performance limitations, such as mobile platforms. We need to understand some key factors to optimize our shader so as to improve game performance and maintain the same visual effect as possible.


Especially if your target platform includes the Android system, be sure to take care of the consequences of taking you on the beach in the waves of various Chinese stockades... So if you have never considered these situations for your shader, use and be careful...


In this chapter, we will learn three sections: What is an efficient shader, how to perform Performance Analysis on shader, and how to optimize our shader for the mobile platform.


So what is an efficient shader? This is a complicated problem. It involves many factors. For example, it depends on the number of variables you use, the memory occupied, and the number of textures used by the shader. It is also possible that although your shade works well, we can actually use a half of the target variable to achieve the same effect. We will explore such techniques in this section and explain to you how they are combined to make our shader faster and more efficient, in addition, it can achieve the same high-quality visual effects on various platforms.



Preparations


We will first use one of the most common shader: bumped diffuse shader. That is, the shader of the normal map is applied.


  1. Create a new scene and a sphere, and add a parallel light.
  2. Create a new shader and material, which can be named optimizedshader001.
  3. Assign shader to material and assign material to sphere.
  4. Finally, use the following code to modify the shader.


Shader "Custom/OptimizedShader001" {Properties {_MainTex ("Base (RGB)", 2D) = "white" {}_NormalMap ("Normal Map", 2D) = "bump" {}}SubShader {Tags { "RenderType"="Opaque" }LOD 200CGPROGRAM#pragma surface surf SimpleLambertsampler2D _MainTex;sampler2D _NormalMap;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) {float4 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"}

The simple illumination function implements simple diffuse reflection processing, while the surf function changes the normal of the model.


Finally, the effect you get is probably as follows:





Implementation


Next, we will optimize This shader step by step.


First, we needOptimized variable typeSo that they use as little memory as possible:

  1. Modify the input structure. Previously, our UV coordinates were stored in float2 type variables. Now we change themHalf2:
    struct Input {half2 uv_MainTex;half2 uv_NormalMap;};

  2. Next is the illumination function. Similarly, change the variables of the float family to the correspondingFixedType Variable:
    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. Finally, modify the variable type in the surf function. Also use fixed type variables:
    void surf (Input IN, inout SurfaceOutput o) {fixed4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_NormalMap));}

After modifying the variable type, we can use the built-in lighting function variables of unity so that we can control how the shader handles the light source. To this end, we can Reduce the number of light sources processed by shader. Modify # pragma statement:

CGPROGRAM#pragma surface surf SimpleLambert noforwardadd

Now, we can use Share UV coordinatesTo continue shader optimization. Therefore, we use the UV coordinates of _ maintex to replace the UV of _ normalmap in unpacknormal (), and remove uv_normalmap in the input structure:

o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex));

struct Input {half2 uv_MainTex;};

Finally, let's tell unity that Shader only works on a specific Renderer:

CGPROGRAM#pragma surface surf SimpleLambert exclude_path:prepass noforwardadd

Finally, the effect before and after optimization is as follows (left front right back ):



We can see that we can hardly see any difference with the naked eye, but we have reduced the time it takes for the shader to be drawn to the screen. In the next section, we will use the unity visualization tool to analyze the reduction. But here we are concerned about,Use less data to get the same rendering Effect. Remember this idea when creating our own Shader!


Explanation


There are four optimization methods mentioned above: optimizing variable types, sharing UV coordinates, reducing the number of processed light sources, and allowing the shader to work only on a specific Renderer. Next, let's take a deeper look at how these technologies work, and finally learn other techniques.


Optimized variable type


First, let's take a look at the data size stored by each variable when we declare the variable. When declaring variables, we often have multiple options (float, half, and fixed). Let's take a look at the features of these types:

  • Float: high-precision floating point value, usually 32 bits, is also the slowest of the three. It also corresponds to float2, float3, and float4.

  • Half: Medium precision floating point value. Usually 16 bits in the range of-60000 to + 60000. It is suitable for storage.UV coordinates, Color value, etc., much faster than the float type. It corresponds to half2, half3, and half4.

  • Fixed: Low-precision floating point value. It is usually 11 bits. The range is-2.0 to + 2.0, and the precision is 1/256. This is the smallest of the three and can be usedIllumination computing,Color. Its values include fixed2, fixed3, and fixed4.

The official website provides the following suggestions on the selection of types:
  • Use low-precision variables as much as possible.
  • Fixed is used for color and unit length vectors.
  • For other types, use half if the range and accuracy are appropriate; for other types, use float.


Reduce the number of processed light sources
It can be seen from the above that this optimization is achieved by declaring the noforwardadd value in the # pragma statement. This mainly tells unity that the shader object only accepts a single parallel light source as a pixel-by-pixel light source, other light sources are processed using built-in spherical harmonic functions as vertices. This is obvious when we place another light source in the scene, because our shader uses a normal texture for Pixel-by-pixel operations.

This is certainly good, but what should we do if we need more than one parallel light and want to control which is the main light source for Pixel-by-pixel computing? This requires a setting in the Unity panel! If you observe it carefully, the normal will haveRender ModeDrop-down menu. When you click itAuto,Important, AndNot importantThree options. By selecting important, you can tell unity that the light source needs to be regarded as a pixel-by-pixel light source rather than a vertex-by-vertex light source. If it is set to auto, it is up to unity to make the decision!


Isn't it... In order to illustrate the above meaning, let's test it! Place another vertex light source in the scenario, and then remove main texture from the shader. For the first time, turn on the parallel light source, turn off the point light source (left), and turn off the parallel light source for the second time (right ). You can find that the second point does not affect our normal texture (just illuminating the model, that is, it is only processed by vertex), and only the first parallel light will affect it.




The optimization here is because we regard all other light sources as vertex light sources, while only one primary parallel light is calculated as the pixel light source when calculating the pixel color.



Share UV coordinates


This step of optimization is very simple. We only use the UV coordinates of main texture to replace the UV coordinates of the normal map. This actually reduces the code for extracting the UV coordinates of the normal map internally. This method can simplify our code.


Only works on a specific Renderer


Finally, we declare in the statement to tell unity that This shader will no longer accept any other custom illumination from delayed rendering. This means that we can only use this shader effectively in the forward rendering (Forward render), which is set in the settings of the main camera.


Help link: Forward rendering and delayed rendering.


Conclusion


There are many other optimization strategies. We have learned how to package multiple grayscale images into an rgba texture and how to use a texture to simulate the illumination effect. Due to these many technologies, it is very vague to ask how to optimize the shader. However, understanding these technologies allows us to use appropriate technologies based on different shader and platforms to obtain a shader with stable frame rate.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.