Jump to content
  • Advertisement
Sign in to follow this  
Teenage Death Boy

Simple problem in my Ray Tracer

This topic is 4870 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok so I have recently been starting my Ray Tracer, which uses C++ and saves the rendered scene to .tga and .bmp files. To get me started, I used some of the functions from the ray tracer tutorials over at Ultimate Game Programming. Upon discovering the problem, I have tried downloading and compiling even some of the basic ones which has a 3d scene and it too suffers the same problem, although I can't seem to get any response by email or forum. The problem can be seen here where objects at the edges of the scene get stretched. Since my program is VERY similar to the tutorials at the moment, its probably worth checking out ths source code from the download on the site but I will try and identify the problem here. The ray tracer class has the following members:
  int sceneWidth, sceneHeight, sceneDepth;
  unsigned char *mainBuffer;
  Vector *directions;

In its constructor, they are set as follows:
  sceneWidth = 800; 
  sceneHeight = 600;
  sceneDepth = 255;
  mainBuffer = new unsigned char[sceneWidth * sceneHeight * 3];
  directions = new Vector[sceneWidth * sceneHeight];

Before the trace is begun, the method generateDirections is called:
void RayTracer::generateDirections()
{
  float halfWidth = (float)(sceneWidth >> 1);
  float halfHeight = (float)(sceneHeight >> 1);
  for(int y=0; y < sceneHeight; y++)
  {
    for(int x=0; x < sceneWidth; x++)
    {
      directions[x + y * sceneWidth] = Vector(x - halfWidth, y - halfHeight,(float)sceneDepth);
      directions[x + y * sceneWidth].normal();		
    }
  }
}

As far as I can tell from stepping through the code and checking the values, the directions all seem to be fine (I think). Now here comes the main tracing function:
void RayTracer::traceScene(Scene *scene)
{
  float r=0, g=0, b=0;	// Pixel colour
  int k = 0;
  //Starting point for ray being using for trace
  Ray primaryRay;
  primaryRay.origin.x = 0;
  primaryRay.origin.y = 0;	
  primaryRay.origin.z = -600;	

  for(int y=0; y < sceneHeight; y++)
  {
    for(int x=0; x < sceneWidth; x++, k+=3)
    {
      primaryRay.direction = directions[x + y * sceneWidth];
      TraceResult intersectResult;

      float closestIntersectedDistance = 1000000;
      int closestIntersectedPrimitive = -1;

      for(int currentPrimitive=0; currentPrimitive < scene->primitives.size(); currentPrimitive++)
      {
	if(scene->primitives[currentPrimitive].type == SPHERE && scene->primitives[currentPrimitive].sphere != 0)
	{
          intersectResult = scene->primitives[currentPrimitive].sphere->intersectSphere(primaryRay);
	} else
	if(scene->primitives[currentPrimitive].type == TRIANGLE && scene->primitives[currentPrimitive].triangle != 0)
	{
	  intersectResult = scene->primitives[currentPrimitive].triangle->intersect(primaryRay);
	} else
	if(scene->primitives[currentPrimitive].type == PLANE && scene->primitives[currentPrimitive].plane != 0)
	{
	  intersectResult = scene->primitives[currentPrimitive].plane->intersect(primaryRay);
	}
				
	if(intersectResult.hit)
	{
          if(intersectResult.distance < closestIntersectedDistance)
	  {
	    closestIntersectedDistance = intersectResult.distance;
	    closestIntersectedPrimitive = currentPrimitive;
	  }
	}
      }
      if(closestIntersectedPrimitive != -1)
      {
	lightShadePrimitive(scene->primitives, closestIntersectedPrimitive, primaryRay, closestIntersectedDistance, scene->mainLight, r, g, b);
	mainBuffer[k + 0] = (int)r;
        mainBuffer[k + 1] = (int)g;
	mainBuffer[k + 2] = (int)b;
      }
    }
  }
}

Since the image I used to show the problem has a sphere, here is the intersection code for it:
TraceResult Sphere::intersectSphere(Ray &ray)
{
  TraceResult result;
  Vector RaySphereDirection;
  float RaySphereLength = 0.0f;
  float IntersectPoint = 0.0f;	// Distance intersect occurs
  float SquaredPoint = 0.0f;

  RaySphereDirection = center - ray.origin;
  RaySphereLength = RaySphereDirection.dotProduct(RaySphereDirection); // ???
  IntersectPoint = RaySphereDirection.dotProduct(ray.direction);

  if(IntersectPoint < 0)
  {
    result.hit = false;
    return result;
  }
  SquaredPoint = (radius * radius) - RaySphereLength + (IntersectPoint * IntersectPoint);

  if(SquaredPoint < 0)
  {
    result.hit = false;
    return result;
  }

  result.hit = true;
  result.distance = IntersectPoint - (float)sqrt(SquaredPoint);
  return result;
}

So, I know this is a lot of code, but if anyone can help or point me in the right direction I would greatly appreciate it (if it helps, download one of the tutorials from the site so you get the complete structure etc). Also, if anyone has any links to ray tracing articles or tutorials or would like to share some advice after working on their own ray tracer, I would be interested to hear it. Thanks in advance for any help.

Share this post


Link to post
Share on other sites
Advertisement
at first glance, I'd expect this to be a problem in your primary ray generation. I didn't look at any of the code tho. I couldn't imagin it being anything to do with your ray/sphere intersection routine. it's an odd problem tho. I'd check the primary ray generation. Then your sphere ray intersection code. it's gotta be one or the other.

one other thing, it might be from a ridiculus field of view(fov) paramater. a crazy field of view might cause some odd side effects for objects that are close and viewed obliquely.


Tim

Share this post


Link to post
Share on other sites
After looking at the ray generation code I'm not sure it looks correct. I can't remember exactly how to do it off the top of my head but I'll let you know after I've checked my ratracer code when I get home. For now try increasing the sceneDepth parameter as I believe that would have the same effect as narrowing the FOV. But I'll post back with a better way of generating it later.

Share this post


Link to post
Share on other sites
Hi TDB,
If you notice the scrren shots of the tutorial page 2 on mentioned site you'll
see the same effect. I believe no fov is being applied.

I believe you should be applying a division to (y-halfheight) and (x-halfwidth) in in the loop in your generateDirections function. This would scale the fov. The larger the number the less effect you should see as this correlates to the viewers distance from screen.

As I'm no expert on ray tracing could someone please comment.
Am I at least looking in the right direction?

[Edited by - Infernal_Truth on November 21, 2005 12:14:34 PM]

Share this post


Link to post
Share on other sites
you've got a fish-eye effect it looks like, albeit accidentally. this is just you need to shrink the field of view - try shrinking the multiplying scalars you muliply your ray vectors by (assuming you're using any)... does that make any sense?

what I mean is, if your ray range goes from

-1 to 1 x-ways, (90 degrees) scale it to go from

-.5 to .5 (45 degrees)

or have I just made what I said even more confusing?

i.e. shrink your field of view. The effect you have is just like a real-life fish-eye lense, if you make the field-of-view very small you'll get the effect of a zoom-lense.

Share this post


Link to post
Share on other sites
Thanks guys. I could have sworn I had already tried this, with no change (but then isn't that always the way).

Anyway, I'm a bit a busy with Uni assignments so I've only just had a quick fiddle with the scenedepth, so I won't get to try the other solutions just yet, but thanks to all who helped.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!