1- uint mx_flake_hash(uint seed, uint i)
2- {
3- return (i ^ seed) * 1075385539u;
4- }
5-
6- uint mx_flake_init_seed(ivec3 i)
7- {
8- return mx_flake_hash(mx_flake_hash(mx_flake_hash(0 , i.x), i.y), i.z);
9- }
10-
11- uint mx_flake_xorshift32(uint seed)
12- {
13- seed ^= seed << 13 ;
14- seed ^= seed >> 17 ;
15- seed ^= seed << 5 ;
16- return seed;
17- }
18-
19- float mx_uint_to_01(uint x)
20- {
21- return float (x) / float (0xffffffffu); // scale to [0, 1)
22- }
1+ #include "mx_noise.glsl"
232
243// "Fast Random Rotation Matrices" by James Arvo, Graphics Gems3 P.117
254vec3 mx_rotate_flake(vec3 p, vec3 i)
@@ -35,12 +14,12 @@ vec3 mx_rotate_flake(vec3 p, vec3 i)
3514
3615 float s_theta = sin (theta);
3716 float c_theta = cos (theta);
38- float sx = vx * s_theta - vy * s_theta;
39- float sy = vx * c_theta + vy * c_theta;
17+ float sx = vx * c_theta - vy * s_theta;
18+ float sy = vx * s_theta + vy * c_theta;
4019
4120 mat3 m = mat3 (
42- vx * sx - s_theta , vx * sy - s_theta, vx * vz,
43- vy * sx + c_theta , vy * sy - c_theta, vy * vz,
21+ vx * sx - c_theta , vx * sy - s_theta, vx * vz,
22+ vy * sx + s_theta , vy * sy - c_theta, vy * vz,
4423 vz * sx , vz * sy , 1.0 - z
4524 );
4625
@@ -77,51 +56,41 @@ void mx_flake(
7756
7857 vec3 P = position / vec3 (size);
7958 vec3 base_P = floor (P);
80- ivec3 base_P_int = ivec3 (base_P);
8159
8260 // flake priority in [0..1], 0: no flake, flakes with higher priority shadow flakes "below" them
8361 float flake_priority = 0.0 ;
84- uint flake_seed = 0 ;
62+ vec3 flake_cell = vec3 ( 0.0 ) ;
8563
86- // Examine the 3×3×3 lattice neighborhood around the sample cell. Flakes are seeded at cell
87- // centers but can overlap adjacent cells by up to flake_diameter, so neighbors may contribute
88- // at the sample position. For each neighbor we deterministically generate a seed, reject it
89- // by the density probability, compute a per-flake priority, and test the rotated, centered
90- // flake position for overlap. The highest-priority overlapping flake is selected.
64+ // Examine the 3x3x3 neighborhood of cells around the sample position, selecting the
65+ // highest-priority overlapping flake.
9166 for (int i = - 1 ; i < 2 ; ++ i)
9267 {
9368 for (int j = - 1 ; j < 2 ; ++ j)
9469 {
9570 for (int k = - 1 ; k < 2 ; ++ k)
9671 {
97- uint seed = mx_flake_init_seed(base_P_int + ivec3 (i, j, k) );
72+ vec3 cell_pos = base_P + vec3 (i, j, k);
9873
99- seed = mx_flake_xorshift32(seed );
100- if (mx_uint_to_01(seed ) > probability )
74+ vec3 PP = P - cell_pos - vec3 ( 0.5 );
75+ if (dot (PP, PP ) >= flake_diameter * flake_diameter * 3.0 )
10176 continue ;
10277
103- seed = mx_flake_xorshift32(seed);
104- float priority = mx_uint_to_01(seed);
105- if (priority < flake_priority)
78+ if (mx_cell_noise_float(cell_pos) > probability)
10679 continue ;
10780
108- vec3 flake_P = base_P + vec3 (i, j, k) + vec3 (0.5 );
109- vec3 PP = P - flake_P;
110- if (dot (PP, PP) >= flake_diameter * flake_diameter * 4.0 )
81+ float priority = mx_cell_noise_float(vec4 (cell_pos, 3.0 ));
82+ if (priority < flake_priority)
11183 continue ;
11284
113- vec3 rot;
114- seed = mx_flake_xorshift32(seed); rot.x = mx_uint_to_01(seed);
115- seed = mx_flake_xorshift32(seed); rot.y = mx_uint_to_01(seed);
116- seed = mx_flake_xorshift32(seed); rot.z = mx_uint_to_01(seed);
85+ vec3 rot = mx_cell_noise_vec3(cell_pos);
11786 PP = mx_rotate_flake(PP, rot);
11887
11988 if (abs (PP.x) <= flake_diameter &&
12089 abs (PP.y) <= flake_diameter &&
12190 abs (PP.z) <= flake_diameter)
12291 {
12392 flake_priority = priority;
124- flake_seed = seed ;
93+ flake_cell = cell_pos ;
12594 }
12695 }
12796 }
@@ -138,12 +107,12 @@ void mx_flake(
138107 }
139108
140109 // create a flake normal by importance sampling a microfacet distribution with given roughness
141- uint seed = flake_seed ;
142- float xi0 = mx_uint_to_01(seed); seed = mx_flake_xorshift32(seed) ;
143- float xi1 = mx_uint_to_01(seed); seed = mx_flake_xorshift32(seed) ;
110+ vec3 flake_noise = mx_cell_noise_vec3( vec4 (flake_cell, 2.0 )) ;
111+ float xi0 = flake_noise.x ;
112+ float xi1 = flake_noise.y ;
144113
145- id = int (seed); // not ideal but MaterialX does not support unsigned integer type
146- rand = mx_uint_to_01(seed );
114+ rand = flake_noise.z;
115+ id = int (rand * 2147483647.0 );
147116 presence = flake_priority;
148117
149118 float phi = M_PI * 2.0 * xi0;
0 commit comments