本章导图
- 光源 —— 衡量标准:辐射度(垂直与表面法线上余弦值乘以斜线上的辐射度)
- 吸收和散射 —— 光线经过散射后,一个会散射到物体内部,一个是反射到物体外部
- 着色 —— 利用材质属性和光源信息进行物体表面光照模型的计算过程,称为着色。
- BRDF光照模型 —— 计算光线和物体表面交互的渲染方程。
- 环境光 —— 表述物体表面的间接光照:光线在进入摄像机前,经过了不止一次的物体反射。
- 自发光 —— 光线直接由光源发射进入摄像机
- 漫反射 —— 针对于光线从物体表面随机散射到各个方向的辐射度进行建模。这个时候入射方向反而不重要,因为都会散射到各个方向。而散射的光线强度和光源方向之间夹角的余弦值成正比
- 高光 —— 计算高光由两种模型,一种是Blinn模型,还有一种是Phong模型
- 对于计算光照模型的位置:在片元着色器中计算称为逐像素光照,在顶点着色器中计算称为逐顶点光照。
- Phong着色:以每个像素为基础,计算法线,再根据面片之间对顶点法线进行插值
- 高洛德着色:再每个顶点上计算光照,然后在渲染图元内部进行线性插值,最后输出成像素颜色
- 定义:使用了漫反射和高光反射来对反射光线进行建模,提出的基于经验的计算高光反射的方法。
- 优点:简化了计算,更快
- 局限性:由于是一个经验模型,对于一些复杂的现象,例如菲涅耳反射表现不出来,另外各项同性的特点导致旋转物体时,反射表面不会由任何变化。对于毛发等不适用。
- 环境光:在添加热河照明之前该空间中已经可用的光
- 自发光:在片元着色器输出最后颜色之前,把材质的自发光颜色添加到输出颜色上即可
- 公式:要计算漫反射需要知道4个参数,入射光线的颜色和强度c,材质的漫反射系数m,表面法线n以及光源方向I。为了防止点积结果为负值,需要max操作。
- 逐像素实现漫反射
shader代码如下:
Shader "Unity Shaders Book/Chapter 6/Diffuse Vertex-Level" {
Properties{
_Diffuse("Diffuse", Color) = (1, 1, 1, 1)
}
SubShader{
Pass {
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _Diffuse;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};
v2f vert(a2v v) {
v2f o;
// Transform the vertex from object space to projection space
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.worldNormal = mul(v.normal, (float3x3)_World2Object);
Get ambient term
//fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
Transform the normal from object space to world space
//fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
Get the light direction in world space
//fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
Compute diffuse term
//fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLight));
//o.color = ambient + diffuse;
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
fixed3 color = ambient + diffuse;
return fixed4(i.color, 1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
- 效果如图:
三、在Unity Shader上实现高光反射光照模型
-
公式
-
逐像素实现高光(逐顶点使得高光呈现非线性的特征)
shader代码如下:
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Unity Shaders Book/Chapter 6/Specular Pixel-Level" {
Properties {
_Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
_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 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct a2v {
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f {
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
};
v2f vert(a2v v) {
v2f o;
// Transform the vertex from object space to projection space
o.pos = UnityObjectToClipPos(v.vertex);
// Transform the normal from object space to world space
o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);
// Transform the vertex from object spacet to world space
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
return o;
}
fixed4 frag(v2f i) : SV_Target {
// Get ambient term
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);
// Compute diffuse term
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal, worldLightDir));
// Get the reflect direction in world space
fixed3 reflectDir = normalize(reflect(-worldLightDir, worldNormal));
// Get the view direction in world space
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
// Compute specular term
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir, viewDir)), _Gloss);
return fixed4(ambient + diffuse + specular, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
- 逻辑图如下:



