基础光照模型、着色及效果(二)

参考源Illumination Models and Shaing翻译声明仅供学习交流https://www.cnblogs.com/baolong-chen/category/1559372.html

为了尽可能得到真实感图像画面,必须要模拟物体表面在多种光照条件影响下的图像呈现

一、Lighting Model Method


Lighting Model params

light source参数

  • 位置-Position
  • 光谱光波-Electromagnetic Spectrum
  • 光源形状-Shape

object sucface参数

  • 位置-Position
  • 反射率属性-Reflectance properties
  • 邻近面-Position of nearby surcface

camera(eye)参数

  • 镜头位置-Position Sensor
  • spectrum sensitivities


Ambient Illumination-环境光

假定场景没有方向光只有环境光,且环境光入射到每个物体表面的量和方向是恒定的,这个理想的光照模型在现实世界基本不存在的。

公式:Iamb = Ka·Ia

Ia: 环境光强度,

Ka∈[0,1]: 物体表面反射率

最后把IRamb,IGamb,IBamb传递给模型顶点或像素颜色RGB

Unity中环境光宏定义:#define UNITY_LIGHTMODEL_AMBIENT (glstate_lightmodel_ambient * 2)

 

Diffuse Reflection-漫反射

image图1

漫反射公式:Idiff = Kd·Ip·Cos(θ) = Kd·Ip·(N·L)

Lambert余弦定律:反射强度与表面的平滑度相关,与入射角度Sin(α)成反比或者Cos(θ)成正比

Ip:光源强度,也可作为衰减光源fatt(r)Ip---光照颜色

Kd∈[0,1]:物体表面反射率

N:平面法线, (使用前要归一化运算)

L:光源方向,(使用前要归一化运算)

漫反射和环境光合并公式:I = Idiff + Iamb = Kd·Ip·(N·L) + Ka·Ia

最后把IR IG IB 传递给模型顶点或像素颜色RGB即可

//漫反射和环境光合并
//可以转换到模型空间、切线空间、世界空间
v2f vert(a2v a) {
    v2f v;
    v.pos = UnityObjectToClipPos(a.vertex);
    //模型空间
    /*fixed3 mn = normalize(a.normal);            
    fixed3 lightdir = normalize(ObjSpaceLightDir(a.vertex));
    fixed3 val =  max(0, dot(mn, lightdir));
    fixed3 diff = _Smoothness * _LightColor0.rgb * val * _Diffuse.rgb;
    v.color = UNITY_LIGHTMODEL_AMBIENT.xyz + diff;*/
    //世界空间---由于世界空间有许多信息例如环境映射、光照、视角,一般推荐转换到世界空间
    fixed3 wm = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
    fixed3 lightdir = normalize(_WorldSpaceLightPos0.xyz);
    fixed3 val = max(0, dot(wm, lightdir));
    fixed3 diff = _Smoothness * _LightColor0.rgb * val * _Diffuse.rgb;
    v.color = UNITY_LIGHTMODEL_AMBIENT.xyz + diff;
    return v;
}

 

Specular Reflection-高光反射

镜面(高光)反射,模拟陶瓷、金属等光滑表面材质,反射角影响反射强度。

image图2

image图3

公式(Phong Model):Ispec = Ks·Ip·cosn(Φ) = Ks·Ip·(R·V)n

Ks:物体表面高光反射率

Ip:光源强度---光照颜色

L:光源方向

N:平面法线

R:反射方向

V:视线方向

n:高光反射系数,决定着与理想高光反射模型的偏差

R推导过程

image图4

R推导过程:理想的反射模型是等腰三角形(见图2)。L入射起点,R反射终点。

矢量R = OR = LR–LO = 2LP-LO = 2(LO+OP)-LO = LO+2OP

LO已知,那么求得LO在法向量上的投影OP即可,

取得N的单位向量n:n=OP/|OP|=N/|N|

取得三角函数值: image

结合点积函数与三角函数可得image

R = 2·dot(n, L)·n – L == reflect(-L,n)

v2f vert(a2v a) {
    v2f v;
    v.position = UnityObjectToClipPos(a.vertex);
    fixed3 world_pos        = mul(a.vertex, unity_WorldToObject);
    fixed3 world_n          = normalize(mul(a.normal, (float3x3)unity_WorldToObject));
    fixed3 world_light_dir  = normalize(UnityWorldSpaceLightDir(world_pos));//顶点指向光源
    fixed3 world_view_dir   = normalize(_WorldSpaceCameraPos.xyz - world_pos);//顶点指向摄像机
    //reflect函数参数需要从入射光到顶点方向
    fixed3 world_ref_dir  = normalize(2 * dot(world_n,world_light_dir)*world_n - world_light_dir);//reflect(-world_light_dir,world_n);
    fixed3 spec_color   = _Ks * _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(world_ref_dir, world_view_dir)), _N);
    fixed3 diff_color   = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
    fixed3 ambient      = UNITY_LIGHTMODEL_AMBIENT.xyz;
    fixed3 color        = ambient + diff_color + spec_color;
    v.color = color;
    return v;
 }



组合环境光、漫反射、高光

公式:I = Iamb + Idiff + Ispec = Ka·Ia + Ip (Kd· N ⋅ L + Ks (R⋅V)n)

v2f vert(a2v a) {
    /*同上...*/
    fixed3 diff_color  = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
    fixed3 ambient     = UNITY_LIGHTMODEL_AMBIENT.xyz;
    fixed3 color       = ambient + diff_color + spec_color;

    v.color = color;
     return v;
}

翻译声明仅供学习交流https://www.cnblogs.com/baolong-chen/category/1559372.html

二、Polygon Rendering Methods


Flat Shading-略

UnityStore有一款插件:Poly World

Gouraud Shading

  • 获取每个多边形的顶点法线
  • 带入光照模型计算每个顶点的光照强度
  • 在曲面多边形线性插值顶点强度

根据上述三点,基本确定是在顶点着色内进行着色运算

高洛德着色中,公共顶点法线(红点法线)来源于所有共点面法线的平均值,如下图。主要目的是对三个顶点组成的三角面内部进行着色,而其他三角面没有被照射到,就不会有光照效果。

image图5

实现代码,参考上面的vert(a2f a)函数即可

Phong Shading

  • 获取每个多边形法线
  • 在曲面多边形线性插值顶点法线
  • 带入光照模型计算每个片元内像素点的光照强度

上述三点,前面两点在顶点着色器计算,最后一步的着色计算在片元着色器

v2f vert(a2v a) {
    v2f v;
    v.position          = UnityObjectToClipPos(a.vertex);
    v.world_normal      = UnityObjectToWorldNormal(a.normal);
    v.world_position    = mul(UNITY_MATRIX_M, a.vertex);
    v.world_light_dir   = UnityWorldSpaceLightDir(v.world_position);//顶点指向光源
    v.world_view_dir    = UnityWorldSpaceViewDir(v.world_position);//顶点指向摄像机
    return v;
}
    fixed4 frag(v2f v) : SV_Target{
    fixed3 world_pos    = normalize(v.world_position);
    fixed3 world_n      = normalize(v.world_normal);
    fixed3 world_light_dir   = normalize(v.world_light_dir);
    fixed3 world_view_dir    = normalize(v.world_view_dir); 
    fixed3 world_ref_dir = normalize(2 * dot(world_n, world_light_dir) * world_n - world_light_dir);
    fixed3 spec_color = _Ks * _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(world_ref_dir, world_view_dir)), _N);
    fixed3 diff_color = _Kd * _LightColor0.rgb * saturate(dot(world_n, world_light_dir));
    fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
    fixed3 color   = ambient + diff_color + spec_color;
    return fixed4(color, 1.0f);
}

最后效果图:高洛德着色与冯着色效果如下图:

image图6

原文地址:https://www.cnblogs.com/baolong-chen/p/11669311.html