erebus
diff liberebus/src/brdf.cc @ 21:e49f4d7ad04c
started adding BRDFs
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 28 May 2014 07:06:29 +0300 |
parents | 93894c232d65 |
children | 4a0a288ffb27 |
line diff
1.1 --- a/liberebus/src/brdf.cc Tue May 27 07:49:09 2014 +0300 1.2 +++ b/liberebus/src/brdf.cc Wed May 28 07:06:29 2014 +0300 1.3 @@ -12,6 +12,102 @@ 1.4 return eval(norm, outdir, *indir); 1.5 } 1.6 1.7 +// --- class CompositeRefl ---- 1.8 +CompositeRefl::CompositeRefl() 1.9 +{ 1.10 + valid_checked = false; 1.11 +} 1.12 + 1.13 +int CompositeRefl::pick_brdf(const Vector3 &norm, const Vector3 &outdir) const 1.14 +{ 1.15 + if(sub_brdf.empty()) { 1.16 + return -1; 1.17 + } 1.18 + 1.19 + int brdf_count = (int)sub_brdf.size(); 1.20 + if(brdf_count == 1) { 1.21 + return 0; 1.22 + } 1.23 + 1.24 + // construct CDF from sub-brdf probabilities 1.25 + float *cdf = (float*)alloca(brdf_count * sizeof *cdf); 1.26 + for(int i=0; i<brdf_count; i++) { 1.27 + const SubRefl &sub = sub_brdf[i]; 1.28 + float w = sub.weight_func ? sub.weight_func(norm, outdir) : sub.weight; 1.29 + cdf[i] = i > 0 ? cdf[i - 1] + w : w; 1.30 + } 1.31 + 1.32 + float rval = randf(0.0, cdf[brdf_count - 1]); 1.33 + for(int i=0; i<brdf_count - 1; i++) { 1.34 + if(rval <= cdf[i]) return i; 1.35 + } 1.36 + return brdf_count - 1; 1.37 +} 1.38 + 1.39 +void CompositeRefl::add_brdf(Reflectance *brdf, float weight) 1.40 +{ 1.41 + SubRefl sub; 1.42 + sub.brdf = brdf; 1.43 + sub.weight = weight; 1.44 + sub.weight_func = 0; 1.45 + sub_brdf.push_back(sub); 1.46 + 1.47 + valid_checked = false; 1.48 +} 1.49 + 1.50 +void CompositeRefl::add_brdf(Reflectance *brdf, CompReflWeightFunc weight_func) 1.51 +{ 1.52 + SubRefl sub; 1.53 + sub.brdf = brdf; 1.54 + sub.weight = 0.0; 1.55 + sub.weight_func = weight_func; 1.56 + sub_brdf.push_back(sub); 1.57 + 1.58 + valid_checked = false; 1.59 +} 1.60 + 1.61 +bool CompositeRefl::check_valid() const 1.62 +{ 1.63 + float sum = 0.0; 1.64 + for(size_t i=0; i<sub_brdf.size(); i++) { 1.65 + if(!sub_brdf[i].weight_func) { 1.66 + sum += sub_brdf[i].weight; 1.67 + } 1.68 + } 1.69 + return sum < 1.0001; 1.70 +} 1.71 + 1.72 +static bool warned_composite_usage; 1.73 +static const char *composite_usage_warnstr = 1.74 + "warning: don't call CompositeRefl's sample_dir and eval separately\n" 1.75 + " it'll pick different brdfs each time! use sample instead\n"; 1.76 + 1.77 +Vector3 CompositeRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const 1.78 +{ 1.79 + if(!warned_composite_usage) { 1.80 + fputs(composite_usage_warnstr, stderr); 1.81 + warned_composite_usage = true; 1.82 + } 1.83 + int bidx = pick_brdf(norm, outdir); 1.84 + return sub_brdf[bidx].brdf->sample_dir(norm, outdir); 1.85 +} 1.86 + 1.87 +float CompositeRefl::sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const 1.88 +{ 1.89 + int bidx = pick_brdf(norm, outdir); 1.90 + return sub_brdf[bidx].brdf->sample(norm, outdir, indir); 1.91 +} 1.92 + 1.93 +float CompositeRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const 1.94 +{ 1.95 + if(!warned_composite_usage) { 1.96 + fputs(composite_usage_warnstr, stderr); 1.97 + warned_composite_usage = true; 1.98 + } 1.99 + int bidx = pick_brdf(norm, outdir); 1.100 + return sub_brdf[bidx].brdf->eval(norm, outdir, indir); 1.101 +} 1.102 + 1.103 // --- class LambertRefl --- 1.104 Vector3 LambertRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const 1.105 { 1.106 @@ -23,3 +119,14 @@ 1.107 { 1.108 return dot_product(norm, outdir); 1.109 } 1.110 + 1.111 +// --- class MirrorRefl --- 1.112 +Vector3 MirrorRefl::sample_dir(const Vector3 &norm, const Vector3 &outdir) const 1.113 +{ 1.114 + return outdir.reflection(norm); 1.115 +} 1.116 + 1.117 +float MirrorRefl::eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const 1.118 +{ 1.119 + return 1.0f; 1.120 +}