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

ShWorleyImpl.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 
00025 #ifndef SHUTIL_WORLEYIMPL_HPP 
00026 #define SHUTIL_WORLEYIMPL_HPP
00027 
00028 #include <cstdlib>
00029 #include "ShSyntax.hpp"
00030 #include "ShWorley.hpp"
00031 #include "ShNoise.hpp"
00032 #include "ShFunc.hpp"
00033 #include "ShImage.hpp"
00034 #include "ShTexCoord.hpp"
00035 
00036 namespace ShUtil {
00037 
00038 using namespace SH;
00039 
00040 template<int D, typename T>
00041 void GridGenFactory<D, T>::operator()(const ShGeneric<D, T> &p, Generator<D, T> result[]) const {
00042   ShAttrib<D, SH_TEMP, T> pCell = floor(p);
00043 
00044   // each set of two bits represents offset along one dimension
00045   // if the bit value = 0, offset by -1, 1 = no offset, 2 = offset by 1 
00046   int i, j, offsetBits;
00047   ShConstAttrib3f offsets(-1, 0, 1);
00048   int offsetSwiz[D];
00049   j = 0;
00050   for(offsetBits = 0; offsetBits < (1 << (D * 2)); ++offsetBits) {
00051     for(i = 0; i < D; ++i) {
00052       offsetSwiz[i] = ((offsetBits >> (i * 2)) & 3); 
00053       if(offsetSwiz[i] == 3) break;
00054     }
00055     if(i < D) continue;
00056 
00057     Generator<D, T> gen;
00058     result[j].offset = offsets.template swiz<D>(offsetSwiz); 
00059     SH_DEBUG_PRINT("Offset:" << result[j].offset); 
00060     result[j].cell = pCell + result[j].offset;
00061     makePos(result[j]);
00062     ++j;
00063   }
00064 }
00065 
00066 
00067 template<int D, typename T>
00068 void DefaultGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00069   g.pos = g.cell + cellnoise<D>(g.cell, m_useTexture);
00070 }
00071 
00072 template<int D, typename T>
00073 void NullGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00074   g.pos = g.cell + fillcast<D>(ShAttrib<1, SH_CONST, T>(0.5f)); 
00075 }
00076 
00077 template<int D, typename T>
00078 LerpGenFactory<D, T>::LerpGenFactory(const ShGeneric<1, T> &time, bool useTexture)
00079   : m_time(time), m_useTexture(useTexture) {}
00080 
00081 template<int D, typename T>
00082 void LerpGenFactory<D, T>::makePos(Generator<D, T> &g) const {
00083   ShAttrib<1, SH_TEMP, T> lastTime = floor(m_time);
00084   ShAttrib<1, SH_TEMP, T> timeOffset = frac(m_time);
00085   ShAttrib<D + 1, SH_TEMP, T> offsetCell;
00086 
00087   offsetCell = fillcast<D+1>(g.cell);
00088   offsetCell(D) = lastTime;
00089   ShAttrib<D, SH_TEMP, T> p1 = cellnoise<D>(offsetCell, m_useTexture); 
00090 
00091   offsetCell(D) += 1;
00092   ShAttrib<D, SH_TEMP, T> p2 = cellnoise<D>(offsetCell, m_useTexture); 
00093 
00094   g.pos = g.cell + lerp(timeOffset, p2, p1);
00095 }
00096 
00097 template<int N, int D, typename T, typename P1, typename P2>
00098 CombinedPropFactory<N, D, T, P1, P2>::CombinedPropFactory(const P1 *propFactory1, const P2 *propFactory2)
00099   : m_propFactory1(propFactory1), m_propFactory2(propFactory2) {}
00100 
00101 template<int N, int D, typename T, typename P1, typename P2>
00102 ShGeneric<N, T> CombinedPropFactory<N, D, T, P1, P2>::operator()(
00103     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00104   return join((*m_propFactory1)(p, g), (*m_propFactory2)(p, g));
00105 }
00106 
00107 template<typename P1, typename P2>
00108 PropertyFactory<P1::NUM_PROPS + P2::NUM_PROPS, P1::DIM, typename P1::PropType>*
00109 combine(const P1 *propFactory1, const P2 *propFactory2) {
00110   const int N = P1::NUM_PROPS + P2::NUM_PROPS;
00111   return new CombinedPropFactory<N, P1::DIM, typename P1::PropType, P1, P2>(propFactory1, propFactory2);
00112 }
00113 
00114 template<int D, typename T>
00115 ShGeneric<1, T> DistSqPropFactory<D, T>::operator()(
00116     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00117   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00118   return delta | delta; 
00119 }
00120 
00121 template<int D, typename T>
00122 ShGeneric<1, T> Dist_1PropFactory<D, T>::operator() (
00123     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00124   ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00125   return delta | fillcast<D>(ShConstAttrib1f(1.0f)); 
00126 }
00127 
00128 template<int D, typename T>
00129 ShGeneric<1, T> Dist_InfPropFactory<D, T>::operator() (
00130     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00131   ShAttrib<D, SH_TEMP, T> delta = abs(p - g.pos);
00132 
00133   // TODO replace with tuple max function when implemented 
00134   ShAttrib<1, SH_TEMP, T> result = 0; 
00135   for(int i = 0; i < D; ++i) result = max(result, delta(i));
00136   return result;
00137 }
00138 
00139 template<int D, typename T>
00140 ShGeneric<D + 1, T> DistSqGradientPropFactory<D, T>::operator() (
00141     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00142   ShAttrib<D + 1, SH_TEMP, T> result;
00143   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00144 
00145   result(0) = delta | delta; 
00146   for(int i = 1; i < D + 1; ++i) {
00147     result(i) = delta(i-1) * result(0);
00148   }
00149   return result;
00150 };
00151 
00152 template<int D, typename T>
00153 ShGeneric<D + 1, T> Dist_1GradientPropFactory<D, T>::operator() (
00154     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00155 
00156   ShAttrib<D + 1, SH_TEMP, T> result;
00157   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00158 
00159   ShAttrib<1, SH_CONST, T> ONE(1);
00160   result(0) = abs(delta) | fillcast<D>(ONE);
00161   for(int i = 1; i < D + 1; ++i) { // TODO switch to a swizzled version
00162     result(i) = cond(delta(i-1), ONE, -ONE); 
00163   }
00164   return result;
00165 };
00166 
00167 template<int D, typename T>
00168 ShGeneric<D + 1, T> Dist_InfGradientPropFactory<D, T>::operator() (
00169     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00170   ShAttrib<D + 1, SH_TEMP, T> result;
00171   ShAttrib<D, SH_TEMP, T> delta = p - g.pos;
00172   ShAttrib<D, SH_TEMP, T> absDelta = abs(delta); 
00173 
00174   result(0) = 0;
00175   for(int i = 0; i < D; ++i) result(0) = max(result(0), absDelta(i)); 
00176 
00177   // TODO remove this when constant folding is available
00178   ShAttrib<1, SH_CONST, T> ONE(1);
00179   for(int i = 1; i < D + 1; ++i) { // TODO switch to a swizzled version
00180     result(i) = (absDelta(i-1) >= result(0)) * cond(delta(i-1), ONE, -ONE); 
00181   }
00182   return result;
00183 };
00184 
00185 template<int N, int D, typename T>
00186 ShGeneric<N, T> CellnoisePropFactory<N, D, T>::operator() (
00187     const ShGeneric<D, T> &p, const Generator<D, T> &g) const {
00188   // TODO remove frac once Issue58 fixed
00189   return frac(cellnoise<N>(g.cell, m_useTexture));
00190 };
00191 
00192 template<typename TexType, typename T>
00193 Tex2DPropFactory<TexType, T>::Tex2DPropFactory(
00194     const ShBaseTexture2D<TexType> &tex, const ShGeneric<1, T> &scale)
00195   : m_tex(tex), m_scale(scale), invScale(ShConstAttrib2f(1.0f, 1.0f) / tex.size()) {}
00196 
00197 /* Moved to ShWorley.hpp
00198 template<typename TexType, typename T>
00199 ShGeneric<TexType::typesize, T> Tex2DPropFactory<TexType, T>::operator()(
00200     const ShGeneric<2, T> &p, const Generator<2, T> &g) const {
00201 }
00202 */
00203 
00204 template<int N, int K, int P, typename T>
00205 void kSelect(const ShGeneric<P, T> vals[N], ShGeneric<K, T> result[N], float LARGE = 1e10) {
00206   result[0] = fillcast<K>(ShConstAttrib1f(LARGE));
00207 
00208   int i, j, k, l;
00209   int shiftswiz[K];
00210   ShAttrib1f c;
00211   for(i = 0; i < K; ++i) shiftswiz[i] = (i == 0 ? 0 : i - 1);
00212 
00213   // insert into result one by one
00214   for(i = 0; i < P; ++i) {
00215     // check if smaller than the first one
00216     c = vals[0](i) < result[0](0);
00217     for(j = 0; j < N; ++j) {
00218       result[0] = lerp(c, result[0].template swiz<K>(shiftswiz), result[0]); 
00219       result[0](0) = lerp(c, vals[0](i), result[0](0));
00220     }
00221 
00222     // check for the other ones
00223     for(j = 1; j < K; ++j) {
00224       c = (result[0](j-1) < vals[0](i)) * (vals[0](i) < result[0](j));
00225       for(k = 0; k < N; ++k) {
00226         for(l = 0; l < K; ++l) shiftswiz[l] = l + ( l >= j ? -1 : 0); 
00227         result[k] = lerp(c, result[k].template swiz<K>(shiftswiz), result[k]);
00228         result[k](j) = lerp(c, vals[k](i), result[k](j));
00229       }
00230     }
00231   }
00232 }
00233 
00234 template<int K, int L, int P, int D, typename T>
00235 void worley(ShGeneric<K, T> result[], const ShGeneric<D, T> &p,
00236     const GeneratorFactory<P, D, T> *genFactory,
00237     const PropertyFactory<L, D, T> *propFactory) {
00238 
00239   int i, j;
00240   Generator<D, T> generators[P];
00241   ShAttrib<P, SH_TEMP, T> props[L]; 
00242   ShAttrib<L, SH_TEMP, T> propTemp; 
00243 
00244   (*genFactory)(p, generators); // make generators
00245   for(i = 0; i < P; ++i) {
00246     propTemp = (*propFactory)(p, generators[i]);
00247     for(j = 0; j < L; ++j) props[j](i) = propTemp(j);
00248   }
00249 
00250   // sort points & gradients by distance
00251   groupsort<L>(props); 
00252 
00253   // weighted sum of basis function values to get final result
00254   for(j = 0; j < L; ++j) result[j] = cast<K>(props[j]);
00255 }
00256 
00257 template<int K, int D, typename T>
00258 #ifdef WIn32
00259 ShGeneric<K, T> worley(const ShGeneric<D, T> &p, bool useTexture=true) {
00260 #else
00261 ShGeneric<K, T> worley(const ShGeneric<D, T> &p, bool useTexture=true) {
00262 #endif
00263   DefaultGenFactory<D, T> genFactory(useTexture);
00264   DistSqPropFactory<D, T> propFactory;
00265   ShAttrib<K, SH_TEMP, T> result;
00266   worley(&result, p, &genFactory, &propFactory);
00267   return result;
00268 }
00269 
00270 template<int K, int D, typename T>
00271 #ifdef WIn32
00272 ShProgram shWorley(bool useTexture=true) {
00273 #else
00274 ShProgram shWorley(bool useTexture) {
00275 #endif
00276   DefaultGenFactory<D, T> genFactory(useTexture);
00277   DistSqPropFactory<D, T> propFactory;
00278   return shWorley<K>(&genFactory, &propFactory); 
00279 }
00280 
00281 template<int K, int L, int P, int D, typename T>
00282 ShProgram shWorley(const GeneratorFactory<P, D, T> *genFactory,
00283         const PropertyFactory<L, D, T> *propFactory) {
00284   ShProgram program = SH_BEGIN_PROGRAM() {
00285     ShAttrib<D, SH_INPUT, T, SH_TEXCOORD> SH_DECL(texcoord);
00286 
00287     ShAttrib<K, SH_OUTPUT, T> result[L]; 
00288     worley(&result[0], texcoord, genFactory, propFactory); 
00289   } SH_END_PROGRAM;
00290   return program;
00291 }
00292 
00293 }
00294 
00295 #endif

Generated on Wed Jun 15 18:12:42 2005 for Sh by  doxygen 1.4.3-20050530