public override bool Render() { // Render scene var o = new Vector3F(0.0f, 0.0f, -5.0f); // Initialize timer var msecs = Environment.TickCount; // Render remaining lines for (var lineY = _currLine; lineY < (Height); lineY++) { _sx = _worldX1; // Render pixels for current line for (var lineX = 0; lineX < Width; lineX++) { // Fire primary ray var dir = new Vector3F(_sx, _sy, 0.0f) - o; dir.Normalize(); var r = new Ray(o, dir); var acc = Raytrace(r, 1); var red = (int)(acc.X * 256); var green = (int)(acc.Y * 256); var blue = (int)(acc.Z * 256); if (red > 255) red = 255; if (green > 255) green = 255; if (blue > 255) blue = 255; PixelBuffer[_pPos++] = (uint)((red << 16) + (green << 8) + blue); _sx += _deltaX; } _sy += _deltaY; // See if we've been working to long already if ((Environment.TickCount - msecs) > 100) { // return control to windows so the screen gets updated _currLine = lineY + 1; return false; } } // all done return true; }
public override IntersectionResult Intersect(Ray ray, ref float refDistance) { var tMin = float.NegativeInfinity; var tMax = float.PositiveInfinity; for (var i = 0; i < 3; i++) { var t1 = (Min[i] - ray.Origin[i]) / ray.Direction[i]; var t2 = (Max[i] - ray.Origin[i]) / ray.Direction[i]; tMin = Math.Max(tMin, Math.Min(t1, t2)); tMax = Math.Min(tMax, Math.Max(t1, t2)); } if (tMax >= tMin && tMax >= 0) return IntersectionResult.Hit; return IntersectionResult.Miss; }
public override IntersectionResult Intersect(Ray ray, ref float refDistance) { var d = Vector3F.Dot(Normal, ray.Direction); if (Math.Abs(d) > Tolerance) { var distance = -(Vector3F.Dot(Normal, ray.Origin) + Distance) / d; if (distance > 0.0f) { if (distance < refDistance) { refDistance = distance; return IntersectionResult.Hit; } } } return IntersectionResult.Miss; }
public override IntersectionResult Intersect(Ray ray, ref float distance) { var vector = ray.Origin - Center; var b = -Vector3F.Dot(vector, ray.Direction); var det = (b * b) - Vector3F.Dot(vector, vector) + SquareRadius; var returnValue = IntersectionResult.Miss; if (det > 0) { det = (float)Math.Sqrt(det); var i1 = b - det; var i2 = b + det; if (i2 > 0.0f) { if (i1 < 0.0f) { if (i2 < distance) { distance = i2; returnValue = IntersectionResult.InPrimitive; } } else { if (i1 < distance) { distance = i1; returnValue = IntersectionResult.Hit; } } } } return returnValue; }
protected override Color Raytrace(Ray ray, int depth) { var distance = MaxDistance; var acc = Color.Black; // Trace primary ray Primitive primitive = null; if (depth > MaxDepth) return Color.Black; foreach (var currentPrimitive in Scene.Primitives) { var res = currentPrimitive.Intersect(ray, ref distance); if (res != 0) { primitive = currentPrimitive; } } // No hit, terminate ray if (primitive == null) return Color.Black; // Handle intersection if (primitive.IsLight) { // We hit a light, stop tracing return Color.White; } // Determine color at point of intersection var intersectionPoint = ray.Origin + ray.Direction * distance; // Trace lights foreach (var currentPrimitive in Scene.Primitives.Where(x => x.IsLight)) { var light = currentPrimitive; // Calculate diffuse shading; var lightSource = ((SpherePrimitive)light).Center - intersectionPoint; lightSource.Normalize(); var normal = primitive.GetNormal(intersectionPoint); if (primitive.Material.Diffuse > 0) { // Check for normals facing away from the light (dot < 0) var dot = normal.Dot(lightSource); if (dot > 0) { var diff = dot * primitive.Material.Diffuse; // Add diffuse component to ray color acc += diff * primitive.Material.Color * light.Material.Color; } } } // Calculate reflection var reflection = primitive.Material.Reflection; if (reflection > 0.0f) { var normal = primitive.GetNormal(intersectionPoint); var r = ray.Direction - 2.0f * ray.Direction.Dot(normal) * normal; if (depth < MaxDepth) { var newRay = new Ray(intersectionPoint + r * Epsilon, r); var reflectionColor = Raytrace(newRay, depth + 1); acc += reflection * reflectionColor * primitive.Material.Color; } } return acc; }
protected override Color Raytrace(Ray ray, int depth) { var distance = MaxDistance; // Depth too high, terminate ray if (depth >= MaxDepth) return Color.Black; Primitive primitive = null; foreach (var currentPrimitive in Scene.Primitives) { var res = currentPrimitive.Intersect(ray, ref distance); if (res != 0) { primitive = currentPrimitive; } } // No hit, terminate ray if (primitive == null) return Color.Black; if (primitive.IsLight) return Color.White; var material = primitive.Material; var emittance = material.Color; var intersectionPoint = ray.Origin + ray.Direction * distance; var direction = primitive.GetNormal(intersectionPoint) + new Vector3F((float)_random.NextDouble()); var newRay = new Ray(intersectionPoint, direction); var cosTheta = newRay.Direction.Dot(intersectionPoint); var brdf = 2 * material.Reflection * cosTheta; var reflected = Raytrace(newRay, depth + 1); return emittance + (brdf * reflected); }