nuclear@2: #include "brdf.h" nuclear@2: #include "erebus_impl.h" nuclear@2: nuclear@2: // ---- class Reflectance ---- nuclear@2: Reflectance::Reflectance() nuclear@2: { nuclear@2: } nuclear@2: nuclear@2: float Reflectance::sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const nuclear@2: { nuclear@2: *indir = sample_dir(norm, outdir); nuclear@2: return eval(norm, outdir, *indir); nuclear@2: } nuclear@2: nuclear@21: // --- class CompositeRefl ---- nuclear@21: CompositeRefl::CompositeRefl() nuclear@21: { nuclear@21: valid_checked = false; nuclear@21: } nuclear@21: nuclear@21: int CompositeRefl::pick_brdf(const Vector3 &norm, const Vector3 &outdir) const nuclear@21: { nuclear@21: if(sub_brdf.empty()) { nuclear@21: return -1; nuclear@21: } nuclear@21: nuclear@21: int brdf_count = (int)sub_brdf.size(); nuclear@21: if(brdf_count == 1) { nuclear@21: return 0; nuclear@21: } nuclear@21: nuclear@21: // construct CDF from sub-brdf probabilities nuclear@21: float *cdf = (float*)alloca(brdf_count * sizeof *cdf); nuclear@21: for(int i=0; i 0 ? cdf[i - 1] + w : w; nuclear@21: } nuclear@21: nuclear@21: float rval = randf(0.0, cdf[brdf_count - 1]); nuclear@21: for(int i=0; isample_dir(norm, outdir); nuclear@21: } nuclear@21: nuclear@21: float CompositeRefl::sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const nuclear@21: { nuclear@21: int bidx = pick_brdf(norm, outdir); nuclear@21: return sub_brdf[bidx].brdf->sample(norm, outdir, indir); nuclear@21: } nuclear@21: nuclear@21: float CompositeRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const nuclear@21: { nuclear@21: if(!warned_composite_usage) { nuclear@21: fputs(composite_usage_warnstr, stderr); nuclear@21: warned_composite_usage = true; nuclear@21: } nuclear@21: int bidx = pick_brdf(norm, outdir); nuclear@21: return sub_brdf[bidx].brdf->eval(norm, outdir, indir); nuclear@21: } nuclear@21: nuclear@2: // --- class LambertRefl --- nuclear@2: Vector3 LambertRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const nuclear@2: { nuclear@2: Vector3 dir = Vector3{randf(-1, 1), randf(-1, 1), randf(-1, 1)}.normalized(); nuclear@2: return dot_product(dir, norm) < 0.0 ? -dir : dir; nuclear@2: } nuclear@2: nuclear@2: float LambertRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const nuclear@2: { nuclear@2: return dot_product(norm, outdir); nuclear@2: } nuclear@21: nuclear@21: // --- class MirrorRefl --- nuclear@21: Vector3 MirrorRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const nuclear@21: { nuclear@21: return outdir.reflection(norm); nuclear@21: } nuclear@21: nuclear@21: float MirrorRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const nuclear@21: { nuclear@21: return 1.0f; nuclear@21: }