Shader Cheat Sheet

CG 函数速查手册

Link

UNITY_MATRIX_MVP

使用方法:

1
2
mul(UNITY_MATRIX_MVP,*) //旧版
UnityObjectToClipPos(*) //新版

作用:

将模型空间下的 顶点/方向矢量 变换到 剪裁空间

空间:

  • 模型空间: 模型内部的坐标系
  • 世界空间: 世界坐标系 (变换使用 _Object2World(*) )
  • 观察空间: 以相机为原点的世界空间 (范围没有缩减,只是世界空间的旋转/缩放/平移)
  • 剪裁空间: 两个剪裁平面(近剪裁面/远剪裁面) 构成的菱形(透视)或方形(正交). 原点可以认为是该区域中的某一点(近剪裁面的中心点). 其内部坐标满足与 -w <= xyz <= w, 不满足条件的顶点均不在剪裁空间内
  • 屏幕空间: 最终的2D平面

Properties 种类

Cg/HLSL variable types

  • Color and Vector properties map to float4, half4 or fixed4 variables.
  • Range and Float properties map to float, half or fixed variables.
  • Texture properties map to sampler2D variables for regular (2D) textures; Cubemaps
    map to samplerCUBE; and 3D textures map to sampler3D.

Cg/HLSL can also accept uniform keyword, but it is not necessary

  • The data types for floating-point 2×2, 3×3, and 4×4 matrices are: float2x2, float3x3, and float4x4
  • Apart from float data types, there are additional half types (half, half2, half3, half4, half2x2, half3x3, half4x4, etc.), and fixed types (fixed, fixed2, fixed3, fixed4, etc.)

Link

Link2

Basic data types
The majority of calculations in shaders
are carried out on floating-point numbers (which would be float in regular programming languages like C#). Several variants of floating point types are present: float, half and fixed (as well as vector/matrix variants of them, such as half3 and float4x4). These types differ in precision (and, consequently, performance or power usage):

High precision: float

Highest precision floating point value; generally 32 bits (just like float from regular programming languages).

Full float precision is generally used for world space positions, texture coordinates, or scalar computations involving complex functions such as trigonometry or power/exponentiation.

Medium precision: half

Medium precision floating point value; generally 16 bits (range of –60000 to +60000, with about 3 decimal digits of precision).

Half precision is useful for short vectors, directions, object space positions, high dynamic range colors.

Low precision: fixed

Lowest precision fixed point value. Generally 11 bits, with a range of –2.0 to +2.0 and 1/256th precision.

Fixed precision is useful for regular colors (as typically stored in regular textures) and performing simple operations on them.

Integer data types

Integers (int data type) are often used as loop counters or array indices. For this purpose, they generally work fine across various platforms.

Depending on the platform, integer types might not be supported by the GPU. For example, Direct3D 9 and OpenGL ES 2.0 GPUs only operate on floating point data, and simple-looking integer expressions (involving bit or logical operations) might be emulated using fairly complicated floating point math instructions.

Direct3D 11, OpenGL ES 3, Metal and other modern platforms have proper support for integer data types, so using bit shifts and bit masking works as expected.

[NoScaleOffset] 标签

Properties的纹理加入该标签后则不可以缩放和平移

1
2
3
4
5
Properties {
_MainTex ("Splat Map", 2D) = "white" {}
[NoScaleOffset] _Texture1 ("Texture 1", 2D) = "white" {}
[NoScaleOffset] _Texture2 ("Texture 2", 2D) = "white" {}
}

a2v v2f

  • a: Application 应用层
  • v: Vertex Shader 顶点着色起
  • f: Fragment Shader 片元着色起

_MainTex_ST

使用纹理名称后面加_ST 访问纹理的Scale(S),和Translation(T)属性

1
2
3
4
5
6
7
float4 _MainTex_ST; //声明部分

v2f vert(a2v v) {
...
o.uv = v.texcoord.xy * _MainTex_ST.xy+ _MainTex_ST.zw; //xy是Scale,zw是平移
...
}

tex2D

用于纹理采样

1
2
3
4
fixed4 frag(v2f i) : SV_Target {
fixed4 c = tex2D(_MainTex, i.uv); //首参数未纹理,第二参数为uv坐标
return fixed4(c.rgb, 1.0);
}

手动取MipMappingLevel

Link

1
2
3
4
5
6
7
8
9
10
11
12

// Manually set mip level and return fragment
float mipLevel = GetMipLevel(i.texcoord0, _AtlasSize);
return tex2Dlod(_MainTex, float4(uv.xy, 0, mipLevel));

float GetMipLevel(float2 iUV, float2 iTextureSize)
{
float2 dx = ddx(iUV * iTextureSize.x);
float2 dy = ddy(iUV * iTextureSize.y);
float d = max(dot(dx, dx), dot(dy,dy));
return 0.5 * log2(d);
}

Link

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#define SUB_TEXTURE_SIZE 512.0
#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv )
{
float2 dx = ddx( uv * SUB_TEXTURE_SIZE );
float2 dy = ddy( uv * SUB_TEXTURE_SIZE );
float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts
const float rangeClamp = pow(2, (SUB_TEXTURE_MIPCOUNT - 1) * 2);
d = clamp(d, 1.0, rangeClamp);

float mipLevel = 0.5 * log2(d);
mipLevel = floor(mipLevel);

return mipLevel;
}

Calculating half texel offset for selected mip level also

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#define SUB_TEXTURE_SIZE 512.0
#define SUB_TEXTURE_MIPCOUNT 10

float MipLevel( float2 uv, out float a_halfOffset )
{
float2 dx = ddx( uv * SUB_TEXTURE_SIZE );
float2 dy = ddy( uv * SUB_TEXTURE_SIZE );
float d = max( dot( dx, dx ), dot( dy, dy ) );

// Clamp the value to the max mip level counts
const float rangeClamp = pow(2, SUB_TEXTURE_MIPCOUNT - 1);
d = clamp(sqrt(d), 1.0, rangeClamp);

float mipLevel = log2(d);
mipLevel = floor(mipLevel);

a_halfOffset = d * (1.0 / pow(2.0, SUB_TEXTURE_MIPCOUNT));

return mipLevel;
}

标准光照模型

最终点颜色 = 自发光结果(emissive) + 高光反射结果(specular) + 漫反射(diffuse) + 环境光(ambient)

环境光(ambient)

通过 UNITY_LIGHTMODEL_AMBIENT.xyz访问

漫反射(diffuse)

C_diffuse = (C_light M_diffuse) Max(0,n*l)

比如:

1
2
fixed3 albedo = tex2D(_MainTex,i.uv).rgb * _Color.rgb
fixed3 diffuse _LightColor0.rgb * albedo * max(0,dot(tangentNormal,tangentLightDir))
  • C_light : 就是当前点的光源颜色
  • M_diffuse : 材质的漫反射系数 也就是当前纹理的采样rgb值 * 叠加的颜色值
  • n : 当前坐标系下的单位法线
  • l : 当前坐标系下的光线方向

效果:

根据 光线和法线夹角不同 表现为物体有明暗变化
和相机的角度无关,只和光线有关

C_diffuse = (C_light M_diffuse) (A*(n*l)+B)
C_diffuse = (C_light M_diffuse) (0.5*(n*l)+0.5)

Half Lambert 光照模型. 对漫反射加入偏移修正. 防止背光区域过暗

高光反射(Specular)

C_specular = (C_light M_specular) Max(0,v*r)^M_Gloss

比如

1
2
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz-mul(_Ojbect2World,v.vertext).xyz);
flxed3 specular = _LightColor.rgb * _Specular.rgb * pow(setuarte(dot(reflectDir,viewDir)),_Gloss)
  • viewDir : 视角方向,对应公式中的v 是用相机pos-当前Vertext在世界坐标系的Pos得到
  • reflectDir : 反射角度,对应公式中的r.使用函数reflect(i,n)求得. 手动求反射角度公式及求解方法

Blinn-Phone模型

C_specular = (C_light M_specular) Max(0,n*h)^M_Gloss

  • n : 法线
  • h : normalize(入射Dir+光照Dir)

效果:

高光反射用来处理因为光线而产生的亮斑
高光反射不对纹理进行采样.所以只是往原有颜色上叠加亮斑(_LightColor.rgb * _Specular.rgb 这两个控制叠加的颜色)
_Gloss控制光泽度.也就是值越大则光斑越大

设置全局参数

比如战争迷雾,所有的Shader都需要访问的参数

1
2
3
4
Shader.SetGlobalTexture("$name",$Property)
Shader.SetGlobalFloat("$name",$Property);
Shader.SetGlobalVector("$name", new Vector4($Property, $Property, $Property, $Property));
Shader.SetGlobalColor("$name",$Property);

查询Shader

1
tempShader = Shader.Find("$Path");
坚持原创技术分享,您的支持将鼓励我继续创作!