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