Skip to content

Commit 8e13259

Browse files
committed
hash util in noise
1 parent 2834295 commit 8e13259

3 files changed

Lines changed: 93 additions & 23 deletions

File tree

packages/typegpu-noise/src/generator.ts

Lines changed: 56 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import tgpu, { d, type TgpuFnShell, type TgpuSlot } from 'typegpu';
2-
import { bitcastU32toF32, cos, dot, fract } from 'typegpu/std';
2+
import { cos, dot, fract } from 'typegpu/std';
3+
import { hash, u32To01Float } from './utils.ts';
34

45
export interface StatefulGenerator {
56
seed?: (seed: number) => void;
@@ -49,36 +50,70 @@ export const BPETER: StatefulGenerator = (() => {
4950
})();
5051

5152
/**
52-
* Naive Linear Congruential Generator (LCG)
53+
* Incorporated from https://github.com/chaos-matters/chaos-master
54+
* by deluksic and Komediruzecki
5355
*/
54-
export const LCG: StatefulGenerator = (() => {
55-
const seed = tgpu.privateVar(d.u32);
56+
export const XOROSHIRO64STARSTAR: StatefulGenerator = (() => {
57+
const seed = tgpu.privateVar(d.vec2u);
58+
59+
const rotl = tgpu.fn(
60+
[d.u32, d.u32],
61+
d.u32,
62+
)((x, k) => {
63+
return (x << k) | (x >> (32 - k));
64+
});
65+
66+
const next = tgpu.fn([])(() => {
67+
const s0 = seed.$[0];
68+
let s1 = seed.$[1];
5669

57-
const u32To01Float = tgpu.fn(
58-
[d.u32],
59-
d.f32,
60-
)((value) => {
61-
const mantissa = value >> 9;
62-
const bits = 0x3f800000 | mantissa;
63-
const f = bitcastU32toF32(bits);
64-
return f - 1;
70+
s1 ^= s0;
71+
seed.$[0] = rotl(s0, 26) ^ s1 ^ (s1 << 9);
72+
seed.$[1] = rotl(s1, 13);
6573
});
6674

6775
return {
68-
seed: tgpu.fn([d.f32])((value) => {
69-
seed.$ = d.u32(value * 32768);
70-
}),
71-
7276
seed2: tgpu.fn([d.vec2f])((value) => {
73-
seed.$ = d.u32(value.x * 32768 + value.y * 1024);
77+
seed.$ = d.vec2u(value);
7478
}),
7579

76-
seed3: tgpu.fn([d.vec3f])((value) => {
77-
seed.$ = d.u32(value.x * 32768 + value.y * 1024 + value.z * 32);
80+
sample: randomGeneratorShell(() => {
81+
'use gpu';
82+
next();
83+
const r = seed.$.x;
84+
return u32To01Float(r);
85+
}).$name('sample'),
86+
};
87+
})();
88+
89+
/**
90+
* Naive Linear Congruential Generator (LCG) with 32 bits state
91+
*/
92+
export const LCG32: StatefulGenerator = (() => {
93+
const seed = tgpu.privateVar(d.u32);
94+
95+
return {
96+
seed: tgpu.fn([d.f32])((value) => {
97+
seed.$ = hash(d.u32(value));
7898
}),
7999

80-
seed4: tgpu.fn([d.vec4f])((value) => {
81-
seed.$ = d.u32(value.x * 32768 + value.y * 1024 + value.z * 32 + value.w);
100+
sample: randomGeneratorShell(() => {
101+
'use gpu';
102+
seed.$ = seed.$ * 1664525 + 1013904223; // % 2 ^ 32
103+
return u32To01Float(seed.$);
104+
}).$name('sample'),
105+
};
106+
})();
107+
108+
/**
109+
* Naive Linear Congruential Generator (LCG) with 64 bits state
110+
*/
111+
export const LCG64: StatefulGenerator = (() => {
112+
const seed = tgpu.privateVar(d.u32);
113+
114+
return {
115+
seed: tgpu.fn([d.f32])((value) => {
116+
seed.$ = d.u32(value) * 1048577;
82117
}),
83118

84119
sample: randomGeneratorShell(() => {

packages/typegpu-noise/src/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,9 @@ export {
145145
BPETER,
146146
// The default (Can change between releases to improve uniformity).
147147
DefaultGenerator,
148-
LCG,
148+
LCG32,
149+
LCG64,
150+
XOROSHIRO64STARSTAR,
149151
// ---
150152
randomGeneratorShell,
151153
randomGeneratorSlot,

packages/typegpu-noise/src/utils.ts

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { d } from 'typegpu';
1+
import tgpu, { d, std } from 'typegpu';
22

33
export type Prettify<T> = {
44
[K in keyof T]: T[K];
@@ -28,3 +28,36 @@ export function quinticDerivative(t: d.vecBase): d.vecBase {
2828
'use gpu';
2929
return 30 * t * t * (t * (t - 2) + 1);
3030
}
31+
32+
/*
33+
* Converts u32 to f32 value in the range [0.0, 1.0).
34+
*/
35+
export const u32To01Float = tgpu.fn(
36+
[d.u32],
37+
d.f32,
38+
)((value) => {
39+
const mantissa = value >> 9;
40+
const bits = 0x3f800000 | mantissa;
41+
const f = std.bitcastU32toF32(bits);
42+
return f - 1;
43+
});
44+
45+
/**
46+
* Simple hashing function to scramble the seed.
47+
*
48+
* Incorporated from https://github.com/chaos-matters/chaos-master
49+
* by deluksic and Komediruzecki
50+
*/
51+
export const hash = tgpu.fn(
52+
[d.u32],
53+
d.u32,
54+
)((v) => {
55+
let x = v ^ (v >> 17);
56+
x *= d.u32(0xed5ad4bb);
57+
x ^= x >> 11;
58+
x *= d.u32(0xac4c1b51);
59+
x ^= x >> 15;
60+
x *= d.u32(0x31848bab);
61+
x ^= x >> 14;
62+
return x;
63+
});

0 commit comments

Comments
 (0)