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 GetShaded2(XorShift64Star random, Scene scene, Vector3 position, Vector3 direction, Vector3 normal) { Vector3 shaded = new Vector3(); float fresnel = Helper.Schlick(normal, direction, 1f, ReflectionIOR); if (Diffuse > 0) { shaded += GetDirectDiffuse(random, scene, position, normal) * (1f - fresnel); shaded += GetIndirectDiffuse2(random, scene, position, normal) * (1f - fresnel); } if (Reflectivity > 0) { shaded += GetReflection2(random, scene, position, direction, normal) * fresnel; } shaded += GetEmissive(direction, normal); return(shaded); }
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); }
public Vector3 GetDirectDiffuse(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal) { Vector3 lightAccumulator = new Vector3(); for (int i = 0; i < scene.SceneLights.Length; i++) { Light l = scene.SceneLights[i]; Vector3 dir = Vector3.Normalize(l.GetPoint(random) - position); if (Vector3.Dot(normal, dir) <= 0) { continue; } Ray r = new Ray(position + dir * 0.002f, dir); Intersection intersection = scene.TraceScene(r); if (!intersection.HitLight) { continue; } Vector3 lightC = l.GetColor(dir) * Vector3.Dot(dir, normal) * l.GetAttenuation(intersection.IntersectionLength, dir); lightAccumulator += Vector3.Multiply(lightC, DiffuseColor * Diffuse); } return(lightAccumulator); }
public Vector3 GetIndirectDiffuse3(XorShift64Star random, Scene scene, Vector3 position, Vector3 normal) { return(GetDirectDiffuse(random, scene, position, normal)); }
public PseudorandomNumberGeneratorsBenchmark() { linearCongruentialRandomNumberGenerator = new LinearCongruentialRandomNumberGenerator(); xOrShift64Star = new XorShift64Star(); xOrShift1024Star = new XorShift1024Star(); }
private static void ColorRay(int index, Ray ray, dFramebuffer framebuffer, dWorldBuffer world, XorShift64Star rng, Camera camera) { Vec3 attenuation = new Vec3(1f, 1f, 1f); Vec3 lighting = new Vec3(); Ray working = ray; bool attenuationHasValue = false; float minT = 0.1f; for (int i = 0; i < camera.maxBounces; i++) { HitRecord rec = GetWorldHit(working, world, minT); if (rec.materialID == -1) { if (i == 0 || attenuationHasValue) { framebuffer.DrawableIDBuffer[index] = -2; } float t = 0.5f * (working.b.y + 1.0f); attenuation *= (1.0f - t) * new Vec3(1.0f, 1.0f, 1.0f) + t * new Vec3(0.5f, 0.7f, 1.0f); break; } else { if (i == 0) { framebuffer.ZBuffer[index] = rec.t; framebuffer.DrawableIDBuffer[index] = rec.drawableID; } ScatterRecord sRec = Scatter(working, rec, rng, world.materials, minT); if (sRec.materialID != -1) { attenuationHasValue = sRec.mirrorSkyLightingFix; attenuation *= sRec.attenuation; working = sRec.scatterRay; } else { framebuffer.DrawableIDBuffer[index] = -1; break; } } for (int j = 0; j < world.lightSphereIDs.Length; j++) { Sphere s = world.spheres[world.lightSphereIDs[j]]; Vec3 lightDir = s.center - rec.p; HitRecord shadowRec = GetWorldHit(new Ray(rec.p, lightDir), world, minT); if (shadowRec.materialID != -1 && (shadowRec.p - rec.p).length() > lightDir.length() - (s.radius * 1.1f)) // the second part of this IF could probably be much more efficent { MaterialData material = world.materials[shadowRec.materialID]; if (material.type != 1) { lightDir = Vec3.unitVector(lightDir); lighting += material.color * XMath.Max(0.0f, Vec3.dot(lightDir, rec.normal)); lighting *= XMath.Pow(XMath.Max(0.0f, Vec3.dot(-Vec3.reflect(rec.normal, -lightDir), ray.b)), material.reflectivity) * material.color; } } } } int rIndex = index * 3; int gIndex = rIndex + 1; int bIndex = rIndex + 2; framebuffer.ColorFrameBuffer[rIndex] = attenuation.x; framebuffer.ColorFrameBuffer[gIndex] = attenuation.y; framebuffer.ColorFrameBuffer[bIndex] = attenuation.z; framebuffer.LightingFrameBuffer[rIndex] = lighting.x; framebuffer.LightingFrameBuffer[gIndex] = lighting.y; framebuffer.LightingFrameBuffer[bIndex] = lighting.z; }
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)); }
//Applies a random detune value based on the current randomness parameter and the max specified detune level. public void ApplyDetuneRandomness() { detune_current = Tools.Lerp(_detune, 1.0, (XorShift64Star.NextDouble()) * detune_randomness); }