Ray Tracer Question


#43

Ok, I have given up the code posted above and decided to try the algorithm from an other tutorialinsted.

I find the code in that tutorial kind of confusing as the variable names and commenst are weird. So I have rewriten it in my own words insted. Is this right?

I am not sure what everything here does, as my math knowledge is kind of limited (going to cover this next year :slight_smile: ) so I was wondering if someone could comment in a bit or something to give me a clue of what is going one.

Kind of feeling like I am flooding the forum here:p When you are tierdof me, just ask me to shut up :slight_smile:


for(each light in the scene)
{
		 // dist = the distance between the ray.org and the intersectionPoint
		 Vector lenght = Sphere.position - (ray.org + ray.dir * dist)
		 Normalize(lenght)
		 
		 Vector normal = Normal(ray.org + ray.dir + dist)
		 
		 dotProduct = Dot(normal, light)
		 if(dotPoroduct > 0)
		 {
			 DiffuseColor = dotPoroduct * sphere.diffuseValue
			 finalColor += DiffuseColor * sphere.color * lightColor
		 }
}



#44

Please keep posting. :smiley:


#45

This seems almost correct.

for (each light)
{
Vector Normal = intersection_pt - sphere.position;

Normal.normalize(); // normalize the normal

Vector LightDir = light.position - intersection_pt;

LightDir.normalize(); // normalize the light vector

float dot = clamp(0, 1, Dot(Normal, LightDir));

finalColor += dot * sphere.diffuseValue (this is a scalar value to increase the diffuse effect) * sphere.color * lightColor;

}


#46

for (each light)
{
Vector Normal = intersection_pt - sphere.position;

Normal.normalize(); // normalize the normal

Vector LightDir = light.position  - intersection_pt;

LightDir.normalize(); // normalize the light vector

float dot = clamp(0, 1, Dot(Normal, LightDir));

 finalColor += dot * sphere.diffuseValue (this is a scalar value to increase the diffuse effect) * sphere.color * lightColor;

}

Thanks for sharing, I will try to add it do my own code tonight.

The more and more I work on this project I realize that I have a fundamental problem, as I lack knowledge in math and fundamental computer graphics. So I guess I have to find the money to get myself a new book. Could anyone recomend a book which covers the math in computer graphics? Not just has it as an introduction before the other topic starts, but that has math as one of its main topics. Other topics I would like to know more about is rendering/raytracing and physic simulation. So, do anyone by chance know of a book that would work for me?

Thanks in advance


#47

Woho, next step reached :slight_smile:


#48

How many lights do you have in the scene? The bottom of the spheres seems off unless you have a light placed near the bottom of the sphere and pointed up.

Btw, congrats on the next level! :thumbsup:

I’ll leave you to exploring now. Good Luck!

Cheers,

-M


#49

woohoo! go H3ro!! isn’t it satisfying to see the results of something you’ve made from scratch :slight_smile: i think i’ve still got the pic of my v first ray-traced sphere (yes i know i’m a little bit sad)

books-wise i’ve got the classic Foley book: Introduction to Computer Graphics
http://www.amazon.com/Introduction-Computer-Graphics-James-Foley/dp/0201609215/ref=sr_1_3/103-9288412-5006250?ie=UTF8&s=books&qid=1177319231&sr=8-3

I had to buy it for a course at uni but i really think it’s worthwhile. it doesn’t cover things like differential equations but it does all your vector/matrix math very clearly - as well as projections, parametric curves/surgaces, solid modelling etc. there are a couple of chapters that are’nt interesting to me at all (Input Devices, Graphics Hardware etc) but it gives you a nice theoretical coverage of main topics. Only problem is that it doesn’t go into detail on everything - but it’s a great all-rounder. And i found that you can google anything that’s missing.

finally - try the sticky at the top of this forum - i think there’s a book review there


#50

How many lights do you have in the scene? The bottom of the spheres seems o unless you have a light placed near the bottom of the sphere and pointed up.

There is only one light in the scene, so there is a small bug somewhere. I guess it has something to do with my light being to bright(have to do finalColor / 1000000 to get something usefull).

woohoo! go H3ro!! isn’t it satisfying to see the results of something you’ve made from scratch :slight_smile: i think i’ve still got the pic of my v first ray-traced sphere (yes i know i’m a little bit sad)

Hehe, its like a baby:P It was kind of satisfying to see that something that I have spendt that much time

books-wise i’ve got the classic Foley book: Introduction to Computer Graphics
http://www.amazon.com/Introduction-…77319231&sr=8-3

I will see if I can get my hands on it, thanks for recomending:)

I am now in the progres of rewriting the whole program (lot of crap and “hacks” to make it work) so that it can support more interesting objects than just spheres. Finally the book I first bought are starting to make some sense to me, so hopefully I will be able to use it as a reference instead of browsing for tutorials and sourcecode online.

I will post more when I have something interesting to show :slight_smile:

Thanks for all support, would never got this to work if it was not for the help I got from you guys.


#51

By the looks of it, I’d say you’re calculating how perpendicular/parralel the normal on the sphere is without taking into account whether its facing towards or away from the light (+/- relative). I’m afraid I’m not especially well ATM so maybe someone else can demonstrate the math relative to a non-planar object?

Also, the Introduction book may not go into great detail, but the other book listed under ‘better together’ is one I’ve recommended many a time, is by the same authors and goes into stupid levels of detail… and by stupid I mean BSc (Honours) levels of detail.


#52

Now I have rewritten my intersection code so that it takes into account if its starts inside of an object. I am not sure how to calc the intersection point, but I think it is done by:
(ray.dir + distanceBetweenRayAndSphere) + ray.start

Is that right?


 // The intersectiontest between a sphere and a ray:
 result Sphere::intersectionTest(Ray r)
 {
 	   // A variable for holding the result
 	   result res;
 	   
 	   // Change the point where the ray starts into a vector to
 	   // ease calculations later on
 	   Point rayOrgP = r.getOrigin();
 	   Vector3D rayOrg(rayOrgP.getX(), rayOrgP.getY(), rayOrgP.getZ());
 	   
 	   // Find a vector from the ray origin to the center of the sphere,
 	   Vector3D RaySphereDirection = getPos() - rayOrg;
 	   
 	   float DotRaySphereDirection = Dot(RaySphereDirection, RaySphereDirection);
 	   
 	   // Check if the ray starts inside of the sphere
 	   if (DotRaySphereDirection < (radius * radius))
 	   {
 		   // Find t
 		   float t = Dot(RaySphereDirection, r.getDirection());
 		   float t2 = (radius * radius) - DotRaySphereDirection + (t * t) / 
 					  (Dot(r.getDirection(),r.getDirection()));
 		   float distance = t - sqrt(t2);
 		   
 		   // The ray hits the inside of the sphere
 		   res.hit = -1;
 		   res.distance = distance;
 		   //res.intersectionPoint = ??
 		   
 		   return res;
 	   }
 	   else
 	   {
 		   float t = Dot(RaySphereDirection,r.getDirection());
 		   if (t < 0)
 		   {
 				 // The ray points away from the sphere
 				 // MISS
 				 res.hit = 0;
 				 
 				 return res;
 		   }
 		   float t2 = (radius * radius) - DotRaySphereDirection + (t * t) /
 					  (Dot(r.getDirection(),r.getDirection()));
 					  
 		   if (t2 > 0)
 		   {
 				  // The ray hits the outside
 				  res.hit = 1;
 				  res.distance = t - sqrt(t2);
 				  //res.intersectionPoint = ??
 		   }
 		   else
 		   {
 			   res.hit = 0;
 		   }
 	   }	  
 }
 

#53

Shaderhacker - is this the C equivalent of:

struct RGB{
unsigned int r;
unsigned int g;
unsigned int b;
unsigned int a;
};

???

or is there a subtle difference?
cheers
Holly


#54

In strict C, this struct :

 
  struct RGB{
  unsigned int r;
    unsigned int g;
    unsigned int b;
    unsigned int a;
};
  

would need to instanced with :


  struct RGB someInstance;
  

so, you could do :


  typedef struct RGB RGB;
  
  RGB someInstance;
  

or, you could collapse the entire thing to :

 
   typedef struct {
  unsigned int r;
  unsigned int g;
  unsigned int b;
  unsigned int a;
} RGB;
   

which would typedef the entire struct definition to RGB. In C++, this was one of the first things that got simplified, so to maintain portability :

 
   struct RGB {
  unsigned int r;
  unsigned int g;
  unsigned int b;
  unsigned int a;
};
   

can be instanced (in C++) with either :

 
  struct RGB someInstance;
  
  // or 
  RGB someInstance;
   

#55

cool - thanks Rob - that’s what i thought


#56

Ok, now I’m back again, with some more questions:P

I have rewritten most of the raytracer, so it can more easily take different types of objects, and removed alot of nasty stuff and crap.

I am now at the point where the other raytracer was, so nothing new. But this time something weird has happened, I have transparency, but no clue why :stuck_out_tongue:

Here is the code:


  Color addDiffuse(int closestPrim, Ray &r, Vector3D &intersectionPoint, Scene &thisScene)
  {
  	 Color primCol;
  	 primCol.r = 0;
  	 primCol.g = 0;
  	 primCol.b = 0;
  	  
  	 for (int currentLight = 0; currentLight <= thisScene.getNrLights(); currentLight++)
  	 {
  		 // Find the closest Primitive and the material of it
  		 Primitive *closestPrimitive = thisScene.getPrimitive(closestPrim);
  		 Material *primColor = closestPrimitive->getMaterial();
  		 
  		 // Find the light we are currently using and the color of it
  		 Light *testLight = thisScene.getLight(currentLight);
  		 Color lightColor = testLight->getColor();
  		 
  		 // Find the normal
  		 Vector3D normal = intersectionPoint - closestPrimitive->getPos();
  		 normal.normalize();
  		 
  		 // Find the light direction
  		 Vector3D lightDir = testLight->getPos() - intersectionPoint;
  		 lightDir.normalize();
  		 
  		 float dot = Dot(normal, lightDir);
  		 if (dot < 0)
  			dot = 0;
  			
  		 // Find the color
  		 primCol.r += (int)(dot * primColor->getDiffuse() * primColor->getR() * lightColor.r);
  		 primCol.g += (int)(dot * primColor->getDiffuse() * primColor->getG() * lightColor.g);
  		 primCol.b += (int)(dot * primColor->getDiffuse() * primColor->getB() * lightColor.b);
  		 
  		 // Clamp he color
  		 if (primCol.r >= 255)
  			primCol.r = 255;
  		 if (primCol.g >= 255)
  			primCol.g = 255;
  		 if (primCol.b >= 255)
  			primCol.b = 255;   
  	 }
  	 return primCol;
  }
  

Any ideas anyone?

EDIT: Firefox with spell checker now installed:)

:slight_smile:


#57

I only have time for a quick look but it appears that your diffuse code is fine (I think; again, I only glossed over it). One thing to check is that you’re only computing the surface of the closest ray (and not adding up the result from all objects the ray could intersect).

Double check all sections of code where you’re adding colours together, chances are that’s where the problem is originating from :slight_smile:


#58

Thanks for your reply. That was the first thing I suspected as well, but the problem is that there is not adding up of colors. Or there is one, where I add the effects of all the lights, but as there is only one light in my scene this should not cause the effect.


   		 // Find the color
   		 primCol.r += (int)(dot * primColor->getDiffuse() * primColor->getR() * lightColor.r);
   		 primCol.g += (int)(dot * primColor->getDiffuse() * primColor->getG() * lightColor.g);
   		 primCol.b += (int)(dot * primColor->getDiffuse() * primColor->getB() * lightColor.b);
 

I have also tried to change the above code from “+=” to “=” but the result is the same. After what I know about raytracing(limited knowledge) it should be impossible to have transparency without shooting some secondary rays to find whats behind the original object?

The part belove here is the “core” part of the raytracer, if that in someway can help.


 	// This is where the raytracing is done. Here we create a ray 
 	// and trace it through the scene to see if there is an 
 	// intersection. Then we set the color at the corresponding pixel
 	// We make a loop for the hight and the width in order to trace
 	// all pixels
 	for (int y = 0; y < hight; y++)
 	{
 		for (int x = 0; x < widht; x++, arrayTracer+=3)
 		{			
 			//std::cout << x << "," << y << ": We are here" << std::endl;
 			// Set the ray to trace through the current pixel
 			currentRay.setDirection(directionList[x + y * widht]);
 			
 			// Variables for checking which objects that are closest to the
 			// camera
 			float closestDistance = 1000000;
 			int closestPrimitive = -1;
 
 			
 			// Loop through all the primitives in the scene and return the 
 			// the closest one
 			for (int currentPrimitive = 0; currentPrimitive <=totalPrimitves;
 				 currentPrimitive++)
 			{	
 				 // Find the primitive we are currently testing against
 				 Primitive* testObject = thisScene.getPrimitive(currentPrimitive);
 				 
 				 // Check if the ray hits the current object
 				 intersectionRes = testObject->intersectionTest(currentRay);
 				 
 				 // If the ray hits something, check if its the closest object
 				 if  (intersectionRes.hit == 1)
 				 {   
 					// Find closest primitive by comparing distance
 					if (intersectionRes.distance < closestDistance )
 					{
 						closestDistance = intersectionRes.distance;
 						closestPrimitive = currentPrimitive;	
 					}
 				 }
 			}
 			
 			// We now know if the ray has hit something and what the closest object is
 			if (closestPrimitive != -1)
 			{				 
 				 // Store the color 
 				 Color currentColor;
 				 
 				 // Find the intersectionPoint between the ray and the closest
 				 // primitive
 				 Vector3D interPoint = currentRay.getDirection();
 				 interPoint.scale(intersectionRes.distance);
 				 interPoint = interPoint + PointToVector3D(currentRay.getOrigin());
 				 
 				 // Add diffuse lighting
 				 currentColor = addDiffuse(closestPrimitive, interPoint, thisScene);
 				 
 				 // Add the color to the colorBuffer
 				 colBuffer[arrayTracer + 0] = currentColor.r;
 				 colBuffer[arrayTracer + 1] = currentColor.g;
 				 colBuffer[arrayTracer + 2] = currentColor.b;
 				
 			}
 		}
 

#59

Now i have tried to use the ray/sphere intersection code from my “old” raytracer, and the old diffuse code. But I still got this weird transparancy bug, so I don’t think the problem is in any of those parts. Frankly, I am very very lost now. I have checked the whole thing a thousand times without any luck. When trying to render spheres of different sizes where all of them are positioned at 0,0,0 it looks like there is something wrong with the intersection code or that the program are having trouble with deciding which of the spheres that are closest. But when I try to debug it all works fine.

I think I am going to leave this project for a while now, before I get really angry and smash my computer or something.

Anyway, here is the whole project (Dev-c++) if anyone enjoys things like this.

Thanks for all the help, I’m going to get back to this sometime and try to fix it, maybe when my programming skills have gotten a bit better or something. Back to basic:)


#60

Did you ever fix your dot product bug in your intersection code? You can’t just take the dot product of the ray direction vector and the vector from the eye to the center of the sphere and if they are > 0 then that’s an intersection. You must compute the length of the vector between the center point of the sphere and a point on the ray direction vector that is parallel to the radius. To do this, you must solve the pythagorean theorem from the two vectors that you use to compute the dot product. Once you get the length of that vector, you can then compare it to the radius. If it’s greater than the radius, then it misses the sphere EVEN if the dot product is > 0. This is probably your problem.

-M


#61

I think so, I have tryed to do it the same way as they do it in the devmaster wiki about ray/sphere intersection

Link


// The intersectiontest between a sphere and a ray:
 result Sphere::intersectionTest(Ray r)
 {
 	   // A variable for holding the result
 	   result res;
 	   
 	   // Change the point where the ray starts into a vector to
 	   // ease calculations later on
 	   Point rayOrgP = r.getOrigin();
 	   Vector3D rayOrg(rayOrgP.getX(), rayOrgP.getY(), rayOrgP.getZ());
 	   
 	   // Find a vector from the ray origin to the center of the sphere,
 	   Vector3D RaySphereDirection = getPos() - rayOrg;
 	   
 	   float DotRaySphereDirection = Dot(RaySphereDirection, RaySphereDirection);
 	   
 	   // Check if the ray starts inside of the sphere
 	   if (DotRaySphereDirection < (radius * radius))
 	   {
 		   // Find t
 		   float t = Dot(RaySphereDirection, r.getDirection());
 		   float t2 = (radius * radius) - DotRaySphereDirection + (t * t) / 
 					  (Dot(r.getDirection(),r.getDirection()));
 		   float distance = t - sqrt(t2);
 		   
 		   // The ray hits the inside of the sphere
 		   res.hit = -1;
 		   res.distance = distance;
 		   //res.intersectionPoint = ??
 		   
 		   return res;
 	   }
 	   else
 	   {
 		   float t = Dot(RaySphereDirection,r.getDirection());
 		   if (t < 0)
 		   {
 				 // The ray points away from the sphere
 				 // MISS
 				 res.hit = 0;
 				 
 				 return res;
 		   }
 		   float t2 = (radius * radius) - DotRaySphereDirection + (t * t) /
 					  (Dot(r.getDirection(),r.getDirection()));
 					  
 		   if (t2 > 0)
 		   {
 				  // The ray hits the outside
 				  res.hit = 1;
 				  res.distance = t - sqrt(t2);
 				  //res.intersectionPoint = ??
 		   }
 		   else
 		   {
 			   res.hit = 0;
 		   }
 	   }	  
 }


#62

This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.