static void Test() { SceneDebug dbg = new SceneDebug(); dbg.BeginBranch(new Vector3(1, 1, 1)); dbg.BeginBranch(new Vector3(2, 2, 2)); dbg.BeginBranch(new Vector3(3, 3, 3)); dbg.EndBranch(); dbg.BeginBranch(new Vector3(4, 4, 4)); dbg.EndBranch(); string fname = $"A:\\img\\{FileName()}"; dbg.SaveToFile(fname + ".obj"); }
public override Light IntersectLight(Vector3 point, Vector3 dir, Vector3 normal, int deep) { #if RayDebugger SceneDebug Debugger = Scene.debugger; if (Debugger != null) { Debugger.BeginBranch(point); Debugger.EndBranch(); } #endif if (dir.Y > 0.94f) { return(Light.White); } float y = 0.5f * (dir.Y + 1.0f); return((1.0f - y) * Light.White + y * new Light(0.51f, 0.68f, 0.95f)); }
/// <summary> /// 相交点辐射光 /// </summary> /// <param name="point"></param> /// <param name="normal"></param> /// <param name="deep"></param> /// <returns></returns> public virtual Light IntersectLight(Vector3 point, Vector3 dir, Vector3 normal, int deep) { #if RayDebugger SceneDebug Debugger = Scene.debugger; if (Debugger != null) { Debugger.BeginBranch(point); } #endif Light returnlight = default; // 发光体返回发光颜色 if (Material.LightAble) { returnlight = Material.LightColor; goto returnPoint; } // 递归深度极限 if (deep <= 1) { returnlight = Material.BaseColor * 0.3f; goto returnPoint; } dir = Vector3.Normalize(dir); bool IsBackFace = false; if (Vector3.Dot(dir, normal) > 0) // 背面 { IsBackFace = true; normal = -normal; } #region 计算追踪光线总数 int traceRayNum = RenderConfiguration.Configurations.ReflectSmapingLevel - RenderConfiguration.Configurations.RayTraceDeep + deep; { traceRayNum = (int)(traceRayNum * Material.AMetalDegree); if (traceRayNum < 1) { traceRayNum = 1; } traceRayNum = traceRayNum * 3 - 2; } #endregion #region 计算折射光 Light refractl = default; // 折射光 float refractPower = 0.0f; // 折射光强度 if (Material.IsTransparent) { float riindex = Material.RefractiveIndices; if (!IsBackFace) { riindex = 1.0f / riindex; } // 计算折射光线 (float pow, Vector3 rdir) = Tools.Refract(dir, normal, riindex); if (pow < 0) { goto endRefract; } refractPower = pow * Material.TransparentIndex; int raycount = (int)(traceRayNum * refractPower); traceRayNum -= raycount; float randomScale = Material.AMetalDegree * Material.AMetalDegree * 0.5f; //raycount = (int)(traceRayNum * randomScale); //raycount = (int)(traceRayNum * Material.AMetalDegree); if (raycount < 1 && refractPower > 0.00001) { raycount = 1; } if (raycount == 0) { refractl = Material.BaseColor; goto endRefract; } rdir = normal * randomScale + rdir * (1.0f - randomScale); for (int nsmap = 0; nsmap < raycount; nsmap++) { Vector3 raydir = Tools.RandomPointInSphere() * randomScale + rdir; Ray r = new Ray(point, raydir); //Console.WriteLine('\t' + this.Name + " [refract] : " + r); (Light c, float distance) = Scene.Light(r, deep - 1, this); if (IsBackFace) //内部光线,进行吸收计算 { float xsl = Math.Log(distance + 1.0f) + 1.0f; refractl *= Material.BaseColor / xsl; } refractl += c; } refractl /= raycount; } endRefract: #endregion #region 计算反射光 Light reflectl = default; // 反射光 { int raycount = traceRayNum; if (raycount < 1) { if (refractPower < 0.99f) { raycount = 1; } else { reflectl = Material.BaseColor; goto endReflact; } } Vector3 spO; { //Vector3 spRO = Tools.Reflect(dir, normal); Vector3 spRO = Vector3.Reflect(dir, normal); //spO = normal * (1.0f - Material.MetalDegree) + spRO * Material.MetalDegree; spO = Vector3.Lerp(normal, spRO, Material.MetalDegree); } for (int nsmap = 0; nsmap < raycount; nsmap++) { Vector3 tp = Tools.RandomPointInSphere() * Material.AMetalDegree + spO; Vector3 raydir = tp; while (raydir.LengthSquared() < 0.1) { tp = Tools.RandomPointInSphere() + spO; raydir = tp; } Ray r = new Ray(point, raydir); //Console.WriteLine('\t' + this.Name + " [reflact] : " + r); (Light c, float _) = Scene.Light(r, deep - 1, this); //, this); reflectl += c; } reflectl /= raycount; reflectl *= (0.06f * Material.MetalDegree + 0.93f) * Material.BaseColor; } #endregion returnlight = refractl * refractPower + reflectl * (1.0f - refractPower); endReflact: returnPoint: #if RayDebugger if (Debugger != null) { Debugger.EndBranch(); } #endif return(returnlight); }