00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "stdafx.h"
00027 #include "volume.h"
00028
00029
00030 struct MeasuredSS {
00031 const char *name;
00032 float sigma_prime_s[3], sigma_a[3];
00033 };
00034
00035
00036 static MeasuredSS mss[] = {
00037
00038
00039
00040 { "Apple", { 2.29, 2.39, 1.97 }, { 0.0030, 0.0034, 0.046 }, },
00041 { "Chicken1", { 0.15, 0.21, 0.38 }, { 0.015, 0.077, 0.19 }, },
00042 { "Chicken2", { 0.19, 0.25, 0.32 }, { 0.018, 0.088, 0.20 }, },
00043 { "Cream", { 7.38, 5.47, 3.15 }, { 0.0002, 0.0028, 0.0163 }, },
00044 { "Ketchup", { 0.18, 0.07, 0.03 }, { 0.061, 0.97, 1.45 }, },
00045 { "Marble", { 2.19, 2.62, 3.00 }, { 0.0021, 0.0041, 0.0071 }, },
00046 { "Potato", { 0.68, 0.70, 0.55 }, { 0.0024, 0.0090, 0.12 }, },
00047 { "Skimmilk", { 0.70, 1.22, 1.90 }, { 0.0014, 0.0025, 0.0142 }, },
00048 { "Skin1", { 0.74, 0.88, 1.01 }, { 0.032, 0.17, 0.48 }, },
00049 { "Skin2", { 1.09, 1.59, 1.79 }, { 0.013, 0.070, 0.145 }, },
00050 { "Spectralon", { 11.6, 20.4, 14.9 }, { 0.00, 0.00, 0.00 }, },
00051 { "Wholemilk", { 2.55, 3.21, 3.77 }, { 0.0011, 0.0024, 0.014 }, },
00052
00053
00054
00055
00056 { "Lowfat Milk", { 0.912600, 1.074800, 1.250000 }, { 0.000200, 0.000400, 0.000800 } },
00057 { "Reduced Milk", { 1.075000, 1.221300, 1.394100 }, { 0.000200, 0.000400, 0.001000 } },
00058 { "Regular Milk", { 1.187400, 1.329600, 1.460200 }, { 0.000100, 0.000300, 0.001300 } },
00059 { "Espresso", { 0.437600, 0.511500, 0.604800 }, { 0.166900, 0.228700, 0.307800 } },
00060 { "Mint Mocha Coffee", { 0.190000, 0.260000, 0.350000 }, { 0.098400, 0.151900, 0.204000 } },
00061 { "Lowfat Soy Milk", { 0.141900, 0.162500, 0.274000 }, { 0.000100, 0.000500, 0.002500 } },
00062 { "Regular Soy Milk", { 0.243400, 0.271900, 0.459700 }, { 0.000100, 0.000500, 0.003400 } },
00063 { "Lowfat Chocolate Milk", { 0.428200, 0.501400, 0.579100 }, { 0.000500, 0.001600, 0.006800 } },
00064 { "Regular Chocolate Milk", { 0.735900, 0.917200, 1.068800 }, { 0.000700, 0.003000, 0.010000 } },
00065 { "Coke", { 0.714300, 1.168800, 1.716900 }, { 0.696600, 1.148000, 1.716900 } },
00066 { "Pepsi", { 0.643300, 0.999000, 1.442000 }, { 0.637500, 0.984900, 1.442000 } },
00067 { "Sprite", { 0.129900, 0.128300, 0.139500 }, { 0.123000, 0.119400, 0.130600 } },
00068 { "Gatorade", { 0.400900, 0.418500, 0.432400 }, { 0.161700, 0.125800, 0.057900 } },
00069 { "Chardonnay", { 0.157700, 0.174800, 0.351200 }, { 0.154700, 0.170100, 0.344300 } },
00070 { "White Zinfandel", { 0.176300, 0.237000, 0.291300 }, { 0.173200, 0.232200, 0.284700 } },
00071 { "Merlot", { 0.763900, 1.642900, 1.919600 }, { 0.758600, 1.642900, 1.919600 } },
00072 { "Budweiser Beer", { 0.148600, 0.321000, 0.736000 }, { 0.144900, 0.314100, 0.728600 } },
00073 { "Coors Light Beer", { 0.029500, 0.066300, 0.152100 }, { 0.026800, 0.060800, 0.152100 } },
00074 { "Clorox", { 0.160000, 0.250000, 0.330000 }, { 0.017500, 0.077700, 0.137200 } },
00075 { "Apple Juice", { 0.121500, 0.210100, 0.440700 }, { 0.101400, 0.185800, 0.408400 } },
00076 { "Cranberry Juice", { 0.270000, 0.630000, 0.830000 }, { 0.257200, 0.614500, 0.810400 } },
00077 { "Grape Juice", { 0.550000, 1.250000, 1.530000 }, { 0.542800, 1.250000, 1.530000 } },
00078 { "Ruby Grapefruit Juice", { 0.251300, 0.351700, 0.430500 }, { 0.089600, 0.191100, 0.263600 } },
00079 { "White Grapefruit Juice", { 0.360900, 0.380000, 0.563200 }, { 0.009600, 0.013100, 0.039500 } },
00080 { "Shampoo", { 0.028800, 0.071000, 0.095200 }, { 0.018400, 0.059600, 0.080500 } },
00081 { "Strawberry Shampoo", { 0.021700, 0.078800, 0.102200 }, { 0.018900, 0.075600, 0.098900 } },
00082 { "Head & Shoulders Shampoo", { 0.367400, 0.452700, 0.521100 }, { 0.088300, 0.163700, 0.212500 } },
00083 { "Lemon Tea", { 0.340000, 0.580000, 0.880000 }, { 0.260200, 0.490200, 0.772700 } },
00084 { "Orange Juice Powder", { 0.337700, 0.557300, 1.012200 }, { 0.144900, 0.344100, 0.786300 } },
00085 { "Pink Lemonade", { 0.240000, 0.370000, 0.450000 }, { 0.116500, 0.236600, 0.319500 } },
00086 { "Cappuccino Powder", { 0.257400, 0.353600, 0.484000 }, { 0.192000, 0.265400, 0.327200 } },
00087 { "Salt Powder", { 0.760000, 0.868500, 0.936300 }, { 0.511500, 0.586300, 0.614700 } },
00088 { "Sugar Powder", { 0.079500, 0.175900, 0.278000 }, { 0.065000, 0.159700, 0.257800 } },
00089 { "Suisse Mocha", { 0.509800, 0.647600, 0.794400 }, { 0.187500, 0.289300, 0.379600 } },
00090 { "Pacific Ocean Surface Water", { 3.364500, 3.315800, 3.242800 }, { 3.184500, 3.132400, 3.014700 } },
00091
00092 };
00093
00094
00095 static float RdIntegral(float alphap, float A) {
00096 float sqrtTerm = sqrtf(3.f * (1.f - alphap));
00097 return alphap / 2.f * (1.f + expf(-4.f/3.f * A * sqrtTerm)) *
00098 expf(-sqrtTerm);
00099 }
00100
00101
00102 static float RdToAlphap(float reflectance, float A) {
00103 float alphaLow = 0., alphaHigh = 1.f;
00104 float kd0 = RdIntegral(alphaLow, A);
00105 float kd1 = RdIntegral(alphaHigh, A);
00106 for (int i = 0; i < 16; ++i) {
00107 Assert(kd0 <= reflectance && kd1 >= reflectance);
00108 float alphaMid = (alphaLow + alphaHigh) * 0.5f;
00109 float kd = RdIntegral(alphaMid, A);
00110 if (kd < reflectance) { alphaLow = alphaMid; kd0 = kd; }
00111 else { alphaHigh = alphaMid; kd1 = kd; }
00112 }
00113 return (alphaLow + alphaHigh) * 0.5f;
00114 }
00115
00116
00117
00118
00119 float PhaseIsotropic(const Vector &, const Vector &) {
00120 return 1.f / (4.f * M_PI);
00121 }
00122
00123
00124 float PhaseRayleigh(const Vector &w, const Vector &wp) {
00125 float costheta = Dot(w, wp);
00126 return 3.f/(16.f*M_PI) * (1 + costheta * costheta);
00127 }
00128
00129
00130 float PhaseMieHazy(const Vector &w, const Vector &wp) {
00131 float costheta = Dot(w, wp);
00132 return (0.5f + 4.5f * powf(0.5 * (1.f + costheta), 8.f)) / (4.f*M_PI);
00133 }
00134
00135
00136 float PhaseMieMurky(const Vector &w, const Vector &wp) {
00137 float costheta = Dot(w, wp);
00138 return (0.5f + 16.5f * powf(0.5 * (1.f + costheta), 32.f)) / (4.f*M_PI);
00139 }
00140
00141
00142 float PhaseHG(const Vector &w, const Vector &wp, float g) {
00143 float costheta = Dot(w, wp);
00144 return 1.f / (4.f * M_PI) *
00145 (1.f - g*g) / powf(1.f + g*g - 2.f * g * costheta, 1.5f);
00146 }
00147
00148
00149 float PhaseSchlick(const Vector &w, const Vector &wp, float g) {
00150 float k = 1.55f * g - .55f * g * g * g;
00151 float kcostheta = k * Dot(w, wp);
00152 return 1.f / (4.f * M_PI) *
00153 (1.f - k*k) / ((1.f - kcostheta) * (1.f - kcostheta));
00154 }
00155
00156
00157 VolumeRegion::~VolumeRegion() {
00158 }
00159
00160
00161 Spectrum VolumeRegion::sigma_t(const Point &p, const Vector &w,
00162 float time) const {
00163 return sigma_a(p, w, time) + sigma_s(p, w, time);
00164 }
00165
00166
00167 AggregateVolume::AggregateVolume(const vector<VolumeRegion *> &r) {
00168 regions = r;
00169 for (uint32_t i = 0; i < regions.size(); ++i)
00170 bound = Union(bound, regions[i]->WorldBound());
00171 }
00172
00173
00174 Spectrum AggregateVolume::sigma_a(const Point &p, const Vector &w,
00175 float time) const {
00176 Spectrum s(0.);
00177 for (uint32_t i = 0; i < regions.size(); ++i)
00178 s += regions[i]->sigma_a(p, w, time);
00179 return s;
00180 }
00181
00182
00183 Spectrum AggregateVolume::sigma_s(const Point &p, const Vector &w, float time) const {
00184 Spectrum s(0.);
00185 for (uint32_t i = 0; i < regions.size(); ++i)
00186 s += regions[i]->sigma_s(p, w, time);
00187 return s;
00188 }
00189
00190
00191 Spectrum AggregateVolume::Lve(const Point &p, const Vector &w, float time) const {
00192 Spectrum L(0.);
00193 for (uint32_t i = 0; i < regions.size(); ++i)
00194 L += regions[i]->Lve(p, w, time);
00195 return L;
00196 }
00197
00198
00199 float AggregateVolume::p(const Point &p, const Vector &w, const Vector &wp,
00200 float time) const {
00201 float ph = 0, sumWt = 0;
00202 for (uint32_t i = 0; i < regions.size(); ++i) {
00203 float wt = regions[i]->sigma_s(p, w, time).y();
00204 sumWt += wt;
00205 ph += wt * regions[i]->p(p, w, wp, time);
00206 }
00207 return ph / sumWt;
00208 }
00209
00210
00211 Spectrum AggregateVolume::sigma_t(const Point &p, const Vector &w, float time) const {
00212 Spectrum s(0.);
00213 for (uint32_t i = 0; i < regions.size(); ++i)
00214 s += regions[i]->sigma_t(p, w, time);
00215 return s;
00216 }
00217
00218
00219 Spectrum AggregateVolume::tau(const Ray &ray, float step, float offset) const {
00220 Spectrum t(0.);
00221 for (uint32_t i = 0; i < regions.size(); ++i)
00222 t += regions[i]->tau(ray, step, offset);
00223 return t;
00224 }
00225
00226
00227 bool AggregateVolume::IntersectP(const Ray &ray,
00228 float *t0, float *t1) const {
00229 *t0 = INFINITY;
00230 *t1 = -INFINITY;
00231 for (uint32_t i = 0; i < regions.size(); ++i) {
00232 float tr0, tr1;
00233 if (regions[i]->IntersectP(ray, &tr0, &tr1)) {
00234 *t0 = min(*t0, tr0);
00235 *t1 = max(*t1, tr1);
00236 }
00237 }
00238 return (*t0 < *t1);
00239 }
00240
00241
00242 AggregateVolume::~AggregateVolume() {
00243 for (uint32_t i = 0; i < regions.size(); ++i)
00244 delete regions[i];
00245 }
00246
00247
00248 BBox AggregateVolume::WorldBound() const {
00249 return bound;
00250 }
00251
00252
00253 bool GetVolumeScatteringProperties(const string &name, Spectrum *sigma_a,
00254 Spectrum *sigma_prime_s) {
00255 for (uint32_t i = 0; i < sizeof(mss) / sizeof(mss[0]); ++i) {
00256 if (name == mss[i].name) {
00257 *sigma_a = Spectrum::FromRGB(mss[i].sigma_a);
00258 *sigma_prime_s = Spectrum::FromRGB(mss[i].sigma_prime_s);
00259 return true;
00260 }
00261 }
00262 return false;
00263 }
00264
00265
00266 void SubsurfaceFromDiffuse(const Spectrum &Kd, float meanPathLength,
00267 float eta, Spectrum *sigma_a, Spectrum *sigma_prime_s) {
00268 float A = (1.f + Fdr(eta)) / (1.f - Fdr(eta));
00269 float rgb[3];
00270 Kd.ToRGB(rgb);
00271 float sigma_prime_s_rgb[3], sigma_a_rgb[3];
00272 for (int i = 0; i < 3; ++i) {
00273
00274 float alphap = RdToAlphap(rgb[i], A);
00275 float sigma_tr = 1.f / meanPathLength;
00276 float sigma_prime_t = sigma_tr / sqrtf(3.f * 1.f - alphap);
00277 sigma_prime_s_rgb[i] = alphap * sigma_prime_t;
00278 sigma_a_rgb[i] = sigma_prime_t - sigma_prime_s_rgb[i];
00279 }
00280 *sigma_a = Spectrum::FromRGB(sigma_a_rgb);
00281 *sigma_prime_s = Spectrum::FromRGB(sigma_prime_s_rgb);
00282 }
00283
00284
00285 Spectrum DensityRegion::tau(const Ray &r, float stepSize,
00286 float u) const {
00287 float t0, t1;
00288 float length = r.d.Length();
00289 if (length == 0.f) return 0.f;
00290 Ray rn(r.o, r.d / length, r.mint * length, r.maxt * length, r.time);
00291 if (!IntersectP(rn, &t0, &t1)) return 0.;
00292 Spectrum tau(0.);
00293 t0 += u * stepSize;
00294 while (t0 < t1) {
00295 tau += sigma_t(rn(t0), -rn.d, r.time);
00296 t0 += stepSize;
00297 }
00298 return tau * stepSize;
00299 }
00300
00301