Skip to content

Commit 6c6ac6c

Browse files
authored
Merge pull request #7978 from LalitNarayanYadav/patch-11
Add 3D noise(vec3) support to p5.strands
2 parents 39ea296 + b1fa600 commit 6c6ac6c

File tree

3 files changed

+114
-44
lines changed

3 files changed

+114
-44
lines changed

src/strands/strands_api.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { StrandsConditional } from './strands_conditionals'
1515
import * as CFG from './ir_cfg'
1616
import * as FES from './strands_FES'
1717
import { getNodeDataFromID } from './ir_dag'
18-
import noiseGLSL from '../webgl/shaders/functions/noiseGLSL.glsl';
18+
import noiseGLSL from '../webgl/shaders/functions/noise3DGLSL.glsl';
1919

2020
//////////////////////////////////////////////
2121
// User nodes
@@ -125,15 +125,17 @@ export function initGlobalStrandsAPI(p5, fn, strandsContext) {
125125
strandsContext.fragmentDeclarations.add(noiseGLSL);
126126
// Handle noise(x, y) as noise(vec2)
127127
let nodeArgs;
128-
if (args.length === 2) {
129-
nodeArgs = [fn.vec2(args[0], args[1])];
128+
if (args.length === 3) {
129+
nodeArgs = [fn.vec3(args[0], args[1], args[2])];
130+
} else if (args.length === 2) {
131+
nodeArgs = [fn.vec3(args[0], args[1], 0)];
130132
} else {
131133
nodeArgs = args;
132134
}
133135

134136
const { id, dimension } = build.functionCallNode(strandsContext, 'noise', nodeArgs, {
135137
overloads: [{
136-
params: [DataType.float2],
138+
params: [DataType.float3],
137139
returnType: DataType.float1,
138140
}]
139141
});
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Based on https://github.com/stegu/webgl-noise/blob/22434e04d7753f7e949e8d724ab3da2864c17a0f/src/noise3D.glsl
2+
// MIT licensed, adapted for p5.strands
3+
4+
vec3 mod289(vec3 x) {
5+
return x - floor(x * (1.0 / 289.0)) * 289.0;
6+
}
7+
8+
vec4 mod289(vec4 x) {
9+
return x - floor(x * (1.0 / 289.0)) * 289.0;
10+
}
11+
12+
vec4 permute(vec4 x) {
13+
return mod289(((x*34.0)+10.0)*x);
14+
}
15+
16+
vec4 taylorInvSqrt(vec4 r)
17+
{
18+
return 1.79284291400159 - 0.85373472095314 * r;
19+
}
20+
21+
float baseNoise(vec3 v)
22+
{
23+
const vec2 C = vec2(1.0/6.0, 1.0/3.0) ;
24+
const vec4 D = vec4(0.0, 0.5, 1.0, 2.0);
25+
26+
// First corner
27+
vec3 i = floor(v + dot(v, C.yyy) );
28+
vec3 x0 = v - i + dot(i, C.xxx) ;
29+
30+
// Other corners
31+
vec3 g = step(x0.yzx, x0.xyz);
32+
vec3 l = 1.0 - g;
33+
vec3 i1 = min( g.xyz, l.zxy );
34+
vec3 i2 = max( g.xyz, l.zxy );
35+
36+
// x0 = x0 - 0.0 + 0.0 * C.xxx;
37+
// x1 = x0 - i1 + 1.0 * C.xxx;
38+
// x2 = x0 - i2 + 2.0 * C.xxx;
39+
// x3 = x0 - 1.0 + 3.0 * C.xxx;
40+
vec3 x1 = x0 - i1 + C.xxx;
41+
vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
42+
vec3 x3 = x0 - D.yyy; // -1.0+3.0*C.x = -0.5 = -D.y
43+
44+
// Permutations
45+
i = mod289(i);
46+
vec4 p = permute( permute( permute(
47+
i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
48+
+ i.y + vec4(0.0, i1.y, i2.y, 1.0 ))
49+
+ i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
50+
51+
// Gradients: 7x7 points over a square, mapped onto an octahedron.
52+
// The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
53+
float n_ = 0.142857142857; // 1.0/7.0
54+
vec3 ns = n_ * D.wyz - D.xzx;
55+
56+
vec4 j = p - 49.0 * floor(p * ns.z * ns.z); // mod(p,7*7)
57+
58+
vec4 x_ = floor(j * ns.z);
59+
vec4 y_ = floor(j - 7.0 * x_ ); // mod(j,N)
60+
61+
vec4 x = x_ *ns.x + ns.yyyy;
62+
vec4 y = y_ *ns.x + ns.yyyy;
63+
vec4 h = 1.0 - abs(x) - abs(y);
64+
65+
vec4 b0 = vec4( x.xy, y.xy );
66+
vec4 b1 = vec4( x.zw, y.zw );
67+
68+
//vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
69+
//vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
70+
vec4 s0 = floor(b0)*2.0 + 1.0;
71+
vec4 s1 = floor(b1)*2.0 + 1.0;
72+
vec4 sh = -step(h, vec4(0.0));
73+
74+
vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
75+
vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
76+
77+
vec3 p0 = vec3(a0.xy,h.x);
78+
vec3 p1 = vec3(a0.zw,h.y);
79+
vec3 p2 = vec3(a1.xy,h.z);
80+
vec3 p3 = vec3(a1.zw,h.w);
81+
82+
//Normalise gradients
83+
vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
84+
p0 *= norm.x;
85+
p1 *= norm.y;
86+
p2 *= norm.z;
87+
p3 *= norm.w;
88+
89+
// Mix final noise value
90+
vec4 m = max(0.5 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
91+
m = m * m;
92+
return 105.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1),
93+
dot(p2,x2), dot(p3,x3) ) );
94+
}
95+
96+
float noise(vec3 st) {
97+
float result = 0.0;
98+
float amplitude = 1.0;
99+
float frequency = 1.0;
100+
101+
for (int i = 0; i < 4; i++) {
102+
result += amplitude * baseNoise(st * frequency);
103+
frequency *= 2.0;
104+
amplitude *= 0.5;
105+
}
106+
107+
return result;
108+
}

src/webgl/shaders/functions/noiseGLSL.glsl

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)