00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "volume.h"
00025
00026 namespace lux
00027 {
00028
00029
00030 float PhaseIsotropic(const Vector &, const Vector &) {
00031 return 1.f / (4.f * M_PI);
00032 }
00033 float PhaseRayleigh(const Vector &w, const Vector &wp) {
00034 float costheta = Dot(w, wp);
00035 return 3.f/(16.f*M_PI) * (1 + costheta * costheta);
00036 }
00037 float PhaseMieHazy(const Vector &w, const Vector &wp) {
00038 float costheta = Dot(w, wp);
00039 return (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI);
00040 }
00041 float PhaseMieMurky(const Vector &w, const Vector &wp) {
00042 float costheta = Dot(w, wp);
00043 return (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI);
00044 }
00045
00046 float PhaseHG(const Vector &w, const Vector &wp, float g) {
00047 float costheta = Dot(w, wp);
00048 return 1.f / (4.f * M_PI) * (1.f - g*g) /
00049 powf(1.f + g*g - 2.f * g * costheta, 1.5f);
00050 }
00051
00052 float PhaseSchlick(const Vector &w,
00053 const Vector &wp, float g) {
00054 float k = 1.55f * g - .55f * g * g * g;
00055 float kcostheta = k * Dot(w, wp);
00056 return 1.f / (4.f * M_PI) * (1.f - k*k) /
00057 ((1.f - kcostheta) * (1.f - kcostheta));
00058 }
00059 RGBColor VolumeRegion::sigma_t(const Point &p,
00060 const Vector &w) const {
00061 return sigma_a(p, w) + sigma_s(p, w);
00062 }
00063 DensityRegion::DensityRegion(const RGBColor &sa,
00064 const RGBColor &ss, float gg,
00065 const RGBColor &emit,
00066 const Transform &VolumeToWorld)
00067 : sig_a(sa), sig_s(ss), le(emit), g(gg) {
00068 WorldToVolume = VolumeToWorld.GetInverse();
00069 }
00070 AggregateVolume::
00071 AggregateVolume(const vector<VolumeRegion *> &r) {
00072 regions = r;
00073 for (u_int i = 0; i < regions.size(); ++i)
00074 bound = Union(bound, regions[i]->WorldBound());
00075 }
00076 RGBColor AggregateVolume::sigma_a(const Point &p,
00077 const Vector &w) const {
00078 RGBColor s(0.);
00079 for (u_int i = 0; i < regions.size(); ++i)
00080 s += regions[i]->sigma_a(p, w);
00081 return s;
00082 }
00083 RGBColor AggregateVolume::sigma_s(const Point &p, const Vector &w) const {
00084 RGBColor s(0.);
00085 for (u_int i = 0; i < regions.size(); ++i)
00086 s += regions[i]->sigma_s(p, w);
00087 return s;
00088 }
00089 RGBColor AggregateVolume::Lve(const Point &p, const Vector &w) const {
00090 RGBColor L(0.);
00091 for (u_int i = 0; i < regions.size(); ++i)
00092 L += regions[i]->Lve(p, w);
00093 return L;
00094 }
00095 float AggregateVolume::P(const Point &p, const Vector &w, const Vector &wp) const {
00096 float ph = 0, sumWt = 0;
00097 for (u_int i = 0; i < regions.size(); ++i) {
00098 float sigt = regions[i]->sigma_t(p, w).Y();
00099 if (sigt != 0.f) {
00100 float wt = regions[i]->sigma_s(p, w).Y() / sigt;
00101 sumWt += wt;
00102 ph += wt * regions[i]->P(p, w, wp);
00103 }
00104 }
00105 return ph / sumWt;
00106 }
00107 RGBColor AggregateVolume::sigma_t(const Point &p, const Vector &w) const {
00108 RGBColor s(0.);
00109 for (u_int i = 0; i < regions.size(); ++i)
00110 s += regions[i]->sigma_t(p, w);
00111 return s;
00112 }
00113 RGBColor AggregateVolume::Tau(const Ray &ray, float step, float offset) const {
00114 RGBColor t(0.);
00115 for (u_int i = 0; i < regions.size(); ++i)
00116 t += regions[i]->Tau(ray, step, offset);
00117 return t;
00118 }
00119 bool AggregateVolume::IntersectP(const Ray &ray,
00120 float *t0, float *t1) const {
00121 *t0 = INFINITY;
00122 *t1 = -INFINITY;
00123 for (u_int i = 0; i < regions.size(); ++i) {
00124 float tr0, tr1;
00125 if (regions[i]->IntersectP(ray, &tr0, &tr1)) {
00126 *t0 = min(*t0, tr0);
00127 *t1 = max(*t1, tr1);
00128 }
00129 }
00130 return (*t0 < *t1);
00131 }
00132 AggregateVolume::~AggregateVolume() {
00133 for (u_int i = 0; i < regions.size(); ++i)
00134 delete regions[i];
00135 }
00136 BBox AggregateVolume::WorldBound() const {
00137 return bound;
00138 }
00139 RGBColor DensityRegion::Tau(const Ray &r,
00140 float stepSize, float u) const {
00141 float t0, t1;
00142 float length = r.d.Length();
00143 if (length == 0.f) return 0.f;
00144 Ray rn(r.o, r.d / length,
00145 r.mint * length,
00146 r.maxt * length);
00147 if (!IntersectP(rn, &t0, &t1)) return 0.;
00148 RGBColor tau(0.);
00149 t0 += u * stepSize;
00150 while (t0 < t1) {
00151 tau += sigma_t(rn(t0), -rn.d);
00152 t0 += stepSize;
00153 }
00154 return tau * stepSize;
00155 }
00156
00157 }
00158