In the lesson on the basics of lighting, we briefly reviewed the Phong lighting model, which allows us to give a significant share of realism to our scenes. The Phong model looks quite good, but it has several drawbacks that we will focus on in this lesson.
The Phong model is a very effective approximation for calculating lighting, but under certain conditions it can lose some of the components of the specular highlights. This can be noticed at small values of the gloss power ( shininess ) when the specular reflection area becomes rather large. The figure below shows what happens when we use a specular gloss of 1.0 for a flat textured surface:
As you can see, the area of mirror reflection has a sharply defined border. This occurs because the angle between the viewing vector and the reflection vector should not exceed 90 degrees, otherwise their scalar product becomes negative, which makes the component of the mirror highlights equal to zero. You might think that there is nothing terrible in this, because we should not get any illumination at angles above 90 degrees, right?
Not really. This is applicable only to the diffuse component, where the angle above 90 degrees between the normal vector and the direction of light means that the light source is below the illuminated surface and, therefore, the contribution of diffuse illumination should be zero. However, in the case of a mirror component, we do not measure the angle between the direction of light and the normal, but the angle between the viewing and reflecting vectors. Take a look at the following two figures:
Now the problem becomes obvious. On the left, we see the familiar picture of the Phong reflection with θ less than 90 degrees. In the right figure, the angle θ between the directions of view and reflection is greater than 90 degrees, as a result of which the contribution of the mirror light is canceled. This is usually not a cause for concern, as the viewing vector is often noticeably distant from the reflection vector. But for small values of the specular gloss, the radius of the reflection region becomes quite large, and makes a significant contribution to the overall picture. Using the Phong model, we cancel this contribution at angles greater than 90 degrees (as seen in the first image).
In 1977, James F. Blinn introduced the Blinna-Phong lighting model as an addition to the Phong model that we have used so far. It is in many ways similar to the Phong model, but uses a slightly different approach to the calculation of the mirror component, which allows us to solve our problem. Instead of relying on the reflection vector, we use the so-called median vector ( halfway vector ), which is a unit vector exactly midway between the direction of view and the direction of light. The closer this vector is to the surface normal, the greater will be the contribution of the mirror component.
When the viewing direction coincides fully with the (now imaginary) reflection vector, the median vector coincides with the normal to the surface. Thus, the closer the viewing direction is to the reflection direction, the stronger the specular brilliance becomes.
Obviously, regardless of the direction from which the observer looks, the angle between the median vector and the normal to the surface will never exceed 90 degrees (unless, of course, the light source is below the surface). Due to this, we get slightly different results compared to the Fongov reflection, and in general the picture looks more visually plausible, especially at low values of the specular gloss. It was the Blinna-Phong lighting model that was used in the earlier, fixed OpenGL pipeline.
Finding the median vector is easy: you need to add the vector of the direction of light with the review vector and normalize the result:
In GLSL it looks like this:
vec3 lightDir = normalize(lightPos - FragPos); vec3 viewDir = normalize(viewPos - FragPos); vec3 halfwayDir = normalize(lightDir + viewDir);
Thus, the calculation of the mirror component is reduced to a simple calculation of the scalar product between the normal to the surface and the median vector in order to obtain the cosine value of the angle between them, which we again raise to the power of the specular gloss:
float spec = pow(max(dot(normal, halfwayDir), 0.0), shininess); vec3 specular = lightColor * spec;
Actually, this is all about the Blinna-Phong model. The only difference between the mirror reflection in the Blinna-Phong and Phong models is that we now measure the angle between the normal and the median vector instead of the angle between the direction of the view and the reflection vector.
Using the median vector to calculate the components of the specular highlights, we will no longer have a problem typical of the Phong model with a sharp boundary of the specular reflection region. The image below shows the region of specular reflection of both methods with a specular gloss of 0.5:
Another small difference between the Phong and Blinna-Phong models is that the angle between the median vector and the surface normal is often less than the angle between the viewing and reflecting vectors. Therefore, in order to obtain similar Phong model results, the value of the specular gloss strength should be slightly higher. It is empirically established that it is somewhere 2-4 times more compared with the Phong model.
The following is a comparison of the mirror component between models with a specular gloss of 8 for the Phong model and 32 for the Blinna-Phong model:
As can be seen, the mirror component of the Blinna-Phong is sharper. It usually requires a small adjustment to get results similar to those obtained earlier using the Phong model, but, in general, the Blinna-Phong coverage gives a more realistic picture.
For this demonstration, we used a simple fragmentary shader that switches between regular Phong reflection and Blinna-Phong reflection:
void main() { [...] float spec = 0.0; if(blinn) { vec3 halfwayDir = normalize(lightDir + viewDir); spec = pow(max(dot(normal, halfwayDir), 0.0), 16.0); } else { vec3 reflectDir = reflect(-lightDir, normal); spec = pow(max(dot(viewDir, reflectDir), 0.0), 8.0); } [...]
The source code for this tutorial can be found here . By pressing the b key, you can switch from the Phong model to the Blinna-Phong model and back.
Source: https://habr.com/ru/post/353054/
All Articles