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 float Noise(float x, float y, float z) {
00174
00175 int ix = Floor2Int(x);
00176 int iy = Floor2Int(y);
00177 int iz = Floor2Int(z);
00178 float dx = x - ix, dy = y - iy, dz = z - iz;
00179
00180 ix &= (NOISE_PERM_SIZE-1);
00181 iy &= (NOISE_PERM_SIZE-1);
00182 iz &= (NOISE_PERM_SIZE-1);
00183 float w000 = Grad(ix, iy, iz, dx, dy, dz);
00184 float w100 = Grad(ix+1, iy, iz, dx-1, dy, dz);
00185 float w010 = Grad(ix, iy+1, iz, dx, dy-1, dz);
00186 float w110 = Grad(ix+1, iy+1, iz, dx-1, dy-1, dz);
00187 float w001 = Grad(ix, iy, iz+1, dx, dy, dz-1);
00188 float w101 = Grad(ix+1, iy, iz+1, dx-1, dy, dz-1);
00189 float w011 = Grad(ix, iy+1, iz+1, dx, dy-1, dz-1);
00190 float w111 = Grad(ix+1, iy+1, iz+1, dx-1, dy-1, dz-1);
00191
00192 float wx = NoiseWeight(dx);
00193 float wy = NoiseWeight(dy);
00194 float wz = NoiseWeight(dz);
00195 float x00 = Lerp(wx, w000, w100);
00196 float x10 = Lerp(wx, w010, w110);
00197 float x01 = Lerp(wx, w001, w101);
00198 float x11 = Lerp(wx, w011, w111);
00199 float y0 = Lerp(wy, x00, x10);
00200 float y1 = Lerp(wy, x01, x11);
00201 return Lerp(wz, y0, y1);
00202 }
00203 float Noise(const Point &P) {
00204 return Noise(P.x, P.y, P.z);
00205 }
00206 inline float Grad(int x, int y, int z, float dx,
00207 float dy, float dz) {
00208 int h = NoisePerm[NoisePerm[NoisePerm[x]+y]+z];
00209 h &= 15;
00210 float u = h<8 || h==12 || h==13 ? dx : dy;
00211 float v = h<4 || h==12 || h==13 ? dy : dz;
00212 return ((h&1) ? -u : u) + ((h&2) ? -v : v);
00213 }
00214 inline float NoiseWeight(float t) {
00215 float t3 = t*t*t;
00216 float t4 = t3*t;
00217 return 6.f*t4*t - 15.f*t4 + 10.f*t3;
00218 }
00219 float FBm(const Point &P, const Vector &dpdx,
00220 const Vector &dpdy, float omega, int maxOctaves) {
00221
00222 float s2 = max(dpdx.LengthSquared(), dpdy.LengthSquared());
00223 float foctaves = min((float)maxOctaves,
00224 1.f - .5f * Log2(s2));
00225 int octaves = Floor2Int(foctaves);
00226
00227 float sum = 0., lambda = 1., o = 1.;
00228 for (int i = 0; i < octaves; ++i) {
00229 sum += o * Noise(lambda * P);
00230 lambda *= 1.99f;
00231 o *= omega;
00232 }
00233 float partialOctave = foctaves - octaves;
00234 sum += o * SmoothStep(.3f, .7f, partialOctave) *
00235 Noise(lambda * P);
00236 return sum;
00237 }
00238 float Turbulence(const Point &P, const Vector &dpdx,
00239 const Vector &dpdy, float omega, int maxOctaves) {
00240
00241 float s2 = max(dpdx.LengthSquared(), dpdy.LengthSquared());
00242 float foctaves = min((float)maxOctaves,
00243 1.f - .5f * Log2(s2));
00244 int octaves = Floor2Int(foctaves);
00245
00246 float sum = 0., lambda = 1., o = 1.;
00247 for (int i = 0; i < octaves; ++i) {
00248 sum += o * fabsf(Noise(lambda * P));
00249 lambda *= 1.99f;
00250 o *= omega;
00251 }
00252 float partialOctave = foctaves - octaves;
00253 sum += o * SmoothStep(.3f, .7f, partialOctave) *
00254 fabsf(Noise(lambda * P));
00255 return sum;
00256 }
00257
00258 float Lanczos(float x, float tau) {
00259 x = fabsf(x);
00260 if (x < 1e-5) return 1;
00261 if (x > 1.) return 0;
00262 x *= M_PI;
00263 float s = sinf(x * tau) / (x * tau);
00264 float lanczos = sinf(x) / x;
00265 return s * lanczos;
00266 }
00267
00268 }
00269