Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | 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 // runs x * d + e, d may be an Attrib or a float 00082 template<int M, typename T> 00083 ShGeneric<M, T> _pmad(const ShGeneric<M, T> &x, T d, T e) { 00084 T vals[M]; 00085 for(int i = 0; i < M; ++i) vals[i] = e; 00086 ShAttrib<M, SH_CONST, T> ec(vals); 00087 return mad(x, d, ec); 00088 } 00089 00090 template<int M, typename T> 00091 ShGeneric<M, T> _pmad(const ShGeneric<M, T> &x, const ShGeneric<M, T> &d, T e) { 00092 T vals[M]; 00093 for(int i = 0; i < M; ++i) vals[i] = e; 00094 ShAttrib<M, SH_CONST, T> ec(vals); 00095 return mad(x, d, ec); 00096 } 00097 00098 template<int M, typename T> 00099 ShGeneric<M, T> _psmootht(const ShGeneric<M, T> &t) 00100 { 00101 return t * t * t * _pmad(t, _pmad(t, 6.0f, -15.0f), 10.0f); 00102 } 00103 00104 // adds x to a float d componentwise 00105 template<int M, typename T> 00106 ShGeneric<M, T> _padd(const ShGeneric<M, T> &x, T d) { 00107 T vals[M]; 00108 for(int i = 0; i < M; ++i) vals[i] = d; 00109 ShAttrib<M, SH_CONST, T> c(vals); 00110 return x + c; 00111 } 00112 00113 template<int M, typename T, int P> 00114 template<int K> 00115 ShGeneric<M, T> ShNoise<M, T, P>::perlin(const ShGeneric<K, T> &p, bool useTexture) 00116 { 00117 init(); 00118 int i, j; 00119 typedef ShAttrib<K, SH_TEMP, T> TempType; 00120 typedef ShAttrib<M, SH_TEMP, T> ResultType; 00121 typedef ShAttrib<K, SH_CONST, T> ConstTempType; 00122 static const int NUM_SAMPLES = 1 << K; 00123 00124 TempType rp = frac(p); // offset from integer lattice point 00125 TempType p0, p1; // positive coordinates in [0, P)^3 00126 TempType ip0, ip1; // integer lattice point in [0,P)^3 for hash, [0,1)^3 for tex lookup 00127 00128 p0 = frac(p * invP) * constP; 00129 p1 = frac(mad(p, invP, fillcast<K>(invP))) * constP; 00130 ip0 = floor(p0); 00131 ip1 = floor(p1); 00132 if(useTexture) { // convert to tex coordiantes (TODO remove when we have RECT textures) 00133 ip0 = _padd(ip0, 0.5f) * invP; 00134 ip1 = _padd(ip1, 0.5f) * invP; 00135 } 00136 00137 // find gradients at the NUM_SAMPLES adjacent grid points (NUM_SAMPLES = 2^K for dimension K lookup) 00138 ResultType grad[NUM_SAMPLES]; 00139 00140 T flip[K]; 00141 for(i = 0; i < NUM_SAMPLES; ++i) { 00142 for(j = 0; j < K; ++j) { 00143 if(j == 0) flip[j] = i & 1; 00144 else flip[j] = (i >> j) & 1; 00145 } 00146 ConstTempType offsets(flip); 00147 TempType intLatticePoint = lerp(offsets, ip1, ip0); 00148 if(useTexture) { 00149 grad[i] = noiseTex(fillcast<3>(intLatticePoint)); // lookup 3D texture 00150 } else { 00151 grad[i] = cast<M>(hashmrg(intLatticePoint)); 00152 } 00153 } 00154 00155 TempType t = _psmootht(rp); //ShNoise's improved polynomial interpolant 00156 for(i = K - 1; i >= 0; --i) { 00157 int offset = 1 << i; 00158 for(j = 0; j < offset; ++j) { 00159 grad[j] = lerp(t(i), grad[j+offset], grad[j]); 00160 } 00161 } 00162 00163 return grad[0]; 00164 } 00165 00166 template<int M, typename T, int P> 00167 template<int K> 00168 ShGeneric<M, T> ShNoise<M, T, P>::cellnoise(const ShGeneric<K, T> &p, bool useTexture) 00169 { 00170 init(); 00171 ShAttrib<K, SH_TEMP, T> ip; 00172 00173 ip = floor(p); 00174 00175 if( useTexture ) { 00176 ip = frac(ip * invP); 00177 return noiseTex(fillcast<3>(ip)); 00178 } 00179 return fillcast<M>(hashmrg(ip)); 00180 } 00181 00182 #define SHNOISE_WITH_AMP(name) \ 00183 template<int N, int M, int K, typename T>\ 00184 ShGeneric<N, T> name(const ShGeneric<M, T> &p, const ShGeneric<K, T> &amp, bool useTexture) {\ 00185 ShAttrib<N, SH_TEMP, T> result; \ 00186 T freq = 1;\ 00187 result *= 0; \ 00188 for(int i = 0; i < K; ++i, freq *= 2.0) {\ 00189 result = mad(name<N>(p * freq, useTexture), amp(i), result);\ 00190 }\ 00191 return result;\ 00192 } 00193 00194 template<int N, int M, typename T> 00195 ShGeneric<N, T> perlin(const ShGeneric<M, T> &p, bool useTexture) { 00196 return ShNoise<N, T>::perlin(p, useTexture); 00197 } 00198 SHNOISE_WITH_AMP(perlin); 00199 00200 template<int N, int M, typename T> 00201 ShGeneric<N, T> sperlin(const ShGeneric<M, T> &p, bool useTexture) { 00202 return _pmad( perlin<N>(p, useTexture), 2.0f, -1.0f ); 00203 } 00204 SHNOISE_WITH_AMP(sperlin); 00205 00206 template<int N, int M, typename T> 00207 ShGeneric<N, T> cellnoise(const ShGeneric<M, T> &p, bool useTexture) { 00208 return ShNoise<N, T>::cellnoise(p, useTexture); 00209 } 00210 SHNOISE_WITH_AMP(cellnoise); 00211 00212 template<int N, int M, typename T> 00213 ShGeneric<N, T> scellnoise(const ShGeneric<M, T> &p, bool useTexture) { 00214 return _pmad( cellnoise<N>(p, useTexture), 2.0f, -1.0f ); 00215 } 00216 SHNOISE_WITH_AMP(scellnoise); 00217 00218 00219 template<int N, int M, typename T> 00220 ShGeneric<N, T> turbulence(const ShGeneric<M, T> &p, bool useTexture) { 00221 abs(sperlin<N>(p, useTexture)); 00222 } 00223 SHNOISE_WITH_AMP(turbulence); 00224 00225 template<int N, int M, typename T> 00226 ShGeneric<N, T> sturbulence(const ShGeneric<M, T> &p, bool useTexture) { 00227 return _pmad(abs(sperlin<N>(p, useTexture)), 2.0f, -1.0f); 00228 } 00229 SHNOISE_WITH_AMP(sturbulence); 00230 00231 } // namespace ShUtil 00232 00233 #endif

Generated on Mon Oct 18 14:17:39 2004 for Sh by doxygen 1.3.7