-
Notifications
You must be signed in to change notification settings - Fork 410
Add flake node implementations #2676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
jstone-lucasfilm
merged 16 commits into
AcademySoftwareFoundation:main
from
msuzuki-nvidia:add-flake-nodes
Mar 2, 2026
+583
−1
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
1664738
add flake nodes
msuzuki-nvidia d98d231
remove unnecessary #include
msuzuki-nvidia a437224
add comment
msuzuki-nvidia 543414d
redefine PI for metal
msuzuki-nvidia ad7c85b
Merge branch 'main' into add-flake-nodes
msuzuki-nvidia 4b5c979
fix conflicts and test failure
msuzuki-nvidia 53d339f
Merge branch 'main' into add-flake-nodes
jstone-lucasfilm ee1d742
update `presense` description
msuzuki-nvidia 985c20d
Merge branch 'main' into add-flake-nodes
jstone-lucasfilm 7fa7842
Add final newline
jstone-lucasfilm bf7af1a
Add final newline
jstone-lucasfilm 299584d
Merge branch 'main' into add-flake-nodes
jstone-lucasfilm 37cc9ec
Align spacing in tables
jstone-lucasfilm 125d66a
Add final newline
jstone-lucasfilm a027bc2
Add final newline
jstone-lucasfilm b0496af
Remove extra newlines
jstone-lucasfilm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,158 @@ | ||
| uint mx_flake_hash(uint seed, uint i) | ||
| { | ||
| return (i ^ seed) * 1075385539u; | ||
| } | ||
|
|
||
| uint mx_flake_init_seed(ivec3 i) | ||
| { | ||
| return mx_flake_hash(mx_flake_hash(mx_flake_hash(0, i.x), i.y), i.z); | ||
| } | ||
|
|
||
| uint mx_flake_xorshift32(uint seed) | ||
| { | ||
| seed ^= seed << 13; | ||
| seed ^= seed >> 17; | ||
| seed ^= seed << 5; | ||
| return seed; | ||
| } | ||
|
|
||
| float mx_uint_to_01(uint x) | ||
| { | ||
| return float(x) / float(0xffffffffu); // scale to [0, 1) | ||
| } | ||
|
|
||
| // "Fast Random Rotation Matrices" by James Arvo, Graphics Gems3 P.117 | ||
| vec3 mx_rotate_flake(vec3 p, vec3 i) | ||
| { | ||
| float theta = M_PI * 2.0 * i.x; | ||
| float phi = M_PI * 2.0 * i.y; | ||
| float z = i.z * 2.0; | ||
|
|
||
| float r = sqrt(z); | ||
| float vx = sin(phi) * r; | ||
| float vy = cos(phi) * r; | ||
| float vz = sqrt(2.0 - z); | ||
|
|
||
| float s_theta = sin(theta); | ||
| float c_theta = cos(theta); | ||
| float sx = vx * s_theta - vy * s_theta; | ||
| float sy = vx * c_theta + vy * c_theta; | ||
|
|
||
| mat3 m = mat3( | ||
| vx * sx - s_theta, vx * sy - s_theta, vx * vz, | ||
| vy * sx + c_theta, vy * sy - c_theta, vy * vz, | ||
| vz * sx , vz * sy , 1.0 - z | ||
| ); | ||
|
|
||
| return m * p; | ||
| } | ||
|
|
||
| // compute a flake probability for a given flake coverage density x | ||
| float mx_flake_density_to_probability(float x) | ||
| { | ||
| // constants for numerical fitted curve to observed flake noise density behavior | ||
| const vec4 abcd = vec4(-26.19771808f, 26.39663835f, 85.53857017f, -102.35069432f); | ||
| const vec2 ef = vec2(-101.42634862f, 118.45082288f); | ||
| float xx = x * x; | ||
|
|
||
| return (abcd.x * xx + abcd.y * x) / (abcd.z * xx * x + abcd.w * xx + ef.x * x + ef.y); | ||
| } | ||
|
|
||
| void mx_flake( | ||
| float size, | ||
| float roughness, | ||
| float coverage, | ||
| vec3 position, | ||
| vec3 normal, | ||
| vec3 tangent, | ||
| vec3 bitangent, | ||
| out int id, | ||
| out float rand, | ||
| out float presence, | ||
| out vec3 flakenormal | ||
| ) | ||
| { | ||
| float probability = mx_flake_density_to_probability(clamp(coverage, 0.0, 1.0)); | ||
| const float flake_diameter = 1.5 / sqrt(3.0); | ||
|
|
||
| vec3 P = position / vec3(size); | ||
| vec3 base_P = floor(P); | ||
| ivec3 base_P_int = ivec3(base_P); | ||
|
|
||
| // flake priority in [0..1], 0: no flake, flakes with higher priority shadow flakes "below" them | ||
| float flake_priority = 0.0; | ||
| uint flake_seed = 0; | ||
|
|
||
| // Examine the 3×3×3 lattice neighborhood around the sample cell. Flakes are seeded at cell | ||
| // centers but can overlap adjacent cells by up to flake_diameter, so neighbors may contribute | ||
| // at the sample position. For each neighbor we deterministically generate a seed, reject it | ||
| // by the density probability, compute a per-flake priority, and test the rotated, centered | ||
| // flake position for overlap. The highest-priority overlapping flake is selected. | ||
| for (int i = -1; i < 2; ++i) | ||
| { | ||
| for (int j = -1; j < 2; ++j) | ||
| { | ||
| for (int k = -1; k < 2; ++k) | ||
| { | ||
| uint seed = mx_flake_init_seed(base_P_int + ivec3(i, j, k)); | ||
|
|
||
| seed = mx_flake_xorshift32(seed); | ||
| if (mx_uint_to_01(seed) > probability) | ||
| continue; | ||
|
|
||
| seed = mx_flake_xorshift32(seed); | ||
| float priority = mx_uint_to_01(seed); | ||
| if (priority < flake_priority) | ||
| continue; | ||
|
|
||
| vec3 flake_P = base_P + vec3(i, j, k) + vec3(0.5); | ||
| vec3 PP = P - flake_P; | ||
| if (dot(PP, PP) >= flake_diameter * flake_diameter * 4.0) | ||
| continue; | ||
|
|
||
| vec3 rot; | ||
| seed = mx_flake_xorshift32(seed); rot.x = mx_uint_to_01(seed); | ||
| seed = mx_flake_xorshift32(seed); rot.y = mx_uint_to_01(seed); | ||
| seed = mx_flake_xorshift32(seed); rot.z = mx_uint_to_01(seed); | ||
| PP = mx_rotate_flake(PP, rot); | ||
|
|
||
| if (abs(PP.x) <= flake_diameter && | ||
| abs(PP.y) <= flake_diameter && | ||
| abs(PP.z) <= flake_diameter) | ||
| { | ||
| flake_priority = priority; | ||
| flake_seed = seed; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (flake_priority <= 0.0) | ||
| { | ||
| // no flake | ||
| id = 0; | ||
| rand = 0.0; | ||
| presence = 0.0; | ||
| flakenormal = normal; | ||
| return; | ||
| } | ||
|
|
||
| // create a flake normal by importance sampling a microfacet distribution with given roughness | ||
| uint seed = flake_seed; | ||
| float xi0 = mx_uint_to_01(seed); seed = mx_flake_xorshift32(seed); | ||
| float xi1 = mx_uint_to_01(seed); seed = mx_flake_xorshift32(seed); | ||
|
|
||
| id = int(seed); // not ideal but MaterialX does not support unsigned integer type | ||
| rand = mx_uint_to_01(seed); | ||
| presence = flake_priority; | ||
|
|
||
| float phi = M_PI * 2.0 * xi0; | ||
| float tan_theta = roughness * roughness * sqrt(xi1) / sqrt(1.0 - xi1); // GGX | ||
| float sin_theta = tan_theta / sqrt(1.0 + tan_theta * tan_theta); | ||
| float cos_theta = sqrt(1.0 - sin_theta * sin_theta); | ||
|
|
||
| flakenormal = tangent * cos(phi) * sin_theta + | ||
| bitangent * sin(phi) * sin_theta + | ||
| normal * cos_theta; | ||
| flakenormal = normalize(flakenormal); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| #include "lib/mx_flake.glsl" | ||
|
|
||
| void mx_flake2d( | ||
| float size, | ||
| float roughness, | ||
| float coverage, | ||
| vec2 texcoord, | ||
| vec3 normal, | ||
| vec3 tangent, | ||
| vec3 bitangent, | ||
| out int id, | ||
| out float rand, | ||
| out float presence, | ||
| out vec3 flakenormal | ||
| ) | ||
| { | ||
| // reuse the 3d flake implementation. this could be optimized by using a 2d flake implementation | ||
| vec3 position = vec3(texcoord.x, texcoord.y, 0.0); | ||
msuzuki-nvidia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| mx_flake(size, roughness, coverage, position, normal, tangent, bitangent, id, rand, presence, flakenormal); | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| #include "lib/mx_flake.glsl" | ||
|
|
||
| void mx_flake3d( | ||
| float size, | ||
| float roughness, | ||
| float coverage, | ||
| vec3 position, | ||
| vec3 normal, | ||
| vec3 tangent, | ||
| vec3 bitangent, | ||
| out int id, | ||
| out float rand, | ||
| out float presence, | ||
| out vec3 flakenormal | ||
| ) | ||
| { | ||
| mx_flake(size, roughness, coverage, position, normal, tangent, bitangent, id, rand, presence, flakenormal); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| #define M_FLOAT_EPS 1e-8 | ||
| #define M_PI M_PI_F | ||
|
|
||
| #define mx_sin metal::sin | ||
| #define mx_cos metal::cos | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
resources/Materials/TestSuite/pbrlib/surfaceshader/flake_surfaceshader.mtlx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| <?xml version="1.0"?> | ||
| <materialx version="1.39"> | ||
| <surfacematerial name="flake_surfaceshader" type="material"> | ||
| <input name="surfaceshader" type="surfaceshader" nodename="standard_surface_surfaceshader" /> | ||
| </surfacematerial> | ||
| <standard_surface name="standard_surface_surfaceshader" type="surfaceshader"> | ||
| <input name="normal" type="vector3" output="flakenormal" nodename="flake3d" /> | ||
| <input name="metalness" type="float" value="1" /> | ||
| <input name="coat" type="float" value="1" /> | ||
| <input name="specular_roughness" type="float" value="0.1" /> | ||
| <input name="coat_roughness" type="float" value="0" /> | ||
| <input name="specular" type="float" value="1" /> | ||
| <input name="base_color" type="color3" nodename="multiply_color3FA" /> | ||
| <input name="base" type="float" value="1" /> | ||
| </standard_surface> | ||
| <flake3d name="flake3d" type="multioutput"> | ||
| <input name="coverage" type="float" value="1" /> | ||
| <input name="roughness" type="float" value="0.2" /> | ||
| <input name="size" type="float" value="0.002" /> | ||
| <output name="id" type="integer" /> | ||
| <output name="presence" type="float" /> | ||
| <output name="flakenormal" type="vector3" /> | ||
| </flake3d> | ||
| <randomcolor name="randomcolor_float" type="color3"> | ||
| <input name="seed" type="integer" output="id" nodename="flake3d" /> | ||
| <output name="out" type="color3" /> | ||
| <input name="saturationhigh" type="float" value="0" /> | ||
| <input name="saturationlow" type="float" value="0.5" /> | ||
| </randomcolor> | ||
| <multiply name="multiply_color3" type="color3"> | ||
| <input name="in2" type="color3" nodename="randomcolor_float" /> | ||
| <output name="out" type="color3" /> | ||
| <input name="in1" type="color3" value="0.399894, 0.0183279, 0.530191" /> | ||
| </multiply> | ||
| <multiply name="multiply_color3FA" type="color3"> | ||
| <input name="in2" type="float" nodename="safepower_float" /> | ||
| <input name="in1" type="color3" nodename="multiply_color3" /> | ||
| <output name="out" type="color3" /> | ||
| </multiply> | ||
| <safepower name="safepower_float" type="float"> | ||
| <input name="in1" type="float" output="presence" nodename="flake3d" /> | ||
| <input name="in2" type="float" value="8" /> | ||
| </safepower> | ||
| </materialx> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.