00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00027 #ifndef SHUTIL_NOISEIMPL_HPP
00028 #define SHUTIL_NOISEIMPL_HPP
00029
00030 #include <cstdlib>
00031 #include "ShDebug.hpp"
00032 #include "ShNoise.hpp"
00033 #include "ShFunc.hpp"
00034 #include "ShImage3D.hpp"
00035 #include "ShLib.hpp"
00036
00037 namespace ShUtil {
00038
00039 using namespace SH;
00040
00041
00042 template<int M, typename T, int P>
00043 ShArray3D<ShColor<M, SH_TEMP, T> > ShNoise<M, T, P>::noiseTex(P, P, P);
00044
00045 template<int M, typename T, int P>
00046 bool ShNoise<M, T, P>::m_init = false;
00047
00048 template<int M, typename T, int P>
00049 ShAttrib<1, SH_CONST, T> ShNoise<M, T, P>::constP(P);
00050
00051 template<int M, typename T, int P>
00052 ShAttrib<1, SH_CONST, T> ShNoise<M, T, P>::invP(1.0 / P);
00053
00054 template<int M, typename T, int P>
00055 void ShNoise<M, T, P>::init() {
00056 if(m_init) return;
00057
00058 int i, j, k, l;
00059
00060
00061
00062
00063 #ifdef WIN32
00064 srand(13);
00065 #else
00066 srand48(13);
00067 #endif
00068 ShImage3D noiseImage(P, P, P, M);
00069 for(k = 0; k < P; ++k) {
00070 for(i = 0; i < P; ++i) for(j = 0; j < P; ++j) for(l = 0; l < M; ++l) {
00071 #ifdef WIN32
00072 noiseImage(i, j, k, l) = ((float)rand())/(RAND_MAX+1.0);
00073 #else
00074 noiseImage(i, j, k, l) = drand48();
00075 #endif
00076 }
00077 }
00078 noiseTex.memory(noiseImage.memory());
00079 }
00080
00081 template<int M, typename T>
00082 ShGeneric<M, T> _psmootht(const ShGeneric<M, T> &t)
00083 {
00084 return t * t * t * mad(t, mad(t, 6.0f, fillcast<M>(-15.0f)), fillcast<M>(10.0f));
00085 }
00086
00087 template<int M, typename T, int P>
00088 template<int K>
00089 ShGeneric<M, T> ShNoise<M, T, P>::perlin(const ShGeneric<K, T> &p, bool useTexture)
00090 {
00091 init();
00092 int i, j;
00093 typedef ShAttrib<K, SH_TEMP, T> TempType;
00094 typedef ShAttrib<M, SH_TEMP, T> ResultType;
00095 typedef ShAttrib<K, SH_CONST, T> ConstTempType;
00096 static const int NUM_SAMPLES = 1 << K;
00097
00098 TempType rp = frac(p);
00099 TempType p0, p1;
00100 TempType ip0, ip1;
00101
00102 p0 = frac(p * invP) * constP;
00103 p1 = frac(mad(p, invP, fillcast<K>(invP))) * constP;
00104 ip0 = floor(p0);
00105 ip1 = floor(p1);
00106 if(useTexture) {
00107 ip0 = (ip0 + 0.5f) * invP;
00108 ip1 = (ip1 + 0.5f) * invP;
00109 }
00110
00111
00112 ResultType grad[NUM_SAMPLES];
00113
00114 typename TempType::host_type flip[K];
00115 for(i = 0; i < NUM_SAMPLES; ++i) {
00116 for(j = 0; j < K; ++j) {
00117 if(j == 0) flip[j] = i & 1;
00118 else flip[j] = (i >> j) & 1;
00119 }
00120 ConstTempType offsets(flip);
00121 TempType intLatticePoint = lerp(offsets, ip1, ip0);
00122 if(useTexture) {
00123 grad[i] = noiseTex(fillcast<3>(intLatticePoint));
00124 } else {
00125 grad[i] = cast<M>(hashmrg(intLatticePoint));
00126 }
00127 }
00128
00129 TempType t = _psmootht(rp);
00130 for(i = K - 1; i >= 0; --i) {
00131 int offset = 1 << i;
00132 for(j = 0; j < offset; ++j) {
00133 grad[j] = lerp(t(i), grad[j+offset], grad[j]);
00134 }
00135 }
00136
00137 return grad[0];
00138 }
00139
00140 template<int M, typename T, int P>
00141 template<int K>
00142 ShGeneric<M, T> ShNoise<M, T, P>::cellnoise(const ShGeneric<K, T> &p, bool useTexture)
00143 {
00144 init();
00145 ShAttrib<K, SH_TEMP, T> ip;
00146
00147 ip = floor(p);
00148
00149 if( useTexture ) {
00150 ip = frac(ip * invP);
00151 return noiseTex(fillcast<3>(ip));
00152 }
00153 return fillcast<M>(hashmrg(ip));
00154 }
00155
00156 #ifdef WIN32
00157 #define SHNOISE_WITH_AMP(name) \
00158 template<int N, int M, int K, typename T1, typename T2>\
00159 ShGeneric<N, CT1T2> name(const ShGeneric<M, T1> &p, const ShGeneric<K, T2> &, bool useTexture=true) {\
00160 ShAttrib<N, SH_TEMP, CT1T2> result; \
00161 int freq = 1;\
00162 result *= ShDataTypeInfo<CT1T2, SH_HOST>::Zero; \
00163 for(int i = 0; i < K; ++i, freq *= 2) {\
00164 result = mad(name<N>(p * freq, useTexture), amp(i), result);\
00165 }\
00166 return result;\
00167 }
00168 #else
00169 #define SHNOISE_WITH_AMP(name) \
00170 template<int N, int M, int K, typename T1, typename T2>\
00171 ShGeneric<N, CT1T2> name(const ShGeneric<M, T1> &p, const ShGeneric<K, T2> &, bool useTexture) {\
00172 ShAttrib<N, SH_TEMP, CT1T2> result; \
00173 int freq = 1;\
00174 result *= ShDataTypeInfo<CT1T2, SH_HOST>::Zero; \
00175 for(int i = 0; i < K; ++i, freq *= 2) {\
00176 result = mad(name<N>(p * freq, useTexture), amp(i), result);\
00177 }\
00178 return result;\
00179 }
00180 #endif
00181
00182 template<int N, int M, typename T>
00183 #ifdef WIN32
00184 ShGeneric<N, T> perlin(const ShGeneric<M, T> &p, bool useTexture=true) {
00185 #else
00186 ShGeneric<N, T> perlin(const ShGeneric<M, T> &p, bool useTexture) {
00187 #endif
00188 return ShNoise<N, T>::perlin(p, useTexture);
00189 }
00190 SHNOISE_WITH_AMP(perlin);
00191
00192 template<int N, int M, typename T>
00193 #ifdef WIN32
00194 ShGeneric<N, T> sperlin(const ShGeneric<M, T> &p, bool useTexture=true) {
00195 #else
00196 ShGeneric<N, T> sperlin(const ShGeneric<M, T> &p, bool useTexture) {
00197 #endif
00198 return mad( perlin<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00199 }
00200 SHNOISE_WITH_AMP(sperlin);
00201
00202 template<int N, int M, typename T>
00203 #ifdef WIN32
00204 ShGeneric<N, T> cellnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00205 #else
00206 ShGeneric<N, T> cellnoise(const ShGeneric<M, T> &p, bool useTexture) {
00207 #endif
00208 return ShNoise<N, T>::cellnoise(p, useTexture);
00209 }
00210 SHNOISE_WITH_AMP(cellnoise);
00211
00212 template<int N, int M, typename T>
00213 #ifdef WIN32
00214 ShGeneric<N, T> scellnoise(const ShGeneric<M, T> &p, bool useTexture=true) {
00215 #else
00216 ShGeneric<N, T> scellnoise(const ShGeneric<M, T> &p, bool useTexture) {
00217 #endif
00218 return mad( cellnoise<N>(p, useTexture), 2.0f, fillcast<N>(-1.0f));
00219 }
00220 SHNOISE_WITH_AMP(scellnoise);
00221
00222
00223 template<int N, int M, typename T>
00224 #ifdef WIN32
00225 ShGeneric<N, T> turbulence(const ShGeneric<M, T> &p, bool useTexture=true) {
00226 #else
00227 ShGeneric<N, T> turbulence(const ShGeneric<M, T> &p, bool useTexture) {
00228 #endif
00229 abs(sperlin<N>(p, useTexture));
00230 }
00231 SHNOISE_WITH_AMP(turbulence);
00232
00233 template<int N, int M, typename T>
00234 #ifdef WIN32
00235 ShGeneric<N, T> sturbulence(const ShGeneric<M, T> &p, bool useTexture=true) {
00236 #else
00237 ShGeneric<N, T> sturbulence(const ShGeneric<M, T> &p, bool useTexture) {
00238 #endif
00239 return mad(abs(sperlin<N>(p, useTexture)), 2.0f, fillcast<N>(-1.0f));
00240 }
00241 SHNOISE_WITH_AMP(sturbulence);
00242
00243 }
00244
00245 #endif