public (bool, HitRecord) Hit(Ray ray, double tmin, double tmax) { bool anyHits = false; var closestOne = tmax; HitRecord result = new HitRecord(); foreach (var hittable in this) { var(hit, temp) = hittable.Hit(ray, tmin, closestOne); if (hit) { anyHits = true; closestOne = temp.T; result = temp; } } return(anyHits, result); }
public override bool Scatter(Scene scene, Ray ray, HitRecord hit, out Attenuation attenuation, out Ray scattered) { var direction = Vector3.Normalize(ray.direction); Vector3 reflected = Vector3.Reflect(direction, hit.normal); scattered = new Ray(hit.position, reflected + fuzz * Sphere.RandomInUnitSphere()); Vector3 diffuseColor = Vector3.Zero; Vector3 SpecularColor = Vector3.Zero; foreach (var light in scene.lights) { if (CastShadow(scene, light, hit)) { continue; } Vector3 lightDir = -Vector3.Normalize(hit.position - light.position); Vector3 reflectDir = Vector3.Reflect(-lightDir, hit.normal); diffuseColor += light.color * light.insensity * Vector3.Dot(hit.normal, lightDir); SpecularColor += light.color * light.insensity * specularIndex * MathF.Pow(Math.Clamp(Vector3.Dot(reflectDir, -direction), 0, 1), glossIndex); } //环境光 + 光源 var textureColor = GetTextureColor(hit.uv); var allColor = (scene.ambientColor + diffuseColor) * albedo * textureColor + SpecularColor; attenuation = Attenuation.Blend(allColor, blendPercent, albedo * textureColor); attenuation.attenuationType = attenuationType; //兼容easyPipeline if (fuzz == 0 && specularIndex == 1) { attenuation.forceToDoAnotherPass = true; } //attenuation = Attenuation.None(new Vector3(hit.uv.X, hit.uv.Y,0)); return(true);//(Vector3.Dot(scattered.direction, hit.normal) > 0); }
public override bool Hit(Ray ray, float tMin, float tMax, out HitRecord rec) { rec = null; bool hitAnything = false; float closestSoFar = tMax; foreach (var ob in fragments) { if (ob.Hit(ray, tMin, tMax, out HitRecord recTemp)) { hitAnything = true; if (closestSoFar > recTemp.t) { closestSoFar = recTemp.t; rec = recTemp; } } } return(hitAnything); }
public bool Hit(Ray ray, out HitRecord rec, float tMin = 0.001f, float tMax = 10000) { rec = null; bool hitAnything = false; float closestSoFar = tMax; foreach (var ob in hitableObjects) { if (ob.Hit(ray, tMin, tMax, out HitRecord recTemp)) { hitAnything = true; if (closestSoFar > recTemp.t) { closestSoFar = recTemp.t; rec = recTemp; } } } return(hitAnything); }
private Color32 Diffusing(Ray ray, HitableList hitableList, int depth) { var record = new HitRecord(); if (hitableList.Hit(ray, 0.0001f, float.MaxValue, ref record)) { var r = new Ray(Vector3.zero, Vector3.zero); var attenuation = Color32.black; if (depth < MAX_SCATTER_TIME && record.material.scatter(ray, record, ref attenuation, ref r)) { var c = Diffusing(r, hitableList, depth + 1); return(new Color32(c.r * attenuation.r, c.g * attenuation.g, c.b * attenuation.b)); } else { return(Color32.black); } } var t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color32(1, 1, 1) + t * new Color32(0.5f, 0.7f, 1)); }
public (bool isHit, HitRecord hitDetail) Hit(Ray ray, double tmin, double tmax) { var oc = ray.Origin - _center; var a = ray.Direction.LengthSquared(); var halfB = Vector.Dot(oc, ray.Direction); var c = oc.LengthSquared() - _radius * _radius; var discriminant = halfB * halfB - a * c; if (discriminant < 0) { return(false, new HitRecord()); } var sqrtd = Math.Sqrt(discriminant); var root = (-halfB - sqrtd) / a; if (root < tmin || tmax < root) { root = (-halfB + sqrtd) / a; if (root < tmin || tmax < root) { return(false, new HitRecord()); } } var hit = new HitRecord(); hit.T = root; hit = GetHitPoint(ray, hit); var outwardNormal = (hit.Point - _center) / _radius; hit.SetFaceNormal(ray, outwardNormal); return(true, hit); }
public abstract bool Scatter(ref Ray ray, ref HitRecord hit, out Vector3 attenuation, out Ray scattered);
public abstract bool Hit(Ray r, float tMin, float tMax, out HitRecord rec);
public override bool Hit(Ray r, float tMin, float tMax, out HitRecord rec) { //Plane plane = Plane.CreateFromVertices(points[0], points[1], points[2]); var normal = Vector3.Normalize(Vector3.Cross((points[0] - points[1]), (points[1] - points[2]))); r.direction = Vector3.Normalize(r.direction); rec = new HitRecord(); //面片背面剔除 var cos = Vector3.Dot(r.direction, normal); if (cos == 0) { return(false); } if (cullBack && cos < 0) { return(false); } //计算t(距离) rec.t = Vector3.Dot(points[0] - r.from, normal) / Vector3.Dot(r.direction, normal); //rec.t = (Vector3.Dot(normal,points[0]) - Vector3.Dot(normal, r.from) )/ Vector3.Dot(normal,r.direction ); if (float.IsNaN(rec.t) || rec.t < tMin || rec.t > tMax) { return(false); } //计算p(平面交点) var p = r.from + rec.t * r.direction; //光栅剔除 points.Add(points[0]); Vector3 firstTowards = Vector3.Zero; for (int i = 0; i < points.Count - 1; i++) { var oa = Vector3.Normalize(points[i] - points[i + 1]); var op = Vector3.Normalize(points[i] - p); var towards = Vector3.Normalize(Vector3.Cross(oa, op)); if (firstTowards == Vector3.Zero) { firstTowards = towards; } else if (Vector3.Dot(firstTowards, towards) < 0.999999) { points.RemoveAt(points.Count - 1); return(false); } } points.RemoveAt(points.Count - 1); rec.position = p; //是否有normal记录 if (normals.Count == points.Count) { if (uvs.Count == 3) { rec.normal = GetAvgNormalInTriangle(p); } else { rec.normal = GetAvgNormal(p); } } else { rec.normal = normal; } //是否有uv记录 if (uvs.Count == points.Count) { if (uvs.Count == 3) { rec.uv = GetAvgUVInTriangle(p); } else { rec.uv = GetAvgUV(p); } } rec.material = material; return(true); }
public abstract bool Scatter(Scene scene, Ray ray, HitRecord hit, out Attenuation attenuation, out Ray scattered);