00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020 #ifndef SHLIBNOISEIMPL_HPP
00021 #define SHLIBNOISEIMPL_HPP
00022
00023 #include "ShLibNoise.hpp"
00024 #include "ShArray.hpp"
00025 #include "ShImage3D.hpp"
00026
00027 namespace SH {
00028
00029 static const int MRG_REPS = 2;
00030
00031 template<int N, int M, typename T>
00032 ShGeneric<N, T> hash(const ShGeneric<M, T>& p)
00033 {
00034 ShAttrib<N, SH_TEMP, T> result = cast<N>(frac(p * 0.01));
00035 ShGeneric<N, T> a = fillcast<N>(ShConstAttrib4f(M_PI * M_PI * M_PI * M_PI,
00036 std::exp(4.0),
00037 std::pow(13.0, M_PI / 2.0),
00038 std::sqrt(1997.0)));
00039
00040 for(int i = 0; i < MRG_REPS; ++i) {
00041 for(int j = 0; j < N; ++j) {
00042 result(j) = frac(dot(result, a));
00043 }
00044 }
00045 return result;
00046 }
00047
00048 template<int N, int M, typename T>
00049 ShGeneric<N, T> texhash(const ShGeneric<M, T>& p)
00050 {
00051 return hash<N>(p);
00052 }
00053
00058 template<int M, typename T, int P = 16>
00059 class ShNoise
00060 {
00061 public:
00066 template<int K>
00067 static ShGeneric<M, T> noise(const ShGeneric<K, T> &p, bool useTexture);
00068
00073 template<int K>
00074 static ShGeneric<M, T> perlin(const ShGeneric<K, T> &p, bool useTexture);
00075
00077 template<int K>
00078 static ShGeneric<M, T> cellnoise(const ShGeneric<K, T> &p, bool useTexture);
00079
00081 template<int K>
00082 static ShGeneric<M, T> linnoise(const ShGeneric<K, T> &p, bool useTexture);
00083
00084 private:
00085 static ShAttrib<1, SH_CONST, T> constP, invP;
00086 static bool m_init;
00087 static ShArray3D<ShAttrib<M, SH_TEMP, T, SH_COLOR> > noiseTex;
00088
00089 static void init();
00090 };
00091
00092 template<int M, typename T, int P>
00093 ShArray3D<ShAttrib<M, SH_TEMP, T, SH_COLOR> > ShNoise<M, T, P>::noiseTex(P, P, P);
00094
00095 template<int M, typename T, int P>
00096 bool ShNoise<M, T, P>::m_init = false;
00097
00098 template<int M, typename T, int P>
00099 ShAttrib<1, SH_CONST, T> ShNoise<M, T, P>::constP(P);
00100
00101 template<int M, typename T, int P>
00102 ShAttrib<1, SH_CONST, T> ShNoise<M, T, P>::invP(1.0 / P);
00103
00104 template<int M, typename T, int P>
00105 void ShNoise<M, T, P>::init() {
00106 if(m_init) return;
00107
00108 int i, j, k, l;
00109
00110
00111
00112
00113 #ifdef WIN32
00114 srand(13);
00115 #else
00116 srand48(13);
00117 #endif
00118 ShImage3D noiseImage(P, P, P, M);
00119 for(k = 0; k < P; ++k) {
00120 for(i = 0; i < P; ++i) for(j = 0; j < P; ++j) for(l = 0; l < M; ++l) {
00121 #ifdef WIN32
00122 noiseImage(i, j, k, l) = ((float)rand())/(RAND_MAX+1.0);
00123 #else
00124 noiseImage(i, j, k, l) = drand48();
00125 #endif
00126 }
00127 }
00128 noiseTex.memory(noiseImage.memory());
00129 }
00130
00131 template<int M, typename T>
00132 ShGeneric<M, T> _psmootht(const ShGeneric<M, T> &t)
00133 {
00134 return t * t * t * mad(t, mad(t, 6.0f, fillcast<M>(-15.0f)), fillcast<M>(10.0f));
00135 }
00136
00137 template<int M, typename T, int P>
00138 template<int K>
00139 ShGeneric<M, T> ShNoise<M, T, P>::noise(const ShGeneric<K, T> &p, bool useTexture)
00140 {
00141
00142 return perlin(p, useTexture);
00143 }
00144
00145 template<int M, typename T, int P>
00146 template<int K>
00147 ShGeneric<M, T> ShNoise<M, T, P>::perlin(const ShGeneric<K, T> &p, bool useTexture)
00148 {
00149 init();
00150 int i, j;
00151 typedef ShAttrib<K, SH_TEMP, T> TempType;
00152 typedef ShAttrib<M, SH_TEMP, T> ResultType;
00153 typedef ShAttrib<K, SH_CONST, T> ConstTempType;
00154 static const int NUM_SAMPLES = 1 << K;
00155
00156 TempType rp = frac(p);
00157 TempType p0, p1;
00158 TempType ip0, ip1;
00159
00160 p0 = frac(p * invP) * constP;
00161 p1 = frac(mad(p, invP, fillcast<K>(invP))) * constP;
00162 ip0 = floor(p0);
00163 ip1 = floor(p1);
00164 if(useTexture) {
00165 ip0 = (ip0 + 0.5f) * invP;
00166 ip1 = (ip1 + 0.5f) * invP;
00167 }
00168
00169
00170 ResultType grad[NUM_SAMPLES];
00171
00172 typename TempType::host_type flip[K];
00173 for(i = 0; i < NUM_SAMPLES; ++i) {
00174 for(j = 0; j < K; ++j) {
00175 if(j == 0) flip[j] = i & 1;
00176 else flip[j] = (i >> j) & 1;
00177 }
00178 ConstTempType offsets(flip);
00179 TempType intLatticePoint = lerp(offsets, ip1, ip0);
00180 if(useTexture) {
00181 grad[i] = noiseTex(fillcast<3>(intLatticePoint));
00182 } else {
00183 grad[i] = hash<M>(intLatticePoint);
00184 }
00185 }
00186
00187 TempType t = _psmootht(rp);
00188 for(i = K - 1; i >= 0; --i) {
00189 int offset = 1 << i;
00190 for(j = 0; j < offset; ++j) {
00191 grad[j] = lerp(t(i), grad[j+offset], grad[j]);
00192 }
00193 }
00194
00195 return grad[0];
00196 }
00197
00198 template<int M, typename T, int P>
00199 template<int K>
00200 ShGeneric<M, T> ShNoise<M, T, P>::cellnoise(const ShGeneric<K, T> &p, bool useTexture)
00201 {
00202 init();
00203 ShAttrib<K, SH_TEMP, T> ip;
00204
00205 ip = floor(p);
00206
00207 if( useTexture ) {
00208 ip = frac(ip * invP);
00209 return noiseTex(fillcast<3>(ip));
00210 }
00211 return hash<M>(ip);
00212 }
00213
00214 template<int M, typename T, int P>
00215 template<int K>
00216 ShGeneric<M, T> ShNoise<M, T, P>::linnoise(const ShGeneric<K, T> &p, bool useTexture)
00217 {
00218
00219 return cellnoise(p, useTexture);
00220 }
00221
00222 #ifdef WIN32
00223 #define SHNOISE_WITH_AMP(name) \
00224 template<int N, int M, int K, typename T1, typename T2>\
00225 ShGeneric<N, CT1T2> name(const ShGeneric<M, T1> &p, const ShGeneric<K, T2> &, bool useTexture=true) {\
00226 ShAttrib<N, SH_TEMP, CT1T2> result; \
00227 int freq = 1;\
00228 result *= ShDataTypeInfo<CT1T2, SH_HOST>::Zero; \
00229 for(int i = 0; i < K; ++i, freq *= 2) {\
00230 result = mad(name<N>(p * freq, useTexture), amp(i), result);\
00231 }\
00232 return result;\
00233 }
00234 #else
00235 #define SHNOISE_WITH_AMP(name) \
00236 template<int N, int M, int K, typename T1, typename T2>\
00237 ShGeneric<N, CT1T2> name(const ShGeneric<M, T1> &p, const ShGeneric<K, T2> &, bool useTexture) {\
00238 ShAttrib<N, SH_TEMP, CT1T2> result; \
00239 int freq = 1;\
00240 result *= ShDataTypeInfo<CT1T2, SH_HOST>::Zero; \
00241 for(int i = 0; i < K; ++i, freq *= 2) {\
00242 result = mad(name<N>(p * freq, useTexture), amp(i), result);\
00243 }\
00244 return result;\
00245 }
00246 #endif
00247
00248 template<int N, int M, typename T>
00249 #ifdef WIN32
00250 ShGeneric<N, T> noise(const ShGeneric<M, T> &p, bool useTexture=true) {
00251 #else
00252 ShGeneric<N, T> noise(const ShGeneric<M, T> &p, bool useTexture) {
00253 #endif
00254 return ShNoise<N, T>::noise(p, useTexture);
00255 }
00256 SHNOISE_WITH_AMP(noise);
00257
00258 template<int N, int M, typename T>
00259 #ifdef WIN32
00260 ShGeneric<N, T> snoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00261 #else
00262 ShGeneric<N, T> snoise(const ShGeneric<M, T> &p, bool useTexture) {
00263 #endif
00264 return mad( noise<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00265 }
00266 SHNOISE_WITH_AMP(snoise);
00267
00268 template<int N, int M, typename T>
00269 #ifdef WIN32
00270 ShGeneric<N, T> perlin(const ShGeneric<M, T> &p, bool useTexture=true) {
00271 #else
00272 ShGeneric<N, T> perlin(const ShGeneric<M, T> &p, bool useTexture) {
00273 #endif
00274 return ShNoise<N, T>::perlin(p, useTexture);
00275 }
00276 SHNOISE_WITH_AMP(perlin);
00277
00278 template<int N, int M, typename T>
00279 #ifdef WIN32
00280 ShGeneric<N, T> sperlin(const ShGeneric<M, T> &p, bool useTexture=true) {
00281 #else
00282 ShGeneric<N, T> sperlin(const ShGeneric<M, T> &p, bool useTexture) {
00283 #endif
00284 return mad( perlin<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00285 }
00286 SHNOISE_WITH_AMP(sperlin);
00287
00288 template<int N, int M, typename T>
00289 #ifdef WIN32
00290 ShGeneric<N, T> cellnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00291 #else
00292 ShGeneric<N, T> cellnoise(const ShGeneric<M, T> &p, bool useTexture) {
00293 #endif
00294 return ShNoise<N, T>::cellnoise(p, useTexture);
00295 }
00296 SHNOISE_WITH_AMP(cellnoise);
00297
00298 template<int N, int M, typename T>
00299 #ifdef WIN32
00300 ShGeneric<N, T> scellnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00301 #else
00302 ShGeneric<N, T> scellnoise(const ShGeneric<M, T> &p, bool useTexture) {
00303 #endif
00304 return mad( cellnoise<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00305 }
00306 SHNOISE_WITH_AMP(scellnoise);
00307
00308 template<int N, int M, typename T>
00309 #ifdef WIN32
00310 ShGeneric<N, T> linnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00311 #else
00312 ShGeneric<N, T> linnoise(const ShGeneric<M, T> &p, bool useTexture) {
00313 #endif
00314 return ShNoise<N, T>::linnoise(p, useTexture);
00315 }
00316 SHNOISE_WITH_AMP(linnoise);
00317
00318 template<int N, int M, typename T>
00319 #ifdef WIN32
00320 ShGeneric<N, T> slinnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00321 #else
00322 ShGeneric<N, T> slinnoise(const ShGeneric<M, T> &p, bool useTexture) {
00323 #endif
00324 return mad( linnoise<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00325 }
00326 SHNOISE_WITH_AMP(slinnoise);
00327
00328 template<int N, int M, typename T>
00329 #ifdef WIN32
00330 ShGeneric<N, T> turbulence(const ShGeneric<M, T> &p, bool useTexture=true) {
00331 #else
00332 ShGeneric<N, T> turbulence(const ShGeneric<M, T> &p, bool useTexture) {
00333 #endif
00334 return abs(sperlin<N>(p, useTexture));
00335 }
00336 SHNOISE_WITH_AMP(turbulence);
00337
00338 template<int N, int M, typename T>
00339 #ifdef WIN32
00340 ShGeneric<N, T> sturbulence(const ShGeneric<M, T> &p, bool useTexture=true) {
00341 #else
00342 ShGeneric<N, T> sturbulence(const ShGeneric<M, T> &p, bool useTexture) {
00343 #endif
00344 return mad(abs(sperlin<N>(p, useTexture)), 2.0f, fillcast<N>(-1.0f));
00345 }
00346 SHNOISE_WITH_AMP(sturbulence);
00347
00348 }
00349
00350 #endif // SHLIBNOISEIMPL_HPP