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 ~Checkerboard2D() {
00067 delete mapping;
00068 }
00069 T Evaluate(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(dg);
00084 return tex2->Evaluate(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(dg) +
00096 area2 * tex2->Evaluate(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(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(dgs);
00125 else
00126 value += wt * tex2->Evaluate(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(dg);
00134 return tex2->Evaluate(dg);
00135 }
00136 private:
00137
00138 boost::shared_ptr<Texture<T> > tex1, tex2;
00139 TextureMapping2D *mapping;
00140 };
00141 template <class T> class Checkerboard3D : public Texture<T> {
00142 public:
00143
00144 Checkerboard3D(TextureMapping3D *m,
00145 boost::shared_ptr<Texture<T> > c1,
00146 boost::shared_ptr<Texture<T> > c2) {
00147 mapping = m;
00148 tex1 = c1;
00149 tex2 = c2;
00150 }
00151 T Evaluate(const DifferentialGeometry &dg) const {
00152
00153 #define N_SAMPLES 4
00154 float samples[2*N_SAMPLES*N_SAMPLES];
00155 StratifiedSample2D(samples, N_SAMPLES, N_SAMPLES);
00156 T value = 0.;
00157 float filterSum = 0.;
00158 for (int i = 0; i < N_SAMPLES*N_SAMPLES; ++i) {
00159
00160 float dx = samples[2*i] - 0.5f;
00161 float dy = samples[2*i+1] - 0.5f;
00162 DifferentialGeometry dgs = dg;
00163 dgs.p += dx * dgs.dpdx + dy * dgs.dpdy;
00164 dgs.u += dx * dgs.dudx + dy * dgs.dudy;
00165 dgs.v += dx * dgs.dvdx + dy * dgs.dvdy;
00166 dgs.dudx /= N_SAMPLES;
00167 dgs.dudy /= N_SAMPLES;
00168 dgs.dvdx /= N_SAMPLES;
00169 dgs.dvdy /= N_SAMPLES;
00170
00171 Vector dPPdx, dPPdy;
00172 Point PP = mapping->Map(dgs, &dPPdx, &dPPdy);
00173 float wt = expf(-2.f * (dx*dx + dy*dy));
00174 filterSum += wt;
00175 if ((Floor2Int(PP.x) + Floor2Int(PP.y) + Floor2Int(PP.z)) % 2 == 0)
00176 value += wt * tex1->Evaluate(dgs);
00177 else
00178 value += wt * tex2->Evaluate(dgs);
00179 }
00180 return value / filterSum;
00181 }
00182 private:
00183
00184 boost::shared_ptr<Texture<T> > tex1, tex2;
00185 TextureMapping3D *mapping;
00186 };
00187
00188 namespace Checkerboard
00189 {
00190 Texture<float> * CreateFloatTexture(const Transform &tex2world, const TextureParams &tp);
00191 Texture<Spectrum> * CreateSpectrumTexture(const Transform &tex2world, const TextureParams &tp);
00192 }
00193
00194 }
00195
00196 #endif
00197