From c44dc508ab2b12f4bf00c999c0c7694fea986cca Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Tue, 29 Oct 2024 17:23:12 -0700 Subject: [PATCH 1/9] add GLSL hextiling implementation --- libraries/stdlib/genglsl/lib/mx_geometry.glsl | 29 ++++ libraries/stdlib/genglsl/lib/mx_hextile.glsl | 144 ++++++++++++++++++ .../stdlib/genglsl/mx_hextiledimage.glsl | 102 +++++++++++++ .../stdlib/genglsl/mx_hextilednormalmap.glsl | 68 +++++++++ .../stdlib/genglsl/stdlib_genglsl_impl.mtlx | 13 ++ libraries/stdlib/stdlib_defs.mtlx | 63 ++++++++ .../TestSuite/stdlib/texture/hextiled.mtlx | 22 +++ .../MaterialXTest/MaterialXGenMdl/GenMdl.cpp | 5 +- source/MaterialXTest/MaterialXGenMdl/GenMdl.h | 2 + .../MaterialXTest/MaterialXGenOsl/GenOsl.cpp | 5 +- source/MaterialXTest/MaterialXGenOsl/GenOsl.h | 1 + 11 files changed, 452 insertions(+), 2 deletions(-) create mode 100644 libraries/stdlib/genglsl/lib/mx_geometry.glsl create mode 100644 libraries/stdlib/genglsl/lib/mx_hextile.glsl create mode 100644 libraries/stdlib/genglsl/mx_hextiledimage.glsl create mode 100644 libraries/stdlib/genglsl/mx_hextilednormalmap.glsl create mode 100644 resources/Materials/TestSuite/stdlib/texture/hextiled.mtlx diff --git a/libraries/stdlib/genglsl/lib/mx_geometry.glsl b/libraries/stdlib/genglsl/lib/mx_geometry.glsl new file mode 100644 index 0000000000..e30c681f59 --- /dev/null +++ b/libraries/stdlib/genglsl/lib/mx_geometry.glsl @@ -0,0 +1,29 @@ +#include "mx_math.glsl" + +// blend 3 normals by blending the gradients +// Morten S. Mikkelsen, Surface Gradient–Based Bump Mapping Framework, Journal of +// Computer Graphics Techniques (JCGT), vol. 9, no. 3, 60–90, 2020 +// http://jcgt.org/published/0009/03/04/ +vec3 mx_normals_to_gradient(vec3 N, vec3 Np) +{ + float d = dot(N, Np); + vec3 g = (d * N - Np) / max(M_FLOAT_EPS, abs(d)); + return g; +} + +vec3 mx_gradient_blend_3_normals(vec3 N, vec3 N1, float N1_weight, vec3 N2, float N2_weight, vec3 N3, float N3_weight) +{ + float w1 = clamp(N1_weight, 0.0, 1.0); + float w2 = clamp(N2_weight, 0.0, 1.0); + float w3 = clamp(N3_weight, 0.0, 1.0); + + vec3 g1 = mx_normals_to_gradient(N, N1); + vec3 g2 = mx_normals_to_gradient(N, N2); + vec3 g3 = mx_normals_to_gradient(N, N3); + + // blend + vec3 gg = w1 * g1 + w2 * g2 + w3 * g3; + + // gradient to normal + return normalize(N - gg); +} diff --git a/libraries/stdlib/genglsl/lib/mx_hextile.glsl b/libraries/stdlib/genglsl/lib/mx_hextile.glsl new file mode 100644 index 0000000000..389d56215c --- /dev/null +++ b/libraries/stdlib/genglsl/lib/mx_hextile.glsl @@ -0,0 +1,144 @@ +// https://www.shadertoy.com/view/4djSRW +vec2 mx_hextile_hash(vec2 p) +{ + vec3 p3 = fract(vec3(p.x, p.y, p.x) * vec3(0.1031, 0.1030, 0.0973)); + p3 += dot(p3, vec3(p3.y, p3.z, p3.x) + 33.33); + return fract((vec2(p3.x, p3.x) + vec2(p3.y, p3.z)) * vec2(p3.z, p3.y)); +} + +// Christophe Schlick. “Fast Alternatives to Perlin’s Bias and Gain Functions”. +// In Graphics Gems IV, Morgan Kaufmann, 1994, pages 401–403. +// https://dept-info.labri.fr/~schlick/DOC/gem2.html +float mx_schlick_gain(float x, float r) +{ + float rr = clamp(r, 0.001, 0.999); // to avoid glitch + float a = (1.0 / rr - 2.0) * (1.0 - 2.0 * x); + return (x < 0.5) ? x / (a + 1.0) : (a - x) / (a - 1.0); +} + +struct HextileData +{ + vec2 coord1; + vec2 coord2; + vec2 coord3; + vec3 weights; + mat3 tangent_rot_mat1; + mat3 tangent_rot_mat2; + mat3 tangent_rot_mat3; + vec2 ddx1; + vec2 ddx2; + vec2 ddx3; + vec2 ddy1; + vec2 ddy2; + vec2 ddy3; +}; + +// Morten S. Mikkelsen, Practical Real-Time Hex-Tiling, Journal of Computer Graphics +// Techniques (JCGT), vol. 11, no. 2, 77-94, 2022 +// http://jcgt.org/published/0011/03/05/ +HextileData mx_hextile_coord( + vec2 coord, + float rotation, + vec2 rotation_range, + float scale, + vec2 scale_range, + float offset, + vec2 offset_range) +{ + float sqrt3_2 = sqrt(3.0) * 2.0; + + // scale coord to maintain the original fit + vec2 st = coord * sqrt3_2; + + // skew input space into simplex triangle grid + // (1, 0, -tan(30), 2*tan(30)) + mat2 to_skewed = mat2(1.0, 0.0, -0.57735027, 1.15470054); + vec2 st_skewed = to_skewed * st; + + // barycentric weights + vec2 st_frac = fract(st_skewed); + vec3 temp = vec3(st_frac.x, st_frac.y, 0.0); + temp.z = 1.0 - temp.x - temp.y; + + float s = step(0.0, -temp.z); + float s2 = 2.0 * s - 1.0; + + float w1 = -temp.z * s2; + float w2 = s - temp.y * s2; + float w3 = s - temp.x * s2; + + // vertex IDs + ivec2 base_id = ivec2(floor(st_skewed)); + int si = int(s); + ivec2 id1 = base_id + ivec2(si, si); + ivec2 id2 = base_id + ivec2(si, 1 - si); + ivec2 id3 = base_id + ivec2(1 - si, si); + + // tile center + mat2 inv_skewed = mat2(1.0, 0.0, 0.5, 1.0 / 1.15470054); + vec2 ctr1 = inv_skewed * vec2(id1) / vec2(sqrt3_2); + vec2 ctr2 = inv_skewed * vec2(id2) / vec2(sqrt3_2); + vec2 ctr3 = inv_skewed * vec2(id3) / vec2(sqrt3_2); + + // reuse hash for performance + vec2 seed_offset = vec2(0.12345); // to avoid some zeros + vec2 rand1 = mx_hextile_hash(vec2(id1) + seed_offset); + vec2 rand2 = mx_hextile_hash(vec2(id2) + seed_offset); + vec2 rand3 = mx_hextile_hash(vec2(id3) + seed_offset); + + // randomized rotation matrix + vec2 rr = radians(rotation_range); + float rv1 = mix(rr.x, rr.y, rand1.x * rotation); + float rv2 = mix(rr.x, rr.y, rand2.x * rotation); + float rv3 = mix(rr.x, rr.y, rand3.x * rotation); + float sin_r1 = sin(rv1); + float sin_r2 = sin(rv2); + float sin_r3 = sin(rv3); + float cos_r1 = cos(rv1); + float cos_r2 = cos(rv2); + float cos_r3 = cos(rv3); + mat2 rm1 = mat2(cos_r1, -sin_r1, sin_r1, cos_r1); + mat2 rm2 = mat2(cos_r2, -sin_r2, sin_r2, cos_r2); + mat2 rm3 = mat2(cos_r3, -sin_r3, sin_r3, cos_r3); + + // rotation matrix for tangent vectors + mat3 trm1 = mat3(cos_r1, 0.0, sin_r1, 0.0, 1.0, 0.0, -sin_r1, 0.0, cos_r1); + mat3 trm2 = mat3(cos_r2, 0.0, sin_r2, 0.0, 1.0, 0.0, -sin_r2, 0.0, cos_r2); + mat3 trm3 = mat3(cos_r3, 0.0, sin_r3, 0.0, 1.0, 0.0, -sin_r3, 0.0, cos_r3); + + // randomized scale + vec2 sr = scale_range; + vec2 scale1 = vec2(mix(1.0, mix(sr.x, sr.y, rand1.y), scale)); + vec2 scale2 = vec2(mix(1.0, mix(sr.x, sr.y, rand2.y), scale)); + vec2 scale3 = vec2(mix(1.0, mix(sr.x, sr.y, rand3.y), scale)); + + // randomized offset + vec2 offset1 = mix(vec2(offset_range.x), vec2(offset_range.y), rand1 * offset); + vec2 offset2 = mix(vec2(offset_range.x), vec2(offset_range.y), rand2 * offset); + vec2 offset3 = mix(vec2(offset_range.x), vec2(offset_range.y), rand3 * offset); + + // get coord + vec2 st1 = ((coord - ctr1) * rm1 / scale1) + ctr1 + offset1; + vec2 st2 = ((coord - ctr2) * rm2 / scale2) + ctr2 + offset2; + vec2 st3 = ((coord - ctr3) * rm3 / scale3) + ctr3 + offset3; + + // derivatives + vec2 ddx = dFdx(coord); + vec2 ddy = dFdy(coord); + vec2 ddx1 = ddx * rm1 / scale1; + vec2 ddx2 = ddx * rm2 / scale2; + vec2 ddx3 = ddx * rm3 / scale3; + vec2 ddy1 = ddy * rm1 / scale1; + vec2 ddy2 = ddy * rm2 / scale2; + vec2 ddy3 = ddy * rm3 / scale3; + + HextileData tile_data = HextileData( + st1, st2, st3, + vec3(w1, w2, w3), + trm1, trm2, trm3, + ddx1, ddx2, ddx3, + ddy1, ddy2, ddy3 + ); + + return tile_data; +} diff --git a/libraries/stdlib/genglsl/mx_hextiledimage.glsl b/libraries/stdlib/genglsl/mx_hextiledimage.glsl new file mode 100644 index 0000000000..c04338a911 --- /dev/null +++ b/libraries/stdlib/genglsl/mx_hextiledimage.glsl @@ -0,0 +1,102 @@ +#include "lib/$fileTransformUv" +#include "lib/mx_hextile.glsl" + +// Morten S. Mikkelsen, Practical Real-Time Hex-Tiling, Journal of Computer Graphics +// Techniques (JCGT), vol. 11, no. 2, 77-94, 2022 +// http://jcgt.org/published/0011/03/05/ +void mx_hextiledimage_color3( + sampler2D tex_sampler, + vec3 default_value, + vec2 tex_coord, + vec2 tiling, + float rotation, + vec2 rotation_range, + float scale, + vec2 scale_range, + float offset, + vec2 offset_range, + float falloff, + float falloff_contrast, + vec3 lumacoeffs, + out vec3 result +) +{ + vec2 coord = mx_transform_uv(tex_coord, tiling, vec2(0.0)); + + HextileData tile_data = mx_hextile_coord(coord, rotation, rotation_range, scale, scale_range, offset, offset_range); + + vec3 c1 = textureGrad(tex_sampler, tile_data.coord1, tile_data.ddx1, tile_data.ddy1).rgb; + vec3 c2 = textureGrad(tex_sampler, tile_data.coord2, tile_data.ddx2, tile_data.ddy2).rgb; + vec3 c3 = textureGrad(tex_sampler, tile_data.coord3, tile_data.ddx3, tile_data.ddy3).rgb; + + // luminance as weights + vec3 cw = vec3(dot(c1, lumacoeffs), dot(c2, lumacoeffs), dot(c3, lumacoeffs)); + cw = mix(vec3(1.0), cw, vec3(falloff_contrast)); + + // blend weights + vec3 w = cw * pow(tile_data.weights, vec3(7.0)); + w /= (w.x + w.y + w.z); + + // apply s-curve gain + if (falloff != 0.5) + { + w.x = mx_schlick_gain(w.x, falloff); + w.y = mx_schlick_gain(w.y, falloff); + w.z = mx_schlick_gain(w.z, falloff); + w /= (w.x + w.y + w.z); + } + + // blend + result = vec3(w.x * c1 + w.y * c2 + w.z * c3); +} + +void mx_hextiledimage_color4( + sampler2D tex_sampler, + vec4 default_value, + vec2 tex_coord, + vec2 tiling, + float rotation, + vec2 rotation_range, + float scale, + vec2 scale_range, + float offset, + vec2 offset_range, + float falloff, + float falloff_contrast, + vec3 lumacoeffs, + out vec4 result +) +{ + vec2 coord = mx_transform_uv(tex_coord, tiling, vec2(0.0)); + + HextileData tile_data = mx_hextile_coord(coord, rotation, rotation_range, scale, scale_range, offset, offset_range); + + vec4 c1 = textureGrad(tex_sampler, tile_data.coord1, tile_data.ddx1, tile_data.ddy1); + vec4 c2 = textureGrad(tex_sampler, tile_data.coord2, tile_data.ddx2, tile_data.ddy2); + vec4 c3 = textureGrad(tex_sampler, tile_data.coord3, tile_data.ddx3, tile_data.ddy3); + + // luminance as weights + vec3 cw = vec3(dot(c1.rgb, lumacoeffs), dot(c2.rgb, lumacoeffs), dot(c3.rgb, lumacoeffs)); + cw = mix(vec3(1.0), cw, vec3(falloff_contrast)); + + // blend weights + vec3 w = cw * pow(tile_data.weights, vec3(7.0)); + w /= (w.x + w.y + w.z); + + // alpha + float a = (c1.a + c2.a + c3.a) / 3.0; + + // apply s-curve gain + if (falloff != 0.5) + { + w.x = mx_schlick_gain(w.x, falloff); + w.y = mx_schlick_gain(w.y, falloff); + w.z = mx_schlick_gain(w.z, falloff); + w /= (w.x + w.y + w.z); + a = mx_schlick_gain(a, falloff); + } + + // blend + result.rgb = vec3(w.x * c1 + w.y * c2 + w.z * c3); + result.a = a; +} \ No newline at end of file diff --git a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl new file mode 100644 index 0000000000..c8a6de2ada --- /dev/null +++ b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl @@ -0,0 +1,68 @@ +#include "lib/$fileTransformUv" +#include "lib/mx_hextile.glsl" +#include "lib/mx_geometry.glsl" + +// Morten S. Mikkelsen, Practical Real-Time Hex-Tiling, Journal of Computer Graphics +// Techniques (JCGT), vol. 11, no. 2, 77-94, 2022 +// http://jcgt.org/published/0011/03/05/ +void mx_hextilednormalmap_vector3( + sampler2D tex_sampler, + vec3 default_value, + vec2 tex_coord, + vec2 tiling, + float rotation, + vec2 rotation_range, + float scale, + vec2 scale_range, + float offset, + vec2 offset_range, + float falloff, + float strength, + bool flip_g, + vec3 N, + vec3 T, + vec3 B, + out vec3 result +) +{ + vec2 coord = mx_transform_uv(tex_coord, tiling, vec2(0.0)); + + HextileData tile_data = mx_hextile_coord(coord, rotation, rotation_range, scale, scale_range, offset, offset_range); + + vec3 nm1 = textureGrad(tex_sampler, tile_data.coord1, tile_data.ddx1, tile_data.ddy1).xyz; + vec3 nm2 = textureGrad(tex_sampler, tile_data.coord2, tile_data.ddx2, tile_data.ddy2).xyz; + vec3 nm3 = textureGrad(tex_sampler, tile_data.coord3, tile_data.ddx3, tile_data.ddy3).xyz; + nm1.y = flip_g ? 1.0 - nm1.y : nm1.y; + nm2.y = flip_g ? 1.0 - nm2.y : nm2.y; + nm3.y = flip_g ? 1.0 - nm3.y : nm3.y; + + // normalmap to shading normal + nm1 = 2.0 * nm1 - 1.0; + nm2 = 2.0 * nm2 - 1.0; + nm3 = 2.0 * nm3 - 1.0; + vec3 T1 = T * tile_data.tangent_rot_mat1 * strength; + vec3 T2 = T * tile_data.tangent_rot_mat2 * strength; + vec3 T3 = T * tile_data.tangent_rot_mat3 * strength; + vec3 B1 = B * tile_data.tangent_rot_mat1 * strength; + vec3 B2 = B * tile_data.tangent_rot_mat2 * strength; + vec3 B3 = B * tile_data.tangent_rot_mat3 * strength; + vec3 N1 = normalize(T1 * nm1.x + B1 * nm1.y + N * nm1.z); + vec3 N2 = normalize(T2 * nm2.x + B2 * nm2.y + N * nm2.z); + vec3 N3 = normalize(T3 * nm3.x + B3 * nm3.y + N * nm3.z); + + // blend weights + vec3 w = pow(tile_data.weights, vec3(7.0)); + w /= (w.x + w.y + w.z); + + // apply s-curve gain + if (falloff != 0.5) + { + w.x = mx_schlick_gain(w.x, falloff); + w.y = mx_schlick_gain(w.y, falloff); + w.z = mx_schlick_gain(w.z, falloff); + w /= (w.x + w.y + w.z); + } + + // blend + result = mx_gradient_blend_3_normals(N, N1, w.x, N2, w.y, N3, w.z); +} \ No newline at end of file diff --git a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx index 69f8f9a7f8..4808b3a400 100644 --- a/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx +++ b/libraries/stdlib/genglsl/stdlib_genglsl_impl.mtlx @@ -41,10 +41,23 @@ + + + + + + + + + + + + + diff --git a/libraries/stdlib/stdlib_defs.mtlx b/libraries/stdlib/stdlib_defs.mtlx index 943e36ec88..6dbbca9f63 100644 --- a/libraries/stdlib/stdlib_defs.mtlx +++ b/libraries/stdlib/stdlib_defs.mtlx @@ -292,6 +292,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp index e1a23cf7d4..dadf9538ef 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.cpp @@ -93,8 +93,11 @@ TEST_CASE("GenShader: MDL Implementation Check", "[genmdl]") generatorSkipNodeTypes.insert("light"); mx::StringSet generatorSkipNodeDefs; + generatorSkipNodeDefs.insert("ND_hextiledimage_color3"); + generatorSkipNodeDefs.insert("ND_hextiledimage_color4"); + generatorSkipNodeDefs.insert("ND_hextilednormalmap_vector3"); - GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 31); + GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 34); } diff --git a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h index ab92a5dacf..a77009d24c 100644 --- a/source/MaterialXTest/MaterialXGenMdl/GenMdl.h +++ b/source/MaterialXTest/MaterialXGenMdl/GenMdl.h @@ -50,6 +50,8 @@ class MdlShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester _skipFiles.insert("heighttonormal_in_nodegraph.mtlx"); } + _skipFiles.insert("hextiled.mtlx"); + ShaderGeneratorTester::addSkipFiles(); } diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp index c89f9ab19d..35875006d3 100644 --- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp +++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.cpp @@ -93,8 +93,11 @@ TEST_CASE("GenShader: OSL Implementation Check", "[genosl]") generatorSkipNodeDefs.insert("ND_chiang_hair_absorption_from_color"); generatorSkipNodeDefs.insert("ND_deon_hair_absorption_from_melanin"); generatorSkipNodeDefs.insert("ND_chiang_hair_bsdf"); + generatorSkipNodeDefs.insert("ND_hextiledimage_color3"); + generatorSkipNodeDefs.insert("ND_hextiledimage_color4"); + generatorSkipNodeDefs.insert("ND_hextilednormalmap_vector3"); - GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 35); + GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 38); } TEST_CASE("GenShader: OSL Unique Names", "[genosl]") diff --git a/source/MaterialXTest/MaterialXGenOsl/GenOsl.h b/source/MaterialXTest/MaterialXGenOsl/GenOsl.h index f02f750d26..c40ec2b3da 100644 --- a/source/MaterialXTest/MaterialXGenOsl/GenOsl.h +++ b/source/MaterialXTest/MaterialXGenOsl/GenOsl.h @@ -47,6 +47,7 @@ class OslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester { _skipFiles.insert("hair_bsdf.mtlx"); _skipFiles.insert("hair_surfaceshader.mtlx"); + _skipFiles.insert("hextiled.mtlx"); } // Ignore light shaders in the document for OSL From 9f4df4bdf6960b68424facb685407bee08d3e5f2 Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:17:59 -0700 Subject: [PATCH 2/9] attempt to workaround failure on msl test --- source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp | 3 +++ source/MaterialXTest/MaterialXGenMsl/GenMsl.h | 1 + 2 files changed, 4 insertions(+) diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp index 414bc3dd5d..ecc39f77a1 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp @@ -88,6 +88,9 @@ TEST_CASE("GenShader: MSL Implementation Check", "[genmsl]") generatorSkipNodeDefs.insert("ND_chiang_hair_absorption_from_color"); generatorSkipNodeDefs.insert("ND_deon_hair_absorption_from_melanin"); generatorSkipNodeDefs.insert("ND_chiang_hair_bsdf"); + generatorSkipNodeDefs.insert("ND_hextiledimage_color3"); + generatorSkipNodeDefs.insert("ND_hextiledimage_color4"); + generatorSkipNodeDefs.insert("ND_hextilednormalmap_vector3"); GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 34); } diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.h b/source/MaterialXTest/MaterialXGenMsl/GenMsl.h index 692c283fda..e0977bffe5 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.h +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.h @@ -45,6 +45,7 @@ class MslShaderGeneratorTester : public GenShaderUtil::ShaderGeneratorTester { _skipFiles.insert("hair_bsdf.mtlx"); _skipFiles.insert("hair_surfaceshader.mtlx"); + _skipFiles.insert("hextiled.mtlx"); } void setupDependentLibraries() override From cf852cf7a07a4724b5cee187661516e76a21e62f Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:24:31 -0700 Subject: [PATCH 3/9] another attempt --- source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp index ecc39f77a1..b6dca6deaa 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp @@ -92,7 +92,7 @@ TEST_CASE("GenShader: MSL Implementation Check", "[genmsl]") generatorSkipNodeDefs.insert("ND_hextiledimage_color4"); generatorSkipNodeDefs.insert("ND_hextilednormalmap_vector3"); - GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 34); + GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 33); } TEST_CASE("GenShader: MSL Unique Names", "[genmsl]") From 981c0fb8486c9de4c24e6269a1db82850d1d5011 Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Tue, 29 Oct 2024 18:25:58 -0700 Subject: [PATCH 4/9] again --- source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp index b6dca6deaa..565ff05fb7 100644 --- a/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp +++ b/source/MaterialXTest/MaterialXGenMsl/GenMsl.cpp @@ -92,7 +92,7 @@ TEST_CASE("GenShader: MSL Implementation Check", "[genmsl]") generatorSkipNodeDefs.insert("ND_hextiledimage_color4"); generatorSkipNodeDefs.insert("ND_hextilednormalmap_vector3"); - GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 33); + GenShaderUtil::checkImplementations(context, generatorSkipNodeTypes, generatorSkipNodeDefs, 37); } TEST_CASE("GenShader: MSL Unique Names", "[genmsl]") From e582fbc99cf00bf77aaa86cea1ba59d8cbc4067b Mon Sep 17 00:00:00 2001 From: Lee Kerley Date: Wed, 30 Oct 2024 10:49:32 -0700 Subject: [PATCH 5/9] Update code to work with MSL. --- libraries/stdlib/genglsl/lib/mx_geometry.glsl | 1 - libraries/stdlib/genglsl/lib/mx_hextile.glsl | 37 ++++++++----------- libraries/stdlib/genmsl/lib/mx_math.metal | 5 +++ libraries/stdlib/genmsl/lib/mx_texture.metal | 5 +++ source/MaterialXGenMsl/MslShaderGenerator.cpp | 1 + 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/libraries/stdlib/genglsl/lib/mx_geometry.glsl b/libraries/stdlib/genglsl/lib/mx_geometry.glsl index e30c681f59..ac3cec5467 100644 --- a/libraries/stdlib/genglsl/lib/mx_geometry.glsl +++ b/libraries/stdlib/genglsl/lib/mx_geometry.glsl @@ -1,4 +1,3 @@ -#include "mx_math.glsl" // blend 3 normals by blending the gradients // Morten S. Mikkelsen, Surface Gradient–Based Bump Mapping Framework, Journal of diff --git a/libraries/stdlib/genglsl/lib/mx_hextile.glsl b/libraries/stdlib/genglsl/lib/mx_hextile.glsl index 389d56215c..e4db6f15be 100644 --- a/libraries/stdlib/genglsl/lib/mx_hextile.glsl +++ b/libraries/stdlib/genglsl/lib/mx_hextile.glsl @@ -87,7 +87,7 @@ HextileData mx_hextile_coord( vec2 rand3 = mx_hextile_hash(vec2(id3) + seed_offset); // randomized rotation matrix - vec2 rr = radians(rotation_range); + vec2 rr = mx_radians(rotation_range); float rv1 = mix(rr.x, rr.y, rand1.x * rotation); float rv2 = mix(rr.x, rr.y, rand2.x * rotation); float rv3 = mix(rr.x, rr.y, rand3.x * rotation); @@ -101,10 +101,13 @@ HextileData mx_hextile_coord( mat2 rm2 = mat2(cos_r2, -sin_r2, sin_r2, cos_r2); mat2 rm3 = mat2(cos_r3, -sin_r3, sin_r3, cos_r3); + HextileData tile_data; + tile_data.weights = vec3(w1, w2, w3); + // rotation matrix for tangent vectors - mat3 trm1 = mat3(cos_r1, 0.0, sin_r1, 0.0, 1.0, 0.0, -sin_r1, 0.0, cos_r1); - mat3 trm2 = mat3(cos_r2, 0.0, sin_r2, 0.0, 1.0, 0.0, -sin_r2, 0.0, cos_r2); - mat3 trm3 = mat3(cos_r3, 0.0, sin_r3, 0.0, 1.0, 0.0, -sin_r3, 0.0, cos_r3); + tile_data.tangent_rot_mat1 = mat3(cos_r1, 0.0, sin_r1, 0.0, 1.0, 0.0, -sin_r1, 0.0, cos_r1); + tile_data.tangent_rot_mat2 = mat3(cos_r2, 0.0, sin_r2, 0.0, 1.0, 0.0, -sin_r2, 0.0, cos_r2); + tile_data.tangent_rot_mat3 = mat3(cos_r3, 0.0, sin_r3, 0.0, 1.0, 0.0, -sin_r3, 0.0, cos_r3); // randomized scale vec2 sr = scale_range; @@ -118,27 +121,19 @@ HextileData mx_hextile_coord( vec2 offset3 = mix(vec2(offset_range.x), vec2(offset_range.y), rand3 * offset); // get coord - vec2 st1 = ((coord - ctr1) * rm1 / scale1) + ctr1 + offset1; - vec2 st2 = ((coord - ctr2) * rm2 / scale2) + ctr2 + offset2; - vec2 st3 = ((coord - ctr3) * rm3 / scale3) + ctr3 + offset3; + tile_data.coord1 = ((coord - ctr1) * rm1 / scale1) + ctr1 + offset1; + tile_data.coord2 = ((coord - ctr2) * rm2 / scale2) + ctr2 + offset2; + tile_data.coord3 = ((coord - ctr3) * rm3 / scale3) + ctr3 + offset3; // derivatives vec2 ddx = dFdx(coord); vec2 ddy = dFdy(coord); - vec2 ddx1 = ddx * rm1 / scale1; - vec2 ddx2 = ddx * rm2 / scale2; - vec2 ddx3 = ddx * rm3 / scale3; - vec2 ddy1 = ddy * rm1 / scale1; - vec2 ddy2 = ddy * rm2 / scale2; - vec2 ddy3 = ddy * rm3 / scale3; - - HextileData tile_data = HextileData( - st1, st2, st3, - vec3(w1, w2, w3), - trm1, trm2, trm3, - ddx1, ddx2, ddx3, - ddy1, ddy2, ddy3 - ); + tile_data.ddx1 = ddx * rm1 / scale1; + tile_data.ddx2 = ddx * rm2 / scale2; + tile_data.ddx3 = ddx * rm3 / scale3; + tile_data.ddy1 = ddy * rm1 / scale1; + tile_data.ddy2 = ddy * rm2 / scale2; + tile_data.ddy3 = ddy * rm3 / scale3; return tile_data; } diff --git a/libraries/stdlib/genmsl/lib/mx_math.metal b/libraries/stdlib/genmsl/lib/mx_math.metal index afd8fb4a7e..ef0c4ebebe 100644 --- a/libraries/stdlib/genmsl/lib/mx_math.metal +++ b/libraries/stdlib/genmsl/lib/mx_math.metal @@ -127,3 +127,8 @@ float mx_radians(float degree) { return (degree * M_PI_F / 180.0f); } + +vec2 mx_radians(vec2 degree) +{ + return (degree * M_PI_F / 180.0f); +} diff --git a/libraries/stdlib/genmsl/lib/mx_texture.metal b/libraries/stdlib/genmsl/lib/mx_texture.metal index 479a8836bf..12cb5233b7 100644 --- a/libraries/stdlib/genmsl/lib/mx_texture.metal +++ b/libraries/stdlib/genmsl/lib/mx_texture.metal @@ -19,6 +19,11 @@ float4 textureLod(MetalTexture mtlTex, float2 uv, float lod) return mtlTex.tex.sample(mtlTex.s, uv, level(lod)); } +float4 textureGrad(MetalTexture mtlTex, float2 uv, float2 dx, float2 dy) +{ + return mtlTex.tex.sample(mtlTex.s, uv, gradient2d(dx, dy)); +} + int2 textureSize(MetalTexture mtlTex, int mipLevel) { return int2(mtlTex.get_width(), mtlTex.get_height()); diff --git a/source/MaterialXGenMsl/MslShaderGenerator.cpp b/source/MaterialXGenMsl/MslShaderGenerator.cpp index 9511fac7ba..caf6697555 100644 --- a/source/MaterialXGenMsl/MslShaderGenerator.cpp +++ b/source/MaterialXGenMsl/MslShaderGenerator.cpp @@ -694,6 +694,7 @@ void MslShaderGenerator::emitDirectives(GenContext&, ShaderStage& stage) const emitLine("#define bvec2 bool2", stage, false); emitLine("#define bvec3 bool3", stage, false); emitLine("#define bvec4 bool4", stage, false); + emitLine("#define mat2 float2x2", stage, false); emitLine("#define mat3 float3x3", stage, false); emitLine("#define mat4 float4x4", stage, false); From cfba41126611712d61afa36c459cf7d93125777e Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:18:24 -0700 Subject: [PATCH 6/9] fix tangent vector rotation was not correct --- libraries/stdlib/genglsl/lib/mx_hextile.glsl | 20 +++++++++---------- libraries/stdlib/genglsl/lib/mx_math.glsl | 12 +++++++++++ .../stdlib/genglsl/mx_hextilednormalmap.glsl | 16 +++++++++------ 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/libraries/stdlib/genglsl/lib/mx_hextile.glsl b/libraries/stdlib/genglsl/lib/mx_hextile.glsl index e4db6f15be..bc8959a00b 100644 --- a/libraries/stdlib/genglsl/lib/mx_hextile.glsl +++ b/libraries/stdlib/genglsl/lib/mx_hextile.glsl @@ -22,9 +22,9 @@ struct HextileData vec2 coord2; vec2 coord3; vec3 weights; - mat3 tangent_rot_mat1; - mat3 tangent_rot_mat2; - mat3 tangent_rot_mat3; + float rot_radian1; + float rot_radian2; + float rot_radian3; vec2 ddx1; vec2 ddx2; vec2 ddx3; @@ -101,14 +101,6 @@ HextileData mx_hextile_coord( mat2 rm2 = mat2(cos_r2, -sin_r2, sin_r2, cos_r2); mat2 rm3 = mat2(cos_r3, -sin_r3, sin_r3, cos_r3); - HextileData tile_data; - tile_data.weights = vec3(w1, w2, w3); - - // rotation matrix for tangent vectors - tile_data.tangent_rot_mat1 = mat3(cos_r1, 0.0, sin_r1, 0.0, 1.0, 0.0, -sin_r1, 0.0, cos_r1); - tile_data.tangent_rot_mat2 = mat3(cos_r2, 0.0, sin_r2, 0.0, 1.0, 0.0, -sin_r2, 0.0, cos_r2); - tile_data.tangent_rot_mat3 = mat3(cos_r3, 0.0, sin_r3, 0.0, 1.0, 0.0, -sin_r3, 0.0, cos_r3); - // randomized scale vec2 sr = scale_range; vec2 scale1 = vec2(mix(1.0, mix(sr.x, sr.y, rand1.y), scale)); @@ -120,6 +112,12 @@ HextileData mx_hextile_coord( vec2 offset2 = mix(vec2(offset_range.x), vec2(offset_range.y), rand2 * offset); vec2 offset3 = mix(vec2(offset_range.x), vec2(offset_range.y), rand3 * offset); + HextileData tile_data; + tile_data.weights = vec3(w1, w2, w3); + tile_data.rot_radian1 = rv1; + tile_data.rot_radian2 = rv2; + tile_data.rot_radian3 = rv3; + // get coord tile_data.coord1 = ((coord - ctr1) * rm1 / scale1) + ctr1 + offset1; tile_data.coord2 = ((coord - ctr2) * rm2 / scale2) + ctr2 + offset2; diff --git a/libraries/stdlib/genglsl/lib/mx_math.glsl b/libraries/stdlib/genglsl/lib/mx_math.glsl index d196615e70..2713ff6551 100644 --- a/libraries/stdlib/genglsl/lib/mx_math.glsl +++ b/libraries/stdlib/genglsl/lib/mx_math.glsl @@ -33,3 +33,15 @@ vec3 mx_srgb_encode(vec3 color) vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; return mix(linSeg, powSeg, isAbove); } + +mat3 mx_axis_rotation_matrix(vec3 a, float r) +{ + float s = sin(r); + float c = cos(r); + float omc = 1.0 - c; + return mat3( + a.x*a.x*omc + c, a.x*a.y*omc - a.x*s, a.x*a.z*omc + a.y*s, + a.y*a.x*omc + a.z*s, a.y*a.y*omc + c, a.y*a.z*omc - a.x*s, + a.z*a.x*omc - a.y*s, a.z*a.y*omc + a.x*s, a.z*a.z*omc + c + ); +} diff --git a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl index c8a6de2ada..831de4c5a6 100644 --- a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl +++ b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl @@ -1,4 +1,5 @@ #include "lib/$fileTransformUv" +#include "lib/mx_math.glsl" #include "lib/mx_hextile.glsl" #include "lib/mx_geometry.glsl" @@ -40,12 +41,15 @@ void mx_hextilednormalmap_vector3( nm1 = 2.0 * nm1 - 1.0; nm2 = 2.0 * nm2 - 1.0; nm3 = 2.0 * nm3 - 1.0; - vec3 T1 = T * tile_data.tangent_rot_mat1 * strength; - vec3 T2 = T * tile_data.tangent_rot_mat2 * strength; - vec3 T3 = T * tile_data.tangent_rot_mat3 * strength; - vec3 B1 = B * tile_data.tangent_rot_mat1 * strength; - vec3 B2 = B * tile_data.tangent_rot_mat2 * strength; - vec3 B3 = B * tile_data.tangent_rot_mat3 * strength; + mat3 tangent_rot_mat1 = mx_axis_rotation_matrix(N, -tile_data.rot_radian1); + mat3 tangent_rot_mat2 = mx_axis_rotation_matrix(N, -tile_data.rot_radian2); + mat3 tangent_rot_mat3 = mx_axis_rotation_matrix(N, -tile_data.rot_radian3); + vec3 T1 = tangent_rot_mat1 * T * strength; + vec3 T2 = tangent_rot_mat2 * T * strength; + vec3 T3 = tangent_rot_mat3 * T * strength; + vec3 B1 = tangent_rot_mat1 * B * strength; + vec3 B2 = tangent_rot_mat2 * B * strength; + vec3 B3 = tangent_rot_mat3 * B * strength; vec3 N1 = normalize(T1 * nm1.x + B1 * nm1.y + N * nm1.z); vec3 N2 = normalize(T2 * nm2.x + B2 * nm2.y + N * nm2.z); vec3 N3 = normalize(T3 * nm3.x + B3 * nm3.y + N * nm3.z); From 98d00c041dc03c09b8ca65942fe523d60ddd6fa1 Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Fri, 1 Nov 2024 14:48:23 -0700 Subject: [PATCH 7/9] attempt to fix MSL build failure --- libraries/stdlib/genglsl/mx_hextilednormalmap.glsl | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl index 831de4c5a6..69e856c434 100644 --- a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl +++ b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl @@ -1,5 +1,4 @@ #include "lib/$fileTransformUv" -#include "lib/mx_math.glsl" #include "lib/mx_hextile.glsl" #include "lib/mx_geometry.glsl" From 67eadaa6c3738357fdcfbed3d36b541a5b965fa5 Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Fri, 1 Nov 2024 15:13:40 -0700 Subject: [PATCH 8/9] testing include guard for MSL --- libraries/stdlib/genglsl/lib/mx_math.glsl | 5 +++++ libraries/stdlib/genglsl/mx_hextilednormalmap.glsl | 1 + 2 files changed, 6 insertions(+) diff --git a/libraries/stdlib/genglsl/lib/mx_math.glsl b/libraries/stdlib/genglsl/lib/mx_math.glsl index 2713ff6551..cad51db092 100644 --- a/libraries/stdlib/genglsl/lib/mx_math.glsl +++ b/libraries/stdlib/genglsl/lib/mx_math.glsl @@ -1,3 +1,6 @@ +#ifndef MX_MATH_GLSL +#define MX_MATH_GLSL + #define M_FLOAT_EPS 1e-8 #define mx_mod mod @@ -45,3 +48,5 @@ mat3 mx_axis_rotation_matrix(vec3 a, float r) a.z*a.x*omc - a.y*s, a.z*a.y*omc + a.x*s, a.z*a.z*omc + c ); } + +#endif // MX_MATH_GLSL diff --git a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl index 69e856c434..831de4c5a6 100644 --- a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl +++ b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl @@ -1,4 +1,5 @@ #include "lib/$fileTransformUv" +#include "lib/mx_math.glsl" #include "lib/mx_hextile.glsl" #include "lib/mx_geometry.glsl" From e3854fa32e12b64d94070e84a91f34955efa27ec Mon Sep 17 00:00:00 2001 From: Masuo Suzuki <153872239+msuzuki-nvidia@users.noreply.github.com> Date: Fri, 1 Nov 2024 16:34:51 -0700 Subject: [PATCH 9/9] remove include guard, move a function out from mx_math.glsl --- libraries/stdlib/genglsl/lib/mx_geometry.glsl | 14 ++++++++++++++ libraries/stdlib/genglsl/lib/mx_math.glsl | 17 ----------------- .../stdlib/genglsl/mx_hextilednormalmap.glsl | 1 - 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/libraries/stdlib/genglsl/lib/mx_geometry.glsl b/libraries/stdlib/genglsl/lib/mx_geometry.glsl index ac3cec5467..06af9a4bab 100644 --- a/libraries/stdlib/genglsl/lib/mx_geometry.glsl +++ b/libraries/stdlib/genglsl/lib/mx_geometry.glsl @@ -26,3 +26,17 @@ vec3 mx_gradient_blend_3_normals(vec3 N, vec3 N1, float N1_weight, vec3 N2, floa // gradient to normal return normalize(N - gg); } + +// this function should be categorized in mx_math.glsl but it causes build errors in MSL +// so adding here for a workaround +mat3 mx_axis_rotation_matrix(vec3 a, float r) +{ + float s = sin(r); + float c = cos(r); + float omc = 1.0 - c; + return mat3( + a.x*a.x*omc + c, a.x*a.y*omc - a.x*s, a.x*a.z*omc + a.y*s, + a.y*a.x*omc + a.z*s, a.y*a.y*omc + c, a.y*a.z*omc - a.x*s, + a.z*a.x*omc - a.y*s, a.z*a.y*omc + a.x*s, a.z*a.z*omc + c + ); +} diff --git a/libraries/stdlib/genglsl/lib/mx_math.glsl b/libraries/stdlib/genglsl/lib/mx_math.glsl index cad51db092..d196615e70 100644 --- a/libraries/stdlib/genglsl/lib/mx_math.glsl +++ b/libraries/stdlib/genglsl/lib/mx_math.glsl @@ -1,6 +1,3 @@ -#ifndef MX_MATH_GLSL -#define MX_MATH_GLSL - #define M_FLOAT_EPS 1e-8 #define mx_mod mod @@ -36,17 +33,3 @@ vec3 mx_srgb_encode(vec3 color) vec3 powSeg = 1.055 * pow(max(color, vec3(0.0)), vec3(1.0 / 2.4)) - 0.055; return mix(linSeg, powSeg, isAbove); } - -mat3 mx_axis_rotation_matrix(vec3 a, float r) -{ - float s = sin(r); - float c = cos(r); - float omc = 1.0 - c; - return mat3( - a.x*a.x*omc + c, a.x*a.y*omc - a.x*s, a.x*a.z*omc + a.y*s, - a.y*a.x*omc + a.z*s, a.y*a.y*omc + c, a.y*a.z*omc - a.x*s, - a.z*a.x*omc - a.y*s, a.z*a.y*omc + a.x*s, a.z*a.z*omc + c - ); -} - -#endif // MX_MATH_GLSL diff --git a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl index 831de4c5a6..69e856c434 100644 --- a/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl +++ b/libraries/stdlib/genglsl/mx_hextilednormalmap.glsl @@ -1,5 +1,4 @@ #include "lib/$fileTransformUv" -#include "lib/mx_math.glsl" #include "lib/mx_hextile.glsl" #include "lib/mx_geometry.glsl"