 CSG, fisheye and spotlights. |
Posted - 5/5/2008 9:17:12 PM | One way of constructing solids is to use a method named constructive solid geometry (or CSG for short). I added two simple CSG operators - intersection and subtraction - that both take two surfaces and return the result.

In the above image, the surface that makes up the ceiling is created by subtracting a sphere from a plane. Of course, much more interesting examples can be created. For example, here is the surface created by taking a sphere and subtracting three cylinders from it (each cylinder points directly along an axis).

One problem with the camera implementation was that it couldn't be rotated. To try and aid this, I used a spherical to cartesian conversion to generate the rays - which has the side-effect of images with "fisheye" distortion.

The above left image also demonstrates a small amount of refraction - something that I've not got working properly - through the surface. The above right image is the result of the intersection of three cylinders aligned along the x,y and z axes.
To try and combat the fisheye distortion, I hacked together a simple matrix structure that could be used to rotate the vectors generated by the earlier linear projection. The result looks a little less distorted!

The final addition to the raytracer before calling it a day was a spotlight. The spotlight has an origin, like the existing point light - but it adds a direction (in which it points) and an angle to specify how wide the beam is. In fact, there are two angles - if you're inside the inner one, you're fully lit; if you're outside the outer one, you're completely in the dark; if you're between the two then the light's intensity is blended accordingly.

In the above screenshot, a spotlight is shining down and backwards away from the camera towards a grid of spheres.
If you're interested in an extremely slow, buggy, and generally badly written raytracer, I've uploaded the C# 3 source and project file. The majority of the maths code has been pinched and hacked about from various sites on the internet, and there are no performance optimisations in place. I do not plan on taking this project any further.

Building and running the project will result in the above image, though you may well wish to put the kettle on and make yourself a cup of tea whilst it's working. 
| |
Comments
 |  sprite_hound GDNet+
Member since: 2/20/2007 From: Southampton |
Posted - 5/6/2008 1:18:40 AM | This is really cool. Especially liking the CSG.
| |
 |  siaspete
Member since: 10/10/2001 From: Edinburgh, City of Edinburgh |
Posted - 5/6/2008 1:36:42 AM | Hi Ben,
Thanks for sharing your project, your journal is a good read.
In my hobby project I'll need to texture map a sphere soon. I had a little look at the source code (Sphere.cs) to see how you did the mapping from polar coords to texture coords.
If I understand correctly, you more or less map it as if it were a cylinder, so that the texture will appear to pinch together at the top and bottom of the sphere, is that right?
Peter
| |
 |  benryves GDNet+
Member since: 9/4/2003 From: Purley, Greater London |
Posted - 5/6/2008 10:47:14 AM | Cheers for the comments! 
Quote:| If I understand correctly, you more or less map it as if it were a cylinder, so that the texture will appear to pinch together at the top and bottom of the sphere, is that right? |
Absolutely correct; it uses simple trig to turn the cartestian coordinates of the struck point on the sphere's surface to polar coordinates, which it then divides by the requisite multiple of Pi to normalise it to the 0..1 range.
There are techniques for reducing the pinching, such as this one which requires that the 2D texture is distorted as a preprocessing step.
| |
 |  MrEvil
Member since: 6/8/2004 From: Belfast, Belfast |
Posted - 5/6/2008 4:59:06 PM | This series inspired me to stop being lazy try rewriting my own in C#. It's so much less painful (except for writing all the maths code again) than it was in C++ it's not funny.
I think I'm going to try implementing something I didn't get around to last time, like depth of field or fuzzy reflections.
I wanted to try CSG last time, interesting to see that you made it work. Nice job 
Pictar
| |
 |  benryves GDNet+
Member since: 9/4/2003 From: Purley, Greater London |
Posted - 5/6/2008 6:14:35 PM | Quote: Looks good! I really couldn't think of a decent way to render soft shadows/soft reflections/depth of field effects, so I look forwards to seeing what you come up with!
| |
 |  MrEvil
Member since: 6/8/2004 From: Belfast, Belfast |
Posted - 5/7/2008 4:42:52 AM | Quote:Original post by benryves
Quote: Looks good! I really couldn't think of a decent way to render soft shadows/soft reflections/depth of field effects, so I look forwards to seeing what you come up with! |
Well, the ideas I currently have are not really so great They all involve casting out tons of rays or jittering.
For fuzzy reflections the rays don't bounce off the surface in a straight line, but are jittered slightly. Whether this jittering will be random or uniform, I don't know. From my experience it needs a lot of rays to not look grainy.
For the "area shadows" shown, well, the filename gave it away - those are pretty fake. There's just 9 lights positioned close to each other It might be possible to do it instead by randomly jittering the point shadow testing is being performed on, perhaps based on the surface normal.
I guess the area in which the point can be jittered would be obtained using the size of the light and the distance from it, but I don't really see how exactly it would work. Maybe like this:

And depth of field can be done without too much effort, if I recall correctly. The first ray is cast, and the depth value it returns is used to manipulate the creation of the others. You simply offset the subrays outside of the actual pixel and it magically becomes blurry. There's probably some (hiss) mathematics in there somewhere, too.
| |
 |  LachlanL GDNet+
Member since: 11/30/2005 From: Sydney, New South Wales |
Posted - 5/6/2008 5:06:40 PM | Great work mate. Turned out very.... feature-full 
I too like the CSG.
| |
 |  elfprince13
Member since: 5/6/2008 |
Posted - 5/6/2008 10:36:39 PM | ben, any plans to handle indexes (indices?) of refraction?
also, why not make the number of subsections it divides into configurable, to allow as many processors as the user wants to work on rendering?
| |
 |  benryves GDNet+
Member since: 9/4/2003 From: Purley, Greater London |
Posted - 5/7/2008 6:18:59 AM | Quote:Original post by MrEvil
Well, the ideas I currently have are not really so great They all involve casting out tons of rays or jittering. |
Going by the noisy quality of the depth of field effects in POV-Ray, I assumed some sort of jittering trick was being used, but didn't understand how. Your explanations make sense!
As for soft shadows; rather than projecting a line back from the surface point to the light I assumed one could project a cone, but then I wasn't sure how you'd then calculate its intersection with the other surfaces to find out how much of its area was blocked.
Quote:Original post by elfprince13
ben, any plans to handle indexes (indices?) of refraction? |
There is some code in there to attempt that (each material has a RefractiveIndex property), but values other than 1 don't work very well (lots of noise) and if two surfaces interact with eachother then it's completely wrong (it only handles the ray moving in or out of "air").
Quote:| also, why not make the number of subsections it divides into configurable, to allow as many processors as the user wants to work on rendering? |
The Raytrace() method in MainInterface.cs has a variable at the top - int ThreadCount = 3; - that controls how many threads are created. 3 seemed a decent compromise between my two cores and splitting the image into a top/middle/bottom so you could see the more interesting stuff that was being rendered sooner.
| |
 |  MrEvil
Member since: 6/8/2004 From: Belfast, Belfast |
Posted - 5/7/2008 7:29:16 AM | Quote:Original post by benryves
As for soft shadows; rather than projecting a line back from the surface point to the light I assumed one could project a cone, but then I wasn't sure how you'd then calculate its intersection with the other surfaces to find out how much of its area was blocked. |
I do like the cone idea, if it could be made to work. It may be easier to use cones where possible, and fall back to jittering where necessary (assuming you can figure out when cones can be intersected with). It could also be interesting to intersect with cones for antialiasing too.
It could also be interesting to play with global illumination. I did this in my C++ attempt, tracing photons from the light and marking where they landing, interpolating them. It worked OK if you used enough samples, but it was slow.

One thing I'd really like to do is volumetric light/shadows (e.g. for seeing cones of light in the dust, etc.) but I have no idea on how I would do it. Probably something iterative.
| |
|
| S | M | T | W | T | F | S | | | | 1 | 2 | 3 | 4 | | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | | |
OPTIONS
Track this Journal
ARCHIVES
September, 2010
August, 2010
July, 2010
June, 2010
April, 2010
March, 2010
February, 2010
January, 2010
December, 2009
November, 2009
October, 2009
August, 2009
June, 2009
May, 2009
March, 2009
February, 2009
January, 2009
December, 2008
November, 2008
October, 2008
September, 2008
August, 2008
July, 2008
June, 2008
May, 2008
April, 2008
March, 2008
February, 2008
November, 2007
October, 2007
September, 2007
August, 2007
July, 2007
May, 2007
April, 2007
February, 2007
January, 2007
December, 2006
November, 2006
October, 2006
September, 2006
August, 2006
July, 2006
June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
September, 2005
August, 2005
April, 2005
February, 2005
January, 2005
|