00001
00002
00003 #ifndef __PHONG_BRDF_H
00004 #define __PHONG_BRDF_H
00005
00006 #include <esg/Definitions.h>
00007 #include <esg/visitor/MatVisitor.h>
00008 #include <esg/brdf/SpecularBRDF.h>
00009 #include <esg/geometry/Hemisphere.h>
00010
00011 namespace esg {
00012
00024 class OGSCENE_EXPORT PhongBRDF : public SpecularBRDF {
00025 protected:
00026 virtual void _duplicate_attributes (const BRDF& src) {
00027 SpecularBRDF::_duplicate_attributes(src);
00028 }
00029
00030 public:
00034 PhongBRDF (void) : SpecularBRDF(true) {}
00035
00036 virtual RetVal reflectance(const MatVisitor& visitor,
00037 const Vector3* L,
00038 const Vector3* V,
00039 const Vector3* N,
00040 Vector3& color) {
00041 if (!N || !L || !V) return BAD_PARAMS;
00042
00043 register double nl = N->dot(*L);
00044 if (nl <= 0.0) return NL_NEGATIVE;
00045
00046 color.set(*N);
00047 color.scale(2.0 * nl);
00048 color.sub(*L);
00049 register double vr = V->dot(color);
00050
00051 if (vr <= 0.0) return ZERO_CONTRIB;
00052 color.set(visitor.specular());
00053 color.scale(pow(vr, (double)visitor.intRoughness()) / nl);
00054 return NONZERO_CONTRIB;
00055 }
00056
00057 virtual RetVal reflectanceVNL(const MatVisitor& visitor,
00058 const Vector3* L,
00059 const Vector3* V,
00060 const Vector3* N,
00061 double NV,
00062 double NL,
00063 Vector3& color) {
00064 if (!N || !L || !V) return BAD_PARAMS;
00065
00066 color.set(*N);
00067 color.scale(2.0 * NL);
00068 color.sub(*L);
00069 register double vr = V->dot(color);
00070
00071 if (vr <= 0.0) return ZERO_CONTRIB;
00072 color.set(visitor.specular());
00073 color.scale(pow(vr, (double)visitor.intRoughness()) / NL);
00074 return NONZERO_CONTRIB;
00075 }
00076
00077 virtual RetVal reflectanceNL(const MatVisitor& visitor,
00078 const Vector3* L,
00079 const Vector3* V,
00080 const Vector3* N,
00081 double NL,
00082 Vector3& color) {
00083 if (!N || !L || !V) return BAD_PARAMS;
00084
00085 color.set(*N);
00086 color.scale(2.0 * NL);
00087 color.sub(*L);
00088 register double vr = V->dot(color);
00089
00090 if (vr <= 0.0) return ZERO_CONTRIB;
00091 color.set(visitor.specular());
00092 color.scale(pow(vr, (double)visitor.intRoughness()) / NL);
00093 return NONZERO_CONTRIB;
00094 }
00095
00096 virtual BRDF* clone (void) const { return new PhongBRDF(); }
00097
00108 virtual double albedo (const MatVisitor& visitor,
00109 const Vector3& N,
00110 const Vector3* V) const {
00111 return ((V) ? (2. * PI * visitor.avgSpecular() /
00112 (visitor.intRoughness()+2.) *
00113 V->dot(N)) : -1.);
00114 }
00115
00133 virtual void importanceSample(const MatVisitor& visitor,
00134 const Vector3& D,
00135 double r1,
00136 double r2,
00137 Vector3& dir,
00138 double* pPDFVal) {
00139 Hemisphere h(D);
00140 dir.set(h.samplePriorToPoweredZenith(r1, r2,
00141 visitor.intRoughness(),
00142 pPDFVal));
00143 }
00144
00157 virtual Vector2 dir2uv (const MatVisitor& visitor,
00158 const Vector3& N,
00159 const Vector3& D) const {
00160 Hemisphere h(N);
00161 return Vector2(h.dir2uvPriorToPoweredZenith(D, visitor.intRoughness()));
00162 }
00163 };
00164
00165 };
00166
00167 #endif // __PHONG_BRDF_H