static void Main(string[] args) { RayObjects = new List<SLRayPrimitive>(); Lights = new List<SLLight>(); ReadScene("scene.urt"); dir = EYE - SPOT; right = UP.Cross(dir); right.Normalize(); screenCenter = dir.Cross(right); screenV = screenCenter * (float)Math.Tan(FOVY * 0.5f); screenU = right * screenV.Magnitude() * ASPECT; WIDTH_DIV_2 = ImageWidth / 2; HEIGHT_DIV_2 = ImageHeight / 2; random = new Random(01478650229); Bitmap outputImage = new Bitmap(ImageWidth, ImageHeight); // add some objects float distance = 20.0f; float offset = distance / 2.0f; for (int i = 0; i < 5; i++) { float x = (float)(random.NextDouble() * distance) - offset; float y = (float)(random.NextDouble() * distance) - offset; float z = (float)(random.NextDouble() * 10.0f + 2.0f); Color c = Color.FromArgb(255, random.Next(255), random.Next(255), random.Next(255)); SLSphere s = new SLSphere(new SLVector3f(x, y, z), (float)(random.NextDouble() + 0.5), c); RayObjects.Add(s); } int dotPeriod = ImageHeight / 10; Stopwatch stopwatch = new Stopwatch(); System.Console.WriteLine("Rendering...\n"); System.Console.WriteLine("|0%---100%|"); stopwatch.Start(); for (int j = 0; j < ImageHeight; j++) { if ((j % dotPeriod) == 0) System.Console.Write("*"); for (int i = 0; i < ImageWidth; i++) { // Go through each pixel to get the color Color c = Render(i, j); outputImage.SetPixel(i, j, c); } } stopwatch.Stop(); TimeSpan ts = stopwatch.Elapsed; string output = ts.Minutes.ToString() + "_" + ts.Seconds.ToString() + ".png"; outputImage.Save(output); }
static Color SetPixelColor(SLRay ray, int depth) { // Get closest intersection IF ANY GetClosestIntersection(ref ray); // Return if the ray didn't hit anything if (ray.ClosestPointDistance >= SLRay.Max_Distance || ray.ClosestPrimitive == null) return BG_COLOR; // Set ambient light float r = LaR * ray.ClosestPrimitive.PrimitiveColor.R; float g = LaG * ray.ClosestPrimitive.PrimitiveColor.G; float b = LaB * ray.ClosestPrimitive.PrimitiveColor.B; // Add contributions of each light SLVector3f normal = ray.ClosestPrimitive.PointNormal(ray.ClosestPoint); SLVector3f viewDir = -ray.Direction; foreach (SLLight light in Lights) { SLVector3f lightDir = new SLVector3f(); float lightDistance; // Find light direction and distance lightDir = light.position - ray.ClosestPoint; lightDistance = lightDir.Magnitude(); lightDir.Normalize(); SLRay pointToLight = new SLRay(ray.ClosestPoint + (lightDir * TINY), lightDir); pointToLight.ClosestPointDistance = lightDistance; GetClosestIntersection(ref pointToLight); if (pointToLight.ClosestPrimitive != null) continue; // DIFFUSE LIGHTING float lDotN = normal.Dot(lightDir); // Clamp if (lDotN <= 0) continue; float diffColorContrR = (light.color.R * lDotN)/255.0f; float diffColorContrG = (light.color.G * lDotN)/ 255.0f; float diffColorContrB = (light.color.B * lDotN)/ 255.0f; // Add this light's diffuse contribution to our running totals r += diffColorContrR * ray.ClosestPrimitive.PrimitiveColor.R; g += diffColorContrG * ray.ClosestPrimitive.PrimitiveColor.G; b += diffColorContrB * ray.ClosestPrimitive.PrimitiveColor.B; if (MATERIAL_SPECULAR_COEFFICIENT > TINY) { // Specular component - dot product of light's reflection vector and viewer direction // Direction to the viewer is simply negative of the ray direction SLVector3f lightReflectionDir = normal * (lDotN * 2) - lightDir; float specularFactor = viewDir.Dot(lightReflectionDir); if (specularFactor > 0) { // To get smaller, sharper highlights we raise it to a power and multiply it specularFactor = MATERIAL_SPECULAR_COEFFICIENT * (float)Math.Pow(specularFactor, MATERIAL_SPECULAR_POWER); // Add the specular contribution to our running totals r += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.R; g += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.G; b += MATERIAL_SPECULAR_COEFFICIENT * specularFactor * ray.ClosestPrimitive.PrimitiveColor.B; } } if (depth < MAX_DEPTH && MATERIAL_REFLECTION_COEFFICIENT > TINY) { // Set up the reflected ray - notice we move the origin out a tiny bit again SLVector3f reflectedDir = ray.Direction.Reflection(normal); SLRay reflectionRay = new SLRay(ray.ClosestPoint + reflectedDir * TINY, reflectedDir); // And trace! Color reflectionCol = SetPixelColor(reflectionRay, depth + 1); // Add reflection results to running totals, scaling by reflect coeff. r += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.R; g += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.G; b += MATERIAL_REFLECTION_COEFFICIENT * reflectionCol.B; } } // Clamp if (r > 255) r = 255; if (g > 255) g = 255; if (b > 255) b = 255; // Take care of NaN if (r < 0) r = 0; if (g < 0) g = 0; if (b < 0) b = 0; return (Color.FromArgb(255, (int)r, (int)g, (int)b)); }