00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00045
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
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) {
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
00178 ShAttrib<1, SH_CONST, T> ONE(1);
00179 for(int i = 1; i < D + 1; ++i) {
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
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
00198
00199
00200
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
00214 for(i = 0; i < P; ++i) {
00215
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
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);
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
00251 groupsort<L>(props);
00252
00253
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