Jump to content
  • Advertisement
Sign in to follow this  
Eelco

Refraction in a raytracer

This topic is 5072 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

to anyone who has ever done this before: can you spot any obvious flaws in the following code snippet? it looks almost right. in most cases it looks great, but somehow lenses dont enlarge and never-ending internal reflection seems to occur way too often resulting in completely black spots in an object. ive spent a lot of time doublechecking my formulas and code, but to no avail... besides im sure its not because of fucked up normals.
			if (hit.e.Stuff.transparent && depth < MaxRecursions){
				newray.infinite = true;

				float alpha, beta;

				float ci;
				
				if (!hit.e.Volume.iv.state){		//refract inwards
					ci = -(ray.dir.x*normal.x + ray.dir.y*normal.y + ray.dir.z*normal.z);
					alpha = 1 / hit.e.Stuff.refractionindex;
					beta = alpha*ci - sqrt(1+alpha*alpha*(ci*ci-1));
assert(beta<0);					
					newray.dir.x = alpha*ray.dir.x + beta*normal.x;
					newray.dir.y = alpha*ray.dir.y + beta*normal.y;
					newray.dir.z = alpha*ray.dir.z + beta*normal.z;

//printf("in:%f\n",newray.dir.Length);
					newray.state = true;
					
					Vector3 l = TraceRay(newray, depth+1).light;
					hit.light.x = hit.light.x + l.x;
					hit.light.y = hit.light.y + l.y;
					hit.light.z = hit.light.z + l.z;
				}else{
					ci = -(ray.dir.x*normal.x + ray.dir.y*normal.y + ray.dir.z*normal.z);
					alpha = hit.e.Stuff.refractionindex;
					beta = 1+alpha*alpha*(ci*ci-1);
					if (beta < 0){			//total inner reflection
						dp = (ray.dir.x*normal.x + ray.dir.y*normal.y + ray.dir.z*normal.z) * 2;
						newray.dir.x = ray.dir.x - normal.x * dp;
						newray.dir.y = ray.dir.y - normal.y * dp;
						newray.dir.z = ray.dir.z - normal.z * dp;

//						if (newray.dir.Length()==1f) printf("ref:%f\n",newray.dir.Length);
						newray.state = true;
						
						Vector3 l = TraceRay(newray, depth+1).light;
						hit.light.x = hit.light.x + l.x * pow(hit.e.Stuff.color.x, first);
						hit.light.y = hit.light.y + l.y * pow(hit.e.Stuff.color.y, first);
						hit.light.z = hit.light.z + l.z * pow(hit.e.Stuff.color.z, first);
											
					}else{					//refract outwards
						beta = alpha*ci - sqrt(beta);
assert(beta>0);
						newray.dir.x = alpha*ray.dir.x + beta*normal.x;
						newray.dir.y = alpha*ray.dir.y + beta*normal.y;
						newray.dir.z = alpha*ray.dir.z + beta*normal.z;

//printf("out:%f\n",newray.dir.Length);

						newray.state = false;
											
						Vector3 l = TraceRay(newray, depth+1).light;
						float t = pow(hit.e.Stuff.transparency, first);
						hit.light.x = hit.light.x + l.x * pow(hit.e.Stuff.color.x, first+1);
						hit.light.y = hit.light.y + l.y * pow(hit.e.Stuff.color.y, first+1);
						hit.light.z = hit.light.z + l.z * pow(hit.e.Stuff.color.z, first+1);
					}
				}
			}

anyone?

Share this post


Link to post
Share on other sites
Advertisement
I haven't got time to go through your code, but have a few things you should be doing...

* Flip the normals if you hit a back-facing triangle.

* Keep track of all refractive indices, the indices of the material you are in and are going into. Consider the use of a stack to keep track of the materials you are in - this allows transparent objects within transparent objects etc. etc.

Ignore these if you've done them.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!