{"id":16204083,"url":"https://github.com/aras-p/toymeshpathtracer","last_synced_at":"2025-07-22T23:02:31.797Z","repository":{"id":140930549,"uuid":"177998747","full_name":"aras-p/ToyMeshPathTracer","owner":"aras-p","description":"Toy Mesh Path Tracer that I used as a base for job interview tasks","archived":false,"fork":false,"pushed_at":"2019-05-02T06:54:17.000Z","size":3407,"stargazers_count":121,"open_issues_count":0,"forks_count":11,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-15T13:19:50.217Z","etag":null,"topics":["cpp","path-tracing"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aras-p.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-27T13:20:31.000Z","updated_at":"2025-04-18T18:55:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"497f3f1a-5548-4cf8-8ebe-b0f6905c7fe8","html_url":"https://github.com/aras-p/ToyMeshPathTracer","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/aras-p/ToyMeshPathTracer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aras-p%2FToyMeshPathTracer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aras-p%2FToyMeshPathTracer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aras-p%2FToyMeshPathTracer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aras-p%2FToyMeshPathTracer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aras-p","download_url":"https://codeload.github.com/aras-p/ToyMeshPathTracer/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aras-p%2FToyMeshPathTracer/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266586839,"owners_count":23952199,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-22T02:00:09.085Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cpp","path-tracing"],"created_at":"2024-10-10T09:56:25.506Z","updated_at":"2025-07-22T23:02:31.781Z","avatar_url":"https://github.com/aras-p.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Toy Mesh Path Tracer for a job interview task\n\nI used the task below for some job interviews I did in 2019 Q2. The initial version was a super simple brute-force\ntriangle mesh path tracer (no acceleration structures, no threading, etc.), and the task was to make it faster.\nOf course I wanted to know how much faster it *can* get, so I did some simple speedups myself in parallel.\n\nThe original non-optimized-at-all version is at\n[`01-initial-job-task`](https://github.com/aras-p/ToyMeshPathTracer/tree/01-initial-job-task) tag.\nI made other tags for later snapshots; here they are with performance numbers *(measured on 2018 MacBookPro i9)*,\non the `teapot.obj` (15706 triangles) and `sponza.obj` (66452 triangles) scenes respectively:\n\n* `01-initial-job-task`, initial: 3.5 and LOLNOPE Krays/s\n* `02-multi-threaded`, multi-threading: 18.9 and LOLNOPE Krays/s\n* `03-bvh`, simple bounding volume hierarchy: 6978.2 and 1350.3 Krays/s\n* `04-simd`, simplistic naïve SIMD: 8919.0 and 1853.1 Krays/s\n* `05-change-ray-tri-algo`, better ray-triangle intersection test: 10251.1 and 1952.5 Krays/s\n* `06-shadow-rays`, faster code path for shadow rays: 10888.0 and 2568.3 Krays/s\n* `07-compare-with-embree`, compare with [Intel Embree](https://embree.github.io/) 3.5.2: 75965.0 and 40800.8 Krays/s *(yup, Embree is fast!)*\n* `08-compare-with-nanort`, compare with [NanoRT](https://github.com/lighttransport/nanort): 20638.2 and 4197.9 Krays/s\n\nAnd yeah, I know -- most obvious next steps would be to use better BVH building heuristics (like SAH), and\ndoing SIMD properly instead of \"let's make our vector/ray/color class use SIMD\". I did not get to that (yet?),\nbut in any case -- the code is already over 3000 *times* faster than the initial version. With the BVH being the major\nwin, as one would expect.\n\n*Original desceription of the interview task is below:*\n\n# Interview task/assignment: speed up a simple path tracer\n\nThis project contains a simple triangle mesh path tracer implemented in C++.\nIt's a command line application that takes screen size \u0026 input .OBJ data file parameters,\nrenders it using \"path tracing\" algorithm and produces `output.png` result file.\n\nHere are some images that the program can produce with the data files present under `data/` directory:\n\n![result1](/result3Suzanne.png?raw=true \"Suzanne\")\n![result2](/result5Sponza.png?raw=true \"Sponza\")\n\n## The Task\n\nCurrent program is slow. *Really slow*. Rendering that monkey head model (\"Suzanne\") at a lowly 640x360 resolution,\n4 samples per pixel, takes **one minute** on my PC! Rendering the other image (\"Sponza\") at the same resolution takes **five hours**.\n\nYour task then is, of course, to make the program faster :)\n\nI know for sure that it is possible to make it faster by *more than a hundred times* -- e.g. I got Suzanne from a minute down\nto 0.2 seconds, and Sponza from five hours down to 8 seconds. It might be possible to make it even faster, but I\ndid not quite go there.\n\nNow, **your task is to make it run as fast as you can**. I'm not asking for a \"hundred times\", but something like\n\"**at least ten times faster**\" is what you should aim for.\n\nIt's entirely your choice how you will do it. Better algorithms? More efficient math? Better data layout? Multi-threading? SIMD?\nRewrite in assembly? Rewrite as a compute shader / CUDA / OpenCL? Rewrite for NVIDIA RTX? All of these? You pick :) Some of what I listed\nhere is \"certainly overkill\" and not needed; achieving a 10x faster performance is entirely possible using relatively simple means.\n\nGo!\n\n#### What I will be looking at\n\n* Overall I would recommend making a clone of this project on github and using \"actual version control\" workflow to make your changes.\nIf you don't like git or version control, that's fine; I can accept submissions in zip or dropbox or google drive (or whatever) form.\nAs long as I can see the code and try it out.\n* Your optimized program should produce same looking images as the original one, just *do it faster*.\n* I'll be looking at \"everything\" that is important in programming job: whether the code works correctly, is understandable,\n  how is it structured, how it behaves performance wise (computing usage, memory usage etc.).\n* It is *very* likely that your first submission will not be quite good, so do not delay it until the last day! Usually it\n  takes 2-4 iterations to arrive at a good solution.\n\n\n\n## About the code\n\nI made it work on Windows (Visual Studio 2017) and Mac (Xcode 10); the project files for them are respectively in\n`projects/VisualStudio/TrimeshTracer.sln` and `projects/Xcode/TrimeshTracer.xcodeproj`. In Visual Studio project, you might need to update settings to whatever Windows SDK version you have, I picked the oldest I had on my machine. If you have any trouble building or running it,\nask me!\n\nThe application accepts four command line arguments as input: `\u003cwidth\u003e \u003cheight\u003e \u003cspp\u003e \u003cdatafile\u003e`:\n\n* `width` is image width in pixels,\n* `height` is image height in pixels,\n* `spp` is \"samples per pixel\"; kind of like \"anti-aliasing level\",\n* `datafile` is path to a mesh to render; in Wavefront .OBJ format.\n\nI added some example meshes under `data/` folder; initially I suggest starting with e.g. `data/cube.obj` which is just a simple\ncube. I do *not* recommend trying to run the non-optimized version of the program on for example the Sponza model - it contains 66k\ntriangles and will run *very very slow*.\n\nThe code itself is fairly simple C++ code, and I tried to comment it extensively. No previous experience with ray-tracers\nor path-tracers should be required.\n\nIf you *do* want to read up on what this \"path tracing\" thing is *(and maybe even get some ideas how to make it faster? who knows)*,\nI can recommend \"Ray Tracing in a Weekend\", \"Ray Tracing: The Next Week\" and \"Ray Tracing: the Rest of Your Life\" minibook series,\nwhich have been recently [made free here](http://www.realtimerendering.com/raytracing/). The internet is full of other information about ray/path tracing as well.\n\nFor reference, here are the performance numbers I get on my laptop (2019 MacBookPro i9 2.9GHz), rendering at 640x360, 4 samples per pixel, on this un-optimized implementation:\n\n* cube.obj (14 triangles): 3818.3 KRay/s (0.6 sec)\n* suzanne.obj (970 triangles): 48.3 KRays/s (53.0 sec)\n* teapot.obj (15706 triangles): 3.5 KRays/s (683.0 sec)\n* sponza.obj (66452 triangles): LOL nope, ain't nobody got time for that\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faras-p%2Ftoymeshpathtracer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faras-p%2Ftoymeshpathtracer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faras-p%2Ftoymeshpathtracer/lists"}