public static TraceResult Render(TraceParams parameters, ProgressReportDelegate progressReport = null, float[] backbuffer = null) { // Allocate backbuffer if (ReferenceEquals(backbuffer, null) || backbuffer.Length != (parameters.width * parameters.height * 3)) { backbuffer = new float[parameters.width * parameters.height * 3]; } TraceResult result = new TraceResult() { parameters = parameters, backbuffer = backbuffer }; TraceRuntimeParams runtimeParams = new TraceRuntimeParams(); runtimeParams.invWidth = 1.0f / parameters.width; runtimeParams.invHeight = 1.0f / parameters.height; runtimeParams.invSamplesPerPixel = 1.0f / parameters.samplesPerPixel; runtimeParams.sampleBatchCount = (int)Mathf.Ceiling(parameters.samplesPerPixel / (float)runtimeParams.batchSize); List <TileTraceParameters> traceTiles = new List <TileTraceParameters>(); for (int y = 0; y < parameters.height; y += parameters.traceTileDimension) { for (int x = 0; x < parameters.width; x += parameters.traceTileDimension) { var tt = new TileTraceParameters() { xStart = x, yStart = y, parameters = parameters, runtimeParams = runtimeParams }; tt.xEnd = Math.Min(tt.xStart + parameters.traceTileDimension, parameters.width); tt.yEnd = Math.Min(tt.yStart + parameters.traceTileDimension, parameters.height); traceTiles.Add(tt); } } parameters.tracingProcessor.Trace(traceTiles, ref result, progressReport); return(result); }
public static void TraceTile(TileTraceParameters tile, float[] backbuffer, out long rayCount) { InitBatchArray(ref _rays); InitBatchArray(ref _hits); InitBatchArray(ref _localColor); Ray[] rays = _rays; HitInfo[] hits = _hits; Vector3[] localColor = _localColor; uint rndState = FastRandom.Seed(); rayCount = 0; for (int x = tile.xStart; x < tile.xEnd; x++) { for (int y = tile.yStart; y < tile.yEnd; y++) { Vector3 color = new Vector3(0, 0, 0); // Sample bouncing batches for (int b = 0; b < tile.runtimeParams.sampleBatchCount; b++) { // Calculate batch info int batchStart = b * tile.runtimeParams.batchSize, batchEnd = batchStart + tile.runtimeParams.batchSize; int batchRayCount = Math.Min(batchEnd, tile.parameters.samplesPerPixel); batchRayCount -= batchStart; uint hitMask = 0; uint bounces = uint.MaxValue; float u = x * tile.runtimeParams.invWidth, v = y * tile.runtimeParams.invHeight; // Get initial rays tile.parameters.camera.GetRays(u, v, rays, batchRayCount, ref rndState); // Reset local colors for (int i = 0; i < batchRayCount; i++) { localColor[i] = tile.parameters.ambientLight; } Vector3 atten; int bounceCount = 0; while (bounceCount < tile.parameters.maxBounces && bounces != 0) { tile.parameters.scene.Raycast(rays, hits, 0.01f, tile.parameters.maxDepth, batchRayCount, bounces, ref hitMask, ref rayCount); if (hitMask == 0) { break; } bounces = 0; for (int i = 0; i < batchRayCount; i++) { if (BitHelper.GetBit(ref hitMask, i)) // Did ray hit? { if (hits[i].material.Scatter(ref hits[i], out atten, ref rays[i], tile.parameters.scene, ref rndState)) { BitHelper.SetBit(ref bounces, i); } localColor[i] *= atten; } } bounceCount++; } for (int i = 0; i < batchRayCount; i++) { color += localColor[i]; } } color *= tile.runtimeParams.invSamplesPerPixel; // Write backbuffer int idx = (y * (tile.parameters.width * 3)) + (x * 3); backbuffer[idx] = color.X; backbuffer[idx + 1] = color.Y; backbuffer[idx + 2] = color.Z; } } }