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 "texture.h"
00025 #include "paramset.h"
00026 #include "shape.h"
00027
00028 namespace lux
00029 {
00030
00031
00032 inline float Grad(int x, int y, int z, float dx, float dy, float dz);
00033 inline float NoiseWeight(float t);
00034
00035 #define NOISE_PERM_SIZE 256
00036 static int NoisePerm[2 * NOISE_PERM_SIZE] = {
00037 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96,
00038 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142,
00039
00040 8, 99, 37, 240, 21, 10, 23,
00041 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
00042 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
00043 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
00044 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
00045 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
00046 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
00047 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
00048 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
00049 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
00050 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
00051 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180,
00052 151, 160, 137, 91, 90, 15,
00053 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23,
00054 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
00055 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166,
00056 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244,
00057 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196,
00058 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123,
00059 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42,
00060 223, 183, 170, 213, 119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
00061 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228,
00062 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14, 239, 107,
00063 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254,
00064 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
00065 };
00066
00067 UVMapping2D::UVMapping2D(float _su, float _sv,
00068 float _du, float _dv) {
00069 su = _su; sv = _sv;
00070 du = _du; dv = _dv;
00071 }
00072 void UVMapping2D::Map(const DifferentialGeometry &dg,
00073 float *s, float *t, float *dsdx, float *dtdx,
00074 float *dsdy, float *dtdy) const {
00075 *s = su * dg.u + du;
00076 *t = sv * dg.v + dv;
00077
00078 *dsdx = su * dg.dudx;
00079 *dtdx = sv * dg.dvdx;
00080 *dsdy = su * dg.dudy;
00081 *dtdy = sv * dg.dvdy;
00082 }
00083 void SphericalMapping2D::Map(const DifferentialGeometry &dg,
00084 float *s, float *t, float *dsdx, float *dtdx,
00085 float *dsdy, float *dtdy) const {
00086 sphere(dg.p, s, t);
00087
00088 float sx, tx, sy, ty;
00089 const float delta = .1f;
00090 sphere(dg.p + delta * dg.dpdx, &sx, &tx);
00091 *dsdx = (sx - *s) / delta;
00092 *dtdx = (tx - *t) / delta;
00093 if (*dtdx > .5) *dtdx = 1.f - *dtdx;
00094 else if (*dtdx < -.5f) *dtdx = -(*dtdx + 1);
00095 sphere(dg.p + delta * dg.dpdy, &sy, &ty);
00096 *dsdy = (sy - *s) / delta;
00097 *dtdy = (ty - *t) / delta;
00098 if (*dtdy > .5) *dtdy = 1.f - *dtdy;
00099 else if (*dtdy < -.5f) *dtdy = -(*dtdy + 1);
00100 }
00101 void SphericalMapping2D::sphere(const Point &p, float *s,
00102 float *t) const {
00103 Vector vec =
00104 Normalize(WorldToTexture(p) - Point(0,0,0));
00105 float theta = SphericalTheta(vec);
00106 float phi = SphericalPhi(vec);
00107 *s = theta * INV_PI;
00108 *t = phi * INV_TWOPI;
00109 }
00110 void
00111 CylindricalMapping2D::Map(const DifferentialGeometry &dg,
00112 float *s, float *t, float *dsdx, float *dtdx,
00113 float *dsdy, float *dtdy) const {
00114 cylinder(dg.p, s, t);
00115
00116 float sx, tx, sy, ty;
00117 const float delta = .01f;
00118 cylinder(dg.p + delta * dg.dpdx, &sx, &tx);
00119 *dsdx = (sx - *s) / delta;
00120 *dtdx = (tx - *t) / delta;
00121 if (*dtdx > .5) *dtdx = 1.f - *dtdx;
00122 else if (*dtdx < -.5f) *dtdx = -(*dtdx + 1);
00123 cylinder(dg.p + delta * dg.dpdy, &sy, &ty);
00124 *dsdy = (sy - *s) / delta;
00125 *dtdy = (ty - *t) / delta;
00126 if (*dtdy > .5) *dtdy = 1.f - *dtdy;
00127 else if (*dtdy < -.5f) *dtdy = -(*dtdy + 1);
00128 }
00129 void CylindricalMapping2D::cylinder(const Point &p,
00130 float *s, float *t) const {
00131 Vector vec =
00132 Normalize(WorldToTexture(p) - Point(0,0,0));
00133 *s = (M_PI + atan2f(vec.y, vec.x)) / (2.f * M_PI);
00134 *t = vec.z;
00135 }
00136 PlanarMapping2D::PlanarMapping2D(const Vector &_v1,
00137 const Vector &_v2, float _ds, float _dt) {
00138 vs = _v1;
00139 vt = _v2;
00140 ds = _ds;
00141 dt = _dt;
00142 }
00143 void PlanarMapping2D::Map(const DifferentialGeometry &dg,
00144 float *s, float *t, float *dsdx, float *dtdx,
00145 float *dsdy, float *dtdy) const {
00146 Vector vec = dg.p - Point(0,0,0);
00147 *s = ds + Dot(vec, vs);
00148 *t = dt + Dot(vec, vt);
00149 *dsdx = Dot(dg.dpdx, vs);
00150 *dtdx = Dot(dg.dpdx, vt);
00151 *dsdy = Dot(dg.dpdy, vs);
00152 *dtdy = Dot(dg.dpdy, vt);
00153 }
00154 Point IdentityMapping3D::Map(const DifferentialGeometry &dg,
00155 Vector *dpdx, Vector *dpdy) const {
00156 *dpdx = WorldToTexture(dg.dpdx);
00157 *dpdy = WorldToTexture(dg.dpdy);
00158 return WorldToTexture(dg.p);
00159 }
00160 void IdentityMapping3D::Apply3DTextureMappingOptions(const TextureParams &tp) {
00161
00162 Vector scalev = tp.FindVector("scale", Vector(1., 1., 1.));
00163 WorldToTexture = WorldToTexture * Scale(1.f/scalev.x, 1.f/scalev.y, 1.f/scalev.z);
00164
00165 Vector rotatev = tp.FindVector("rotate", Vector(0., 0., 0.));
00166 WorldToTexture = WorldToTexture * RotateX(rotatev.x);
00167 WorldToTexture = WorldToTexture * RotateY(rotatev.y);
00168 WorldToTexture = WorldToTexture * RotateZ(rotatev.z);
00169
00170 Vector translatev = tp.FindVector("translate", Vector(0., 0., 0.));
00171 WorldToTexture = WorldToTexture * Translate(-translatev);
00172 }
00173 void LatLongMapping::Map(const Vector &wh, float *s, float *t) const {
00174 *s = SphericalPhi(wh) * INV_TWOPI;
00175 *t = SphericalTheta(wh) * INV_PI;
00176 }
00177 void AngularMapping::Map(const Vector &wh, float *s, float *t) const {
00178 float r = sqrtf(wh.y*wh.y + wh.z*wh.z);
00179 if (r > 1e-9)
00180 r = INV_TWOPI * acosf(Clamp(-wh.x, -1.f, 1.f)) / r;
00181 *s = 0.5f - wh.y * r;
00182 *t = 0.5f - wh.z * r;
00183 }
00184 void VerticalCrossMapping::Map(const Vector &wh, float *s, float *t) const {
00185 int axis = 0;
00186 float ma = fabsf(wh.x);
00187 if (fabsf(wh.y) > ma) {
00188 ma = fabsf(wh.y);
00189 axis = 1;
00190 }
00191 if (fabsf(wh.z) > ma) {
00192 ma = fabsf(wh.z);
00193 axis = 2;
00194 }
00195 float ima = 1.f / ma;
00196 float sc = 0.0f, tc = 0.0f;
00197 float so = 0.0f, to = 0.0f;
00198
00199 switch (axis) {
00200 case 0:
00201 if (wh.x > 0) {
00202 sc = -wh.y;
00203 tc = wh.z;
00204 so = 1.f;
00205 to = 3.f;
00206 } else {
00207 sc = -wh.y;
00208 tc = -wh.z;
00209 so = 1.f;
00210 to = 1.f;
00211 }
00212 break;
00213 case 1:
00214 if (wh.y > 0) {
00215 sc = -wh.x;
00216 tc = -wh.z;
00217 so = 0.f;
00218 to = 1.f;
00219 } else {
00220 sc = wh.x;
00221 tc = -wh.z;
00222 so = 2.f;
00223 to = 1.f;
00224 }
00225 break;
00226 case 2:
00227 if (wh.z > 0) {
00228 sc = -wh.y;
00229 tc = -wh.x;
00230 so = 1.f;
00231 to = 0.f;
00232 } else {
00233 sc = -wh.y;
00234 tc = wh.x;
00235 so = 1.f;
00236 to = 2.f;
00237 }
00238 break;
00239 }
00240 *s = Clamp((sc * ima + 1.f) * 0.5f, 0.f, 1.f);
00241 *t = Clamp((tc * ima + 1.f) * 0.5f, 0.f, 1.f);
00242
00243 *s = (*s + so) * (1.f / 3.f);
00244 *t = (*t + to) * (1.f / 4.f);
00245 }
00246 float Noise(float x, float y, float z) {
00247
00248 int ix = Floor2Int(x);
00249 int iy = Floor2Int(y);
00250 int iz = Floor2Int(z);
00251 float dx = x - ix, dy = y - iy, dz = z - iz;
00252
00253 ix &= (NOISE_PERM_SIZE-1);
00254 iy &= (NOISE_PERM_SIZE-1);
00255 iz &= (NOISE_PERM_SIZE-1);
00256 float w000 = Grad(ix, iy, iz, dx, dy, dz);
00257 float w100 = Grad(ix+1, iy, iz, dx-1, dy, dz);
00258 float w010 = Grad(ix, iy+1, iz, dx, dy-1, dz);
00259 float w110 = Grad(ix+1, iy+1, iz, dx-1, dy-1, dz);
00260 float w001 = Grad(ix, iy, iz+1, dx, dy, dz-1);
00261 float w101 = Grad(ix+1, iy, iz+1, dx-1, dy, dz-1);
00262 float w011 = Grad(ix, iy+1, iz+1, dx, dy-1, dz-1);
00263 float w111 = Grad(ix+1, iy+1, iz+1, dx-1, dy-1, dz-1);
00264
00265 float wx = NoiseWeight(dx);
00266 float wy = NoiseWeight(dy);
00267 float wz = NoiseWeight(dz);
00268 float x00 = Lerp(wx, w000, w100);
00269 float x10 = Lerp(wx, w010, w110);
00270 float x01 = Lerp(wx, w001, w101);
00271 float x11 = Lerp(wx, w011, w111);
00272 float y0 = Lerp(wy, x00, x10);
00273 float y1 = Lerp(wy, x01, x11);
00274 return Lerp(wz, y0, y1);
00275 }
00276 float Noise(const Point &P) {
00277 return Noise(P.x, P.y, P.z);
00278 }
00279 inline float Grad(int x, int y, int z, float dx,
00280 float dy, float dz) {
00281 int h = NoisePerm[NoisePerm[NoisePerm[x]+y]+z];
00282 h &= 15;
00283 float u = h<8 || h==12 || h==13 ? dx : dy;
00284 float v = h<4 || h==12 || h==13 ? dy : dz;
00285 return ((h&1) ? -u : u) + ((h&2) ? -v : v);
00286 }
00287 inline float NoiseWeight(float t) {
00288 float t3 = t*t*t;
00289 float t4 = t3*t;
00290 return 6.f*t4*t - 15.f*t4 + 10.f*t3;
00291 }
00292 float FBm(const Point &P, const Vector &dpdx,
00293 const Vector &dpdy, float omega, int maxOctaves) {
00294
00295 float s2 = max(dpdx.LengthSquared(), dpdy.LengthSquared());
00296 float foctaves = min((float)maxOctaves,
00297 1.f - .5f * Log2(s2));
00298 int octaves = Floor2Int(foctaves);
00299
00300 float sum = 0., lambda = 1., o = 1.;
00301 for (int i = 0; i < octaves; ++i) {
00302 sum += o * Noise(lambda * P);
00303 lambda *= 1.99f;
00304 o *= omega;
00305 }
00306 float partialOctave = foctaves - octaves;
00307 sum += o * SmoothStep(.3f, .7f, partialOctave) *
00308 Noise(lambda * P);
00309 return sum;
00310 }
00311 float Turbulence(const Point &P, const Vector &dpdx,
00312 const Vector &dpdy, float omega, int maxOctaves) {
00313
00314 float s2 = max(dpdx.LengthSquared(), dpdy.LengthSquared());
00315 float foctaves = min((float)maxOctaves,
00316 1.f - .5f * Log2(s2));
00317 int octaves = Floor2Int(foctaves);
00318
00319 float sum = 0., lambda = 1., o = 1.;
00320 for (int i = 0; i < octaves; ++i) {
00321 sum += o * fabsf(Noise(lambda * P));
00322 lambda *= 1.99f;
00323 o *= omega;
00324 }
00325 float partialOctave = foctaves - octaves;
00326 sum += o * SmoothStep(.3f, .7f, partialOctave) *
00327 fabsf(Noise(lambda * P));
00328 return sum;
00329 }
00330
00331 float Lanczos(float x, float tau) {
00332 x = fabsf(x);
00333 if (x < 1e-5) return 1;
00334 if (x > 1.) return 0;
00335 x *= M_PI;
00336 float s = sinf(x * tau) / (x * tau);
00337 float lanczos = sinf(x) / x;
00338 return s * lanczos;
00339 }
00340
00341 }
00342