/** * Compute the diffusely reemited light data and place the result into reemited. * localBasis : the object localBasis at the computation point. * surfaceCoordinate : the surface coordinate (texture coordinate) of the computation * point on the object. * incident : the incident ray (light ray) * view : the view ray (from the camera or bounced) * incidentLight : the incident light comming from the incident ray. * reemitedLight : the light reemited into the view direction (result will be placed * here). */ void RoughLambertianBRDF::getDiffuseReemited(const Basis& localBasis, const Point2D& surfaceCoordinate, const LightVector& incidentLight, LightVector& reemitedLight) { Vector view = reemitedLight.getRay().v; Vector incident = incidentLight.getRay().v; Real cosOi = -incident.dot(localBasis.k); Real cosOv = -view.dot(localBasis.k); if(cosOi <= 0) { reemitedLight.clear(); return; } if(cosOi>=1.0) cosOi=1.0; if(cosOv>=1.0) cosOv=1.0; Real Oi = std::acos(cosOi); Real Ov = std::acos(cosOv); Real Pi = std::atan2(incident.dot(localBasis.j), incident.dot(localBasis.i)); Real Pv = std::atan2(view.dot(localBasis.j), view.dot(localBasis.i)); Real factor = OrenNayarFormula::orenNayarReflectance(Oi, Pi, Ov, Pv, _roughness); for(unsigned int i=0; i<reemitedLight.size(); i++) reemitedLight[i].setRadiance(incidentLight[i].getRadiance()*_spectrum[incidentLight[i].getIndex()]*factor); reemitedLight.changeReemitedPolarisationFramework(localBasis.k); }
/** * Compute the secondary rays for diffuse reflexion and place them into the subrays * vector. * localBasis : the local base on the object at the computation point. * surfaceCoordinate : the surface coordinate (texture coordinate) of the computation * point on the object. * view : the view ray (from the camera or bounced) * nbRays : the number of wanted ray. It is an indicative information. * subrays : the vector were the secondaries rays will be put. * weights : the weights corresponding to the distribution */ void RoughLambertianBRDF::getRandomDiffuseRay(const Basis& localBasis, const Point2D& surfaceCoordinate, LightVector& reemitedLight, unsigned int nbRays, std::vector<LightVector>& subrays) { Vector normal=localBasis.k; if(normal.dot(reemitedLight.getRay().v)>0) normal.mul(-1); for(unsigned int i=0; i<nbRays; i++) { Vector incident; Real norm2; Real cosOi; do{ incident[0]=rand()*2.0/RAND_MAX - 1.0; incident[1]=rand()*2.0/RAND_MAX - 1.0; incident[2]=rand()*2.0/RAND_MAX - 1.0; norm2=incident.square(); incident.normalize(); cosOi=incident.dot(normal); }while(norm2>cosOi*cosOi || cosOi<=0.0); LightVector subray; subray.setRay(localBasis.o, incident); subray.changeReemitedPolarisationFramework(normal); subray.initSpectralData(reemitedLight); subray.setWeight(1.0/M_PI); subrays.push_back(subray); } }
/** * Compute the diffusely reemited light data and place the result into reemited. * localBasis : the object localBasis at the computation point. * surfaceCoordinate : the surface coordinate (texture coordinate) of the computation * point on the object. * incident : the incident ray (light ray) * view : the view ray (from the camera or bounced) * incidentLight : the incident light comming from the incident ray. * reemitedLight : the light reemited into the view direction (result will be placed * here). */ void BeckmannBRDF::getDiffuseReemited(const Basis& localBasis, const Point2D& surfaceCoordinate, const LightVector& incidentLight, LightVector& reemitedLight) { const Vector& incident = incidentLight.getRay().v; const Vector& view = reemitedLight.getRay().v; //Computing the micro normal Vector microNormal; microNormal.setsum(incident, view); microNormal.mul(-1.0); microNormal.normalize(); //Computing some cosinuses and sinuses Real cosLN = -localBasis.k.dot(incident); // incident and normal Real cosVN = -localBasis.k.dot(view); // view and normal Real cosHN = localBasis.k.dot(microNormal); // micro normal and normal Real cosLH = -microNormal.dot(incident); // incident and micro normal Real cosVH = -microNormal.dot(view); // view and micro normal //Compute Beckmann and Shadowing&masking coeficients Real beckmann = BeckmannRoughnessFormula::BeckmannDistribution(cosHN, _roughness); Real shadmask = BeckmannRoughnessFormula::BeckmannShadowMasking(cosLN, cosVN, cosVH, cosHN); //Setting the polarisation framework LightVector localIncidentLight(incidentLight); localIncidentLight.changeIncidentPolarisationFramework(microNormal); localIncidentLight.flip(); reemitedLight.changeReemitedPolarisationFramework(microNormal); if(cosVN <=0.001 || cosLN <=0.001) { reemitedLight.clear(); return; } //Computing reflectances for each wavelength for(unsigned int i=0; i<localIncidentLight.size(); i++) { Real ROrth, RPara; getReflectance(cosLH, localIncidentLight[i].getIndex(), ROrth, RPara); reemitedLight[i].applyReflectance(localIncidentLight[i], RPara*beckmann*shadmask, ROrth*beckmann*shadmask); } }
void BeckmannBRDF::getDiffuseReemitedFromAmbiant(const Basis& localBasis, const Point2D& surfaceCoordinate, LightVector& reemitedLight, const Spectrum& incident) { const Vector& light = localBasis.k; const Vector& view = reemitedLight.getRay().v; //Computing the micro normal Vector microNormal; microNormal.setsum(light, view); microNormal.mul(-1.0); microNormal.normalize(); //Computing some cosinuses and sinuses Real cosLN = -localBasis.k.dot(light); // light and normal Real cosVN = -localBasis.k.dot(view); // view and normal Real cosHN = localBasis.k.dot(microNormal); // micro normal and normal Real cosLH = -microNormal.dot(light); // light and micro normal Real cosVH = -microNormal.dot(view); // view and micro normal //Compute Beckmann and Shadowing&masking coeficients Real beckmann = BeckmannRoughnessFormula::BeckmannDistribution(cosHN, _roughness); Real shadmask = BeckmannRoughnessFormula::BeckmannShadowMasking(cosLN, cosVN, cosVH, cosHN); if(cosVN <=0.001 ) { reemitedLight.clear(); return; } for(unsigned int wl=0; wl < reemitedLight.size(); wl++) { Real ROrth, RPara; getReflectance(cosLH, wl, ROrth, RPara); ROrth *= beckmann * shadmask; RPara *= beckmann * shadmask; reemitedLight[wl].setRadiance(incident[wl] /** cosVN*/ * 0.5 * (ROrth + RPara)); } reemitedLight.changeReemitedPolarisationFramework(microNormal); }
/** * Compute the secondary rays for diffuse reflexion and place them into the subrays * vector. * localBasis : the local base on the object at the computation point. * surfaceCoordinate : the surface coordinate (texture coordinate) of the computation * point on the object. * view : the view ray (from the camera or bounced) * nbRays : the number of wanted ray. It is an indicative information. * subrays : the vector were the secondaries rays will be put. * weights : the weights corresponding to the distribution */ void BeckmannBRDF::getRandomDiffuseRay(const Basis& localBasis, const Point2D& surfaceCoordinate, LightVector& reemitedLight, unsigned int nbRays, std::vector<LightVector>& subrays) { Vector view = reemitedLight.getRay().v; view.mul(-1.0); if(view.dot(localBasis.k)<0) return; for(unsigned int i=0; i<nbRays; i++) { Vector dir; Real weight; BeckmannRoughnessFormula::getBeckmannRandomRay(localBasis, view, _roughness, weight, dir); LightVector subray; subray.setRay(localBasis.o, dir); subray.initSpectralData(reemitedLight); subray.changeReemitedPolarisationFramework(localBasis.k); subray.setWeight(weight); subrays.push_back(subray); } }