Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShNoiseImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2005 Serious Hack Inc.
00004 // 
00005 // This software is provided 'as-is', without any express or implied
00006 // warranty. In no event will the authors be held liable for any damages
00007 // arising from the use of this software.
00008 // 
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it
00011 // freely, subject to the following restrictions:
00012 // 
00013 // 1. The origin of this software must not be misrepresented; you must
00014 // not claim that you wrote the original software. If you use this
00015 // software in a product, an acknowledgment in the product documentation
00016 // would be appreciated but is not required.
00017 // 
00018 // 2. Altered source versions must be plainly marked as such, and must
00019 // not be misrepresented as being the original software.
00020 // 
00021 // 3. This notice may not be removed or altered from any source
00022 // distribution.
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); // pseudorandom 3D noise texture
00041 
00042 template<int M, typename T, int P>
00043 bool ShNoise<M, T, P>::m_init = false; // whether Perlin is initialized. 
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   // generate pseudorand noise noiseImage[x + y * P][z] holds the four
00058   // 1D gradient components for lattice points (x, y, z), (x, y, z + 1), (x, y + 1, z),
00059   // and (x, y + 1, z + 1)
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); // offset from integer lattice point
00096   TempType p0, p1; // positive coordinates in [0, P)^3
00097   TempType ip0, ip1; // integer lattice point in [0,P)^3 for hash, [0,1)^3 for tex lookup
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) { // convert to tex coordiantes (TODO remove when we have RECT textures)
00104     ip0 = (ip0 + 0.5f) * invP; 
00105     ip1 = (ip1 + 0.5f) * invP; 
00106   } 
00107 
00108   // find gradients at the NUM_SAMPLES adjacent grid points (NUM_SAMPLES = 2^K for dimension K lookup)
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)); // lookup 3D texture
00121     } else {
00122       grad[i] = cast<M>(hashmrg(intLatticePoint)); 
00123     }
00124   }
00125 
00126   TempType t = _psmootht(rp); //ShNoise's improved polynomial interpolant 
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> &amp, 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> &amp, 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 } // namespace ShUtil
00241 
00242 #endif

Generated on Thu Apr 21 17:32:48 2005 for Sh by  doxygen 1.4.2