Shader "Example/Diffuse Simple"
{
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input
{
float4 color : COLOR;
};
void surf (Input IN, inout SurfaceOutput o)
{
o.Albedo = 1; // 1 = (1,1,1,1) = white
}
ENDCG
}
Fallback "Diffuse"
}
#pragma surface surf Lambert
specify the shader is surface and use Lambertian Lighting Model.
SurfaceOutput has several properties to determine the final aspect of a material.
- fixed3 Albedo: the base color/texture of an object
- fixed3 Normal
- fixed3 Emission: how much light this object is generating by itself
- half Specular: light reflection
- fixed Alpha
float
is supported, but we barely use 32 bit precision, so we use half
. 16 bits.
fixed
spans at least from -2 to 2, 10 bits.
Sampling Textures
Texture maps 3D objects. They typically contain UV and color data. UV is a 2D vector which indicates which point of the texture is mapped to the vertex.
Shader "Example/Diffuse Texture"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType" = "Opaque" }
CGPROGRAM
#pragma surface surf Lambert
struct Input {
float2 uv_MainTex;
};
sampler2D _MainTex;
void surf (Input IN, inout SurfaceOutput o) {
o.Albedo = tex2D (_MainTex, IN.uv_MainTex).rgb;
}
ENDCG
}
Fallback "Diffuse"
}
_MainText
is a texture. uv_MainTex
is the current pixel’s UV data. tex2D
returns the RGBA color by giving the pixel’s texture and UV data. UV coordinates are stored only in the vertices. When the shader evaluates a pixel is not a vertex, the function tex2D interpolates the UV coordinates of the three closest vertices.
Snow Shader
Shader "Custom/SurfaceShader"
{
Properties
{
_MainColor("Main Color", Color) = (1., 1., 1., 1.)
_MainTex("Texture", 2D) = "white" {}
_Bump ("Bump", 2D) = "bump" {}
_Snow("Level of snow", Range(1, -1)) = 1
_SnowColor ("Color of snow", Color) = (1., 1., 1., 1.)
_SnowDirection("Direction of snow", Vector) = (0, 1, 0)
_SnowDepth("Depth of snow", Range (0, 0.0001)) = 0
}
SubShader
{
Tags
{
"RenderType" = "Opaque"
}
LOD 200
CGPROGRAM
#pragma surface surf Lambert vertex:vert
sampler2D _MainTex;
sampler2D _Bump;
float _Snow;
float4 _SnowColor;
float4 _MainColor;
float4 _SnowDirection;
float _SnowDepth;
struct Input
{
float2 uv_MainTex;
float2 uv_Bump;
float3 worldNormal;INTERNAL_DATA
};
void vert (inout appdata_full v)
{
float4 sn = mul(_SnowDirection, unity_WorldToObject);
if (dot(v.normal, sn.xyz) >= _Snow)
{
v.vertex.xyz += (sn.xyz + v.normal) * _SnowDepth * _Snow;
}
}
void surf (Input IN, inout SurfaceOutput o)
{
half4 c = tex2D(_MainTex, IN.uv_MainTex);
o.Normal = UnpackNormal(tex2D(_Bump, IN.uv_Bump));
if (dot(WorldNormalVector(IN, o.Normal), _SnowDirection.xyz) >= _Snow)
{
o.Albedo = _SnowColor.rgb;
}
else
{
o.Albedo = c.rgb * _MainColor;
}
o.Alpha = 1;
}
ENDCG
}
Fallback "Diffuse"
}
LOD (Level of Details) indicates how computationally demanding the subshader is.
It’s a convenient way to specify shaders on different platforms. myShader.maximumLOD = 100
makes the only use shader with LOD 100 or lower, so PC and smart phones can both run it.
unity_WorldToObject
is a built-in variables. The inverse of current world matrix.
tex2D
performs a texture lookup in a given 2D sampler.
float3 worldNormal; INTERNAL_DATA
contains world normal vector if surface shader writes to o.Normal
. To get the normal vector based on per-pixel normal map, use WorldNormalVector(IN, o.Normal)
.