Jump to content
  • Advertisement
Sign in to follow this  
Chris_F

Fresnel equation

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

Out of curiocity I wanted to compare Schlick's approximation to the real thing, so I had my hand at implementing it, though, admittedly, I'm not very good with the maths... sleep.png so I may have made a mistake, or more.

 

float CosTheta = dot(N, L);
float SinTheta = sqrt(1 - CosTheta * CosTheta);
float temp = n1 * (SinTheta / n2);
temp = n2 * sqrt(1 - temp * temp);
temp = (n1 * CosTheta - temp) / (n1 * CosTheta + temp);
float fresnel = temp * temp;

 

I'm getting a pretty noticable difference between this and Schlick's.

Edited by Chris_F

Share this post


Link to post
Share on other sites
Advertisement

You implemented the formula for s-polarized light. But you want to implement the formula for non-polarized light. Which is simply R = (Rs + Rp) / 2.

Share this post


Link to post
Share on other sites

You implemented the formula for s-polarized light. But you want to implement the formula for non-polarized light. Which is simply R = (Rs + Rp) / 2.

 

Doh. Second try?

 

 

float CosTheta = dot(N, L);
float SinTheta = sqrt(1 - CosTheta * CosTheta);

float t1 = n1 * (SinTheta / n2);
t1 = sqrt(1 - t1 * t1);
float t2 = (n1 * CosTheta - n2 * t1) / (n1 * CosTheta + n2 * t1);
float Rs = t2 * t2;
t2 = (n2 * CosTheta - n1 * t1) / (n2 * CosTheta + n1 * t1);
float Rp = t2 * t2;
float R = (Rs + Rp) / 2;
Edited by Chris_F

Share this post


Link to post
Share on other sites

I'd reduce unnecessary calculations even more. Also your nominators were subtracting the values instead of adding them: 

 

float cosThetaIncidence = dot(N, L);
float sinThetaIncidence = sqrt(1 - cosThetaIncidence * cosThetaIncidence);

float sinThetaTransmittance = n1 * (sinThetaIncidence / n2);
float cosThetaTransmittance = sqrt(1 - sinThetaTransmittance * sinThetaTransmittance);

float n1CosThetaTransmittance = n1 * cosThetaTransmittance;
float n2CosThetaTransmittance = n2 * cosThetaTransmittance;
float n1CosThetaIncidence = n1 * cosThetaIncidence;
float n2CosThetaIncidence = n2 * cosThetaIncidence;

float sPolarizedSqrt = (n1CosThetaIncidence - n2CosThetaTransmittance) / (n1CosThetaIncidence + n2CosThetaTransmittance);
float sPolarized = sPolarizedSqrt * sPolarizedSqrt;

float pPolarizedSqrt = (n2CosThetaIncidence - n1CosThetaTransmittance) / (n2CosThetaIncidence + n1CosThetaTransmittance);
float pPolarized = pPolarizedSqrt * pPolarizedSqrt;

float fresnel = (sPolarized + pPolarized) / 2;

 

 

Edited by CryZe

Share this post


Link to post
Share on other sites

I'd reduce unnecessary calculations even more. Also your nominators were subtracting the values instead of adding them:

 

float CosTheta = dot(N, L);
float SinTheta = sqrt(1 - CosTheta * CosTheta);

float t1 = n1 * (SinTheta / n2);
t1 = sqrt(1 - t1 * t1);

float n1CosThetaTransmittance = n1 * t1;
float n2CosThetaTransmittance = n2 * t1;
float n1CosThetaIncidence = n1 * CosTheta;
float n2CosThetaIncidence = n2 * CosTheta;

float t2 = (n1CosThetaIncidence - n2CosThetaTransmittance) / (n1CosThetaIncidence + n2CosThetaTransmittance);
float Rs = t2 * t2;
t2 = (n2CosThetaIncidence - n1CosThetaTransmittance) / (n2CosThetaIncidence + n1CosThetaTransmittance);
float Rp = t2 * t2;
float R = (Rs + Rp) / 2;

 

Could do, but it's unlikely to make a difference as shader compilers are pretty sly.

 

Edit: For me, it seems as though this full implementation is about 24% more instructions than Schlick's method.

Edited by Chris_F

Share this post


Link to post
Share on other sites

For me, it seems as though this full implementation is about 24% more instructions than Schlick's method.


Only 24% more? Isn't Schlick Fresnel ks + (1 - ks) * pow(1 - dot(L, H), 5), which would be about 9 instructions? The full fresnel equation would be about 29 instructions.

Also, why is it dot(N, L) in your code? It should be the microfacets normal and not the normal of the macro surface. Edited by CryZe

Share this post


Link to post
Share on other sites

For me, it seems as though this full implementation is about 24% more instructions than Schlick's method.


Only 24% more? Isn't Schlick Fresnel ks + (1 - ks) * pow(1 - dot(L, H), 5), which would be about 9 instructions? The full fresnel equation would be about 29 instructions.

Also, why is it dot(N, L) in your code? It should be the microfacets normal and not the normal of the macro surface.

 

I included the instruction cost of calculating f0 with pow((n2-n1) / (n2+n1) , 2.0), and I used N.L because I was testing this with normalized Blinn-Phong, not a microfaceted BRDF.

Edited by Chris_F

Share this post


Link to post
Share on other sites


I was testing this with normalized Blinn-Phong, not a microfaceted BRDF


Blinn-Phong is the microfacet version of Phong. Blinn-Phong describes the percentage of microfacets oriented towards the halfway vector, cause these are the only microfacets reflecting light into the eye. So if you are extending your already partially existing microfacet BRDF by a fresnel term, you should use the microfacets normal, aka your halfway vector. Edited by CryZe

Share this post


Link to post
Share on other sites

OK, one last question, since as I said, I am not very familiar with the math yet. I use sqrt(1-cos^2(theta)) to get sin(theta). Is this correct? It seems to work, but as far as I know, sqrt(1-cos^2(theta)) is actually only equal to abs(sin(theta)). Assuming this works, is this method preferable to taking the length of the cross product?

Share this post


Link to post
Share on other sites

abs(sin(theta)) is fine in this case. I'd use your method instead of the cross product, since the calculation of the length of the cross product requires a square root as well, so your method is faster.

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!