CookTorranceBRDF.cc

Go to the documentation of this file.
00001 #include <esg/brdf/CookTorranceBRDF.h>
00002 
00003 using namespace esg;
00004 
00005 BRDF::RetVal CookTorranceBRDF::reflectance(const MatVisitor& visitor,
00006                                            const Vector3*    L,
00007                                            const Vector3*    V,
00008                                            const Vector3*    N,
00009                                            Vector3&          color)
00010 {
00011     static Vector3 H;
00012     
00013     /*
00014      * Precomputation of vectors and angles (Blinn-like)
00015      */
00016     if (!N || !L || !V) return BAD_PARAMS;
00017 
00018     register double nv = N->dot(*V);
00019     if (nv <= 0.0) return NV_NEGATIVE;
00020     register double nl = N->dot(*L);
00021     if (nl <= 0.0) return NL_NEGATIVE;
00022     H.set(*V);
00023     H.add(*L);
00024     H.scale(0.5);
00025     register double hn = H.dot(*N);
00026 
00027     /*
00028      * modelling micro-geometry (normal distribution function):
00029      *    D = k exp[-(alpha/m)^2]
00030      * where
00031      *    k     = any constant
00032      *    alpha = angle of the microfacet with respect to the normal of the
00033      *            (mean) surface = NH
00034      *    m     = standard deviation the distribution
00035      */
00036     color.set(visitor.gaussianCoef());
00037     color.scale(exp(-pow(acos(hn)/visitor.roughness(),2)));
00038 
00039     /*
00040      * shadowing and masking effects:
00041      *    Gm = 2(NH)(NV)/VH
00042      *    Gs = 2(NH)(NL)/VH
00043      *    G  = min{1, Gm, Gs}
00044      */
00045     double aux = (2 * hn) / H.dot(*V);
00046     double Gm  = aux * nv;
00047     double Gs  = aux * nl;
00048     double G   = 1;
00049     if (Gm < G) G = Gm;
00050     if (Gs < G) G = Gs;
00051 
00052 #ifndef WIN32
00053 #warning "TODO: Interpolated Fresnel term"
00054 #endif
00055     /*
00056      * the Fresnel term:
00057      *    F_a = F0 + (1 - cos a)^5 (1 - F0)
00058      * where
00059      *    F0 = value of F at normal incidence, can be computed as
00060      *        F0 = (n-1)^2 / (n+1)^2
00061      *    where
00062      *        n = refractive index of material (zero for dielectric = plastic)
00063      */
00064     Vector3 F(visitor.fresnelTerm());
00065     Vector3 F0(1,1,1);
00066     F0.sub(F);
00067     F0.scale(pow(1-nl,5));
00068     F.add(F0);
00069 
00070     /*
00071      * Specular component:
00072      *    s*(DGF/(NV))
00073      * where
00074      *    NV = glare effect term (view geometry)
00075      *    s  = specular coefficients
00076      */
00077     F.scale(G/nv);
00078     //c.x *= F.x * visitor.specular().x;
00079     //c.y *= F.y * visitor.specular().y;
00080     //c.z *= F.z * visitor.specular().z;
00081     color.x *= F.x;
00082     color.y *= F.y;
00083     color.z *= F.z;
00084 
00085     /*
00086      * Diffuse component:
00087      *    well-known Lambertian reflection
00088      */
00089     Vector3 auxv(visitor.diffuse());
00090     auxv.scale(nl);
00091     color.add(auxv);
00092 
00093     /*
00094      * Final formula:
00095      *    BRDF = sR_s + dR_d
00096      * where
00097      *    R_s = specular component DGF/(NV)
00098      *    R_d = Lambertian diffuse component
00099      *    s   = specular coefficient
00100      *    d   = diffuse coefficient
00101      *    s+d = 1
00102      */
00103     
00104     return NONZERO_CONTRIB;
00105 }
00106 
00107 BRDF::RetVal CookTorranceBRDF::reflectanceVNL(const MatVisitor& visitor,
00108                                               const Vector3*    L,
00109                                               const Vector3*    V,
00110                                               const Vector3*    N,
00111                                               double            NV,
00112                                               double            NL,
00113                                               Vector3&          color)
00114 {
00115     static Vector3 H;
00116     
00117     /*
00118      * Precomputation of vectors and angles (Blinn-like)
00119      */
00120     if (!N || !L || !V) return BAD_PARAMS;
00121 
00122     H.set(*V);
00123     H.add(*L);
00124     H.scale(0.5);
00125     register double hn = H.dot(*N);
00126 
00127     /*
00128      * modelling micro-geometry (normal distribution function):
00129      *    D = k exp[-(alpha/m)^2]
00130      * where
00131      *    k     = any constant
00132      *    alpha = angle of the microfacet with respect to the normal of the
00133      *            (mean) surface = NH
00134      *    m     = standard deviation the distribution
00135      */
00136     color.set(visitor.gaussianCoef());
00137     color.scale(exp(-pow(acos(hn)/visitor.roughness(),2)));
00138 
00139     /*
00140      * shadowing and masking effects:
00141      *    Gm = 2(NH)(NV)/VH
00142      *    Gs = 2(NH)(NL)/VH
00143      *    G  = min{1, Gm, Gs}
00144      */
00145     double aux = (2 * hn) / H.dot(*V);
00146     double Gm  = aux * NV;
00147     double Gs  = aux * NL;
00148     double G   = 1;
00149     if (Gm < G) G = Gm;
00150     if (Gs < G) G = Gs;
00151 
00152 #ifndef WIN32
00153 #warning "TODO: Interpolated Fresnel term"
00154 #endif
00155     /*
00156      * the Fresnel term:
00157      *    F_a = F0 + (1 - cos a)^5 (1 - F0)
00158      * where
00159      *    F0 = value of F at normal incidence, can be computed as
00160      *        F0 = (n-1)^2 / (n+1)^2
00161      *    where
00162      *        n = refractive index of material (zero for dielectric = plastic)
00163      */
00164     Vector3 F(visitor.fresnelTerm());
00165     Vector3 F0(1,1,1);
00166     F0.sub(F);
00167     F0.scale(pow(1-NL,5));
00168     F.add(F0);
00169 
00170     /*
00171      * Specular component:
00172      *    s*(DGF/(NV))
00173      * where
00174      *    NV = glare effect term (view geometry)
00175      *    s  = specular coefficients
00176      */
00177     F.scale(G/NV);
00178     color.x *= F.x * visitor.specular().x;
00179     color.y *= F.y * visitor.specular().y;
00180     color.z *= F.z * visitor.specular().z;
00181 
00182     /*
00183      * Diffuse component:
00184      *    well-known Lambertian reflection
00185      */
00186     Vector3 auxv(visitor.diffuse());
00187     auxv.scale(NL);
00188     color.add(auxv);
00189 
00190     /*
00191      * Final formula:
00192      *    BRDF = sR_s + dR_d
00193      * where
00194      *    R_s = specular component DGF/(NV)
00195      *    R_d = Lambertian diffuse component
00196      *    s   = specular coefficient
00197      *    d   = diffuse coefficient
00198      *    s+d = 1
00199      */
00200     
00201     return NONZERO_CONTRIB;
00202 }
00203 
00204 BRDF::RetVal CookTorranceBRDF::reflectanceNL(const MatVisitor& visitor,
00205                                              const Vector3*    L,
00206                                              const Vector3*    V,
00207                                              const Vector3*    N,
00208                                              double            NL,
00209                                              Vector3&          color)
00210 {
00211     static Vector3 H;
00212     
00213     /*
00214      * Precomputation of vectors and angles (Blinn-like)
00215      */
00216     if (!N || !L || !V) return BAD_PARAMS;
00217 
00218     register double nv = N->dot(*V);
00219     if (nv <= 0.0) return NV_NEGATIVE;
00220     H.set(*V);
00221     H.add(*L);
00222     H.scale(0.5);
00223     register double hn = H.dot(*N);
00224 
00225     /*
00226      * modelling micro-geometry (normal distribution function):
00227      *    D = k exp[-(alpha/m)^2]
00228      * where
00229      *    k     = any constant
00230      *    alpha = angle of the microfacet with respect to the normal of the
00231      *            (mean) surface = NH
00232      *    m     = standard deviation the distribution
00233      */
00234     color.set(visitor.gaussianCoef());
00235     color.scale(exp(-pow(acos(hn)/visitor.roughness(),2)));
00236 
00237     /*
00238      * shadowing and masking effects:
00239      *    Gm = 2(NH)(NV)/VH
00240      *    Gs = 2(NH)(NL)/VH
00241      *    G  = min{1, Gm, Gs}
00242      */
00243     double aux = (2 * hn) / H.dot(*V);
00244     double Gm  = aux * nv;
00245     double Gs  = aux * NL;
00246     double G   = 1;
00247     if (Gm < G) G = Gm;
00248     if (Gs < G) G = Gs;
00249 
00250 #ifndef WIN32
00251 #warning "TODO: Interpolated Fresnel term"
00252 #endif
00253     /*
00254      * the Fresnel term:
00255      *    F_a = F0 + (1 - cos a)^5 (1 - F0)
00256      * where
00257      *    F0 = value of F at normal incidence, can be computed as
00258      *        F0 = (n-1)^2 / (n+1)^2
00259      *    where
00260      *        n = refractive index of material (zero for dielectric = plastic)
00261      */
00262     Vector3 F(visitor.fresnelTerm());
00263     Vector3 F0(1,1,1);
00264     F0.sub(F);
00265     F0.scale(pow(1-NL,5));
00266     F.add(F0);
00267 
00268     /*
00269      * Specular component:
00270      *    s*(DGF/(NV))
00271      * where
00272      *    NV = glare effect term (view geometry)
00273      *    s  = specular coefficients
00274      */
00275     F.scale(G/nv);
00276     color.x *= F.x * visitor.specular().x;
00277     color.y *= F.y * visitor.specular().y;
00278     color.z *= F.z * visitor.specular().z;
00279 
00280     /*
00281      * Diffuse component:
00282      *    well-known Lambertian reflection
00283      */
00284     Vector3 auxv(visitor.diffuse());
00285     auxv.scale(NL);
00286     color.add(auxv);
00287 
00288     /*
00289      * Final formula:
00290      *    BRDF = sR_s + dR_d
00291      * where
00292      *    R_s = specular component DGF/(NV)
00293      *    R_d = Lambertian diffuse component
00294      *    s   = specular coefficient
00295      *    d   = diffuse coefficient
00296      *    s+d = 1
00297      */
00298     
00299     return NONZERO_CONTRIB;
00300 }
00301 
00302 

Generated on Wed Jun 28 12:24:29 2006 for esg by  doxygen 1.4.6