Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

#ActualSuen

Posted 21 May 2012 - 07:57 PM

First I'd like to thank all of you for the replies so far.

Hello, greatly appreciate the suggestion. I'm kind of curious whether it's view direction and the halfway vector or if it's the light and normal as you said. I've seen some people suggesting the halfway vector and view direction in their implementation but when I had a look at nvidias whitepaper that describes Fresnel reflection, the article describes it as you do, that you want the angle between the direction to the light and the surface normal. What exactly is the difference between the two?

The input to Schlick's approximation is cos theta, where 2*theta is the angle between the incoming light and reflected light direction.
So 2*theta == angleDiff( in, out ), and we also know that out == reflect( in, N ), and thus angleDiff( in, N ) == angleDiff( out, N ) == theta.
in  N  out
  \o|o/  
   \|/	(o is theta)
So from in to out is 2*theta, and from in to N is theta and from N to out is theta. Or alternatively, dot(N,L) == dot(N,reflect(L,N) == cos theta.


This makes sense and of course is how I understood it at first when I read through nvidias article. The formula I had at first where I used dot product between the halfway vector and view direction was taken from here and apparently the formula there is taken from GPU Gems 3. Either way it made me confused as to what the angle represents, the one between the incoming light and surface normal or the one between the halfway vector and view direction.

I have the vague feeling that the product of Fresnel and dot(halfVector, normal) is rather small and thus barely discernible. Maybe that’s the problem?
Could you output the fresnel term as red and the dot(halfVector, normal) as green? Does any yellow appear?

Frankly, I haven’t seen the fresnel term being applied to the specular light in the blinn phong model. It’s more common for blending between mirror-like reflections and refractions. Ashikhmin-Shirley does use it (among others) for weighting the specular light, though.

Best regards


It might indeed be the case that product of the Fresnal and dot product is so small that I get no result from it. I'll explain below to Hodgman's reply why. And forgive me, this is a really really stupid question but how would I output the fresnel term as red and the dot(halfVector, normal) as green? Both are scalar values to begin with, if I have to change them into red and green wouldn't I need a vec3? It's probably a stupid question...

have the vague feeling that the product of Fresnel and dot(halfVector, normal) is rather small and thus barely discernible. Maybe that’s the problem?
Could you output the fresnel term as red and the dot(halfVector, normal) as green? Does any yellow appear?

Trying some debug visualisations like this is a good idea to find your problematic variable.
N.B. that the original (non-normalized) blinn-phong model isn't energy conserving, and a lot of energy goes missing (isn't reflected) when you use high power values -- it could be that your pow-80 light source is simply too dim to see when combined with your 0.018 spec mask. Try outputting the specular result times a thousand into a channel to see if it's still missing/black. If you're going for physically correct lighting, you're going to have to drop blinn-phong in favour of normalized blinn-phong.

Also, on a side note, you don't need your specularConstant variable any more, because your fZero variable is acting as your spec mask as well - so you've currently got two spec mask values.

Frankly, I haven’t seen the fresnel term being applied to the specular light in the blinn phong model. It’s more common for blending between mirror-like reflections and refractions. Ashikhmin-Shirley does use it (among others) for weighting the specular light, though.

Seeing reflection=specular and refraction=diffuse, most physically based models should use fresnel to mix their diffuse/spec lighting - including normalized blinn-phong.


I didn't have the slightest idea that Blinn-Phong was not energy conserving. I've read that the Phong-reflection model was not energy conserving but that's about as far as I got. I had no idea that a normalized Blinn-Phong model existed hahaha. But I think I will look into using it as soon as I get things working with the non-normalized one, it shouldn't be too hard to just replace it then with the normalized one.

Regarding the specular mask, you said I don't need my constant anymore as this is what my fresnel value is supposed to account for instead. But again it is just a scalar value, should I just create a vec3 where all values in the vector correspond to the fresnel value?
Update: Read what you said wrong, you actually mentioned fZero and not the fresnel value itself. So did you something more like this:

vec3 specularReflection = (vec3(fZero)-vec3(fZero)*exp+exp)*max(0.0,pow(dot(f_eyeNormal, halfWay), 80));

At least this is the approach I took when trying your suggestion above. I created a vec3(fresnel) and multiplied it by my pow-80. I then multiplied the red channel by 1000 and the specular highlights appeared. Going by this, if I implemented your suggestion correct, should I assume it's as you and Tsus said, that the values I had were so small that the specular highlights were barely visible?

#1Suen

Posted 21 May 2012 - 09:20 AM

First I'd like to thank all of you for the replies so far.

Hello, greatly appreciate the suggestion. I'm kind of curious whether it's view direction and the halfway vector or if it's the light and normal as you said. I've seen some people suggesting the halfway vector and view direction in their implementation but when I had a look at nvidias whitepaper that describes Fresnel reflection, the article describes it as you do, that you want the angle between the direction to the light and the surface normal. What exactly is the difference between the two?

The input to Schlick's approximation is cos theta, where 2*theta is the angle between the incoming light and reflected light direction.
So 2*theta == angleDiff( in, out ), and we also know that out == reflect( in, N ), and thus angleDiff( in, N ) == angleDiff( out, N ) == theta.
in  N  out
  \o|o/  
   \|/	(o is theta)
So from in to out is 2*theta, and from in to N is theta and from N to out is theta. Or alternatively, dot(N,L) == dot(N,reflect(L,N) == cos theta.


This makes sense and of course is how I understood it at first when I read through nvidias article. The formula I had at first where I used dot product between the halfway vector and view direction was taken from here and apparently the formula there is taken from GPU Gems 3. Either way it made me confused as to what the angle represents, the one between the incoming light and surface normal or the one between the halfway vector and view direction.

I have the vague feeling that the product of Fresnel and dot(halfVector, normal) is rather small and thus barely discernible. Maybe that’s the problem?
Could you output the fresnel term as red and the dot(halfVector, normal) as green? Does any yellow appear?

Frankly, I haven’t seen the fresnel term being applied to the specular light in the blinn phong model. It’s more common for blending between mirror-like reflections and refractions. Ashikhmin-Shirley does use it (among others) for weighting the specular light, though.

Best regards


It might indeed be the case that product of the Fresnal and dot product is so small that I get no result from it. I'll explain below to Hodgman's reply why. And forgive me, this is a really really stupid question but how would I output the fresnel term as red and the dot(halfVector, normal) as green? Both are scalar values to begin with, if I have to change them into red and green wouldn't I need a vec3? It's probably a stupid question...

have the vague feeling that the product of Fresnel and dot(halfVector, normal) is rather small and thus barely discernible. Maybe that’s the problem?
Could you output the fresnel term as red and the dot(halfVector, normal) as green? Does any yellow appear?

Trying some debug visualisations like this is a good idea to find your problematic variable.
N.B. that the original (non-normalized) blinn-phong model isn't energy conserving, and a lot of energy goes missing (isn't reflected) when you use high power values -- it could be that your pow-80 light source is simply too dim to see when combined with your 0.018 spec mask. Try outputting the specular result times a thousand into a channel to see if it's still missing/black. If you're going for physically correct lighting, you're going to have to drop blinn-phong in favour of normalized blinn-phong.

Also, on a side note, you don't need your specularConstant variable any more, because your fZero variable is acting as your spec mask as well - so you've currently got two spec mask values.

Frankly, I haven’t seen the fresnel term being applied to the specular light in the blinn phong model. It’s more common for blending between mirror-like reflections and refractions. Ashikhmin-Shirley does use it (among others) for weighting the specular light, though.

Seeing reflection=specular and refraction=diffuse, most physically based models should use fresnel to mix their diffuse/spec lighting - including normalized blinn-phong.


I didn't have the slightest idea that Blinn-Phong was not energy conserving. I've read that the Phong-reflection model was not energy conserving but that's about as far as I got. I had no idea that a normalized Blinn-Phong model existed hahaha. But I think I will look into using it as soon as I get things working with the non-normalized one, it shouldn't be too hard to just replace it then with the normalized one.

Regarding the specular mask, you said I don't need my constant anymore as this is what my fresnel value is supposed to account for instead. But again it is just a scalar value, should I just create a vec3 where all values in the vector correspond to the fresnel value?

At least this is the approach I took when trying your suggestion above. I created a vec3(fresnel) and multiplied it by my pow-80. I then multiplied the red channel by 1000 and the specular highlights appeared. Going by this, if I implemented your suggestion correct, should I assume it's as you and Tsus said, that the values I had were so small that the specular highlights were barely visible?

PARTNERS