public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth) { //Phong公式: L = Kd * I * max(0, n·l) + Ks * I * max(0, n·h)^p // Kd是散射系数, n是表面法向量,l是光源方向(从相交点指向光源), Ks是高光系数,h是v+l的单位向量,v是视线反方向(从相交点只想视点), I是光强(光在这一点的颜色) Vec3 l = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize()); float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l)); Vec3 h = (-view_ray.Direction + l).normalize(); float n_dot_h = Math.Max(0, Vec3.dot(record.normal, h)); Vec3 I = Vec3.one; Vec3 dif = diffuse * n_dot_l; Vec3 spe = specular * (float)Math.Pow(n_dot_h, phong_exp); spe *= _smoothstep(0, 0.12f, n_dot_l);//为了解决背光面高光的问题,如果n_dot_l<0直接spe=0会有颜色间断层,需要做插值处理 Vec3 L = Vec3.product(I, dif + spe); //上面有两个bug/疑问 //(1)背光面也能出现高光,因为公式里n·l<0并不影响 Ks * I * max(0, n·h)^p的值; //(2)求出来的L超过(1,1,1)范围了.---暂时强行映射到[0,1] //上面两个问题估计都是要改diffuse和specular来处理 //目前先特殊处理下,以后看看大佬们怎么搞的 return(L); }
public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth) { Vec3 l = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize()); float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l)); Vec3 I = Vec3.one; Vec3 dif = diffuse * n_dot_l; Vec3 L = Vec3.product(I, dif); return(L); }
public override Vec3 GetColor(BaseLight light, Ray view_ray, HitRecord record, float depth) { Vec3 l = -(light.GetLightRay(record.hit_point, view_ray.DeltaTime).Direction.normalize()); float n_dot_l = Math.Max(0, Vec3.dot(record.normal, l)); Vec3 I = Vec3.one; Vec3 color = texture == null ? diffuse : texture.GetColorValue(0, 0, record.hit_point);//这里还要改的,下面的material也是,感觉material用来定义反射之类的物理计算公式。颜色映射还是交给texture吧 Vec3 dif = color * n_dot_l; Vec3 L = Vec3.product(I, dif); return(L); }