// sample: samples a single path up to a maximum depth private Vector3 Sample(Ray ray, int depth, int x, int y) { // find nearest ray/scene intersection Scene.Intersect(ray); if (ray.objIdx == -1) { // no scene primitive encountered; skybox return(1.0f * scene.SampleSkydome(ray.D)); } // calculate intersection point Vector3 I = ray.O + ray.t * ray.D; // get material at intersection point Material material = scene.GetMaterial(ray.objIdx, I); if (material.emissive) { // hit light return(material.diffuse); } // terminate if path is too long if (depth >= MAXDEPTH) { return(Vector3.Zero); } // handle material interaction float r0 = RTTools.RandomFloat(); Vector3 R = Vector3.Zero; if (r0 < material.refr) { // dielectric: refract or reflect RTTools.Refraction(ray.inside, ray.D, ray.N, ref R); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); extensionRay.inside = (Vector3.Dot(ray.N, R) < 0); return(material.diffuse * Sample(extensionRay, depth + 1, x, y)); } else if ((r0 < (material.refl + material.refr)) && (depth < MAXDEPTH)) { // pure specular reflection R = Vector3.Reflect(ray.D, ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); return(material.diffuse * Sample(extensionRay, depth + 1, x, y)); } else { // diffuse reflection if (x == 500 && y == 400) { //Console.WriteLine("test"); //return new Vector3(255,255,255); } R = RTTools.DiffuseReflection(RTTools.GetRNG(), ray.N); Ray extensionRay = new Ray(I + R * EPSILON, R, 1e34f); return(Vector3.Dot(R, ray.N) * material.diffuse * Sample(extensionRay, depth + 1, x, y)); } }
// tick: renders one frame public void Tick() { // initialize timer if (firstFrame) { timer.Reset(); timer.Start(); firstFrame = false; } // handle keys, only when running time set to -1 (infinite) if (runningTime == -1) if (camera.HandleInput()) { // camera moved; restart ClearAccumulator(); } // render if (false) // if (useGPU) { // add your CPU + OpenCL path here // mind the gpuPlatform parameter! This allows us to specify the platform on our // test system. // note: it is possible that the automated test tool provides you with a different // platform number than required by your hardware. In that case, you can hardcode // the platform during testing (ignoring gpuPlatform); do not forget to put back // gpuPlatform before submitting! } else { // this is your CPU only path float scale = 1.0f / (float)++spp; for( int y = 0; y < screen.height; y++ ) { for( int x = 0; x < screen.width; x++ ) { // generate primary ray Ray ray = camera.Generate( RTTools.GetRNG(), x, y ); // trace path int pixelIdx = x + y * screen.width; accumulator[pixelIdx] += Sample( ray, 0 ); // plot final color screen.pixels[pixelIdx] = RTTools.Vector3ToIntegerRGB( scale * accumulator[pixelIdx] ); } } } // stop and report when max render time elapsed int elapsedSeconds = (int)(timer.ElapsedMilliseconds / 1000); if (runningTime != -1) if (elapsedSeconds >= runningTime) { OpenTKApp.Report( (int)timer.ElapsedMilliseconds, spp, screen ); } }
static public void Refraction(bool inside, Vector3 D, Vector3 N, ref Vector3 R) { float nc = inside ? 1 : 1.2f, nt = inside ? 1.2f : 1; float nnt = nt / nc, ddn = Vector3.Dot(D, N); float cos2t = 1.0f - nnt * nnt * (1 - ddn * ddn); R = Vector3.Reflect(D, N); if (cos2t >= 0) { float r1 = RTTools.RandomFloat(); float a = nt - nc, b = nt + nc, R0 = a * a / (b * b), c = 1 + ddn; float Tr = 1 - (R0 + (1 - R0) * c * c * c * c * c); if (r1 < Tr) { R = (D * nnt - N * (ddn * nnt + (float)Math.Sqrt(cos2t))); } } }
// initialize renderer: takes in command line parameters passed by template code public void Init(int rt, bool gpu, int platformIdx) { // pass command line parameters runningTime = rt; useGPU = gpu; gpuPlatform = platformIdx; // initialize accumulator accumulator = new Vector3[screen.width * screen.height]; ClearAccumulator(); // setup scene scene = new Scene(); // setup camera camera = new Camera(screen.width, screen.height); // Generate randoms Console.Write("Generating randoms....\t"); randoms = new float[1000]; Random r = RTTools.GetRNG(); for (int i = 0; i < 1000; i++) { randoms[i] = (float)r.NextDouble(); } int variable = r.Next(); Console.WriteLine("Done!"); // initialize required opencl things if gpu is used if (useGPU) { StreamReader streamReader = new StreamReader("../../kernel.cl"); string clSource = streamReader.ReadToEnd(); streamReader.Close(); platform = ComputePlatform.Platforms[0]; context = new ComputeContext(ComputeDeviceTypes.Gpu, new ComputeContextPropertyList(platform), null, IntPtr.Zero); queue = new ComputeCommandQueue(context, context.Devices[0], ComputeCommandQueueFlags.None); program = new ComputeProgram(context, clSource); try { program.Build(null, null, null, IntPtr.Zero); kernel = program.CreateKernel("Main"); sceneBuffer = new ComputeBuffer <Vector4>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, scene.toCL()); rndBuffer = new ComputeBuffer <float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, randoms); cameraBuffer = new ComputeBuffer <Vector3>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, camera.toCL()); outputBuffer = new ComputeBuffer <int>(context, ComputeMemoryFlags.WriteOnly | ComputeMemoryFlags.UseHostPointer, screen.pixels); skydome = new ComputeBuffer <float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, scene.Skydome); kernel.SetMemoryArgument(0, outputBuffer); kernel.SetValueArgument(1, screen.width); kernel.SetValueArgument(2, screen.height); kernel.SetMemoryArgument(3, sceneBuffer); kernel.SetValueArgument(4, scene.toCL().Length); kernel.SetMemoryArgument(5, skydome); kernel.SetMemoryArgument(6, cameraBuffer); kernel.SetMemoryArgument(7, rndBuffer); } catch (ComputeException e) { Console.WriteLine("Error in kernel code: {0}", program.GetBuildLog(context.Devices[0])); Console.ReadLine(); useGPU = false; } } else { return; } }
// tick: renders one frame public void Tick() { // initialize timer if (firstFrame) { timer.Reset(); timer.Start(); firstFrame = false; } // handle keys, only when running time set to -1 (infinite) if (runningTime == -1) { if (camera.HandleInput()) { // camera moved; restart ClearAccumulator(); } } // render if (false) // if (useGPU) { // add your CPU + OpenCL path here // mind the gpuPlatform parameter! This allows us to specify the platform on our // test system. // note: it is possible that the automated test tool provides you with a different // platform number than required by your hardware. In that case, you can hardcode // the platform during testing (ignoring gpuPlatform); do not forget to put back // gpuPlatform before submitting! long[] workSize = { screen.width, screen.height }; long[] localSize = { 16, 2 }; queue.Execute(kernel, null, workSize, null, null); queue.Finish(); queue.ReadFromBuffer(outputBuffer, ref screen.pixels, true, null); Console.WriteLine(screen.pixels[0]); Random r = RTTools.GetRNG(); for (int i = 0; i < 1000; i++) { randoms[i] = (float)r.NextDouble(); } rndBuffer = new ComputeBuffer <float>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, randoms); cameraBuffer = new ComputeBuffer <Vector3>(context, ComputeMemoryFlags.ReadOnly | ComputeMemoryFlags.UseHostPointer, camera.toCL()); kernel.SetMemoryArgument(6, cameraBuffer); kernel.SetMemoryArgument(7, rndBuffer); } else { // this is your CPU only path float scale = 1.0f / (float)++spp; Parallel.For(0, screen.height, y => { for (int x = 0; x < screen.width; x++) { // generate primary ray Ray ray = camera.Generate(RTTools.GetRNG(), x, y); // trace path int pixelIdx = x + y * screen.width; accumulator[pixelIdx] += Sample(ray, 0, x, y); // plot final color screen.pixels[pixelIdx] = RTTools.Vector3ToIntegerRGB(scale * accumulator[pixelIdx]); } }); } // stop and report when max render time elapsed int elapsedSeconds = (int)(timer.ElapsedMilliseconds / 1000); if (runningTime != -1) { if (elapsedSeconds >= runningTime) { OpenTKApp.Report((int)timer.ElapsedMilliseconds, spp, screen); } } }
// tick: renders one frame public void Tick() { //float t = 21.5f; // initialize timer if (firstFrame) { timer.Reset(); timer.Start(); firstFrame = false; } // handle keys, only when running time set to -1 (infinite) if (runningTime == -1) if (camera.HandleInput()) { // camera moved; restart ClearAccumulator(); } // render if (useGPU) { // add your CPU + OpenCL path here // mind the gpuPlatform parameter! This allows us to specify the platform on our // test system. // note: it is possible that the automated test tool provides you with a different // platform number than required by your hardware. In that case, you can hardcode // the platform during testing (ignoring gpuPlatform); do not forget to put back // gpuPlatform before submitting! GL.Finish(); // clear the screen screen.Clear(0); // do opencl stuff if (GLInterop) { kernel.SetMemoryArgument(0, texBuffer); } else { kernel.SetMemoryArgument(0, buffer); } // execute kernel //long[] workSize = { screen.width, screen.height }; long[] localSize = { 8, 12 }; long [] workSize = { screen.width , screen.height }; if (GLInterop) { List<ComputeMemory> c = new List<ComputeMemory>() { texBuffer }; queue.AcquireGLObjects(c, null); queue.Execute(kernel, null, workSize, localSize, null); queue.Finish(); queue.ReleaseGLObjects(c, null); } else { camera.Update(); gpuCamera = new GPUCamera(camera.pos, camera.p1, camera.p2, camera.p3, camera.up, camera.right, screen.width, screen.height, camera.lensSize); float scale = 1.0f / (float)++spp; kernel.SetValueArgument(2, gpuCamera); kernel.SetValueArgument(3, scale); queue.Execute(kernel, null, workSize, localSize, null); queue.Finish(); // fetch results if (!GLInterop) { queue.ReadFromBuffer(buffer, ref data, true, null); // visualize result for (int y = 0; y < screen.height; y++) for (int x = 0; x < screen.width; x++) { int temp = x + y * screen.width; screen.pixels[temp] = data[temp]; } } } } else { // this is your CPU only path float scale = 1.0f / (float)++spp; Parallel.For(0, dataArray.Length, parallelOptions, (id) => { for (int j = dataArray[id].y1; j < dataArray[id].y2 && j < screen.height; j++) { for (int i = dataArray[id].x1; i < dataArray[id].x2 && i < screen.width; i++) { // generate primary ray Ray ray = camera.Generate(RTTools.GetRNG(), i, j); // trace path int pixelIdx = i + j * screen.width; accumulator[pixelIdx] += Sample(ray, 0); // plot final color screen.pixels[pixelIdx] = RTTools.Vector3ToIntegerRGB(scale * accumulator[pixelIdx]); } } }); } // stop and report when max render time elapsed int elapsedSeconds = (int)(timer.ElapsedMilliseconds / 1000); if (runningTime != -1) if (elapsedSeconds >= runningTime) { OpenTKApp.Report((int)timer.ElapsedMilliseconds, spp, screen); } }