Phong Shading的麻烦

时间:2014-06-10 04:17:24

标签: c++ graphics shader raytracing

我根据Phong Model写了一个着色器。我正在尝试实现这个等式:

enter image description here

其中n是法线,l是光的方向,v是摄像机的方向,r是光反射。维基百科文章中更详细地描述了这些方程式。

截至目前,我只测试定向光源,因此没有r ^ 2衰减。环境术语在以下功能之外添加,效果很好。如果点积为负,则函数maxDot3返回0,这通常在Phong模型中完成。

这是我的代码实现上述等式:

#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;
}

不幸的是,由于某些原因,镜面术语似乎消失了。我的输出:

enter image description here

正确输出:

enter image description here

第一个球体只有漫反射和环境阴影。看起来不错。其余的都有镜面术语,并产生不正确的结果。我的实施有什么问题?

1 个答案:

答案 0 :(得分:3)

这一行看起来不对:

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

2*nl是一个标量,所以这是n - l的方向,这显然是错误的方向(你也将结果标准化,因此乘以2*nl什么都不做)。考虑nl指向同一方向的时间。结果r也应该在同一方向,但这个公式产生零向量。

我认为你的括号错位了。我相信它应该是:

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

我们可以轻松地在两个边界上检查这个公式。当nl指向同一方向时,nl为1,因此结果也是正确的相同向量。当l与曲面相切时,nl为零,结果为-l,这也是正确的。