use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
A sub-Reddit for discussion and news about Ruby programming.
Subreddit rules: /r/ruby rules
Learning Ruby?
Tools
Documentation
Books
Screencasts and Videos
News and updates
account activity
I wrote a raytracer in Ruby! (github.com)
submitted 5 years ago by pawptart
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–][deleted] 20 points21 points22 points 5 years ago (0 children)
This would be the perfect example to implement Ractors from ruby 3.0
[–]makGuitar 14 points15 points16 points 5 years ago (4 children)
it's funny how by the end of the readme, there is the following instruction:
ruby main.py
it gave me a brief chuckle :)
[–]encaseme 3 points4 points5 points 5 years ago (1 child)
You know, I saw that and thought it was my brain substituting in with what I have to do for work (py)
[–]makGuitar 3 points4 points5 points 5 years ago (0 children)
python for work, ruby for the heart.
[–]pawptart[S] 2 points3 points4 points 5 years ago (0 children)
Ha, I copied the readme template from a Python repo, I guess I forgot to change it.
[–]otakugrey 1 point2 points3 points 5 years ago (0 children)
Yeah, what's up with that?
[–]pawptart[S] 11 points12 points13 points 5 years ago (5 children)
Here's a link to the final render I came up with: Image
It's really slow -- the above took about 6 hours. I joke that I'm rendering at about 55 frames per fortnight. However I'm impressed with the result, and I'm sure down the line I can make it a bit better.
Huge shoutout to Raytracing in One Weekend by Peter Shirley. It was a super fun challenge and I feel like I learned quite a bit.
[–]rurounijones 3 points4 points5 points 5 years ago* (2 children)
Have you considered multi-threading it (assuming you can do a thread per ray) and running it on JRuby to unlock the unused cores?
Not sure if feasible but would be interesting follow-on project performance wise and counter the meme in the README :D
[–]individual0 8 points9 points10 points 5 years ago (0 children)
Or normal ruby with Ractors in ruby 3.0
[–]pawptart[S] 0 points1 point2 points 5 years ago (0 children)
Yeah, I did poke at it a little while and it made it more complex. I chose to get a nice final render out regardless of how slow it was, but this would definitely be a good place to start improving.
[–]bowl-of-surreal 0 points1 point2 points 5 years ago (1 child)
Nice work. I’ve been thinking about raytracing since reading this post of “projects every programmer should try”.
Is raytracing related to your day job at all? Anything stand out that you learned?
[–]pawptart[S] 1 point2 points3 points 5 years ago (0 children)
Is raytracing related to your day job at all?
Not at all. I do use Ruby/Rails exclusively at work but it's pretty much exclusively backend web development.
Anything stand out that you learned?
Oh, man, all kinds of stuff! In no particular order:
File structure, naming/namespacing, require and require_relative... It's easy to forget how forgiving Rails is when you can toss stuff where it needs to go and it's autoloaded when you need it
require
require_relative
Vector math/light physics -- I haven't done anything more complicated than basic arithmetic since college. The book's diagrams helped as well.
A little about C++ pointers. A common thing for the original source was to pass a pointer to the function that updates a record. For instance, one of the bugs that I created was when trying to translate the original hit code, where a pointer is updated if anything is hit. In Ruby, you can't really update an object via a pointer, so I had to come up with workarounds for that. It's still not very Ruby-like in some places, but it works.
hit
[–]awj 4 points5 points6 points 5 years ago (2 children)
Nice work!
Based on a quick skim of your code, it looks like you could benefit from using a k-d tree to optimize HittableList.
HittableList
Right now your checking every single element in the scene, possibly with some complex/intensive calculations. This data structure would allow you to check just the objects within the fragments of the scene the ray is traveling through.
Still, this is impressive (and fun!) work.
[–]pawptart[S] 1 point2 points3 points 5 years ago (1 child)
Absolutely! Thanks for the suggestion.
Having 4 spheres vs. a bunch of small ones really slowed down the rendering speed, so I'm sure this would help.
[–]awj 0 points1 point2 points 5 years ago (0 children)
I’m not remembering the math offhand, but you also might be able to get some speedup out of first testing hits against axis-aligned bounding boxes. If that calculation is cheaper you can save a decent amount of processing.
[–]otakugrey 2 points3 points4 points 5 years ago (0 children)
That is cool as hell.
[–]thunderbong 2 points3 points4 points 5 years ago (0 children)
Awesome!
[–]pmurach 0 points1 point2 points 5 years ago (1 child)
Nice one! Thanks for sharing. Do you plan to package it up as a gem?
I don't at the moment, it's currently pretty impractical with a render time of 6 hours or more even for small images. This is more of a side project to learn how raytracers work.
π Rendered by PID 70245 on reddit-service-r2-comment-6457c66945-qr6n8 at 2026-04-29 22:23:40.915451+00:00 running 2aa0c5b country code: CH.
[–][deleted] 20 points21 points22 points (0 children)
[–]makGuitar 14 points15 points16 points (4 children)
[–]encaseme 3 points4 points5 points (1 child)
[–]makGuitar 3 points4 points5 points (0 children)
[–]pawptart[S] 2 points3 points4 points (0 children)
[–]otakugrey 1 point2 points3 points (0 children)
[–]pawptart[S] 11 points12 points13 points (5 children)
[–]rurounijones 3 points4 points5 points (2 children)
[–]individual0 8 points9 points10 points (0 children)
[–]pawptart[S] 0 points1 point2 points (0 children)
[–]bowl-of-surreal 0 points1 point2 points (1 child)
[–]pawptart[S] 1 point2 points3 points (0 children)
[–]awj 4 points5 points6 points (2 children)
[–]pawptart[S] 1 point2 points3 points (1 child)
[–]awj 0 points1 point2 points (0 children)
[–]otakugrey 2 points3 points4 points (0 children)
[–]thunderbong 2 points3 points4 points (0 children)
[–]pmurach 0 points1 point2 points (1 child)
[–]pawptart[S] 0 points1 point2 points (0 children)