65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 中的基本照明模型

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (23投票s)

2007年7月26日

GPL3

2分钟阅读

viewsIcon

86765

downloadIcon

1100

C# 中的基本光照模型。

Screenshot - Ambient.png

环境光

Screenshot - Diffuse.png

漫反射

Screenshot - Specular.png

镜面反射

Screenshot - Ambient+Diffuse.png

环境光 + 漫反射

Screenshot - Diffuse+Specular

漫反射 + 镜面反射

Screenshot - Ambient+Diffuse+Specular

环境光 + 漫反射 + 镜面反射

引言

在我之前的文章 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);
     ...
     }
...
© . All rights reserved.