/************************************************************************ * material.h - Functions which compute the light response of materials. * * Author: Larry Gritz (lg AT larrygritz DOT com) * * Reference: * _Advanced RenderMan: Creating CGI for Motion Picture_, * by Anthony A. Apodaca and Larry Gritz, Morgan Kaufmann, 1999. * * $Revision: 1.2 $ $Date: 2003/12/24 06:18:06 $ * ************************************************************************/ #ifndef MATERIAL_H #define MATERIAL_H #include "locillum.h" #include "reflections.h" /* Compute the color of the surface using a simple plastic-like BRDF. * Typical values are Ka=1, Kd=0.8, Ks=0.5, roughness=0.1. */ color MaterialPlastic (normal Nf; color basecolor; float Ka, Kd, Ks, roughness;) { extern vector I; return basecolor * (Ka*ambient() + Kd*diffuse(Nf)) + Ks*specular(Nf,-normalize(I),roughness); } /* Compute the color of the surface using a simple Lambertian BRDF. */ color MaterialMatte (normal Nf; color basecolor; float Ka, Kd;) { return basecolor * (Ka*ambient() + Kd*diffuse(Nf)); } /* Compute the color of the surface using a simple metal-like BRDF. To * give a metallic appearance, both diffuse and specular components are * scaled by the color of the metal. It is recommended that Kd < 0.1, * Ks > 0.5, and roughness > 0.15 to give a believable metallic appearance. */ color MaterialRoughMetal (normal Nf; color basecolor; float Ka, Kd, Ks, roughness;) { extern vector I; return basecolor * (Ka*ambient() + Kd*diffuse(Nf) + Ks*specular(Nf,-normalize(I),roughness)); } /* Compute the color of the surface using a simple thin plastic-like BRDF. * We call it _thin_ because it includes a transmisison component to allow * light from the _back_ of the surface to affect the appearance. Typical * values are Ka=1, Kd=0.8, Kt = 0.2, Ks=0.5, roughness=0.1. */ color MaterialThinPlastic (normal Nf; vector V; color basecolor; float Ka, Kd, Kt, Ks, roughness;) { return basecolor * (Ka*ambient() + Kd*diffuse(Nf) + Kt*diffuse(-Nf)) + Ks*specular(Nf,V,roughness); } /* Compute the color of the surface using a simple plastic-like BRDF, with * fresnel-attenuated coherent reflections. * If twosided is nonzero, both sides are shiny, but if you know that * the object has N facing outward, twosided==0 is a good optimization * (especially when using the ray server). */ color MaterialShinyPlastic (normal Nf; color basecolor; float Ka, Kd, Ks, roughness, Kr, blur, ior; uniform float twosided; DECLARE_ENVPARAMS; ) { extern vector I; extern point P; extern normal N; vector IN = normalize(I), V = -IN; float fkr, fkt; vector R, T; fresnel (IN, Nf, 1/ior, fkr, fkt, R, T); fkt = 1-fkr; if (twosided == 0 && N.I > 0) fkr = 0; return fkt * basecolor * (Ka*ambient() + Kd*diffuse(Nf)) + (Ks) * specular(Nf,V,roughness) + SampleEnvironment (P, R, fkr*Kr, blur, ENVPARAMS); } /* Compute the color of the surface using a simple metal-like BRDF. To * give a metallic appearance, both diffuse and specular components are * scaled by the color of the metal. It is recommended that Kd < 0.1, * Ks > 0.5, and roughness > 0.15 to give a believable metallic appearance. * If twosided is nonzero, both sides are shiny, but if you know that * the object has N facing outward, twosided==0 is a good optimization * (especially when using the ray server). */ color MaterialShinyMetal (normal Nf; color basecolor; float Ka, Kd, Ks, roughness, Kr, blur; uniform float twosided; DECLARE_ENVPARAMS;) { extern point P; extern vector I; extern normal N; float kr = Kr; if (twosided == 0 && N.I > 0) kr = 0; vector IN = normalize(I), V = -IN; vector R = reflect (IN, Nf); return basecolor * (Ka*ambient() + Kd*diffuse(Nf) + Ks*specular(Nf,V,roughness) + SampleEnvironment (P, R, kr, blur, ENVPARAMS)); } /* Compute the color of the surface of a very rough, totally nonspecular * material like clay. Use an Oren/Nayar BRDF for the diffuse term. */ color MaterialClay (normal Nf; color basecolor; float Ka, Kd, roughness;) { extern vector I; return basecolor * (Ka*ambient() + Kd*LocIllumOrenNayar(Nf,-normalize(I),roughness)); } /* Compute the color of the surface using an anisotropic BRDF. To * give a metallic appearance, both diffuse and specular components are * scaled by the color of the metal. It is recommended that Kd < 0.1, * Ks > 0.5, and roughness > 0.15 to give a believable metallic appearance. */ color MaterialBrushedMetal (normal Nf; color basecolor; float Ka, Kd, Ks; vector xdir; float uroughness, vroughness;) { extern vector I; color spec = LocIllumWardAnisotropic (Nf, -normalize(I), xdir, uroughness, vroughness); return basecolor * (Ka*ambient() + Kd*diffuse(Nf) + Ks*spec); } /* Compute the color of a ceramic object. Like plastic, but use a * "glossy" specular term. */ color MaterialCeramic (normal Nf; color basecolor; float Ka, Kd, Ks, roughness, specsharpness;) { extern vector I; vector V = -normalize(I); return basecolor * (Ka*ambient() + Kd*diffuse(Nf)) + Ks * LocIllumGlossy (Nf, V, roughness/10, specsharpness); } /* Compute the color of a glass-like surface with coherent reflections * and refractions. */ color MaterialGlass (normal Nf; color basecolor; float Ka, Kd, Ks, roughness, Kr, reflblur; float Kt, refrblur, eta; color transmitcolor; uniform float refrrayjitter, refrraysamples; DECLARE_ENVPARAMS;) { extern point P; extern vector I; extern normal N; vector IN = normalize (I); /* Compute the reflection & refraction directions and amounts */ vector Rfldir, Rfrdir; /* Smooth reflection/refraction directions */ float kr, kt; fresnel (IN, Nf, (I.N < 0) ? 1.0/eta : eta, kr, kt, Rfldir, Rfrdir); kt = 1-kr; /* Physically incorrect, but portable */ kr *= Kr; kt *= Kt; #if (defined(BMRT) || defined(RAYSERVER_H)) /* Speedup -- at deep ray levels, reflection is unimportant */ if (raylevel() > 0) kr = 0; #endif #ifndef BMRT /* Speedup for PRMan -- don't shade back sides, but you HAVE to be sure * that normals correctly face outward. */ if (N.I > 0) kr = kt = 0; #endif /* Calculate the reflection & refraction color */ color Crefl = SampleEnvironment (P, normalize(Rfldir), kr, reflblur, ENVPARAMS); color Crefr = SampleEnvironment (P, normalize(Rfrdir), kt, refrblur, envname, envspace, envrad, refrrayjitter, refrraysamples); return (basecolor * (Ka*ambient() + Kd*diffuse(Nf)) + (Crefl + Ks*LocIllumGlossy(Nf,-IN,roughness,0.5)) + transmitcolor * Crefr); } #endif /* defined(MATERIAL_H) */