public static bool Plane(Plane p, Ray3f r, float tMin, float tMax, out HitRecord hit) { hit = new HitRecord(); const float eps = 0.0001f; if (math.abs(math.dot(r.direction, p.Normal)) > eps) { float t = math.dot((p.Center - r.origin), p.Normal) / math.dot(r.direction, p.Normal); if (t > eps) { hit.t = t; hit.point = PointOnRay(r, t); hit.normal = p.Normal; return(true); } } return(false); }
// Todo: optimize by splitting the below into boolean intersection funct, and then: // dist field // color field // normal field // material field // evaluating those for all the intermediate steps is useless // basically: https://www.shadertoy.com/view/ldl3zN IQ piano private static bool IntersectField(Ray3f r, Scene scene, short maxStep, float maxDist, out HitRecord hit) { hit = new HitRecord(); const float eps = 0.001f; float3 p = r.origin; float totalDist = 0; for (int d = 0; d < maxStep; d++) { float dist = 99999f; float3 normal = new float3(0, 0, 1); Material material = new Material(); HitSphere(p, ref dist, ref normal, ref material); HitSpheres(p, ref dist, ref normal, ref material); HitFloor(p, ref dist, ref normal, ref material); if (dist <= eps) { hit.point = p; hit.normal = normal; hit.material = material; hit.t = totalDist; return(true); } totalDist += dist; p += r.direction * dist; } return(false); }
public static bool Scatter(Ray3f ray, HitRecord hit, ref Random rng, NativeArray <float3> fibs, out Ray3f scattered) { const float epsEscape = 0.002f; const float refIdx = 1.5f; switch (hit.material.Type) { case MaterialType.Dielectric: { float3 outwardNormal; float nint; float3 reflected = math.reflect(ray.direction, hit.normal); float cosine; if (math.dot(ray.direction, hit.normal) > 0f) { outwardNormal = -hit.normal; nint = refIdx; cosine = refIdx * math.dot(ray.direction, hit.normal); } else { outwardNormal = hit.normal; nint = 1f / refIdx; cosine = -math.dot(ray.direction, hit.normal); } float reflectProb = 1f; float3 refracted; if (Trace.Refract(ray.direction, outwardNormal, nint, out refracted)) { reflectProb = Trace.Schlick(cosine, refIdx); } bool reflect = rng.NextFloat() < reflectProb; scattered = new Ray3f( reflect ? hit.point + outwardNormal * epsEscape : hit.point - outwardNormal * epsEscape, reflect ? reflected : refracted ); return(true); } case MaterialType.Metal: { float3 transmitted = math.reflect(ray.direction, hit.normal); transmitted += fibs[rng.NextInt(0, fibs.Length - 1)] * hit.material.Fuzz; transmitted = math.normalize(transmitted); scattered = new Ray3f(hit.point + hit.normal * epsEscape, transmitted); if (math.dot(scattered.direction, hit.normal) > 0) { return(true); } return(false); } case MaterialType.Lambertian: default: { float3 target = hit.normal + fibs[rng.NextInt(0, fibs.Length - 1)]; float3 transmitted = math.normalize(target - hit.point); scattered = new Ray3f(hit.point + hit.normal * epsEscape, transmitted); return(true); } } }