erebus
changeset 21:e49f4d7ad04c
started adding BRDFs
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 28 May 2014 07:06:29 +0300 |
parents | ea95b62dbc87 |
children | 11cdaa510201 |
files | liberebus/src/brdf.cc liberebus/src/brdf.h src/main.cc |
diffstat | 3 files changed, 147 insertions(+), 4 deletions(-) [+] |
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 +}
2.1 --- a/liberebus/src/brdf.h Tue May 27 07:49:09 2014 +0300 2.2 +++ b/liberebus/src/brdf.h Wed May 28 07:06:29 2014 +0300 2.3 @@ -1,6 +1,7 @@ 2.4 #ifndef BRDF_H_ 2.5 #define BRDF_H_ 2.6 2.7 +#include <vector> 2.8 #include "texture.h" 2.9 2.10 class Reflectance { 2.11 @@ -13,10 +14,43 @@ 2.12 virtual float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const = 0; 2.13 }; 2.14 2.15 +typedef float (*CompReflWeightFunc)(const Vector3 &norm, const Vector3 &outdir); 2.16 + 2.17 +class CompositeRefl : public Reflectance { 2.18 +private: 2.19 + struct SubRefl { 2.20 + Reflectance *brdf; 2.21 + float weight; 2.22 + CompReflWeightFunc weight_func; // if null, use static weight above 2.23 + }; 2.24 + std::vector<SubRefl> sub_brdf; 2.25 + mutable bool valid_checked; 2.26 + 2.27 + int pick_brdf(const Vector3 &norm, const Vector3 &outdir) const; 2.28 + 2.29 +public: 2.30 + CompositeRefl(); 2.31 + 2.32 + virtual void add_brdf(Reflectance *brdf, float weight); 2.33 + virtual void add_brdf(Reflectance *brdf, CompReflWeightFunc weight_func); 2.34 + 2.35 + bool check_valid() const; 2.36 + 2.37 + Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const override; 2.38 + float sample(const Vector3 &norm, const Vector3 &outdir, Vector3 *indir) const override; 2.39 + float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; 2.40 +}; 2.41 + 2.42 class LambertRefl : public Reflectance { 2.43 public: 2.44 Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const override; 2.45 float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; 2.46 }; 2.47 2.48 +class MirrorRefl : public Reflectance { 2.49 +public: 2.50 + Vector3 sample_dir(const Vector3 &norm, const Vector3 &outdir) const override; 2.51 + float eval(const Vector3 &norm, const Vector3 &outdir, const Vector3 &indir) const override; 2.52 +}; 2.53 + 2.54 #endif // BRDF_H_
3.1 --- a/src/main.cc Tue May 27 07:49:09 2014 +0300 3.2 +++ b/src/main.cc Wed May 28 07:06:29 2014 +0300 3.3 @@ -75,10 +75,12 @@ 3.4 } 3.5 } 3.6 3.7 - printf("begin rendering\n"); 3.8 - render_pending = true; 3.9 - glutIdleFunc(idle); 3.10 - erb_begin_frame(erb, 0); 3.11 + if(!sfiles.empty()) { 3.12 + printf("begin rendering\n"); 3.13 + render_pending = true; 3.14 + glutIdleFunc(idle); 3.15 + erb_begin_frame(erb, 0); 3.16 + } 3.17 3.18 glEnable(GL_TEXTURE_2D); 3.19 return true;