Color GetColorForTestMetal(Ray ray, HitableList hitableList, int depth) { HitRecord record = new HitRecord(); // 当光线撞击在球上的时候 // 这里包括了法线毛绒球和两个金属球 if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { Ray r = new Ray(Vector3.zero, Vector3.zero); Color attenuation = Color.black; // 说一下scatter 调用中的 ref 关键字 这个表示按照引用传递 因此后面运算中的attenuation 的值是材质本身设定的衰减值 并不是black // material 是 Metal 和 漫反射的毛绒球(兰伯特光照) 不同的材质对scatter 有不同的实现 if (depth < MAX_SCATTER_TIME / 10 && record.material.scatter(ray, record, ref attenuation, ref r)) { Color c = GetColorForTestMetal(r, hitableList, depth + 1); //将镜面反射的光线再次进行碰撞计算 return(new Color(c.r * attenuation.r, c.g * attenuation.g, c.b * attenuation.b)); } else { //假设已经反射了太多次,或者压根就没有发生反射,那么就认为黑了 return(Color.black); } } float t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
Color GetColorForTestAntialiasing(Ray ray, HitableList hitableList) { HitRecord record = new HitRecord(); if (hitableList.Hit(ray, 0f, float.MaxValue, ref record)) { return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f)); } float t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
Color GetColorForTestDiffusing(Ray ray, HitableList hitableList) { HitRecord record = new HitRecord(); if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { Vector3 target = record.p + record.normal + GetRandomPointInUnitSphereForTestDiffusing(); //此处假定有50%的光被吸收,剩下的则从入射点开始取随机方向再次发射一条射线 return(0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList)); } float t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
Color GetColorForTestHitRecord(Ray ray, HitableList hitableList) { HitRecord record = new HitRecord(); if (hitableList.Hit(ray, 0f, float.MaxValue, ref record)) { // 没有直接返回 record.normal.xyz 是因为默认颜色有点暗 return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f)); } float t = 0.5f * ray.normalDirection.y + 1f; // 控制浅蓝的背景色 return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
Color GetColorForTestAntialiasing(Ray ray, HitableList hitableList) { HitRecord record = new HitRecord(); // 实际上调用的是 SimpleSphere 的 Hit if (hitableList.Hit(ray, 0f, float.MaxValue, ref record)) { // 这里+1 都是为了更好的视觉效果 return(0.5f * new Color(record.normal.x + 1, record.normal.y + 1, record.normal.z + 1, 2f)); } float t = 0.5f * ray.normalDirection.y + 1f; // 控制浅蓝的背景色 return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
// https://www.guokr.com/question/569971/ // 光线追踪 如果遇到漫反射面的话一般是需要产生非常多的次级射线往下递归才能达到比较好的效果(否则噪点比较明显) Color GetColorForTestDiffusing(Ray ray, HitableList hitableList) { HitRecord record = new HitRecord(); // 这里对应的是 simpleSphere 的 Hit 方法 if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { Vector3 target = record.p + record.normal + GetRandomPointInUnitSphereForTestDiffusing(); //此处假定有50%的光被吸收,剩下的则从入射点开始取随机方向再次发射一条射线 //return 0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList); // 即便文中说的是使用随机的光线 但是即使是漫反射 也还是和物体本身的法线方向相关的 //所以这里还需要考虑到法线 return(0.5f * GetColorForTestDiffusing(new Ray(record.p, record.normal + GetRandomPointInUnitSphereForTestDiffusing() * 0.5f), hitableList)); } float t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
Color GetColorForTestDefocus(Ray ray, HitableList hitableList, int depth) { HitRecord record = new HitRecord(); if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { Ray r = new Ray(Vector3.zero, Vector3.zero); Color attenuation = Color.black; if (depth < MAX_SCATTER_TIME && record.material.scatter(ray, record, ref attenuation, ref r)) { Color c = GetColorForTestDefocus(r, hitableList, depth + 1); return(new Color(c.r * attenuation.r, c.g * attenuation.g, c.b * attenuation.b)); } else { //假设已经反射了太多次,或者压根就没有发生反射,那么就认为黑了 return(Color.black); } } float t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }