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 (c) 2003 University of Waterloo Computer Graphics Laboratory
00004 // Project administrator: Michael D. McCool
00005 // Authors: Zheng Qin, Stefanus Du Toit, Kevin Moule, Tiberiu S. Popa,
00006 //          Bryan Chan, Michael D. McCool
00007 // 
00008 // This software is provided 'as-is', without any express or implied
00009 // warranty. In no event will the authors be held liable for any damages
00010 // arising from the use of this software.
00011 // 
00012 // Permission is granted to anyone to use this software for any purpose,
00013 // including commercial applications, and to alter it and redistribute it
00014 // freely, subject to the following restrictions:
00015 // 
00016 // 1. The origin of this software must not be misrepresented; you must
00017 // not claim that you wrote the original software. If you use this
00018 // software in a product, an acknowledgment in the product documentation
00019 // would be appreciated but is not required.
00020 // 
00021 // 2. Altered source versions must be plainly marked as such, and must
00022 // not be misrepresented as being the original software.
00023 // 
00024 // 3. This notice may not be removed or altered from any source
00025 // distribution.
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); // pseudorandom 3D noise texture
00044 
00045 template<int M, typename T, int P>
00046 bool ShNoise<M, T, P>::m_init = false; // whether Perlin is initialized. 
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   // generate pseudorand noise noiseImage[x + y * P][z] holds the four
00061   // 1D gradient components for lattice points (x, y, z), (x, y, z + 1), (x, y + 1, z),
00062   // and (x, y + 1, z + 1)
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); // offset from integer lattice point
00099   TempType p0, p1; // positive coordinates in [0, P)^3
00100   TempType ip0, ip1; // integer lattice point in [0,P)^3 for hash, [0,1)^3 for tex lookup
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) { // convert to tex coordiantes (TODO remove when we have RECT textures)
00107     ip0 = (ip0 + 0.5f) * invP; 
00108     ip1 = (ip1 + 0.5f) * invP; 
00109   } 
00110 
00111   // find gradients at the NUM_SAMPLES adjacent grid points (NUM_SAMPLES = 2^K for dimension K lookup)
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)); // lookup 3D texture
00124     } else {
00125       grad[i] = cast<M>(hashmrg(intLatticePoint)); 
00126     }
00127   }
00128 
00129   TempType t = _psmootht(rp); //ShNoise's improved polynomial interpolant 
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> &amp, 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> &amp, 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 } // namespace ShUtil
00244 
00245 #endif

Generated on Mon Jan 24 18:36:33 2005 for Sh by  doxygen 1.4.1