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; } } }