フォンシェーディングの法線補間は線形でいいんだっけ?

2009-11-13

フォンシェーディングの法線

フォトンマッピングにポリゴンの交差判定を組み込んで、水面でコースティクスを作ろうとしてるんだけどどうもうまくいかない。 そもそも、ポリゴンの法線の補間、フォンシェーディングがうまくいってるのかいまいち自信がない。 フォンシェーディングは三角形の各頂点法線をbarycentric座標系によって線形補間したものを正規化すればいいんだっけ? なんか間違ってるのかどうだか、判断がつかない…。

三角形:

class Triangle extends Object {
vec vtx0;
vec edge1, edge2;
vec planenormal;
vec nrm0, dnrm1, dnrm2;

Triangle(vec vtx0_, vec vtx1_, vec vtx2_, Material material_, vec nrm0_, vec nrm1_, vec nrm2_) {
material = material_;
vtx0 = vtx0_;

/* find vectors for two edges sharing vert0 */
edge1 = vtx1_.sub(vtx0);
edge2 = vtx2_.sub(vtx0);
planenormal = edge1.cross(edge2).normal();

if (nrm0_ == null) nrm0_ = planenormal;
if (nrm1_ == null) nrm1_ = planenormal;
if (nrm2_ == null) nrm2_ = planenormal;

nrm0 = nrm0_;
dnrm1 = nrm1_.sub(nrm0_);
dnrm2 = nrm2_.sub(nrm0_);
}

float intersect_line(vec normal, vec orig, vec dir) {
/* begin calculating determinant - also used to calculate U parameter */
vec pvec = dir.cross(edge2);

/* if determinant is near zero, ray lies in plane of triangle */
float det = edge1.dot(pvec);
if (abs(det) < 0.000001)
return -1;
float inv_det = 1.0 / det;

/* calculate distance from vert0 to ray origin */
vec tvec = orig.sub(vtx0);

/* calculate U parameter and test bounds */
float u = tvec.dot(pvec) * inv_det;
if (u < 0.0 || u > 1.0)
return -1;

/* prepare to test V parameter */
vec qvec = tvec.cross(edge1);

/* calculate V parameter and test bounds */
float v = dir.dot(qvec) * inv_det;
if (v < 0.0 || u + v > 1.0)
return -1;

/* calculate t, ray intersects triangle */
float t = edge2.dot(qvec) * inv_det;

normal.set(nrm0.add(dnrm1.scale(u)).add(dnrm2.scale(v)).normal());

return t;
}
}