public static void Kernel(Index2 index, ArrayView2D <Vector3> dataView, Scene scene, ArrayView <Geometry> sceneGeometry, ArrayView <Light> sceneLights, int seed) { Vector3 outputColor = Vector3.Zero; scene.SceneGeometry = sceneGeometry; scene.SceneLights = sceneLights; //Models.Random random = new Models.Random((uint) (index.X * index.Y + seed)); XorShift64Star random = new XorShift64Star((ulong)index.X + (ulong)scene.Camera.ScreenWidth * (ulong)index.Y + (ulong)seed); float xOffset = random.NextFloat(); random.NextFloat(); float yOffset = random.NextFloat(); Ray ray = scene.Camera.GetRaySimple(index.X + (xOffset * 2f - 1f) * 0.5f, index.Y + (yOffset * 2f - 1f) * 0.5f); Intersection intersection = scene.TraceScene(ray); if (intersection.Hit) { outputColor = intersection.HitObject.Material.GetShaded(random, scene, intersection.HitPosition, ray.Direction, intersection.HitNormal); } else if (intersection.HitLight) { outputColor = intersection.HitLightObject.GetColor(ray.Direction); } dataView[index] += outputColor; }
private static Vec3 RandomUnitVector(XorShift64Star rng) { float a = 2f * XMath.PI * rng.NextFloat(); float z = (rng.NextFloat() * 2f) - 1f; float r = XMath.Sqrt(1f - z * z); return(new Vec3(r * XMath.Cos(a), r * XMath.Sin(a), z)); }
public static Vector3 PointOnHemisphere(this XorShift64Star random, Vector3 n) { float azimuthal = random.NextFloat() * XMath.PI * 2f; float z = random.NextFloat(); float xyproj = XMath.Sqrt(1 - z * z); Vector3 v = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z); if (Vector3.Dot(v, n) < 0) { return(v * -1); } else { return(v); } }
public Vector3 GetReflection2(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction, Vector3 normal) { float roughness = 0.01f; Vector3 accu = Vector3.Zero; for (int i = 0; i < 2; i++) { random.NextFloat(); Vector3 microfacetNormal = Helper.GetGGXMicrofacet(random, roughness, normal); Vector3 reflectedDir = Vector3.Reflect(direction, microfacetNormal); Ray r = new Ray(position + reflectedDir * 0.002f, reflectedDir); Intersection intersection = scene.TraceScene(r); if (!intersection.Hit) { continue; } Material mat = intersection.HitObject.Material; Vector3 reflectionColor = mat.GetShaded3(random, scene, intersection.HitPosition, reflectedDir, intersection.HitNormal); accu += reflectionColor; } return(accu / 2f); }
public Vector3 GetDirectReflection(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction, Vector3 normal) { float roughness = 0.01f; Vector3 lightAccumulator = new Vector3(); for (int i = 0; i < scene.SceneLights.Length; i++) { random.NextFloat(); Light l = scene.SceneLights[i]; Vector3 ldir = l.GetPoint(random) - position; ldir /= XMath.Sqrt(Vector3.Dot(ldir, ldir)); Ray r = new Ray(position + ldir * 0.002f, ldir); Intersection intersection = scene.TraceScene(r); if (!intersection.HitLight) { continue; } float probability = Helper.ggxNormalDistribution(Vector3.Dot(Vector3.Reflect(-ldir, normal), -direction), roughness); Vector3 reflectionColor = intersection.HitLightObject.GetColor(ldir); lightAccumulator += reflectionColor * probability; } return(lightAccumulator); }
public static Vector3 GetGGXMicrofacet(XorShift64Star random, float roughness, Vector3 normal) { float rand1 = random.NextFloat(); float rand2 = random.NextFloat(); Vector3 B = GetPerpendicularVector(normal); Vector3 T = Vector3.Cross(B, normal); float a2 = roughness * roughness; float cosThetaH = XMath.Sqrt(XMath.Max(0f, (1f - rand1) / ((a2 - 1f) * rand1 + 1f))); float sinThetaH = XMath.Sqrt(XMath.Max(0f, 1f - cosThetaH * cosThetaH)); float phiH = rand2 * XMath.PI * 2f; return(T * (sinThetaH * XMath.Cos(phiH)) + B * (sinThetaH * XMath.Sin(phiH)) + normal * cosThetaH); }
public static void RenderKernel(Index2 id, dFramebuffer framebuffer, dWorldBuffer world, Camera camera, int rngOffset) { int x = id.X; int y = id.Y; int index = ((y * camera.width) + x); //there is probably a better way to do this, but it seems to work. seed = the tick * a large prime xor (index + 1) * even larger prime XorShift64Star rng = new XorShift64Star((((ulong)(rngOffset + 1) * 3727177) ^ ((ulong)(index + 1) * 113013596393))); //XorShift64Star rng = new XorShift64Star(); Ray ray = camera.GetRay(x + rng.NextFloat(), y + rng.NextFloat()); ColorRay(index, ray, framebuffer, world, rng, camera); }
public Vector3 GetIndirectDiffuse2(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal) { Vector3 lightAccumulator = new Vector3(); int samples = 4; for (int i = 0; i < samples; i++) { float azimuthal = random.NextFloat() * XMath.PI * 2f; float z = random.NextFloat(); float xyproj = XMath.Sqrt(1 - z * z); Vector3 dir = new Vector3(xyproj * XMath.Cos(azimuthal), xyproj * XMath.Sin(azimuthal), z); if (Vector3.Dot(dir, normal) < 0) { dir *= -1; } Ray ray = new Ray(position + dir * 0.002f, dir); Intersection intersection = scene.TraceScene(ray); if (!intersection.Hit && !intersection.HitLight) { lightAccumulator += Vector3.Multiply(scene.SkylightColor * scene.SkylightBrightness * Vector3.Dot(dir, normal), DiffuseColor) * Diffuse; continue; } else if (!intersection.Hit || intersection.HitLight) { continue; } Material hitMaterial = intersection.HitObject.Material; Vector3 lightC = hitMaterial.GetShaded3(random, scene, intersection.HitPosition, dir, intersection.HitNormal); lightC *= Vector3.Dot(dir, normal); lightAccumulator += Vector3.Multiply(lightC, DiffuseColor) * Diffuse; } lightAccumulator /= (float)samples; return(lightAccumulator); }
private static ScatterRecord Scatter(Ray r, HitRecord rec, XorShift64Star rng, ArrayView <MaterialData> materials, float minT) { MaterialData material = materials[rec.materialID]; Ray ray; Vec3 outward_normal; Vec3 refracted; Vec3 reflected; float ni_over_nt; float cosine; if (material.type == 0) //Diffuse { refracted = rec.p + rec.normal + RandomUnitVector(rng); return(new ScatterRecord(rec.materialID, new Ray(rec.p, refracted - rec.p), material.color, false)); } else if (material.type == 1) // dielectric { if (Vec3.dot(r.b, rec.normal) > minT) { outward_normal = -rec.normal; ni_over_nt = material.ref_idx; cosine = Vec3.dot(r.b, rec.normal); cosine = XMath.Sqrt(1.0f - material.ref_idx * material.ref_idx * (1f - cosine * cosine)); } else { outward_normal = rec.normal; ni_over_nt = 1.0f / material.ref_idx; cosine = -Vec3.dot(r.b, rec.normal); } //moved the refract code here because I need the if (discriminant > 0) check float dt = Vec3.dot(r.b, outward_normal); float discriminant = 1.0f - ni_over_nt * ni_over_nt * (1f - dt * dt); if (discriminant > minT) { if (rng.NextFloat() < schlick(cosine, material.ref_idx)) { return(new ScatterRecord(rec.materialID, new Ray(rec.p, Vec3.reflect(rec.normal, r.b)), material.color, true)); } else { return(new ScatterRecord(rec.materialID, new Ray(rec.p, ni_over_nt * (r.b - (outward_normal * dt)) - outward_normal * XMath.Sqrt(discriminant)), material.color, true)); } } else { return(new ScatterRecord(rec.materialID, new Ray(rec.p, Vec3.reflect(rec.normal, r.b)), material.color, true)); } } else if (material.type == 2) //Metal { reflected = Vec3.reflect(rec.normal, r.b); if (material.reflectionConeAngleRadians > minT) { ray = new Ray(rec.p, reflected + (material.reflectionConeAngleRadians * RandomUnitVector(rng))); } else { ray = new Ray(rec.p, reflected); } if ((Vec3.dot(ray.b, rec.normal) > minT)) { return(new ScatterRecord(rec.materialID, ray, material.color, true)); } } else if (material.type == 3) //Lights { refracted = rec.p + rec.normal; return(new ScatterRecord(rec.materialID, new Ray(rec.p, refracted - rec.p), material.color, false)); } return(new ScatterRecord(-1, r, new Vec3(), true)); }