C# 中的基本照明模型






4.87/5 (23投票s)
C# 中的基本光照模型。
环境光
|
漫反射
|
镜面反射
|
环境光 + 漫反射
|
漫反射 + 镜面反射
|
环境光 + 漫反射 + 镜面反射
|
引言
在我之前的文章 C# 中的简单光线追踪 中,我们看到了如何使用简单的光线追踪算法来显示球体。 现在,我们将从最后一点开始,并使用基本的光照模型。
根据定义,我们有三种类型的光
- 环境光
- 漫反射
- 镜面反射
环境光
它被认为是环境中分布的光,它对全局光照有贡献,与光的位置、物体或观察者无关。
漫反射
它是其贡献取决于其入射角的光。 漫反射光可以向各个方向反射。
镜面反射
镜面光代表物体中的亮点; 反射率越高,亮点越小。
背景
要继续使用光照算法,我们需要获取要建模的材料的环境光、漫反射和镜面反射常数; 例如,这里我们使用黄铜常数,它们是
K | 环境光 | 漫反射 | 镜面反射 |
红 | 0.329412 | 0.780392 | 0.992157 |
绿 | 0.223529 | 0.568627 | 0.941176 |
蓝 | 0.027451 | 0.113725 | 0.807843 |
指数 27.8974
所使用的光线追踪算法与您在 C# 中的简单光线追踪 中看到的一样,并改进了基本的光照模型。
方程
光源定义为具有 (vx,vy,vz) 方向向量的 R3 (x,y,z) 点。
观察者定义为具有 (vx,vy,vz) 方向向量的 R3 (x,y,z) 点。
Theta 定义为光线与表面上交点 P 处的法向量之间的夹角。
Phi 定义为在表面上交点 P 处反射光线与观察者光线到同一 P 点之间的夹角。
球体方程
- r2 = (x-cx)2+(y-cy)2+(z-cz)2
给定像素上的光照
- I环境光 = I * K环境光
- I漫反射 = I * K漫反射 * cos(theta)
- I镜面反射 = I * K镜面反射 * cos(phi)n
- I = I环境光 + I漫反射 + I镜面反射
反射计算
- i' = i - (2 * n * dot(i, n))
其中
- i = 入射光线
- n = 交点处的法线
- i' = 反射光线
代码
...
if (spherehit != null)
{
double intersx = px + t * vx, intersy = py + t * vy,
intersz = pz + t * vz;
double vNormalX = intersx - spherehit.cx,
vNormalY=intersy - spherehit.cy,
vNormalZ=intersz - spherehit.cz;
double cost = tAlgebra.GetCosAngleV1V2(lvx, lvy, lvz, vNormalX,
vNormalY, vNormalZ);
if (cost < 0) cost = 0;
double vReflX = 0, vReflY = 0, vReflZ = 0;
double vEye2IntersX = px - intersx, vEye2IntersY = py - intersy,
vEye2IntersZ = pz - intersz;
tAlgebra.Reflect(lvx,lvy,lvz, vNormalX,vNormalY,vNormalZ,ref vReflX,
ref vReflY, ref vReflZ);
double cosf = tAlgebra.GetCosAngleV1V2(vReflX, vReflY, vReflZ,
vEye2IntersX, vEye2IntersY, vEye2IntersZ);
if (cosf < 0) cosf = 0;
double result1 = cost * 255.0;
double result2 = Math.Pow(cosf, spherehit.shininess) * 255.0;
double rgbR = (spherehit.ambientR * 255.0)+(spherehit.diffuseR *
result1) + (spherehit.specularR * result2);
double rgbG = (spherehit.ambientG * 255.0) +(spherehit.diffuseG *
result1) + spherehit.specularG * result2);
double rgbB = (spherehit.ambientB * 255.0) +(spherehit.diffuseB *
result1) + (spherehit.specularB * result2);
rgbR = Math.Min(rgbR, 255);
rgbG = Math.Min(rgbG, 255);
rgbB = Math.Min(rgbB, 255);
color = Color.FromArgb((int)rgbR, (int)rgbG, (int)rgbB);
...
}
...