- Unity 2018 Shaders and Effects Cookbook
- John P. Doran Alan Zucconi
- 536字
- 2025-04-04 16:34:20
How to do it...
The following are the steps to create a normal map shader:
- Let's get the Properties block set up in order to have a color Tint and texture:
Properties { _MainTint ("Diffuse Tint", Color) = (0,1,0,1) _NormalTex ("Normal Map", 2D) = "bump" {} }
In this case, I have 1 in the green and alpha channels and 0 for red and blue, so the default color will be green. For the _NormalTex property, we are using a 2D type, which means we can use a 2D image to dictate what each pixel will use. By initializing the texture as bump, we are telling Unity that _NormalTex will contain a normal map (sometimes referred to as bump maps as well, hence the bump name). If the texture is not set, it will be replaced by a grey texture. The color used (0.5, 0.5, 0.5, 1) indicates no bump at all.
- In the SubShader{} block, scroll below the CGPROGRAM statement and remove the original _MainText, _Glossiness, _Metallic, and _Color definitions. Afterward, add in our _NormalTex and _MainTint:
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
// Link the property to the CG program
sampler2D _NormalTex;
float4 _MainTint;
- We need to make sure that we update the Input struct with the proper variable name so that we can use the model's UVs for the normal map texture:
// Make sure you get the UVs for the texture in the struct struct Input { float2 uv_NormalTex; }
- Finally, we extract the normal information from the normal map texture using the built-in UnpackNormal() function. Then, you only have to apply these new normals to the output of the Surface Shader:
void surf (Input IN, inout SurfaceOutputStandard o) {
// Use the tint provided as the base color for the material
o.Albedo = _MainTint;
// Get the normal data out of the normal map texture
// using the UnpackNormal function
float3 normalMap = UnpackNormal(tex2D(_NormalTex,
IN.uv_NormalTex));
// Apply the new normal to the lighting model
o.Normal = normalMap.rgb;
}
- Save your script and return to the Unity editor. You should notice that the sphere has now become green by default if added. More importantly though, notice the Normal Map property that has been added. Drag and drop the normal map texture into the slot.
- You may notice some changes, but it may be hard to visually see what is going on. In the Normal Map property, change the Tiling to (10, 10). This way, you can see the normal map duplicated 10 times over the course of the sphere in the X and Y axes instead of only once:

- The following screenshot demonstrates the result of our normal map shader:

Shaders can have both a texture map and a normal map. It is not uncommon to use the same UV data to address both. However, it is possible to provide a secondary set of UVs in the vertex data (UV2), which are specifically used for the normal map.