Sign in to follow this  
Eelco

Refraction in a raytracer

Recommended Posts

Eelco    301
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
Hybrid    138
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

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this