00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef LUX_CHECKERBOARD_H
00024 #define LUX_CHECKERBOARD_H
00025
00026
00027 #include "lux.h"
00028 #include "texture.h"
00029 #include "paramset.h"
00030 #include "sampling.h"
00031 #include "shape.h"
00032 #include "error.h"
00033
00034 namespace lux
00035 {
00036
00037
00038 typedef enum { NONE, SUPERSAMPLE, CLOSEDFORM } MethodType;
00039 extern MethodType aaMethod;
00040
00041
00042 template <class T> class Checkerboard2D : public Texture<T> {
00043 public:
00044
00045 Checkerboard2D(TextureMapping2D *m,
00046 boost::shared_ptr<Texture<T> > c1,
00047 boost::shared_ptr<Texture<T> > c2,
00048 const string &aa) {
00049 mapping = m;
00050 tex1 = c1;
00051 tex2 = c2;
00052
00053 if (aa == "none") aaMethod = NONE;
00054 else if (aa == "supersample") aaMethod = SUPERSAMPLE;
00055 else if (aa == "closedform") aaMethod = CLOSEDFORM;
00056 else {
00057
00058
00059
00060 std::stringstream ss;
00061 ss<<"Anti-aliasing mode '"<<aa<<"' not understood by Checkerboard2D, defaulting to 'supersample'";
00062 luxError(LUX_BADTOKEN,LUX_WARNING,ss.str().c_str());
00063 aaMethod = SUPERSAMPLE;
00064 }
00065 }
00066 virtual ~Checkerboard2D() {
00067 delete mapping;
00068 }
00069 virtual T Evaluate(const TsPack *tspack, const DifferentialGeometry &dg) const {
00070 float s, t, dsdx, dtdx, dsdy, dtdy;
00071 mapping->Map(dg, &s, &t, &dsdx, &dtdx, &dsdy, &dtdy);
00072 if (aaMethod == CLOSEDFORM) {
00073
00074
00075 float ds = max(fabsf(dsdx), fabsf(dsdy));
00076 float dt = max(fabsf(dtdx), fabsf(dtdy));
00077 float s0 = s - ds, s1 = s + ds;
00078 float t0 = t - dt, t1 = t + dt;
00079 if (Floor2Int(s0) == Floor2Int(s1) &&
00080 Floor2Int(t0) == Floor2Int(t1)) {
00081
00082 if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
00083 return tex1->Evaluate(tspack, dg);
00084 return tex2->Evaluate(tspack, dg);
00085 }
00086
00087 #define BUMPINT(x) \
00088 (Floor2Int((x)/2) + \
00089 2.f * max((x/2)-Floor2Int(x/2) - .5f, 0.f))
00090 float sint = (BUMPINT(s1) - BUMPINT(s0)) / (2.f * ds);
00091 float tint = (BUMPINT(t1) - BUMPINT(t0)) / (2.f * dt);
00092 float area2 = sint + tint - 2.f * sint * tint;
00093 if (ds > 1.f || dt > 1.f)
00094 area2 = .5f;
00095 return (1.f - area2) * tex1->Evaluate(tspack, dg) +
00096 area2 * tex2->Evaluate(tspack, dg);
00097 }
00098 else if (aaMethod == SUPERSAMPLE) {
00099
00100 #define SQRT_SAMPLES 4
00101 #define N_SAMPLES (SQRT_SAMPLES * SQRT_SAMPLES)
00102 float samples[2*N_SAMPLES];
00103 StratifiedSample2D(tspack, samples, SQRT_SAMPLES, SQRT_SAMPLES);
00104 T value = 0.;
00105 float filterSum = 0.;
00106 for (int i = 0; i < N_SAMPLES; ++i) {
00107
00108 float dx = samples[2*i] - 0.5f;
00109 float dy = samples[2*i+1] - 0.5f;
00110 DifferentialGeometry dgs = dg;
00111 dgs.p += dx * dgs.dpdx + dy * dgs.dpdy;
00112 dgs.u += dx * dgs.dudx + dy * dgs.dudy;
00113 dgs.v += dx * dgs.dvdx + dy * dgs.dvdy;
00114 dgs.dudx /= N_SAMPLES;
00115 dgs.dudy /= N_SAMPLES;
00116 dgs.dvdx /= N_SAMPLES;
00117 dgs.dvdy /= N_SAMPLES;
00118
00119 float ss, ts, dsdxs, dtdxs, dsdys, dtdys;
00120 mapping->Map(dgs, &ss, &ts, &dsdxs, &dtdxs, &dsdys, &dtdys);
00121 float wt = expf(-2.f * (dx*dx + dy*dy));
00122 filterSum += wt;
00123 if ((Floor2Int(ss) + Floor2Int(ts)) % 2 == 0)
00124 value += wt * tex1->Evaluate(tspack, dgs);
00125 else
00126 value += wt * tex2->Evaluate(tspack, dgs);
00127 }
00128 return value / filterSum;
00129 #undef N_SAMPLES // NOBOOK
00130 }
00131
00132 if ((Floor2Int(s) + Floor2Int(t)) % 2 == 0)
00133 return tex1->Evaluate(tspack, dg);
00134 return tex2->Evaluate(tspack, dg);
00135 }
00136 virtual void SetPower(float power, float area) {
00137
00138 tex1->SetPower(power, area);
00139 tex2->SetPower(power, area);
00140 }
00141 virtual void SetIlluminant() {
00142
00143 tex1->SetIlluminant();
00144 tex2->SetIlluminant();
00145 }
00146 private:
00147
00148 boost::shared_ptr<Texture<T> > tex1, tex2;
00149 TextureMapping2D *mapping;
00150 };
00151 template <class T> class Checkerboard3D : public Texture<T> {
00152 public:
00153
00154 Checkerboard3D(TextureMapping3D *m,
00155 boost::shared_ptr<Texture<T> > c1,
00156 boost::shared_ptr<Texture<T> > c2) {
00157 mapping = m;
00158 tex1 = c1;
00159 tex2 = c2;
00160 }
00161 virtual ~Checkerboard3D() { delete mapping; }
00162 virtual T Evaluate(const TsPack *tspack, const DifferentialGeometry &dg) const {
00163
00164 #define N_SAMPLES 4
00165 float samples[2*N_SAMPLES*N_SAMPLES];
00166 StratifiedSample2D(tspack, samples, N_SAMPLES, N_SAMPLES);
00167 T value = 0.;
00168 float filterSum = 0.;
00169 for (int i = 0; i < N_SAMPLES*N_SAMPLES; ++i) {
00170
00171 float dx = samples[2*i] - 0.5f;
00172 float dy = samples[2*i+1] - 0.5f;
00173 DifferentialGeometry dgs = dg;
00174 dgs.p += dx * dgs.dpdx + dy * dgs.dpdy;
00175 dgs.u += dx * dgs.dudx + dy * dgs.dudy;
00176 dgs.v += dx * dgs.dvdx + dy * dgs.dvdy;
00177 dgs.dudx /= N_SAMPLES;
00178 dgs.dudy /= N_SAMPLES;
00179 dgs.dvdx /= N_SAMPLES;
00180 dgs.dvdy /= N_SAMPLES;
00181
00182 Vector dPPdx, dPPdy;
00183 Point PP = mapping->Map(dgs, &dPPdx, &dPPdy);
00184 float wt = expf(-2.f * (dx*dx + dy*dy));
00185 filterSum += wt;
00186 if ((Floor2Int(PP.x) + Floor2Int(PP.y) + Floor2Int(PP.z)) % 2 == 0)
00187 value += wt * tex1->Evaluate(tspack, dgs);
00188 else
00189 value += wt * tex2->Evaluate(tspack, dgs);
00190 }
00191 return value / filterSum;
00192 }
00193 virtual void SetPower(float power, float area) {
00194
00195 tex1->SetPower(power, area);
00196 tex2->SetPower(power, area);
00197 }
00198 virtual void SetIlluminant() {
00199
00200 tex1->SetIlluminant();
00201 tex2->SetIlluminant();
00202 }
00203 private:
00204
00205 boost::shared_ptr<Texture<T> > tex1, tex2;
00206 TextureMapping3D *mapping;
00207 };
00208
00209 class Checkerboard
00210 {
00211 public:
00212 static Texture<float> * CreateFloatTexture(const Transform &tex2world, const TextureParams &tp);
00213 static Texture<SWCSpectrum> * CreateSWCSpectrumTexture(const Transform &tex2world, const TextureParams &tp);
00214 };
00215
00216 }
00217
00218 #endif
00219