00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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);
00044
00045
template<
int M,
typename T,
int P>
00046
bool ShNoise<M, T, P>::m_init =
false;
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
00061
00062
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
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
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);
00125 TempType p0, p1;
00126 TempType ip0, ip1;
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) {
00133 ip0 = _padd(ip0, 0.5f) * invP;
00134 ip1 = _padd(ip1, 0.5f) * invP;
00135 }
00136
00137
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));
00150 }
else {
00151 grad[i] = cast<M>(
hashmrg(intLatticePoint));
00152 }
00153 }
00154
00155 TempType t = _psmootht(rp);
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> &, 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 }
00232
00233
#endif