Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample_) const { Point2f sample(sample_); if (Frame::cosTheta(bRec.wi) <= 0) return Color3f(0.0f); bRec.measure = ESolidAngle; // 1. Select diffuse or specular bool useSpecular = true; if (sample.x() <= m_specSamplingWeight) { sample.x() /= m_specSamplingWeight; } else { sample.x() = (sample.x() - m_specSamplingWeight) / m_diffSamplingWeight; useSpecular = false; } if (useSpecular) { // this is a tricky one // See http://mathinfo.univ-reims.fr/IMG/pdf/Using_the_modified_Phong_reflectance_model_for_Physically_based_rendering_-_Lafortune.pdf float sinTheta = std::sqrt(1.0f - std::pow(sample.y(), 2.0f/(m_exp + 1.0f))); float cosTheta = std::pow(sample.y(), 1.0f/(m_exp + 1.0f)); float phi = 2.0f * M_PI * sample.x(); float cosPhi, sinPhi; sincosf(phi, &sinPhi, &cosPhi); // direction from the lobe axis (i.e. reflection of wi) in lobe coordinate Vector3f lobeAxis = reflect(bRec.wi); Vector3f lobeWo( sinTheta * std::cos(phi), sinTheta * std::sin(phi), cosTheta ); bRec.wo = Frame(lobeAxis).toWorld(lobeWo); // check that we are on the hemisphere if(Frame::cosTheta(bRec.wo) <= 0.0f) return Color3f(0.0f); } else { /* Warp a uniformly distributed sample on [0,1]^2 to a direction on a cosine-weighted hemisphere */ bRec.wo = squareToCosineHemisphere(sample); } /* Relative index of refraction: no change */ bRec.eta = 1.0f; // the importance-weighted sample is given by // f / pdf * cos(wo) Color3f f_eval = eval(bRec); float pdf_eval = pdf(bRec); if(pdf_eval <= 0.0f) return Color3f(0.0f); // let's not explode here return f_eval / pdf_eval * Frame::cosTheta(bRec.wo); }
/// Draw a a sample from the BRDF model Color3f sample(BSDFQueryRecord &bRec, const Point2f &sample) const { if (Frame::cosTheta(bRec.wi) <= 0) return Color3f(0.0f); bRec.measure = ESolidAngle; /* Warp a uniformly distributed sample on [0,1]^2 to a direction on a cosine-weighted hemisphere */ bRec.wo = squareToCosineHemisphere(sample); /* eval() / pdf() * cos(theta) = albedo. There is no need to call these functions. */ return m_albedo; }