private List<RenderJob> PrepareJobs(Scene scene, int passes) { var list = new List<RenderJob>(); var pixelsYleft = _pictureHeight; for (var chunkY = 0; chunkY < _pictureHeight/ChunkSize + 1; chunkY++) { var pixelsXleft = _pictureWidth; var chunkHeight = pixelsYleft > ChunkSize ? ChunkSize : pixelsYleft; for (var chunkX = 0; chunkX < _pictureWidth/ChunkSize + 1; chunkX++) { list.Add(new RenderJob( x: chunkX*ChunkSize, y: chunkY*ChunkSize, width: pixelsXleft > ChunkSize ? ChunkSize : pixelsXleft, height: chunkHeight, passes: passes, scene: scene, pictureWidth: _pictureWidth, pictureHeight: _pictureHeight)); pixelsXleft -= ChunkSize; } pixelsYleft -= ChunkSize; } return list; }
private static Color LocalLighting(Surface surf_, Vector3 pos, Vector3 normal, Vector3 reflect, Scene scene) { Color colorSum = Color.Black(); foreach (Light light in scene.Lights) { Vector3 lightVec = light.Pos - pos; double distance = Vector3.Length(lightVec); lightVec = lightVec * (1 / distance); //shadow ray: test if there is something between pos and light source Intersection isect = scene.FirstIntersect(new Ray() { Start = pos + 0.001 * lightVec, Dir = lightVec }); if (null != isect) { //test if intersection is between lightsource and pos if (isect.Dist < distance) { continue; } } //diffuse with Lambert float illum = (float)Vector3.Dot(lightVec, normal); Color colorDiffuse = illum > 0 ? light.Color * illum : Color.Black(); colorSum += surf_.Diffuse(pos) * colorDiffuse; //phong specular double specular = Vector3.Dot(lightVec, reflect); Color scolor = specular > 0 ? light.Color * (float)Math.Pow(specular, surf_.Roughness) : Color.Black(); colorSum += surf_.Specular(pos) * scolor; } return colorSum; }
public void renderImage(Scene scene, Camera cam, Action<int, int, Color> setPixel) { PointF[] pixels = createPoints(cam.ViewportWidth, cam.ViewportHeight); pixels.Shuffle(); foreach (PointF pixel in pixels) { Color color = renderPixel(scene, cam, pixel.X, pixel.Y); setPixel(Convert.ToInt32(pixel.X), Convert.ToInt32(pixel.Y), color); } }
public Color renderPixel(Scene scene, Camera cam, float x_, float y_) { if (1 == m_iMultiSamples) { return RayTracer.TraceRay(cam.Pos, cam.PerspectiveRayDir(x_, y_), scene, 0); } Color color = Color.Black(); float delta = 1.0f / ((float)Math.Sqrt(m_iMultiSamples)); int count = 0; for (float x = x_ - 0.5f; x < x_ + 0.5f; x += delta) { for (float y = y_ - 0.5f; y < y_ + 0.5f; y += delta) { color += RayTracer.TraceRay(cam.Pos, cam.PerspectiveRayDir(x, y), scene, 0); ++count; } } return color * (1.0f / m_iMultiSamples); }
public static Color TraceRay(Vector3 start, Vector3 dir, Scene scene, int depth_) { if (depth_ >= scene.MaxRayDepth) { return scene.Ambient; } Ray ray = new Ray() { Start = start, Dir = dir }; Intersection isect = scene.FirstIntersect(ray); if (null == isect) { return scene.Background; } //todo light hit Surface surf = isect.Thing.Surface; Vector3 pos = isect.Ray.Start + isect.Dist * isect.Ray.Dir; Vector3 invRayDir = -isect.Ray.Dir; Vector3 normal = isect.Thing.Normal(pos, isect.Inside); Vector3 reflect = Vector3.Reflect(normal, invRayDir); Color ambient = scene.Ambient; Color local = LocalLighting(surf, pos, normal, reflect, scene); float refl = surf.Reflect(pos); float alpha = surf.Alpha(pos); Color reflected = Color.Black(); if (0 < refl && 0 < alpha) { reflected = TraceRay(pos + .001 * reflect, reflect, scene, depth_ + 1) * refl; } Color transmitted = Color.Black(); if (1 > alpha) { double eta = isect.Inside ? 1 / surf.Eta : surf.Eta; Vector3 transmit = Vector3.Refract(normal, invRayDir, eta); transmitted = TraceRay(pos + .001 * transmit, transmit, scene, depth_ + 1); } return ambient + (local + reflected) * alpha + transmitted * (1 - alpha); }
public void Render(Bitmap bmp, Scene scene, Action refreshAction, int passes, ref bool stopFlag) { _pictureHeight = bmp.Height; _pictureWidth = bmp.Width; var renderedMask = new bool[_pictureWidth][]; for (var i = 0; i < _pictureWidth; i++) { renderedMask[i] = new bool[_pictureHeight]; } var waitingJobs = PrepareJobs(scene, passes); var jobsDone = 0; var jobsAssigned = 0; #if DEBUG var processorCount = 1; #else var processorCount = Environment.ProcessorCount; #endif var workers = new List<RenderWorker>(processorCount); var lastPassCount = new int[processorCount]; for (var i = 0; i < processorCount; i++) { var renderWorker = new RenderWorker(); workers.Add(renderWorker); renderWorker.CurrentJob = waitingJobs[i]; renderWorker.Start(); jobsAssigned++; } while (jobsDone < waitingJobs.Count) { for (int workerID = 0; workerID < workers.Count; workerID++) { var renderWorker = workers[workerID]; var passesLeft = renderWorker.CurrentJob.PassesLeft; if (passesLeft != 0) { if( lastPassCount[workerID] != passesLeft) { BlipToScreen(renderWorker.CurrentJob, bmp); } refreshAction(); continue; } var doneJob = renderWorker.CurrentJob; jobsDone++; if (jobsAssigned >= waitingJobs.Count) { renderWorker.Stop(); } else { renderWorker.Pause(true); renderWorker.CurrentJob = waitingJobs[jobsAssigned]; jobsAssigned++; renderWorker.Pause(false); } BlipToScreen(doneJob, bmp); } if (stopFlag) { foreach (var renderWorker in workers) { renderWorker.Stop(); return; } } } }
private Vector3 RenderPixel(Scene scene, int screenX, int screenY, float dX, float dY, int pictureHeight, int pictureWidth) { var viewportX = (screenX + dX)/pictureWidth*2 - 1; // Screen Y is pointed down var viewportY = 1 - (screenY + dY)/pictureHeight*2; return scene.SampleColor(viewportX, viewportY, 4); }
public Vector3 SampleColor(Scene scene, RaycastHit raycastHit, int maxRecursiveRaycasts) { return Shader.Shade(scene, raycastHit, maxRecursiveRaycasts); }
// If a single value is given for resulution then create square image public void Render(int resolution, Scene scene) { Render(new Tuple <int, int>(resolution, resolution), scene); }