Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (112)
games submitted by our members
Games in WIP (553)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Value noise 2D/3D (Java & GLSL)  (Read 2868 times)
0 Members and 1 Guest are viewing this topic.
Offline Roquen
« Posted 2012-12-07 09:53:18 »

As mentioned on the wiki page Noise (bandpassed white), value noise is very defective.  However defective is not the same as useless.  Value noise has an advantage of being very fast in low dimensions.  It simple usages its defects can be an advantage of giving a certain "look" and in more complex usages the defeats can be hidden by how the samples are mixed.

The java version is a mixed implementation.  It restricts itself to a single cell per evaluation for speed purposes, otherwise the complexity becomes too high for it to be of any potential interest.  On the other hand it uses an excellent hashing function and uses a first order continuous weighting function, both of which add in reducing defects.  Note that the hashing functions chosen have short dependency chains and probably performs better than one might expect.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
122  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
135  
136  
137  
138  
139  
140  
141  
142  
143  
144  
145  
146  
147  
148  
149  
150  
151  
152  
153  
154  
155  
156  
157  
158  
159  
160  
161  
162  
163  
164  
165  
166  
167  
168  
169  
170  
171  
172  
173  
public final class ValueNoise
{
  private static final int pseudoFloor(float x)
  {
    return x >= 0 ? (int)x : (int)x-1;
  }

  private static final float weight(float t)
  {
    return (t*t*(3.f-(t+t)));
  }
 
  private static final float normalizeI(int h)
  {
    return (h>>>7)*0x1.0p-24f - 1;
  }

  private static final int M = 0x5bd1e995;

  private static final int postHashM2(int h)
  {
    h ^= h >>> 13; h *= M; h ^= h >>> 15;

    return h;
  }

  private static final int preHashM2(int x)
  {
    int h = 0x9747b28c;

    x *= M; x ^= x >>> 24; x *= M;

    h ^= x; h *= M;

    return h;
  }

  private static final int hashM2(int x)
  {
    return postHashM2(preHashM2(x));
  }

  private static final int preHashM2(int x, int y)
  {
    int h = 0x9747b28c;

    x *= M; x ^= x >>> 24; x *= M;
    y *= M; y ^= y >>> 24; y *= M;

    h ^= x; h *= M; h ^= y;

    return h;
  }

  private static final int hashM2(int x, int y)
  {
    return postHashM2(preHashM2(x,y));
  }

  private static final int preHashM2(int x, int y, int z)
  {
    int h = 0x9747b28c;

    x *= M; x ^= x >>> 24; x *= M;
    y *= M; y ^= y >>> 24; y *= M;
    z *= M; z ^= z >>> 24; z *= M;

    h ^= x; h *= M;
    h ^= y; h *= M;
    h ^= z;

    return h;
  }

  private static final int hashM2(int x, int y, int z)
  {
    return postHashM2(preHashM2(x,y,z));
  }

  private static final float mix(int x)
  {
    int h = hashM2(x);

    return normalizeI(h);
  }

  /** Sample 1D function */
  public static final float calc(float x)
  {
    int   ix = pseudoFloor(x);
    float dx = ease(x-ix);
    float r0 = mix(ix);
    float r1 = mix(ix+1);

    return lerp(dx, r0, r1);
  }

  private static final float mix(int x, int y)
  {
    return normalizeI(hashM2(x,y));
  }

  /** Sample 2D function */
  public static final float calc(float x, float y)
  {
    // get the coordinate of the cell
   int ix = pseudoFloor(x);
    int iy = pseudoFloor(y);

    // compute the offset into the cell, then weight it
   x = weight(x-ix);
    y = weight(y-iy);

    // compute hash values for the four vertices of the cell and
   // convert into a uniform float
   float r00 = mix(ix,   iy);
    float r10 = mix(ix+1, iy);
    float r01 = mix(ix,   iy+1);
    float r11 = mix(ix+1, iy+1);

    float xb = lerp(x, r00, r10);  // lerp bottom edge
   float xt = lerp(x, r01, r11);  // lerp top edge

    return lerp(y, xb, xt);  // lerp the two edges into the final result
 }

  private static final float mix(int x, int y, int z)
  {
    int h = hashM2(x,y,z);

    return normalizeI(h);
  }

  /** Sample 3D function */
  public static final float calc(float x, float y, float z)
  {
    float t0,t1,t2,t3,t4;

    // lower left hand coordinate of cell
   int ix = pseudoFloor(x);
    int iy = pseudoFloor(y);
    int iz = pseudoFloor(z);

    // offset into cell, then convert to weighting value
   x = weight(x-ix);
    y = weight(y-iy);
    z = weight(z-iz);

    // bottom edge of forward face
   t0 = mix(ix,   iy, iz);
    t1 = mix(ix+1, iy, iz);
    t2 = lerp(x, t0, t1);

    // top edge of forward face
   t0 = mix(ix,   iy+1, iz);
    t1 = mix(ix+1, iy+1, iz);
    t3 = lerp(x, t0, t1);
    t3 = lerp(y, t2, t3);                // final result in forward face

    // bottom edge of back face
   t0 = mix(ix,   iy, iz+1);
    t1 = mix(ix+1, iy, iz+1);
    t2 = lerp(x, t0, t1);

    // top edge of back face
   t0 = mix(ix,   iy+1, iz+1);
    t1 = mix(ix+1, iy+1, iz+1);
    t4 = lerp(x, t0, t1);
    t4 = lerp(y, t2, t4);

    return lerp(z, t3, t4);
  }
}


GLSL version using permutation polynomials for hashing/random number:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
#version 150 core

// Permutation polynomial RNG/Hashing from Ashima Arts.
float mod289(float x) { return x - floor(x * (1.0/289.0)) * 289.0; }
vec2  mod289(vec2 x)  { return x - floor(x * (1.0/289.0)) * 289.0; }
vec3  mod289(vec3 x)  { return x - floor(x * (1.0/289.0)) * 289.0; }
vec4  mod289(vec4 x)  { return x - floor(x * (1.0/289.0)) * 289.0; }
vec2  permute(vec2 x) { return mod289(((x*34.0)+1.0)*x); }
vec3  permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); }
vec4  permute(vec4 x) { return mod289(((x*34.0)+1.0)*x); }

float rng(float x)  { return fract(x * (1.f/41.f)); }
vec2  rng(vec2 x)   { return fract(x * (1.f/41.f)); }
vec3  rng(vec3 x)   { return fract(x * (1.f/41.f)); }
vec4  rng(vec4 x)   { return fract(x * (1.f/41.f)); }
float ease(float t) { return (t*t*(3.f-(t+t))); }
vec2  ease(vec2 t)  { return (t*t*(3.f-(t+t))); }
vec3  ease(vec3 t)  { return (t*t*(3.f-(t+t))); }
vec4  ease(vec4 t)  { return (t*t*(3.f-(t+t))); }

// sample 2D noise function
float vnoise(vec2 v)
{
  vec4  c, h;
  vec2  b, ds;
  float r;

  c  = floor(v.xxyy) + vec4(0,1,0,1);  // cell coords: (x0,x1,y0,y1)
 ds = ease(fract(v));                 // offset into cell -> weighting function
 c  = mod289(c);

  // x=hash(x0,y0) : y=hash(x1,y0) : z=hash(x0,y1) : w=hash(x1,y1)
 h  = permute(permute(c.xyxy) + c.zzww);
  h  = rng(h);
  b  = mix(h.xz, h.yw, ds.x);          // lerp top and bottom edges
 r  = mix(b.x, b.y, ds.y);            // lerp in 'y'

  return r+r-1;
}

// sample 3D noise function
float vnoise(vec3 v)
{
  vec4 c  = floor(v.xxyy) + vec4(0,1,0,1);  // cell coords: (x0,x1,y0,y1)
 vec2 z  = floor(v.zz)   + vec2(0,1);      // cell coords: (z0,z1)
 vec3 ds = ease(fract(v));                 // offset into cell -> weighting function
 
  c  = mod289(c);

  // x=hash(x0,y0) : y=hash(x1,y0) : z=hash(x0,y1) : w=hash(x1,y1)
 vec4 h  = permute(permute(c.xyxy) + c.zzww);
  vec4 ff = rng(permute(h + z.xxxx));
  vec4 bf = rng(permute(h + z.yyyy));
  vec2  t = mix(ff.xz, ff.yw, ds.x);  // lerp top and bottom edges (front face)
 vec2  s = mix(bf.xz, bf.yw, ds.x);  // lerp top and bottom edges (back face)
 float a = mix(t.x, t.y, ds.y);
  float b = mix(s.x, s.y, ds.y);
  float r = mix(a, b, ds.z);

  return r+r-1;
}

// EXAMPLE

// Turbulence formulated to insure that cell structures
// are aligned, assuming input coordinates are on 0,1 or
// -1,1, and therefore making defects compound (most
// obvious).
float turb(vec2 v, float s)
{
  float n, r;
  n  = vnoise(s*v.xy); r  = abs((1/ 2.f)*(n)); s += s;
  n  = vnoise(s*v.xy); r += abs((1/ 4.f)*(n)); s += s;
  n  = vnoise(s*v.xy); r += abs((1/ 8.f)*(n)); s += s;
  n  = vnoise(s*v.xy); r += abs((1/16.f)*(n));

  return r;
}

in  vec4 coord;
out vec4 out_Color;

void main(void)
{
  vec4  c;
  float f;

//f = vnoise(10*coord.xy); f = (f+1)*0.5;
 f = turb(coord.xy, 5.f);
  c = vec4(f,f,f,1);

  out_Color.rgb = c.rgb;
}
Offline theagentd
« Reply #1 - Posted 2012-12-07 21:44:30 »

That GLSL code isn't valid. At least my drivers won't allow the function name "uniform".

Quote
Shader compile log:
0(9) : error C0000: syntax error, unexpected '}', expecting ',' or ')' at token "}"
0(21) : error C0000: syntax error, unexpected '=', expecting "::" at token "="
0(39) : error C1038: declaration of "ds" conflicts with previous declaration at 0(18)
0(41) : error C0000: syntax error, unexpected '=', expecting "::" at token "="
0(45) : error C1101: ambiguous overloaded function reference "permute(vec4)"
    0(7) : vec2 permute(vec2)
    0(6) : vec3 permute(vec3)
0(46) : error C1101: ambiguous overloaded function reference "permute(vec4)"
    0(7) : vec2 permute(vec2)
    0(6) : vec3 permute(vec3)
0(50) : error C1038: declaration of "b" conflicts with previous declaration at 0(18)
0(50) : error C7011: implicit cast from "float" to "vec2"
0(51) : error C1031: swizzle mask element not present in operand "z"
0(51) : warning C1068: array index out of bounds
0(51) : error C7011: implicit cast from "float" to "vec2"
0(51) : error C1038: declaration of "r" conflicts with previous declaration at 0(19)
0(53) : error C0000: syntax error, unexpected reserved word "return" at token "return"

You're passing lots of vec4s into your functions... BTW, this was after renaming uniform() to something else so that's not the problem.

Myomyomyo.
Offline Best Username Ever

Junior Member





« Reply #2 - Posted 2012-12-07 22:00:16 »

Over 200 lines of codes in a forum post? Not the pastebin? Stare
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Riven
« League of Dukes »

JGO Overlord


Medals: 783
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #3 - Posted 2012-12-07 22:06:03 »

Over 200 lines of codes in a forum post? Not the pastebin? Stare
This is the Shared Code board. What else did you expect?

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline krasse
« Reply #4 - Posted 2012-12-07 22:50:21 »

Thanks for sharing!

Offline Roquen
« Reply #5 - Posted 2012-12-07 22:52:55 »

Gosh, I guess my cut-and-paste from large file and doing a little clean-up pass in forum post exercise failed.  Indeed uniform is a keyword..opps!  and functionName(paramList} isn't proper syntax. All of that is corrected..now with a trivial example which shows defects at their worst (more or less).
Offline theagentd
« Reply #6 - Posted 2012-12-08 12:50:49 »

Looks better. I'll try it when I get back home. =D

Myomyomyo.
Offline Roquen
« Reply #7 - Posted 2012-12-08 13:12:40 »

Just for fun I quickly hacked a out version using the rng you have on the tricks page:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
float vnoise(vec2 v)
{
  vec2  c   = floor(v);
  vec2  ds  = ease(fract(v));

  float h00 = rand(c);
  float h10 = rand(c + vec2(1,0));
  float h01 = rand(c + vec2(0,1));
  float h11 = rand(c + vec2(1,1));

  float b   = mix(h00,h10, ds.x);
  float t   = mix(h01,h11, ds.x);
  float r   = mix(b,t,     ds.y);

  return r+r-1;
}
Offline Roquen
« Reply #8 - Posted 2012-12-13 15:11:33 »

Strangely the half Rey generator (from theagentd's trick post) version is much faster on my hardware...humm.
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

TehJavaDev (17 views)
2014-08-28 18:26:30

CopyableCougar4 (26 views)
2014-08-22 19:31:30

atombrot (39 views)
2014-08-19 09:29:53

Tekkerue (36 views)
2014-08-16 06:45:27

Tekkerue (33 views)
2014-08-16 06:22:17

Tekkerue (22 views)
2014-08-16 06:20:21

Tekkerue (33 views)
2014-08-16 06:12:11

Rayexar (67 views)
2014-08-11 02:49:23

BurntPizza (45 views)
2014-08-09 21:09:32

BurntPizza (36 views)
2014-08-08 02:01:56
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!