root/OpenSceneGraph/trunk/examples/osgshaders/Noise.cpp @ 4138

Revision 4138, 5.4 kB (checked in by robert, 10 years ago)

From Mike Weiblen, added \n newlines to inline shader program strings.
From Robert Osfield, changed tabs to spaces.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/************************************************************************
2 *                                                                      *
3 *                   Copyright (C) 2002  3Dlabs Inc. Ltd.               *
4 *                                                                      *
5 ************************************************************************/
6
7#include <math.h>
8#include <stdlib.h>
9
10/* Coherent noise function over 1, 2 or 3 dimensions */
11/* (copyright Ken Perlin) */
12
13#define MAXB 0x100
14#define N 0x1000
15#define NP 12   /* 2^N */
16#define NM 0xfff
17
18#define s_curve(t) ( t * t * (3. - 2. * t) )
19#define lerp(t, a, b) ( a + t * (b - a) )
20#define setup(i,b0,b1,r0,r1)\
21        t = vec[i] + N;\
22        b0 = ((int)t) & BM;\
23        b1 = (b0+1) & BM;\
24        r0 = t - (int)t;\
25        r1 = r0 - 1.;
26#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
27#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
28
29static void initNoise(void);
30
31static int p[MAXB + MAXB + 2];
32static double g3[MAXB + MAXB + 2][3];
33static double g2[MAXB + MAXB + 2][2];
34static double g1[MAXB + MAXB + 2];
35
36int start;
37int B;
38int BM;
39
40
41void SetNoiseFrequency(int frequency)
42{
43        start = 1;
44        B = frequency;
45        BM = B-1;
46}
47
48double noise1(double arg)
49{
50   int bx0, bx1;
51   double rx0, rx1, sx, t, u, v, vec[1];
52
53   vec[0] = arg;
54   if (start) {
55      start = 0;
56      initNoise();
57   }
58
59   setup(0,bx0,bx1,rx0,rx1);
60
61   sx = s_curve(rx0);
62   u = rx0 * g1[ p[ bx0 ] ];
63   v = rx1 * g1[ p[ bx1 ] ];
64
65   return(lerp(sx, u, v));
66}
67
68double noise2(double vec[2])
69{
70   int bx0, bx1, by0, by1, b00, b10, b01, b11;
71   double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
72   int i, j;
73
74   if (start) {
75      start = 0;
76      initNoise();
77   }
78
79   setup(0, bx0,bx1, rx0,rx1);
80   setup(1, by0,by1, ry0,ry1);
81
82   i = p[ bx0 ];
83   j = p[ bx1 ];
84
85   b00 = p[ i + by0 ];
86   b10 = p[ j + by0 ];
87   b01 = p[ i + by1 ];
88   b11 = p[ j + by1 ];
89
90   sx = s_curve(rx0);
91   sy = s_curve(ry0);
92
93   q = g2[ b00 ] ; u = at2(rx0,ry0);
94   q = g2[ b10 ] ; v = at2(rx1,ry0);
95   a = lerp(sx, u, v);
96
97   q = g2[ b01 ] ; u = at2(rx0,ry1);
98   q = g2[ b11 ] ; v = at2(rx1,ry1);
99   b = lerp(sx, u, v);
100
101   return lerp(sy, a, b);
102}
103
104double noise3(double vec[3])
105{
106   int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
107   double rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
108   int i, j;
109
110   if (start) {
111      start = 0;
112      initNoise();
113   }
114
115   setup(0, bx0,bx1, rx0,rx1);
116   setup(1, by0,by1, ry0,ry1);
117   setup(2, bz0,bz1, rz0,rz1);
118
119   i = p[ bx0 ];
120   j = p[ bx1 ];
121
122   b00 = p[ i + by0 ];
123   b10 = p[ j + by0 ];
124   b01 = p[ i + by1 ];
125   b11 = p[ j + by1 ];
126
127   t  = s_curve(rx0);
128   sy = s_curve(ry0);
129   sz = s_curve(rz0);
130
131   q = g3[ b00 + bz0 ] ; u = at3(rx0,ry0,rz0);
132   q = g3[ b10 + bz0 ] ; v = at3(rx1,ry0,rz0);
133   a = lerp(t, u, v);
134
135   q = g3[ b01 + bz0 ] ; u = at3(rx0,ry1,rz0);
136   q = g3[ b11 + bz0 ] ; v = at3(rx1,ry1,rz0);
137   b = lerp(t, u, v);
138
139   c = lerp(sy, a, b);
140
141   q = g3[ b00 + bz1 ] ; u = at3(rx0,ry0,rz1);
142   q = g3[ b10 + bz1 ] ; v = at3(rx1,ry0,rz1);
143   a = lerp(t, u, v);
144
145   q = g3[ b01 + bz1 ] ; u = at3(rx0,ry1,rz1);
146   q = g3[ b11 + bz1 ] ; v = at3(rx1,ry1,rz1);
147   b = lerp(t, u, v);
148
149   d = lerp(sy, a, b);
150
151   //fprintf(stderr, "%f\n", lerp(sz, c, d));
152
153   return lerp(sz, c, d);
154}
155
156void normalize2(double v[2])
157{
158   double s;
159
160   s = sqrt(v[0] * v[0] + v[1] * v[1]);
161   v[0] = v[0] / s;
162   v[1] = v[1] / s;
163}
164
165void normalize3(double v[3])
166{
167   double s;
168
169   s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
170   v[0] = v[0] / s;
171   v[1] = v[1] / s;
172   v[2] = v[2] / s;
173}
174
175void initNoise(void)
176{
177   int i, j, k;
178
179   srand(30757);
180   for (i = 0 ; i < B ; i++) {
181      p[i] = i;
182      g1[i] = (double)((rand() % (B + B)) - B) / B;
183
184      for (j = 0 ; j < 2 ; j++)
185         g2[i][j] = (double)((rand() % (B + B)) - B) / B;
186      normalize2(g2[i]);
187
188      for (j = 0 ; j < 3 ; j++)
189         g3[i][j] = (double)((rand() % (B + B)) - B) / B;
190      normalize3(g3[i]);
191   }
192
193   while (--i) {
194      k = p[i];
195      p[i] = p[j = rand() % B];
196      p[j] = k;
197   }
198
199   for (i = 0 ; i < B + 2 ; i++) {
200      p[B + i] = p[i];
201      g1[B + i] = g1[i];
202      for (j = 0 ; j < 2 ; j++)
203         g2[B + i][j] = g2[i][j];
204      for (j = 0 ; j < 3 ; j++)
205         g3[B + i][j] = g3[i][j];
206   }
207}
208
209/* --- My harmonic summing functions - PDB --------------------------*/
210
211/*
212   In what follows "alpha" is the weight when the sum is formed.
213   Typically it is 2, As this approaches 1 the function is noisier.
214   "beta" is the harmonic scaling/spacing, typically 2.
215*/
216
217double PerlinNoise1D(double x,double alpha,double beta,int n)
218{
219   int i;
220   double val,sum = 0;
221   double p,scale = 1;
222
223   p = x;
224   for (i=0;i<n;i++) {
225      val = noise1(p);
226      sum += val / scale;
227      scale *= alpha;
228      p *= beta;
229   }
230   return(sum);
231}
232
233double PerlinNoise2D(double x,double y,double alpha,double beta,int n)
234{
235   int i;
236   double val,sum = 0;
237   double p[2],scale = 1;
238
239   p[0] = x;
240   p[1] = y;
241   for (i=0;i<n;i++) {
242      val = noise2(p);
243      sum += val / scale;
244      scale *= alpha;
245      p[0] *= beta;
246      p[1] *= beta;
247   }
248   return(sum);
249}
250
251double PerlinNoise3D(double x,double y,double z,double alpha,double beta,int n)
252{
253   int i;
254   double val,sum = 0;
255   double p[3],scale = 1;
256
257   p[0] = x;
258   p[1] = y;
259   p[2] = z;
260   for (i=0;i<n;i++) {
261      val = noise3(p);
262      sum += val / scale;
263      scale *= alpha;
264      p[0] *= beta;
265      p[1] *= beta;
266      p[2] *= beta;
267   }
268   return(sum);
269}
Note: See TracBrowser for help on using the browser.