public override bool Hit(RayTrace.Ray ray, float t_min, float t_max, ref HitRecord rec) { var oc = ray.origin - center; float a = Vector3.Dot(ray.direction, ray.direction); float b = 2f * Vector3.Dot(oc, ray.direction); float c = Vector3.Dot(oc, oc) - radius * radius; float discriminant = b * b - 4 * a * c; if (discriminant > 0) { float temp = (-b - Mathf.Sqrt(discriminant)) / a * 0.5f; if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = ray.GetPoint(rec.t); rec.normal = (rec.p - center).normalized; rec.material = material; return(true); } temp = (-b + Mathf.Sqrt(discriminant)) / a * 0.5f; if (temp < t_max && temp > t_min) { rec.t = temp; rec.p = ray.GetPoint(rec.t); rec.normal = (rec.p - center).normalized; rec.material = material; return(true); } } return(false); }
Color GetLightPathColor(Vector3 pos, Vector3 dir, float length) { RayTrace.Ray ray = new RayTrace.Ray(pos, dir, length); RayTrace.Intersect(ref ray); if (ray.geomID == RayTrace.Invalid) { return(Color.white); } else { SimpleModel model = scene.models[(int)ray.geomID]; SimpleMesh mesh = model.mesh; int t0 = mesh.triangles[ray.primID * 3 + 0]; int t1 = mesh.triangles[ray.primID * 3 + 1]; int t2 = mesh.triangles[ray.primID * 3 + 2]; Vector2 uv = RayTraceTool.Lerp(mesh.uv[t0], mesh.uv[t1], mesh.uv[t2], ray.u, ray.v); Vector3 hitPos = ray.pos + ray.dir * ray.length; Color texColor = model.material.PointSample(uv); if (texColor.a < 0.99f) { Color aheadColor = GetLightPathColor(hitPos, dir * 0.01f, length - ray.length); Color blendColor = (aheadColor * (1 - texColor.a)) + (texColor * texColor.a); return(blendColor); } } return(Color.black); }
static bool IsRayCastSphere(Ray ray, Vector3 sphereOrigin, float radiu) { Vector3 oc = ray.direction - sphereOrigin; float a = Vector3.Dot(ray.direction, ray.direction); float b = 2f * Vector3.Dot(ray.direction, oc); float c = Vector3.Dot(oc, oc) - radiu * radiu; float delta = b * b - 4 * a * c; return(delta > 0); }
static Color GetSkyColorFronRay(Ray ray) { if (IsRayCastSphere(ray, new Vector3(0f, 0f, -1f), .5f)) { return(Color.red); } float y = (ray.direction.y + 1) / 2; return((1 - y) * new Color(1, 1, 1) + new Color(0.5f, 0.7f, 1.0f)); }
static Color GetColorForTestNormal(Ray ray) { float t = HitSphereForTestNormal(new Vector3(0, 0, -1), 0.5f, ray); if (t > 0) { Vector3 normal = Vector3.Normalize(ray.GetPoint(t) - new Vector3(0, 0, -1)); return(0.5f * new Color(normal.x + 1, normal.y + 1, normal.z + 1, 2f)); } t = 0.5f * ray.normalDirection.y + 1f; return((1 - t) * new Color(1, 1, 1) + t * new Color(0.5f, 0.7f, 1)); }
private static Color GetColorFromScene(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, 1f)); } float t = (ray.direction.y + 1) * .5f; return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f)); }
private static 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 + GetRandomDir(); return(0.5f * GetColorForTestDiffusing(new Ray(record.p, target - record.p), hitableList)); } float t = (ray.direction.y + 1) * .5f; return((1 - t) * Color.white + new Color(0.5f, 0.7f, 1.0f)); }
public override bool Hit(Ray ray, float t_min, float t_max, ref HitRecord hit) { HitRecord tempRecord = new HitRecord(); bool hitted = false; float closest = t_max; for (int i = 0; i < this.hitLists.Count; i++) { if (this.hitLists[i].Hit(ray, t_min, closest, ref tempRecord)) { hit = tempRecord; closest = tempRecord.t; hitted = true; } } return(hitted); }
static float HitSphereForTestNormal(Vector3 center, float radius, Ray ray) { var oc = ray.origin - center; float a = Vector3.Dot(ray.direction, ray.direction); float b = 2f * Vector3.Dot(oc, ray.direction); float c = Vector3.Dot(oc, oc) - radius * radius; //实际上是判断这个方程有没有根,如果有2个根就是击中 float discriminant = b * b - 4 * a * c; if (discriminant < 0) { return(-1); } else { //返回距离最近的那个根 return((-b - Mathf.Sqrt(discriminant)) / (2f * a)); } }
public static Color[] MakeColors() { int WIDTH = CreatPNG.WIDTH; int HEIGHT = CreatPNG.HEIGHT; int total = WIDTH * HEIGHT; Color[] colors = new Color[total]; Vector3 origin = Vector3.zero; Vector3 horizontal = new Vector3(4, 0, 0); Vector3 vertical = new Vector3(0, 2, 0); Vector3 leftDownCorner = new Vector3(-2, -1, -1); HitableList hitableList = new HitableList(); hitableList.AddHitable(new HitableSphere(new Vector3(0, 0, -1), 0.5f, null)); hitableList.AddHitable(new HitableSphere(new Vector3(0, -100.5f, -1), 100f, null)); for (int i = HEIGHT - 1; i >= 0; i--) { for (int j = 0; j < WIDTH; j++) { Ray ray = new Ray(origin, leftDownCorner + horizontal * ((j + Random.Range(0, 1)) / (float)WIDTH) + vertical * ((i + Random.Range(0, 1)) / (float)HEIGHT)); Color newColor = Color.black; for (int k = 0; k < SAMPLETIMES; k++) { newColor += GetColorForTestDiffusing(ray, hitableList); } colors[j + i * WIDTH] = newColor / SAMPLETIMES; colors[j + i * WIDTH].a = 1; Color temp = colors[j + i * WIDTH]; colors[j + i * WIDTH] = new Color(Mathf.Pow(temp.r, 1 / 2.2f), Mathf.Pow(temp.g, 1 / 2.2f), Mathf.Pow(temp.b, 1 / 2.2f)); } } return(colors); }
public abstract bool Hit(Ray ray, float t_min, float t_max, ref HitRecord hit);
public static extern void Intersect(ref RayTrace.Ray ray);
Color TraceColor(Vector3 startPos, Vector3 rayDir, int sample, int depth) { if (depth <= 0) { return(Color.black); } RayTrace.Ray ray = new RayTrace.Ray(startPos, rayDir, 1000); RayTrace.Intersect(ref ray); if (ray.geomID == RayTrace.Invalid) { return(skyColor); } else { SimpleModel model = scene.models[(int)ray.geomID]; SimpleMesh mesh = model.mesh; int t0 = mesh.triangles[ray.primID * 3 + 0]; int t1 = mesh.triangles[ray.primID * 3 + 1]; int t2 = mesh.triangles[ray.primID * 3 + 2]; Vector2 uv = RayTraceTool.Lerp(mesh.uv[t0], mesh.uv[t1], mesh.uv[t2], ray.u, ray.v); Color texColor = model.material.LinearSample(uv); if (!ignoreMaterialColor) { texColor *= model.material.GetColor(); } if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Opaque) { texColor.a = 1; } Vector3 hitPos = ray.pos + ray.dir * ray.length; Vector3 hitNormal = RayTraceTool.Lerp(mesh.normals[t0], mesh.normals[t1], mesh.normals[t2], ray.u, ray.v); hitNormal = (model.rst.rot * hitNormal); float transFactor = 1 - texColor.a; float glossiness = model.material.glossiness; float reflectFactor = Mathf.Lerp(0.2f * glossiness, 1f, model.material.metallic); if (reflectFactor > 0.01f) { reflectFactor = Fresnel_Schlick(Vector3.Dot(-rayDir, hitNormal), reflectFactor); } float grayscale = texColor.grayscale; float diffuseFactor = Mathf.Clamp01(1 - transFactor - reflectFactor); int transSample = (int)(sample * grayscale * transFactor); int reflectSample = (int)(sample * reflectFactor); int diffuseSample = (int)(sample * grayscale * diffuseFactor); Color finaleColor = Color.black; Color reflectColor = Color.black; { Color finalLightColor = Color.black;// GetAllLightsColor(model, hitPos, hitNormal) * (reflectFactor + scene.lights.Length);//光源直接贡献 if (reflectSample > 0) { Vector3 reflectDir = Vector3.Reflect(rayDir, hitNormal); Vector3[] dirs = RayTraceTool.GetRandomDirs_BlinnPhong_Importance2(hitNormal, reflectDir, glossiness, reflectSample); for (int i = 0; i < reflectSample; i++) { finalLightColor += TraceColor(hitPos + hitNormal * 0.01f, dirs[i], 1, depth - 1);//间接光贡献 } finalLightColor /= (reflectSample); } reflectColor = Color.Lerp(Color.white, texColor, model.material.metallic) * finalLightColor; } Color diffuseColor = Color.black; { Color finalLightColor = GetAllLightsColor(model, hitPos, hitNormal) * (diffuseSample + scene.lights.Length);//光源直接贡献 if (diffuseSample > 0) { Vector3 reflectDir = Vector3.Reflect(rayDir, hitNormal); Vector3[] dirs = RayTraceTool.GetRandomDirs_RoundProj(hitNormal, diffuseSample); for (int i = 0; i < diffuseSample; i++) { finalLightColor += TraceColor(hitPos + hitNormal * 0.01f, dirs[i], 1, depth - 1);//间接光贡献 } } finalLightColor /= (diffuseSample + scene.lights.Length); diffuseColor = texColor * finalLightColor; } //Color reflectColor = Color.black; //if(reflectFactor > 0.01f){ // Vector3 refDir = Vector3.Reflect(rayDir,hitNormal); // Color finalLightColor = TraceColor(hitPos + refDir * 0.01f, refDir,reflectSample ,depth - 1); // reflectColor = finalLightColor; //} finaleColor = reflectColor * reflectFactor + diffuseColor * diffuseFactor; if (texColor.a < 0.99f) { Color transColor = TraceColor(hitPos + rayDir * 0.01f, rayDir, transSample, depth); if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Alphablend) { finaleColor = finaleColor * texColor.a + transColor * (1 - texColor.a); } else if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Multiply) { finaleColor = finaleColor * transColor; } else if (model.material.GetRenderMode() == SimpleMaterial.RenderMode.Additive) { finaleColor = finaleColor + transColor; } } return(finaleColor); } }