00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "bsdf.h"
00024 #include "context.h"
00025
00026 #include <cassert>
00027
00028 using namespace sheep;
00029 using namespace std;
00030 using namespace toxic;
00031
00032 BSDF::BSDF() :
00033 m_total_weight(0.0)
00034 {
00035 }
00036
00037 void BSDF::Insert(const IBRDF *brdf, Real weight) {
00038 assert(brdf);
00039 assert(weight >= 0.0 && weight <= 1.0);
00040
00041 m_brdfs.push_back(make_pair(brdf, weight));
00042
00043 if(brdf->IsSpecular())
00044 m_specular_brdfs.push_back(make_pair(brdf, weight));
00045
00046 m_total_weight += weight;
00047 assert(m_total_weight <= 1.0);
00048 }
00049
00050 void BSDF::Insert(const IBTDF *btdf, Real weight) {
00051 assert(btdf);
00052 assert(weight >= 0.0 && weight <= 1.0);
00053
00054 m_btdfs.push_back(make_pair(btdf, weight));
00055
00056 if(btdf->IsSpecular())
00057 m_specular_btdfs.push_back(make_pair(btdf, weight));
00058
00059 m_total_weight += weight;
00060 assert(m_total_weight <= 1.0);
00061 }
00062
00063 Real BSDF::Evaluate(const Context &context,
00064 const Vector3 &incoming,
00065 const Vector3 &outgoing) const
00066 {
00067 assert(incoming.m_y > 0.0);
00068 assert(incoming.IsUnitLength());
00069 assert(outgoing.m_y > 0.0);
00070 assert(outgoing.IsUnitLength());
00071
00072 Real value = 0.0;
00073
00074 if(incoming.m_y * outgoing.m_y >= 0.0) {
00075
00076 for(brdf_vector_const_it i = m_brdfs.begin(), e = m_brdfs.end(); i != e; ++i)
00077 value += i->second * i->first->Evaluate(context, incoming, outgoing);
00078 } else {
00079
00080 for(btdf_vector_const_it i = m_btdfs.begin(), e = m_btdfs.end(); i != e; ++i)
00081 value += i->second * i->first->Evaluate(context, incoming, outgoing);
00082 }
00083
00084
00085
00086 return value;
00087 }
00088
00089 Real BSDF::EvaluateSpecular(const Context &context,
00090 const Vector3 &incoming,
00091 Vector3 *outgoing) const
00092 {
00093 assert(incoming.m_y > 0.0);
00094 assert(incoming.IsUnitLength());
00095 assert(outgoing);
00096
00097
00098
00099 const int index = context.m_rng->RandomInt(0, m_specular_brdfs.size() + m_specular_btdfs.size() - 1);
00100 const IBDF *chosen_bdf;
00101 Real chosen_bdf_weight;
00102 if(index < m_specular_brdfs.size()) {
00103 chosen_bdf = m_specular_brdfs[index].first;
00104 chosen_bdf_weight = m_specular_brdfs[index].second;
00105 } else {
00106 chosen_bdf = m_specular_btdfs[index - m_specular_brdfs.size()].first;
00107 chosen_bdf_weight = m_specular_btdfs[index - m_specular_brdfs.size()].second;
00108 }
00109
00110
00111 return chosen_bdf_weight * chosen_bdf->EvaluateSpecular(context, incoming, outgoing);
00112 }
00113
00114 void BSDF::Sample(const Context &context,
00115 const Vector3 &incoming,
00116 Vector3 *outgoing,
00117 Real *prob,
00118 Real *value) const
00119 {
00120 assert(incoming.m_y > 0.0);
00121 assert(incoming.IsUnitLength());
00122 assert(outgoing);
00123 assert(prob);
00124 assert(value);
00125
00126
00127
00128 const int index = context.m_rng->RandomInt(0, m_brdfs.size() + m_btdfs.size() - 1);
00129 const IBDF *chosen_bdf;
00130 if(index < m_brdfs.size())
00131 chosen_bdf = m_brdfs[index].first;
00132 else chosen_bdf = m_btdfs[index - m_brdfs.size()].first;
00133
00134
00135 chosen_bdf->Sample(context, incoming, outgoing, prob, value);
00136
00137
00138
00139 for(brdf_vector_const_it i = m_brdfs.begin(), e = m_brdfs.end(); i != e; ++i) {
00140 if(i->first != chosen_bdf)
00141 *prob += i->first->ComputeScatteringProbability(incoming, *outgoing);
00142 }
00143
00144 for(btdf_vector_const_it i = m_btdfs.begin(), e = m_btdfs.end(); i != e; ++i) {
00145 if(i->first != chosen_bdf)
00146 *prob += i->first->ComputeScatteringProbability(incoming, *outgoing);
00147 }
00148
00149
00150 *prob /= m_brdfs.size() + m_btdfs.size();
00151
00152 assert(*prob <= 1.0);
00153 }
00154
00155 Real BSDF::ComputeScatteringProbability(const Vector3 &incoming,
00156 const Vector3 &outgoing) const
00157 {
00158
00159
00160 Real scatteringprob = 0.0;
00161
00162 for(brdf_vector_const_it i = m_brdfs.begin(), e = m_brdfs.end(); i != e; ++i)
00163 scatteringprob += i->first->ComputeScatteringProbability(incoming, outgoing);
00164
00165 for(btdf_vector_const_it i = m_btdfs.begin(), e = m_btdfs.end(); i != e; ++i)
00166 scatteringprob += i->first->ComputeScatteringProbability(incoming, outgoing);
00167
00168
00169 scatteringprob /= m_brdfs.size() + m_btdfs.size();
00170
00171 assert(scatteringprob <= 1.0);
00172
00173 return scatteringprob;
00174 }
00175
00176 Real BSDF::ComputeReflectance(const Context &context) const {
00177 Real reflectance = 0.0;
00178
00179 for(brdf_vector_const_it i = m_brdfs.begin(), e = m_brdfs.end(); i != e; ++i)
00180 reflectance += i->second * i->first->ComputeReflectance(context);
00181
00182 for(btdf_vector_const_it i = m_btdfs.begin(), e = m_btdfs.end(); i != e; ++i)
00183 reflectance += i->second * i->first->ComputeReflectance(context);
00184
00185 return reflectance;
00186 }
00187
00188 Real BSDF::ComputeReflectance(const Context &context,
00189 const Vector3 &incoming) const
00190 {
00191 assert(incoming.m_y > 0.0);
00192 assert(incoming.IsUnitLength());
00193
00194 Real reflectance = 0.0;
00195
00196 for(brdf_vector_const_it i = m_brdfs.begin(), e = m_brdfs.end(); i != e; ++i)
00197 reflectance += i->second * i->first->ComputeReflectance(context, incoming);
00198
00199 for(btdf_vector_const_it i = m_btdfs.begin(), e = m_btdfs.end(); i != e; ++i)
00200 reflectance += i->second * i->first->ComputeReflectance(context, incoming);
00201
00202 return reflectance;
00203 }