Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble with Phong Shading

I am writing a shader according to the Phong Model. I am trying to implement this equation:

enter image description here

where n is the normal, l is direction to light, v is the direction to the camera, and r is the light reflection. The equations are described in more detail in the Wikipedia article.

As of right now, I am only testing on directional light sources so there is no r^2 falloff. The ambient term is added outside the below function and it works well. The function maxDot3 returns 0 if the dot product is negative, as it usually done in the Phong model.

Here's my code implementing the above equation:

#include "PhongMaterial.h"

PhongMaterial::PhongMaterial(const Vec3f &diffuseColor, const Vec3f &specularColor, 
                            float exponent,const Vec3f &transparentColor, 
                             const Vec3f &reflectiveColor,float indexOfRefraction){

            _diffuseColor = diffuseColor;
            _specularColor = specularColor;
            _exponent = exponent;
            _reflectiveColor = reflectiveColor;
            _transparentColor = transparentColor;


}

Vec3f PhongMaterial::Shade(const Ray &ray, const Hit &hit, 
                    const Vec3f &dirToLight, const Vec3f &lightColor) const{

        Vec3f n,l,v,r;
        float nl;

        l = dirToLight;
        n = hit.getNormal();
        v = -1.0*(hit.getIntersectionPoint() - ray.getOrigin());

        l.Normalize();
        n.Normalize();
        v.Normalize();

        nl = n.maxDot3(l);
        r = 2*nl*(n-l);
        r.Normalize();

        return (_diffuseColor*nl + _specularColor*powf(v.maxDot3(r),_exponent))*lightColor;
}

Unfortunately, the specular term seems to disappear for some reason. My output:

enter image description here

Correct output:

enter image description here

The first sphere only has diffuse and ambient shading. It looks right. The rest have specular terms and produce incorrect results. What is wrong with my implementation?

like image 473
Babbu Maan Avatar asked Jun 10 '14 04:06

Babbu Maan


People also ask

Is Phong Shading still used?

Video games Phong shading was eventually introduced to PC gaming with ATI's Radeon 9700 graphics card. However, Phong shading was still rarely used in PC gaming after that because it was computationally expensive.

Why is Phong Shading more computationally demanding than Gouraud shading?

Phong shading is more computationally expensive than Gouraud shading since the reflection model must be computed at each pixel instead of at each vertex. In modern graphics hardware, variants of this algorithm are implemented using pixel or fragment shaders.

Why is Phong Shading more realistic?

Phong shading is a more sophisticated shading algorithm that calculates the surface normal at each vertex and interpolates the surface color between vertices. This gives a more realistic effect, particularly when the surface has a curved shape.

What is importance of fast Phong Shading?

It displays more realistic highlights on a surface and greatly reduces the Match-band effect.


1 Answers

This line looks wrong:

r = 2*nl*(n-l);

2*nl is a scalar, so this is in the direction of n - l, which is clearly the wrong direction (you also normalize the result, so multiplying by 2*nl does nothing). Consider when n and l point in the same direction. The result r should also be in the same direction but this formula produces the zero vector.

I think your parentheses are misplaced. I believe it should be:

r = (2*nl*n) - l;

We can check this formula on two boundaries easily. When n and l point in the same direction, nl is 1 so the result is also the same vector which is correct. When l is tangent to the surface, nl is zero and the result is -l which is also correct.

like image 64
rhashimoto Avatar answered Oct 16 '22 02:10

rhashimoto