ShLibWorleyImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2006 Serious Hack Inc.
00004 // 
00005 // This library is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 //
00010 // This library is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with this library; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
00018 // MA  02110-1301, USA
00020 #ifndef SHLIBWORLEYIMPL_HPP 
00021 #define SHLIBWORLEYIMPL_HPP
00022 
00023 #include "ShLibWorley.hpp"
00024 #include <cstdlib>
00025 #include "ShSyntax.hpp"
00026 #include "ShBaseTexture.hpp"
00027 #include "ShGeneric.hpp"
00028 
00029 namespace SH {
00030 
00031 // Integer Power using template metaprogramming...
00032 // TODO find a better way than this.
00033 // sort on N-tuples needs to know at C++ compile time exactly 
00034 template<int N, int M> 
00035 struct _IntPow {
00036   static const int value = N * _IntPow<N, M-1>::value;
00037 };
00038 
00039 template<int N> 
00040 struct _IntPow<N, 1> {
00041   static const int value = N;
00042 };
00043 
00044 // The foundation for the regular grid-based generators
00045 template<int D, typename T>
00046 struct GridGenFactory: public GeneratorFactory<_IntPow<3, D>::value, D, T> { 
00047   void operator()(const ShGeneric<D, T> &p, Generator<D, T> result[]) const;
00048   
00049 private:
00050   // given a Generator that has its cell and offset filled in, this function
00051   // generates the actual pos.
00052   virtual void makePos(Generator<D, T> &g) const = 0; 
00053 };
00054 
00055 // The default generator - uses a uniform integer grid with one
00056 // generator point in each grid cell.
00057 // If PointType is d-dimensional, it generates 3^d points from 
00058 // p's cell and all adjacent grid cells.
00059 template<int D, typename T>
00060 struct DefaultGenFactory: public GridGenFactory<D, T> { 
00061   DefaultGenFactory(bool useTexture): m_useTexture(useTexture) {}
00062   
00063 private:
00064   void makePos(Generator<D, T> &g) const;
00065   bool m_useTexture;
00066 };
00067 
00068 // a null point generator - just makes a non-jittered grid
00069 // of generators (good for debugging, or certain kinds of patterns...)
00070 template<int D, typename T>
00071 struct NullGenFactory: public GridGenFactory<D, T> { 
00072 private:
00073   void makePos(Generator<D, T> &g) const;
00074 };
00075 
00076 // An animating point generator - uses same uniform integer grid
00077 // method as the default, except that it linearly interpolates
00078 // between pairs of generator point sets, moving through a sequence
00079 // of point sets as time increases. 
00080 template<int D, typename T>
00081 struct LerpGenFactory: GridGenFactory<D, T> {
00082   LerpGenFactory(const ShGeneric<1, T> &time, bool useTexture);
00083   
00084 private:
00085   void makePos(Generator<D, T> &g) const;
00086   const ShGeneric<1, T> &m_time;
00087   bool m_useTexture;
00088 };
00089 
00090 // when ShProgram objects can be called like functions, this will 
00091 // no longer be necessary as it is analogous to the Algebra combine operator.
00092 template<int N, int D, typename T, typename P1, typename P2>
00093 struct CombinedPropFactory: public PropertyFactory<N, D, T> {
00094   CombinedPropFactory(const P1 *propFactory1, const P2 *propFactory2);
00095   
00096   ShGeneric<N, T> operator()(const ShGeneric<D, T> &p,
00097                              const Generator<D, T> &g) const;
00098 
00099 private:
00100   const P1* m_propFactory1;
00101   const P2* m_propFactory2;
00102 };
00103 
00104 
00105 // standard distance based property factories 
00106 // Re-write later to take function pointer (or ShProgram object)
00107 // to a distance function.
00108 template<int D, typename T>
00109 struct DistSqPropFactory: public PropertyFactory<1, D, T> {
00110   ShGeneric<1, T> operator()(const ShGeneric<D, T> &p,
00111                              const Generator<D, T> &g) const; 
00112 };
00113 
00114 template<int D, typename T>
00115 struct Dist_1PropFactory: public PropertyFactory<1, D, T> {
00116   ShGeneric<1, T> operator()(const ShGeneric<D, T> &p,
00117                              const Generator<D, T> &g) const; 
00118 };
00119 
00120 template<int D, typename T>
00121 struct Dist_InfPropFactory: public PropertyFactory<1, D, T> {
00122   ShGeneric<1, T> operator()(const ShGeneric<D, T> &p, 
00123                              const Generator<D, T> &g) const; 
00124 };
00125 
00126 template<int D, typename T>
00127 struct DistSqGradientPropFactory: public PropertyFactory<D + 1, D, T> {
00128   ShGeneric<D + 1, T> operator()(const ShGeneric<D, T> &p, 
00129                                  const Generator<D, T> &g) const; 
00130 };
00131 
00132 template<int D, typename T>
00133 struct Dist_1GradientPropFactory: public PropertyFactory<D + 1, D, T> {
00134   ShGeneric<D + 1, T> operator()(const ShGeneric<D, T> &p, 
00135                                  const Generator<D, T> &g) const; 
00136 };
00137 
00138 template<int D, typename T>
00139 struct Dist_InfGradientPropFactory: public PropertyFactory<D + 1, D, T> {
00140   ShGeneric<D + 1, T> operator()(const ShGeneric<D, T> &p, 
00141                                  const Generator<D, T> &g) const;
00142 };
00143 
00144 template<int N, int D, typename T>
00145 struct CellnoisePropFactory: public PropertyFactory<N, D, T> {
00146   CellnoisePropFactory(bool useTexture): m_useTexture(useTexture) {}
00147   ShGeneric<N, T> operator()(const ShGeneric<D, T> &p,
00148                              const Generator<D, T> &g) const; 
00149 
00150 private:
00151   bool m_useTexture;
00152 };
00153 
00154 template<typename TexType, typename T>
00155 struct Tex2DPropFactory: public PropertyFactory<TexType::typesize, 2, T> {
00156   Tex2DPropFactory(const ShBaseTexture2D<TexType> &tex, 
00157                    const ShGeneric<1, T> &scale);
00158   ShGeneric<TexType::typesize, T> operator()(const ShGeneric<2, T> &p, 
00159                                              const Generator<2, T> &g) const
00160   {
00161     // Moved here from WorleyImpl.hpp because MSVC gets confused otherwise
00162     return m_tex(frac(g.cell * invScale * m_scale)) * ShConstAttrib1f(1.0f);
00163   }
00164 
00165 private:
00166   const ShBaseTexture2D<TexType> &m_tex;
00167   const ShGeneric<1, T> &m_scale;
00168   ShConstAttrib2f invScale;
00169   // TODO remove invScale and restrict to RECT textures later 
00170 };
00171 
00172 //----------------
00173 // IMPLEMENTATION
00174 //----------------
00175 
00176 template<int D, typename T>
00177 void GridGenFactory<D, T>::operator()(const ShGeneric<D, T> &p, 
00178                                       Generator<D, T> result[]) const
00179 {
00180   ShAttrib<D, SH_TEMP, T> pCell = floor(p);
00181 
00182   // each set of two bits represents offset along one dimension
00183   // if the bit value = 0, offset by -1, 1 = no offset, 2 = offset by 1 
00184   int i, j, offsetBits;
00185   ShConstAttrib3f offsets(-1, 0, 1);
00186   int offsetSwiz[D];
00187   j = 0;
00188   for(offsetBits = 0; offsetBits < (1 << (D * 2)); ++offsetBits) {
00189     for(i = 0; i < D; ++i) {
00190       offsetSwiz[i] = ((offsetBits >> (i * 2)) & 3); 
00191       if(offsetSwiz[i] == 3) break;
00192     }
00193     if(i < D) continue;
00194 
00195     Generator<D, T> gen;
00196     result[j].offset = offsets.template swiz<D>(offsetSwiz); 
00197     SH_DEBUG_PRINT("Offset:" << result[j].offset); 
00198     result[j].cell = pCell + result[j].offset;
00199     makePos(result[j]);
00200     ++j;
00201   }
00202 }
00203 
00204 template<int D, typename T>
00205 void DefaultGenFactory<D, T>::makePos(Generator<D, T> &g) const 
00206 {
00207   g.pos = g.cell + cellnoise<D>(g.cell, m_useTexture);
00208 }
00209 
00210 template<int D, typename T>
00211 void NullGenFactory<D, T>::makePos(Generator<D, T> &g) const 
00212 {
00213   g.pos = g.cell + fillcast<D>(ShAttrib<1, SH_CONST, T>(0.5f)); 
00214 }
00215 
00216 template<int D, typename T>
00217 LerpGenFactory<D, T>::LerpGenFactory(const ShGeneric<1, T> &time, bool useTexture)
00218   : m_time(time), m_useTexture(useTexture)
00219 {
00220 }
00221 
00222 template<int D, typename T>
00223 void LerpGenFactory<D, T>::makePos(Generator<D, T> &g) const
00224 {
00225   ShAttrib<1, SH_TEMP, T> lastTime = floor(m_time);
00226   ShAttrib<1, SH_TEMP, T> timeOffset = frac(m_time);
00227   ShAttrib<D + 1, SH_TEMP, T> offsetCell;
00228 
00229   offsetCell = fillcast<D+1>(g.cell);
00230   offsetCell(D) = lastTime;
00231   ShAttrib<D, SH_TEMP, T> p1 = cellnoise<D>(offsetCell, m_useTexture); 
00232 
00233   offsetCell(D) += 1;
00234   ShAttrib<D, SH_TEMP, T> p2 = cellnoise<D>(offsetCell, m_useTexture); 
00235 
00236   g.pos = g.cell + lerp(timeOffset, p2, p1);
00237 }
00238 
00239 template<int N, int D, typename T, typename P1, typename P2>
00240 CombinedPropFactory<N, D, T, P1, P2>::CombinedPropFactory(const P1 *propFactory1, 
00241                                                           const P2 *propFactory2)
00242   : m_propFactory1(propFactory1), m_propFactory2(propFactory2)
00243 {
00244 }
00245 
00246 template<int N, int D, typename T, typename P1, typename P2>
00247 ShGeneric<N, T>
00248 CombinedPropFactory<N, D, T, P1, P2>::operator()(const ShGeneric<D, T> &p,
00249                                                  const Generator<D, T> &g) const
00250 {
00251   return join((*m_propFactory1)(p, g), (*m_propFactory2)(p, g));
00252 }
00253 
00254 template<typename P1, typename P2>
00255 PropertyFactory<P1::NUM_PROPS + P2::NUM_PROPS, P1::DIM, typename P1::PropType>*
00256 combine(const P1 *propFactory1, const P2 *propFactory2)
00257 {
00258   const int N = P1::NUM_PROPS + P2::NUM_PROPS;
00259   return new CombinedPropFactory<N, P1::DIM, typename P1::PropType, P1, P2>(propFactory1, propFactory2);
00260 }
00261 
00262 template<int D, typename T>
00263 ShGeneric<1, T> 
00264 DistSqPropFactory<D, T>::operator()(const ShGeneric<D, T> &p,
00265                                     const Generator<D, T> &g) const
00266 {
00267   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00268   return delta | delta; 
00269 }
00270 
00271 template<int D, typename T>
00272 ShGeneric<1, T> 
00273 Dist_1PropFactory<D, T>::operator() (const ShGeneric<D, T> &p, 
00274                                      const Generator<D, T> &g) const
00275 {
00276   ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00277   return delta | fillcast<D>(ShConstAttrib1f(1.0f)); 
00278 }
00279 
00280 template<int D, typename T>
00281 ShGeneric<1, T> 
00282 Dist_InfPropFactory<D, T>::operator() (const ShGeneric<D, T> &p,
00283                                        const Generator<D, T> &g) const
00284 {
00285   ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00286 
00287   // TODO replace with tuple max function when implemented 
00288   ShAttrib<1, SH_TEMP, T> result = 0; 
00289   for(int i = 0; i < D; ++i) result = max(result, delta(i));
00290   return result;
00291 }
00292 
00293 template<int D, typename T>
00294 ShGeneric<D + 1, T> 
00295 DistSqGradientPropFactory<D, T>::operator() (const ShGeneric<D, T> &p,
00296                                              const Generator<D, T> &g) const
00297 {
00298   ShAttrib<D + 1, SH_TEMP, T> result;
00299   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00300 
00301   result(0) = delta | delta; 
00302   for(int i = 1; i < D + 1; ++i) {
00303     result(i) = delta(i-1) * result(0);
00304   }
00305   return result;
00306 }
00307 
00308 template<int D, typename T>
00309 ShGeneric<D + 1, T> 
00310 Dist_1GradientPropFactory<D, T>::operator() (const ShGeneric<D, T> &p, 
00311                                              const Generator<D, T> &g) const
00312 {
00313 
00314   ShAttrib<D + 1, SH_TEMP, T> result;
00315   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00316 
00317   ShAttrib<1, SH_CONST, T> ONE(1);
00318   result(0) = abs(delta) | fillcast<D>(ONE);
00319   for(int i = 1; i < D + 1; ++i) { // TODO switch to a swizzled version
00320     result(i) = cond(delta(i-1), ONE, -ONE); 
00321   }
00322   return result;
00323 }
00324 
00325 template<int D, typename T>
00326 ShGeneric<D + 1, T> 
00327 Dist_InfGradientPropFactory<D, T>::operator() (const ShGeneric<D, T> &p, 
00328                                                const Generator<D, T> &g) const
00329 {
00330   ShAttrib<D + 1, SH_TEMP, T> result;
00331   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00332   ShAttrib<D, SH_TEMP, T> absDelta = abs(delta); 
00333 
00334   result(0) = 0;
00335   for(int i = 0; i < D; ++i) result(0) = max(result(0), absDelta(i)); 
00336 
00337   // TODO remove this when constant folding is available
00338   ShAttrib<1, SH_CONST, T> ONE(1);
00339   for(int i = 1; i < D + 1; ++i) { // TODO switch to a swizzled version
00340     result(i) = (absDelta(i-1) >= result(0)) * cond(delta(i-1), ONE, -ONE); 
00341   }
00342   return result;
00343 }
00344 
00345 template<int N, int D, typename T>
00346 ShGeneric<N, T>
00347 CellnoisePropFactory<N, D, T>::operator() (const ShGeneric<D, T> &p, 
00348                                            const Generator<D, T> &g) const
00349 {
00350   return cellnoise<N>(g.cell, m_useTexture);
00351 }
00352 
00353 template<typename TexType, typename T>
00354 Tex2DPropFactory<TexType, T>::Tex2DPropFactory(const ShBaseTexture2D<TexType> &tex, 
00355                                               const ShGeneric<1, T> &scale)
00356   : m_tex(tex), m_scale(scale), 
00357     invScale(ShConstAttrib2f(1.0f, 1.0f) / tex.size()) 
00358 {
00359 }
00360 
00361 template<int N, int K, int P, typename T>
00362 void kSelect(const ShGeneric<P, T> vals[N], ShGeneric<K, T> result[N], 
00363              float LARGE = 1e10)
00364 {
00365   result[0] = fillcast<K>(ShConstAttrib1f(LARGE));
00366 
00367   int i, j, k, l;
00368   int shiftswiz[K];
00369   ShAttrib1f c;
00370   for(i = 0; i < K; ++i) shiftswiz[i] = (i == 0 ? 0 : i - 1);
00371 
00372   // insert into result one by one
00373   for(i = 0; i < P; ++i) {
00374     // check if smaller than the first one
00375     c = vals[0](i) < result[0](0);
00376     for(j = 0; j < N; ++j) {
00377       result[0] = lerp(c, result[0].template swiz<K>(shiftswiz), result[0]); 
00378       result[0](0) = lerp(c, vals[0](i), result[0](0));
00379     }
00380 
00381     // check for the other ones
00382     for(j = 1; j < K; ++j) {
00383       c = (result[0](j-1) < vals[0](i)) * (vals[0](i) < result[0](j));
00384       for(k = 0; k < N; ++k) {
00385         for(l = 0; l < K; ++l) shiftswiz[l] = l + ( l >= j ? -1 : 0); 
00386         result[k] = lerp(c, result[k].template swiz<K>(shiftswiz), result[k]);
00387         result[k](j) = lerp(c, vals[k](i), result[k](j));
00388       }
00389     }
00390   }
00391 }
00392 
00393 template<int K, int L, int P, int D, typename T>
00394 void worley(ShGeneric<K, T> result[], const ShGeneric<D, T> &p,
00395             const GeneratorFactory<P, D, T> *genFactory,
00396             const PropertyFactory<L, D, T> *propFactory)
00397 {
00398   int i, j;
00399   Generator<D, T> generators[P];
00400   ShAttrib<P, SH_TEMP, T> props[L]; 
00401   ShAttrib<L, SH_TEMP, T> propTemp; 
00402 
00403   (*genFactory)(p, generators); // make generators
00404   for(i = 0; i < P; ++i) {
00405     propTemp = (*propFactory)(p, generators[i]);
00406     for(j = 0; j < L; ++j) props[j](i) = propTemp(j);
00407   }
00408 
00409   // sort points & gradients by distance
00410   groupsort<L>(props); 
00411 
00412   // weighted sum of basis function values to get final result
00413   for(j = 0; j < L; ++j) result[j] = cast<K>(props[j]);
00414 }
00415 
00416 template<int K, int D, typename T>
00417 ShGeneric<K, T> worley(const ShGeneric<D, T> &p, 
00418 #ifdef _WIN32
00419                        bool useTexture=true)
00420 #else
00421                        bool useTexture)
00422 #endif
00423 {
00424   DefaultGenFactory<D, T> genFactory(useTexture);
00425   DistSqPropFactory<D, T> propFactory;
00426   ShAttrib<K, SH_TEMP, T> result;
00427   worley(&result, p, &genFactory, &propFactory);
00428   return result;
00429 }
00430 
00431 template<int K, int D, typename T>
00432 ShProgram shWorley(
00433 #ifdef _WIN32
00434                    bool useTexture=true)
00435 #else
00436                    bool useTexture)
00437 #endif
00438 {
00439   DefaultGenFactory<D, T> genFactory(useTexture);
00440   DistSqPropFactory<D, T> propFactory;
00441   return shWorley<K>(&genFactory, &propFactory); 
00442 }
00443 
00444 template<int K, int L, int P, int D, typename T>
00445 ShProgram shWorley(const GeneratorFactory<P, D, T> *genFactory, 
00446                    const PropertyFactory<L, D, T> *propFactory)
00447 {
00448   ShProgram program = SH_BEGIN_PROGRAM() {
00449     ShAttrib<D, SH_INPUT, T, SH_TEXCOORD> SH_DECL(texcoord);
00450 
00451     ShAttrib<K, SH_OUTPUT, T> result[L]; 
00452     worley(&result[0], texcoord, genFactory, propFactory); 
00453   } SH_END_PROGRAM;
00454   return program;
00455 }
00456 
00457 } // namespace SH
00458 
00459 #endif // SHLIBWORLEYIMPL_HPP

Generated on Thu Feb 16 14:51:35 2006 for Sh by  doxygen 1.4.6