我根据Phong Model写了一个着色器。我正在尝试实现这个等式:
其中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;
}
不幸的是,由于某些原因,镜面术语似乎消失了。我的输出:
正确输出:
第一个球体只有漫反射和环境阴影。看起来不错。其余的都有镜面术语,并产生不正确的结果。我的实施有什么问题?
答案 0 :(得分:3)
这一行看起来不对:
r = 2*nl*(n-l);
2*nl
是一个标量,所以这是n - l
的方向,这显然是错误的方向(你也将结果标准化,因此乘以2*nl
什么都不做)。考虑n
和l
指向同一方向的时间。结果r
也应该在同一方向,但这个公式产生零向量。
我认为你的括号错位了。我相信它应该是:
r = (2*nl*n) - l;
我们可以轻松地在两个边界上检查这个公式。当n
和l
指向同一方向时,nl
为1,因此结果也是正确的相同向量。当l
与曲面相切时,nl
为零,结果为-l
,这也是正确的。