# Simple ray tracer refraction problem

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

## Recommended Posts

This seems like such a simple thing for me to have already spent nearly a day trying to fix, but refraction in my raytracer does not currently work. Every time I try to render an object that is completly refractive I just end up with a black circle on the screen. I have used multiple sources from books to the internet, but everything I try has similiar result. This leads me to believe that the problem may be because of the code that uses the refraction rather then the refraction code itself, but I have checked that rather thoroughly and it seems OK. So I'll start by showing the source from two of the algorithms I have already tried. This first one I got from the book Real-Time Rendering. l is the incoming vector and n is the normal, the function expects both of them to point away from the surface and already be normalized.
        Vector i = -l;	// The incoming vector points at the surface for this formula
float r = Nl / Nt;
float w =  - (i.Dot(n)) * r;
float k = 1 + (w - r) * (w + r);
if (k < 0.0f)
return Reflect(l, n);

k = sqrt(k);
Vector result = r*i + (w - k)*n;
return result; // This is already normalized


This second formula is from Realistic Image Synthesis Using Photon Mapping.
// Formula from realistic image synthesis using photon mapping
float index = Nl / Nt;
float ldotn = l.Dot(n);
float root = 1 - ( (index*index) * (1 - (ldotn*ldotn)) );
if (root < 0.0f)
return Reflect(l, n);

Vector result = -index * (l - ldotn*n) - sqrt(root)*n;
result.Normalize(); // May not be necessary... investigate once it works.
return result;


I have tried several other similiar formulas from various sources on the internet, but I assumed these two would be the most reliable. Thanks in advance for your help.

##### Share on other sites
In your second block of code, everything looks right except the line that computes result. It should look like this:
Vector result = (index * ldotn - sqrt(root)) * n - index * l;

This assumes that the light direction l points away from the surface.

##### Share on other sites
Hey, I'm stuck implementing my Perspective Camera in my ray tracer. And since you're up to refraction in your ray tracer. I was thinking you can help me.

Many thanks...

##### Share on other sites
Quote:
 Original post by Eric LengyelIn your second block of code, everything looks right except the line that computes result. It should look like this:Vector result = (index * ldotn - sqrt(root)) * n - index * l;This assumes that the light direction l points away from the surface.

Thanks for your help. I tossed a simple triangle into the scene and gave it an index of refraction of 1.3333 and it seems to work. The bad news is that my sphere is still showing up as solid black. It looks like the photons are bouncing around inside the sphere. Do I need to include some special case when ldotn < 0?

Quote:
 Original post by Anonymous PosterHey, I'm stuck implementing my Perspective Camera in my ray tracer. And since you're up to refraction in your ray tracer. I was thinking you can help me.May I ask you to post your Perspective Camera class?Many thanks...

When you trace a ray from the center of projection through the frame buffer the perspective is "built in." If that's not enough to set you on the right path, PM me and I'll try to help some more.

Edit: As timw mentioned, I would have to check ldotn and not the indices of refraction. 4AM post are a bad idea.

[Edited by - Fibonacci One on August 24, 2005 11:09:32 AM]

##### Share on other sites
it doesn't matter if n's are greater or what order they're in. the equation should take care of it. let me just dump my code on you rather then checking yours if you really want I'll read it tomorrow

Vector3 *getRefractionV(Vector3 *pNormal, Vector3 *pDirection, float fN, float fNt, Vector3 *pTransmition) {

double fNdotD = (*pNormal)^(*pDirection);

double fRad = 1 - (((fN*fN)/(fNt*fNt))*(1 - (fNdotD*fNdotD)));

return NULL;

*pTransmition = (fN/fNt)*((*pDirection) - (*pNormal)*(fNdotD)) - (*pNormal)*(sqrt(fRad));
pTransmition->Normalize();

return pTransmition;
}

if the function returns null you have total internal reflection, and you should trace a reflection vector only. if it returns non null it returns the transmision direction and you should trace two rays in proportion using the fresnel equations. here fN is the index of refraction that the ray is LEAVING and fNt is the index of refraction that the ray is ENTERING. also the operator ^ is a dot product.

##### Share on other sites
oh re-reading your post taking care of ordering you simply check to see how the ray is entering the surface. if the dir^normal < 0 it's entering else it's exiting the surface. dir is the direction of the ray of course. ordering does matter in the equation, read the fun above. in my material classes each dielectric surface has two index of refraction, one for entering and one for leaving, in this way we don't have to "fake" interface's that don't have air as the exiting index.

##### Share on other sites
Quote:
 Original post by timwit doesn't matter [stuff] what order they're in. the equation should take care of it.

That's all I needed. I'll start searching through the rest of my code and try to figure out what's wrong.
Thanks.

##### Share on other sites
np man. the order does determin what order the refraction is taking place in tho. like air to water or water to air these situations would have the order of the index of refractions reversed, but I figure you know that, just making sure.

peace

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 13
• 10
• 9
• 35
• 16
• ### Forum Statistics

• Total Topics
634125
• Total Posts
3015671
×