Ray Tracing: A Simple Java, Open Source Implementation - Barak Cohen's (1+ε) Cents: Computer Science and Algorithms Blog

Thursday, October 16, 2008

Ray Tracing: A Simple Java, Open Source Implementation

From Wikipedia: "Ray tracing is a technique for generating an image by tracing the path of light through pixels in an image plane. The technique is capable of producing a very high degree of photorealism".

Basically, it means that we want to render images by imitating how we perceive the physical world as its image is recreated in our mind using the light rays that hit objects in space and are then returned to our eyes. We do this by modeling the world in a virtual 3d space. We place a virtual "eye" which is looking at a given direction and has a viewing plane, which is the portion of the world which the eye sees. Then, project a "ray of light" from the eye and through each pixel on the viewing plane and follow the ray along its path in space.

We test to see if the ray intersects any objects along that path. If it does, we calculate the color of the object at the point of intersection, taking into account visible light sources, the object's properties such as color, material, etc. This process is actually known as "Ray Casting". To make it "Ray Tracing" we continue tracing the ray after the intersection to see if the reflected ray hits any objects, and so on.

One of the assignments in the Computer Graphics course I took last semester was to write a simple ray tracer in Java. Written by myself and my more than capable partner, Gur Dotan, the tracer was implemented from scratch, and includes the following features:
  1. Primitive objects: Sphere, Box, Disc, Cylinder, Rectangle and a Torus.
  2. Light sources: Directional, Point and Light Area.
  3. Phong lighting model: Diffuse, Specular, Ambient and Emission parameters for all objects.
  4. Textures: PNG files, or a Checkers pattern with variable size / colors.
  5. Recursive ray tracing: Trace rays reflection recursively upon intersection.
  6. Supersampling: Using multiple rays per pixel for anti-aliasing
You can download the application here. Simply run the JAR file to start things up. It is completely self contained and has no 3rd party dependencies. The right window is where you enter the model of the world, and you can download some reference scenes here. Then, simply click Render.

The source code is actually pretty straightforward, can be found here, in the form of an Eclipse project. A short document outlining things is contained in the zip file.

Please note that the code is provided mostly for educational purposes and it is released as-is, without warranty of any kind. That being said, feel free to make any use of it. It is free both as in "free beer" and as in "free speech".

If you're looking for a commercial grade ray tracer, I recommend POV-Ray, an excellent open source ray tracer written in C++.

Click to view in my Flickr

Have fun,
Barak

27 comments:

Unknown said...

hi barak
I am studying computer science in switzerland and I have a course about rendering algorithms and ray tracing.I tried to run raytracer projcet that is in your weblog but I couldnot.it always says the error "cannot find the main calss".would you pleas help me more as soon as possible?
thanks
zohre

Barak Cohen said...

hi zohreh,

I downloaded and ran both the JAR file and the Eclipse project, both seemed to work, even on different machines.

It sounds like you're getting a "ClassDefNoFound" exception. The easiest way to run from the source is to import the Eclipse project and run it from inside Eclipse.

If you post a more detailed error I can try to help.

Barak

Zoya said...

hey, i have a course "parallel computing" and my end semester project is to implement parallel ray tracing and later show the speed up. can i use your code and implement it on clusters? would it be troublesome? i mean since graphics donot work on clusters

Barak Cohen said...

Hi Zoya,

Feel free to use my code in any way you'd like. I'd be happy if you sent me a link to the end result.

Ray tracing lends itself well to parallelization since each pixel's color is found independently from other pixels. What you need to do is parallelize the two for loops in RayTracer.renderTo, it shouldn't be too hard, and you should probably get near linear speed-up.

Not sure what yo mean by "graphics don't work on clusters". I guess you'd want to do the rendering (finding pixel colors) in the cluster, then use a client computer to display the result.

Hope this helps,
Barak

Zoya said...

i don't understand one thing, might be the simplest though. The sample images you have given, how do i seethe implementation of ray tracing in that? I open an image and click render, it works fine, but isnt it just image rendering? i have to use only one image throughout and check speed up for that particular image.

Barak Cohen said...

Ray tracing is a form of image rendering. Each sample file is a description of a 3d world model (where the camera is and where it's looking, where objects are placed, etc.). Rendering is the process of constructing an image from the above model.

Read more at Wikipedia

Zoya said...

we have finaly implemented its parallel version using mpj-express:) i will post a link along with instructions to execute shortly:)
thanks alot

MOUrbi said...

Hi Barak,
I take your Ray Tracing as base for an exercise and tray to adapt to my input required. They give me fov, near and far planes. I represent the scene in Opengl and then ray trace, but i cant find the relation between screen-dist and screen-width you use and i don't know how to calculate them from my input. Can you help me?

Ratna said...

hi,
I am not able to download the sample scenes provided for the ray tracer implementation. Can you please provide me the appropriate link so that I can run the ray tracer.

Barak Cohen said...

hi Ratna,
I have updated the download link for the scenes file. you can get it at http://dl.dropbox.com/u/12349904/RayTracer/scenes.zip

enjoy!

Ratna said...

Thank you..

Ratna said...

hi barak,
how can we extend your ray tracing implementation to 3D images containing objects other than primitive shapes.
Ex: Rendering Rabbit Image, Human statue etc..

Barak Cohen said...

Hi,

You can implement your own shape object that can tell whether a given ray intersects it (see Box for a reference example). Alternatively, you can break down your complex object (e.g. bunny) into many small rectangles and render those. Keep in mind though that my code is not production grade and will be very slow if you used a very large number of objects in a single scene.

Ratna said...

thanks for your reply..
i am unable to generate the input files (similar to those you have provided) for images like bunny etc..
however i could find some ply files but we are facing difficulty in parsing those files.
can you please give some input files for such images as we need in our project.

Thank you.

Barak Cohen said...

Sorry, I don't have such images. However the input format is fairly straightforward. You might want to search for a 3rd party library to do the parsing for you.

Ratna said...

oh.. fine.. can you kindly share the input files for the images mentioned in your course site i.e. pool table, etc..

thank you,
ratna

Barak Cohen said...

Sorry (again..), those images were created by others and I don't have access to their model files, but they are just clever arrangements of the same primitives and lighting objects available to you.

Unknown said...

hi barak,
nice work. can you fix the links to reference scenes please?
mark

Unknown said...

ah no worries, just a problem with dropbox i was having

De Youngster said...

Hi, thanks for the source. But unfortunately its not working. I imported it to Eclipse as a project and run it, but i keep getting this error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at ex02.BatchRender.main(BatchRender.java:25)

line 25: public static void main(String[] args) throws Exception {
File inputDir = new File(args[0]);

Could you please kindly help out.
Thanks.

Barak Cohen said...

Hi deYoungster,

Please run the RayTracer class, that's the main class which contains the GUI.

Barak

joselito said...

Hi Barak!
I was looking a ray tracing on the web. luckely i found ur project, but itsn´t exactly the type
of ray tracing im looking,
althoug maybe i could change ur algorithm...
the purpose of my project are acoustic measurements...
so do you think that would be easy to adapt ur code to acoustic aplication¿?

Barak Cohen said...

Hi joselito,

Unfortunately I'm not familiar with the field of acoustic measurements.

However, generally speaking, if you're able to substitute the concepts of "camera" with "ear", "viewing plane" with "eardrum" and "color" with "frequency" you might be able to get what you want.

The code is fairly simple and straightforward and so you should be able to adapt it to your needs.

Good luck, let me know if you end up using it, i'm curious about applications so different than the original intent.

Barak

duke.edb said...

Hello Barak, my name is Daniel, I'm from Argentina. I'm a Java developer, I love it and I love drawing too.
I found raytracing a good way to apply both programming
and drawing together. I like mathematic but I'm not
good about it. I will feel happy when I could create a raytracing program like yours but I realised I need someone who can help me, to guide me about mathematic and get few objectives to achieve this program.

I was following your code, it is simple but I sometimes get lost about mathematic.

I have the following books:

Realistic Ray Tracing - Shirley, Morley
Real-Time Rendering - Akenine, Moller
Physically Based Rendering: From Theory to Implementation - Pharr, Humphreys

And this tutorial is useful:
http://www.inmensia.com/articulos/raytracing

But when I read them I feel demotivated because I don't understand.

Thank you in advance.

joselito said...

Hi Barack, can u give me some information about the methotd intersectBarycentric,

thanx u!

mk said...

can i render a semitransparent cube with this code?

Anonymous said...

For a class, I parallelized your ray tracer using the ParallelJava package. (Tiny change to only one file, but it caused a decent speedup.) My website currently links to this solution, but it does not refer to you. It's a personal site in its infancy; eventually it will give you the props you deserve -- I promise. If you're interested see charego.com/downloads.