Unity shader Note

光照基础

辐照度irradiance

散射scattering 吸收 absorption
散射只改变光的方向 吸收只改变光线的密度和颜色

光线进入如物体会发生折射refraction和投射transmission 以及被散射到外部的反射reflection
区别不同的散射方向 高光反射 specular 漫反射diffuse

出射度 exitance 辐照度和出射度满足线性关系 比值就是漫反射和高光反射的属性

BRDF (Bidirectional Reflection Distribution Function)

标准光照模型 direct light
自发光 emissive 高光specular 漫反射diffuse 环境光ambient

diffuse Lambert’s Law
cdiffuse=(clightmdiffuse)max(0,nl)c_{diffuse} = (c_{light} * m_{diffuse})max(0,n*l)

光源颜色漫反射材质颜色亮度值
Phong光照模型
Cspecular=(clightmspecular)max(0,vr)mglossC_{specular} = (c_{light} * m_{specular})max(0,v*r)^{m_{gloss}}

Blinn-Phong
h=v+lv+lCspecular=(clightmspecular)max(0,nh)mglossh = \frac{v+l}{|v+l|}
C_{specular} = (c_{light} * m_{specular})max(0,n*h)^{m_{gloss}}

Phong shading 逐像素光照 Gouraud shading 逐顶点光照
各向同性isotropic 各向异性anisotropic

坐标转换

投影矩阵

N = near plane
F = far plane
A = aspect ratio
FOV =field of view
S = size

UNITY_UV_STARTS_AT_TOP DX平台和OpenGL差别
_MainTex_TexelSize.y < 0 判定是否开启抗锯齿
DX9/11不支持在vertex shader中采样纹理 使用tex2D() 使用 tex2DLOD(texture2d tex,float4 uv)替代

类型 精度
float 32bit 浮点
half 16bit 浮点 -60000 ~ +60000
fixed 11bit -2.0~+2.0
指令 描述
#pragma target 2.0 DX9 SM2.0 不支持对顶点纹理采样,不支持显示LOD纹理采样
#pragma target 3.0 DX9 SM3.0支持顶点纹理采样
#pragma target 4.0 DX10 SM4,0 支持几何着色器
#pragma target 5.0 DX11 SM5.0

对向量进行转换
mul(v,(float3x3)_World2Object) == mul(_Object2World,v)

屏幕坐标

计算屏幕位置ComputeScreenPos(float4 projectionPos)

ObjSpaceViewDir(float4 objectpos)

采样Depth Texture World

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
struct v2f
{
...
float4 pos :SV_POSITION;
float3 ray : TEXCOORD1;
float4 screenUV : TEXCOORD0;
}

v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,float4(v.pos,1));
o.screenUV = ComputeScreenPos(o.pos);
o.ray = mul(UNITY_MATRIX_MV,float4(v.pos,1).xyz * float3(-1,-1,1));
}

sampler2D_float _CameraDepthTexture;

fixed4 frag(v2f i): SV_Target
{
float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture,i.screenUV.xy/i.screenUV.w);
depth = Linear01Depth(depth); //sample depth texture
i.ray = i.ray *(_ProjectionParams.z / i.ray.z);
float4 vpos = float4(i.ray* depth,1); //view pos
float3 wpos = mul(unity_CameraToWorld,vpos).xyz; //world pos
float3 opos = mul(unity_WorldToObject,float4(wpos,1)).xyz;//object pos
}