The basic texture in shader programming_unity, using Unity Shader to achieve the rendering effect of the basic texture

Learn to achieve the rendering effect of basic textures by using Unity Shader

Table of contents

Learn to achieve the rendering effect of basic textures by using Unity Shader

Question 1: Describe in detail the diffuse texture, height texture, normal texture, gradient texture and mask texture?

Question 2: Explain in detail what is model space, what is tangent space, and what is world space?

Question 3: Explain in detail the advantages and disadvantages of storing normals in the normal texture in the model space and tangent space respectively?

Question 4: What is the difference between the two modes Repeat and Clamp of the Wrap Mode property in the detailed texture property?

Practical

Experiment 1: Use a single texture in Unity to replace the diffuse color of the object, and write shader program code to achieve this effect.

Experiment 2: Use diffuse texture and normal texture in Unity to realize the convex and concave effect of the object, pay attention to the lighting calculation in the tangent space, and write the shader program code to achieve such an effect.

Experiment 3: Use diffuse texture and normal texture in Unity to realize the bump effect of the object, pay attention to the lighting calculation in the world space, and write the shader program code to achieve this effect.


Question 1: Describe in detail the diffuse texture, height texture, normal texture, gradient texture and mask texture?

Answer 1:

Diffuse texture: Usually a texture is used to replace the diffuse color of the object. Declare a texture variable, and then use the tex2D function to sample.

 

Height texture: A height map is used to implement bump mapping. The height map stores the intensity value (intensity), which is used to represent the local altitude of the model surface. Lighter colors indicate that the surface of the location is more outwardly convex, and darker colors indicate that the surface of the location is more concave.

Advantages: very intuitive, you can see the concave-convex shape of the model surface at a glance;

Disadvantages: The calculation is more complicated, and the surface normal cannot be directly obtained during real-time calculation, but it needs to be calculated from the gray value of the pixel, which consumes more performance.


Normal Texture: Stores the normal direction of the surface. Since the component range of the normal direction is [-1,1], and the component range of the pixel is [0,1], a mapping is required, and the mapping usually used is:

pixel = (normal+1)/2

After we are required to sample the normal texture in the shader, we also need to perform an inverse mapping process on the result to get the original normal direction. The process of unmapping is actually using the inverse function of the mapping function above:

Normal = pixel x 2 – 1

The normal of the vertices of the model is defined in the model space, and the surface normal in the modified model space is stored in a texture, which is called the normal texture of the model space (object- space normal map) . However, in actual production, we often use another coordinate space, that is, the tangent space of the model vertices to store the normal.

 

Gradient texture: It is mainly used to control the result of diffuse lighting, and it is mostly used for cartoon-style rendering. Different gradient textures have different properties.

 

Mask texture (mask texture) : common in many commercial games. Masking allows us to protect certain areas from certain modifications; or when making terrain materials, we need to mix multiple images, such as textures for grass, textures for stones, textures for bare land, etc.

Process: The texel value of the mask texture is obtained by sampling , and the value of one (or several) channels is used to multiply it with a certain surface attribute, so that when the value of the channel is 0, the surface can be protected Not affected by this property.

 

Question 2: Explain in detail what is model space, what is tangent space, and what is world space?

Answer 2:

Model space: The coordinate space where all normals are located is the same coordinate space. The normal direction stored at each point is different, and after mapping, it is stored in the texture to correspond to various colors.

Tangent space: The normal texture looks almost all light blue, because each normal direction is in a different coordinate space, which is the respective tangent space for each point on the surface. This normal texture stores the normal perturbation direction for each point in its own tangent space.

World Space: The defined world standard space coordinate system.

 

Question 3: Explain in detail the advantages and disadvantages of storing normals in the normal texture in the model space and tangent space respectively?

Answer 3:

Advantages of storing in model space:

①Easy to implement and more intuitive;

②At the seams and sharp corners of texture coordinates, there are fewer visible mutations (gaps), that is, smooth boundaries that can be provided;

Advantages of storing in tangent space:

The degree of freedom is very high . The normal texture in tangent space records relative normal information. Even if the texture is applied to a completely different grid, a reasonable result can be obtained;

UV animation can be performed , and a bump movement effect can be realized by moving the UV coordinates of a texture;

③The normal texture can be reused , and a normal texture can use 6 bricks;

Compressible , the Z direction of the normal in each normal texture is always the positive direction, so only the XY direction can be stored, and the Z direction can be derived.

 

Question 4: What is the difference between the two modes Repeat and Clamp of the Wrap Mode property in the detailed texture property?

Answer 4:

Repeat: Using this mode, the texture will repeat continuously;

Clamp: In this mode, the part exceeding the range will be intercepted to the boundary value to form a bar structure.

 

Practical

Experiment 1: Use a single texture in Unity to replace the diffuse color of the object, and write shader program code to achieve this effect.

Shader "Unity Shaders Book/Chapter 7/Single Texture" {
//2* 为了使用纹理,我们需要在Priperties语义块中添加一个纹理属性:
	Properties{
		_Color("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex("Main Tex", 2D) = "white" {}
		_Specular("Specular", Color) = (1, 1, 1, 1)
		_Gloss("Gloss", Range(8.0, 256)) = 20
	}
//3* 然后在SubShader语义块中定义了一个Pass语义块。而且,在Pass的第一行指明了该Pass的光照模式:
	SubShader{
		Pass {
			Tags { "LightMode" = "ForwardBase" }
//4* 使用CGPROGRAM和END来包围住CG代码片,以定义最重要的顶点着色器和片元着色器代码。首先,我们使用#

			CGPROGRAM

			#pragma vertex vert
			#pragma fragment frag

			#include "Lighting.cginc"

			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Specular;
			float _Gloss;

			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};

			struct v2f {
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCOORD1;
				float2 uv : TEXCOORD2;
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);

				o.worldNormal = UnityObjectToWorldNormal(v.normal);

				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

				o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				// Or just call the built-in function
//				o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

				return o;
			}

			fixed4 frag(v2f i) : SV_Target {
				fixed3 worldNormal = normalize(i.worldNormal);
				fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

				// Use the texture to sample the diffuse color
				fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));

				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
				fixed3 halfDir = normalize(worldLightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);

				return fixed4(ambient + diffuse + specular, 1.0);
			}

			ENDCG
		}
	}
	FallBack "Specular"
}


Experiment 2: Use diffuse texture and normal texture in Unity to realize the convex and concave effect of the object, pay attention to the lighting calculation in the tangent space, and write the shader program code to achieve such an effect.

Shader "Unity Shaders Book/Chapter 7/Normal Map In Tangent Space" {
	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Main Tex", 2D) = "white" {}
		_BumpMap ("Normal Map", 2D) = "bump" {}
		_BumpScale ("Bump Scale", Float) = 1.0
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}
	SubShader {
		Pass { 
			Tags { "LightMode"="ForwardBase" }
		
			CGPROGRAM
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _BumpMap;
			float4 _BumpMap_ST;
			float _BumpScale;
			fixed4 _Specular;
			float _Gloss;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;
				float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
				float4 pos : SV_POSITION;
				float4 uv : TEXCOORD0;
				float3 lightDir: TEXCOORD1;
				float3 viewDir : TEXCOORD2;
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

				//Compute the binormal
				// float3 binormal = cross(normalize(v.normal),normalize(v.tangent.xyz))*v.tangent.w;
				// //Construct a matrix which transform vectors from object space to tangent space
				// float3×3 rotation = float3×3(v.tangent.xyz,binormal,v.normal);
				//Or just use the bulid-in macro
				TANGENT_SPACE_ROTATION;
				//Transform the light direction from object space to tangent space
				o.lightDir = mul(rotation, ObjSpaceLightDir(v.vertex)).xyz;
				//Transform the view direction from object space to tangent space
				o.viewDir = mul(rotation, ObjSpaceViewDir(v.vertex)).xyz;
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {				
				fixed3 tangentLightDir = normalize(i.lightDir);
				fixed3 tangentViewDir = normalize(i.viewDir);
				
				// Get the texel in the normal map
				fixed4 packedNormal = tex2D(_BumpMap, i.uv.zw);
				fixed3 tangentNormal;
				// If the texture is not marked as "Normal map"
//				tangentNormal.xy = (packedNormal.xy * 2 - 1) * _BumpScale;
//				tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
				
				// Or mark the texture as "Normal map", and use the built-in funciton
				tangentNormal = UnpackNormal(packedNormal);
				tangentNormal.xy *= _BumpScale;
				tangentNormal.z = sqrt(1.0 - saturate(dot(tangentNormal.xy, tangentNormal.xy)));
				
				fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tangentNormal, tangentLightDir));

				fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(tangentNormal, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
			}
			
			ENDCG
		}
	} 
	FallBack "Specular"
}

Experiment 3: Use diffuse texture and normal texture in Unity to achieve the bump effect of the object, pay attention to the lighting calculation in the world space, and write the shader program code to achieve this effect.

// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'

Shader "Unity Shaders Book/Chapter 7/Normal Map In Tangent Space" {
	Properties {
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Main Tex", 2D) = "white" {}
		_BumpMap ("Normal Map", 2D) = "bump" {}
		_BumpScale ("Bump Scale", Float) = 1.0
		_Specular ("Specular", Color) = (1, 1, 1, 1)
		_Gloss ("Gloss", Range(8.0, 256)) = 20
	}
	SubShader {
		Pass { 
			Tags { "LightMode"="ForwardBase" }
		
			CGPROGRAM
// Upgrade NOTE: excluded shader from DX11; has structs without semantics (struct v2f members pos,uv,TtoW0,TtoW1,TtoW2)
#pragma exclude_renderers d3d11
			
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"
			
			fixed4 _Color;
			sampler2D _MainTex;
			float4 _MainTex_ST;
			sampler2D _BumpMap;
			float4 _BumpMap_ST;
			float _BumpScale;
			fixed4 _Specular;
			float _Gloss;
			
			struct a2v {
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 tangent : TANGENT;
				float4 texcoord : TEXCOORD0;
			};
			
			struct v2f {
				float4 pos:SV_POSITION;
				float4 uv:TEXCOORD0;
				float4 TtoW0:TEXCOORD1;
				float4 TtoW1:TEXCOORD2;
				float4 TtoW2:TEXCOORD3;
			};

			v2f vert(a2v v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				
				o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
				o.uv.zw = v.texcoord.xy * _Bump_ST + _BumpMap_ST.zw;

				float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);
				fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);
				fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;
				//Compute the matrix that transform directions from tangent space to world space
				//put the world position in w component for optimization
				o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
				o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
				o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);
				
				return o;
			}
			
			fixed4 frag(v2f i) : SV_Target {

				//Get the position in world space
				float3 worldPos = float3(i.TtoW0.w,i.TtoW1.w,i.TtoW2.w);
				//Compute the light and vie Dir in world space
				fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldpos));
				fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
				//Get the normal in tangent space
				fixed3 bump = UnpackNormal(tex2D(_BumpMap,i.uv.zw));
				bump.xy *= _BumpScale;
				bump.z = sqrt(1.0 - saturate(dot(bump.xy,bump.xy)));
				//Transform the normal from the tangent space to world space
				fixed3 normal = normalize(half3(dot(i.TtoW0.xyz,bump),dot(i.TtoW1.xyz,bump),dot(i.TtoW2.xyz,bump)));

				fixed3 tangentLightDir = normalize(i.lightDir);
				fixed3 tangentViewDir = normalize(i.viewDir);
				
				fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;
				
				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(normal, lightDir));

				fixed3 halfDir = normalize(lightDir + viewDir);
				fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(normal, halfDir)), _Gloss);
				
				return fixed4(ambient + diffuse + specular, 1.0);
			}
			
			ENDCG
		}
	} 
	FallBack "Specular"
}

It's not easy to make, let's encourage the bloggers with a one-click three-link! !

 

 

Guess you like

Origin blog.csdn.net/xichi_12396/article/details/117003372