From 0c3373fc71acafee4a8b2adca98a92cb6a6b5ca4 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 05:15:04 -0300 Subject: [PATCH 1/7] add includes for constructor argument --- examples/jsm/nodes/core/CodeNode.js | 6 +++--- examples/jsm/nodes/core/FunctionNode.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/jsm/nodes/core/CodeNode.js b/examples/jsm/nodes/core/CodeNode.js index 0dfb8938463913..bb571a76ac7526 100644 --- a/examples/jsm/nodes/core/CodeNode.js +++ b/examples/jsm/nodes/core/CodeNode.js @@ -2,15 +2,15 @@ import Node from './Node.js'; class CodeNode extends Node { - constructor( code = '', nodeType = 'code' ) { + constructor( code = '', includes = [] ) { - super( nodeType ); + super( 'code' ); this.isCodeNode = true; this.code = code; - this._includes = []; + this._includes = includes; } diff --git a/examples/jsm/nodes/core/FunctionNode.js b/examples/jsm/nodes/core/FunctionNode.js index 175835bf1315c0..a7806ad88a8471 100644 --- a/examples/jsm/nodes/core/FunctionNode.js +++ b/examples/jsm/nodes/core/FunctionNode.js @@ -3,9 +3,9 @@ import FunctionCallNode from './FunctionCallNode.js'; class FunctionNode extends CodeNode { - constructor( code = '' ) { + constructor( code = '', includes = [] ) { - super( code ); + super( code, includes ); this.keywords = {}; From 87de46756cd95da34de7bbda7c2e7acdadd4aec8 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 05:15:53 -0300 Subject: [PATCH 2/7] add support to array for function call --- examples/jsm/nodes/core/FunctionCallNode.js | 25 ++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/examples/jsm/nodes/core/FunctionCallNode.js b/examples/jsm/nodes/core/FunctionCallNode.js index e5609168ad7e8d..1d257f9d4b4e89 100644 --- a/examples/jsm/nodes/core/FunctionCallNode.js +++ b/examples/jsm/nodes/core/FunctionCallNode.js @@ -40,17 +40,32 @@ class FunctionCallNode extends TempNode { const inputs = functionNode.getInputs( builder ); const parameters = this.parameters; - for ( const inputNode of inputs ) { + if ( Array.isArray( parameters ) ) { - const node = parameters[ inputNode.name ]; + for ( let i = 0; i < parameters.length; i ++ ) { - if ( node !== undefined ) { + const inputNode = inputs[ i ]; + const node = parameters[ i ]; params.push( node.build( builder, inputNode.type ) ); - } else { + } + + } else { + + for ( const inputNode of inputs ) { + + const node = parameters[ inputNode.name ]; + + if ( node !== undefined ) { + + params.push( node.build( builder, inputNode.type ) ); + + } else { + + throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); - throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); + } } From 7b40a3b2b6eedcbecbcf0e364498d5b51646a09c Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 05:16:27 -0300 Subject: [PATCH 3/7] add function interface --- .../jsm/nodes/parsers/GLSLNodeFunction.js | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/jsm/nodes/parsers/GLSLNodeFunction.js b/examples/jsm/nodes/parsers/GLSLNodeFunction.js index 917b9609e9b8f4..a3b3901f2e2651 100644 --- a/examples/jsm/nodes/parsers/GLSLNodeFunction.js +++ b/examples/jsm/nodes/parsers/GLSLNodeFunction.js @@ -117,18 +117,33 @@ class GLSLNodeFunction extends NodeFunction { getCode( name = this.name ) { - const headerCode = this.headerCode; - const presicion = this.presicion; + let code; - let declarationCode = `${ this.type } ${ name } ( ${ this.inputsCode.trim() } )`; + const blockCode = this.blockCode; - if ( presicion !== '' ) { + if ( blockCode !== '' ) { - declarationCode = `${ presicion } ${ declarationCode }`; + const { type, inputsCode, headerCode, presicion } = this; + + let declarationCode = `${ type } ${ name } ( ${ inputsCode.trim() } )`; + + if ( presicion !== '' ) { + + declarationCode = `${ presicion } ${ declarationCode }`; + + } + + code = headerCode + declarationCode + blockCode; + + } else { + + // interface function + + code = ''; } - return headerCode + declarationCode + this.blockCode; + return code; } From 05208ebd5a06f18f83db38a8eb7a399220e884a7 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 05:17:59 -0300 Subject: [PATCH 4/7] convert to nodeObjects function call parameters and includes --- examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js b/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js index 5d8191b2769b06..9fad96e8184ca3 100644 --- a/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +++ b/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js @@ -87,12 +87,12 @@ export const bmat4 = new ConvertType( 'bmat4' ); // @TODO: ArrayUniformNode -export const func = ( code ) => { +export const func = ( code, includes ) => { - const node = nodeObject( new FunctionNode( code ) ); + const node = nodeObject( new FunctionNode( code, includes ) ); const call = node.call.bind( node ); - node.call = ( params ) => nodeObject( call( params ) ); + node.call = ( ...params ) => nodeObject( call( params.length > 1 || params[ 0 ]?.isNode === true ? nodeArray( params ) : nodeObjects( params[ 0 ] ) ) ); return node; From 7696f222bc75aeb6e02e092e63859fc0e51e3776 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 05:18:08 -0300 Subject: [PATCH 5/7] add fn --- examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js b/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js index 9fad96e8184ca3..c7a3a5ca24a901 100644 --- a/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js +++ b/examples/jsm/nodes/shadernode/ShaderNodeBaseElements.js @@ -109,6 +109,8 @@ export const uniform = ( nodeOrType ) => { }; +export const fn = ( code, includes ) => func( code, includes ).call; + export const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) ); export const property = ( name, nodeOrType ) => nodeObject( new PropertyNode( name, getConstNodeType( nodeOrType ) ) ); From b6f2be1ab67f9a7c088f5af3a388746c72b024b1 Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 14:17:49 -0300 Subject: [PATCH 6/7] add materialx noise functions example --- examples/files.json | 1 + examples/jsm/nodes/materialx/Disclaimer.md | 199 ++++++ .../nodes/materialx/functions/lib/mx_hsv.js | 56 ++ .../nodes/materialx/functions/lib/mx_noise.js | 607 ++++++++++++++++++ .../webgl_nodes_materialx_noise.jpg | Bin 0 -> 38436 bytes examples/webgl_nodes_materialx_noise.html | 214 ++++++ 6 files changed, 1077 insertions(+) create mode 100644 examples/jsm/nodes/materialx/Disclaimer.md create mode 100644 examples/jsm/nodes/materialx/functions/lib/mx_hsv.js create mode 100644 examples/jsm/nodes/materialx/functions/lib/mx_noise.js create mode 100644 examples/screenshots/webgl_nodes_materialx_noise.jpg create mode 100644 examples/webgl_nodes_materialx_noise.html diff --git a/examples/files.json b/examples/files.json index 84feb7a1c232b2..b6efb2368c062a 100644 --- a/examples/files.json +++ b/examples/files.json @@ -235,6 +235,7 @@ "webgl_nodes_materials_instance_uniform", "webgl_nodes_materials_physical_clearcoat", "webgl_nodes_materials_standard", + "webgl_nodes_materialx_noise", "webgl_nodes_playground", "webgl_nodes_points" ], diff --git a/examples/jsm/nodes/materialx/Disclaimer.md b/examples/jsm/nodes/materialx/Disclaimer.md new file mode 100644 index 00000000000000..2badec8cfdad74 --- /dev/null +++ b/examples/jsm/nodes/materialx/Disclaimer.md @@ -0,0 +1,199 @@ +## MaterialX + +MaterialX is a project of the +[Academy Software Foundation](https://www.aswf.io/) and relies on the ASWF +governance policies, supported by the Linux Foundation. + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +``` +------------------------------------------------------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS +``` \ No newline at end of file diff --git a/examples/jsm/nodes/materialx/functions/lib/mx_hsv.js b/examples/jsm/nodes/materialx/functions/lib/mx_hsv.js new file mode 100644 index 00000000000000..fa30c833639d3d --- /dev/null +++ b/examples/jsm/nodes/materialx/functions/lib/mx_hsv.js @@ -0,0 +1,56 @@ +import { fn } from '../../../Nodes.js'; + +// Original shader code from: +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_hsv.glsl + +export const mx_hsvtorgb = fn( `vec3 mx_hsvtorgb(vec3 hsv) +{ + // Reference for this technique: Foley & van Dam + float h = hsv.x; float s = hsv.y; float v = hsv.z; + if (s < 0.0001f) { + return vec3 (v, v, v); + } else { + h = 6.0f * (h - floor(h)); // expand to [0..6) + int hi = int(trunc(h)); + float f = h - float(hi); + float p = v * (1.0f-s); + float q = v * (1.0f-s*f); + float t = v * (1.0f-s*(1.0f-f)); + if (hi == 0) + return vec3 (v, t, p); + else if (hi == 1) + return vec3 (q, v, p); + else if (hi == 2) + return vec3 (p, v, t); + else if (hi == 3) + return vec3 (p, q, v); + else if (hi == 4) + return vec3 (t, p, v); + return vec3 (v, p, q); + } +}` ); + +export const mx_rgbtohsv = fn( `vec3 mx_rgbtohsv(vec3 c) +{ + // See Foley & van Dam + float r = c.x; float g = c.y; float b = c.z; + float mincomp = min (r, min(g, b)); + float maxcomp = max (r, max(g, b)); + float delta = maxcomp - mincomp; // chroma + float h, s, v; + v = maxcomp; + if (maxcomp > 0.0f) + s = delta / maxcomp; + else s = 0.0f; + if (s <= 0.0f) + h = 0.0f; + else { + if (r >= maxcomp) h = (g-b) / delta; + else if (g >= maxcomp) h = 2.0f + (b-r) / delta; + else h = 4.0f + (r-g) / delta; + h *= (1.0f/6.0f); + if (h < 0.0f) + h += 1.0f; + } + return vec3(h, s, v); +}` ); diff --git a/examples/jsm/nodes/materialx/functions/lib/mx_noise.js b/examples/jsm/nodes/materialx/functions/lib/mx_noise.js new file mode 100644 index 00000000000000..7d495f9e79b91f --- /dev/null +++ b/examples/jsm/nodes/materialx/functions/lib/mx_noise.js @@ -0,0 +1,607 @@ +import { code, fn } from '../../../Nodes.js'; + +// Original shader code from: +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_noise.glsl + +export const mx_noise = code( `float mx_select(bool b, float t, float f) +{ + return b ? t : f; +} + +float mx_negate_if(float val, bool b) +{ + return b ? -val : val; +} + +int mx_floor(float x) +{ + return int(floor(x)); +} + +// return mx_floor as well as the fractional remainder +float mx_floorfrac(float x, out int i) +{ + i = mx_floor(x); + return x - float(i); +} + +float mx_bilerp(float v0, float v1, float v2, float v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +vec3 mx_bilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, float s, float t) +{ + float s1 = 1.0 - s; + return (1.0 - t) * (v0*s1 + v1*s) + t * (v2*s1 + v3*s); +} +float mx_trilerp(float v0, float v1, float v2, float v3, float v4, float v5, float v6, float v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} +vec3 mx_trilerp(vec3 v0, vec3 v1, vec3 v2, vec3 v3, vec3 v4, vec3 v5, vec3 v6, vec3 v7, float s, float t, float r) +{ + float s1 = 1.0 - s; + float t1 = 1.0 - t; + float r1 = 1.0 - r; + return (r1*(t1*(v0*s1 + v1*s) + t*(v2*s1 + v3*s)) + + r*(t1*(v4*s1 + v5*s) + t*(v6*s1 + v7*s))); +} + +// 2 and 3 dimensional gradient functions - perform a dot product against a +// randomly chosen vector. Note that the gradient vector is not normalized, but +// this only affects the overal "scale" of the result, so we simply account for +// the scale by multiplying in the corresponding "perlin" function. +float mx_gradient_float(uint hash, float x, float y) +{ + // 8 possible directions (+-1,+-2) and (+-2,+-1) + uint h = hash & 7u; + float u = mx_select(h<4u, x, y); + float v = 2.0 * mx_select(h<4u, y, x); + // compute the dot product with (x,y). + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +float mx_gradient_float(uint hash, float x, float y, float z) +{ + // use vectors pointing to the edges of the cube + uint h = hash & 15u; + float u = mx_select(h<8u, x, y); + float v = mx_select(h<4u, y, mx_select((h==12u)||(h==14u), x, z)); + return mx_negate_if(u, bool(h&1u)) + mx_negate_if(v, bool(h&2u)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y) +{ + return vec3(mx_gradient_float(hash.x, x, y), mx_gradient_float(hash.y, x, y), mx_gradient_float(hash.z, x, y)); +} +vec3 mx_gradient_vec3(uvec3 hash, float x, float y, float z) +{ + return vec3(mx_gradient_float(hash.x, x, y, z), mx_gradient_float(hash.y, x, y, z), mx_gradient_float(hash.z, x, y, z)); +} +// Scaling factors to normalize the result of gradients above. +// These factors were experimentally calculated to be: +// 2D: 0.6616 +// 3D: 0.9820 +float mx_gradient_scale2d(float v) { return 0.6616 * v; } +float mx_gradient_scale3d(float v) { return 0.9820 * v; } +vec3 mx_gradient_scale2d(vec3 v) { return 0.6616 * v; } +vec3 mx_gradient_scale3d(vec3 v) { return 0.9820 * v; } + +/// Bitwise circular rotation left by k bits (for 32 bit unsigned integers) +uint mx_rotl32(uint x, int k) +{ + return (x<>(32-k)); +} + +void mx_bjmix(inout uint a, inout uint b, inout uint c) +{ + a -= c; a ^= mx_rotl32(c, 4); c += b; + b -= a; b ^= mx_rotl32(a, 6); a += c; + c -= b; c ^= mx_rotl32(b, 8); b += a; + a -= c; a ^= mx_rotl32(c,16); c += b; + b -= a; b ^= mx_rotl32(a,19); a += c; + c -= b; c ^= mx_rotl32(b, 4); b += a; +} + +// Mix up and combine the bits of a, b, and c (doesn't change them, but +// returns a hash of those three original values). +uint mx_bjfinal(uint a, uint b, uint c) +{ + c ^= b; c -= mx_rotl32(b,14); + a ^= c; a -= mx_rotl32(c,11); + b ^= a; b -= mx_rotl32(a,25); + c ^= b; c -= mx_rotl32(b,16); + a ^= c; a -= mx_rotl32(c,4); + b ^= a; b -= mx_rotl32(a,14); + c ^= b; c -= mx_rotl32(b,24); + return c; +} + +// Convert a 32 bit integer into a floating point number in [0,1] +float mx_bits_to_01(uint bits) +{ + return float(bits) / float(uint(0xffffffff)); +} + +float mx_fade(float t) +{ + return t * t * t * (t * (t * 6.0 - 15.0) + 10.0); +} + +uint mx_hash_int(int x) +{ + uint len = 1u; + uint seed = uint(0xdeadbeef) + (len << 2u) + 13u; + return mx_bjfinal(seed+uint(x), seed, seed); +} + +uint mx_hash_int(int x, int y) +{ + uint len = 2u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z) +{ + uint len = 3u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx) +{ + uint len = 4u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + return mx_bjfinal(a, b, c); +} + +uint mx_hash_int(int x, int y, int z, int xx, int yy) +{ + uint len = 5u; + uint a, b, c; + a = b = c = uint(0xdeadbeef) + (len << 2u) + 13u; + a += uint(x); + b += uint(y); + c += uint(z); + mx_bjmix(a, b, c); + a += uint(xx); + b += uint(yy); + return mx_bjfinal(a, b, c); +} + +uvec3 mx_hash_vec3(int x, int y) +{ + uint h = mx_hash_int(x, y); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +uvec3 mx_hash_vec3(int x, int y, int z) +{ + uint h = mx_hash_int(x, y, z); + // we only need the low-order bits to be random, so split out + // the 32 bit result into 3 parts for each channel + uvec3 result; + result.x = (h ) & 0xFFu; + result.y = (h >> 8 ) & 0xFFu; + result.z = (h >> 16) & 0xFFu; + return result; +} + +float mx_perlin_noise_float(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + float result = mx_bilerp( + mx_gradient_float(mx_hash_int(X , Y ), fx , fy ), + mx_gradient_float(mx_hash_int(X+1, Y ), fx-1.0, fy ), + mx_gradient_float(mx_hash_int(X , Y+1), fx , fy-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +float mx_perlin_noise_float(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + float result = mx_trilerp( + mx_gradient_float(mx_hash_int(X , Y , Z ), fx , fy , fz ), + mx_gradient_float(mx_hash_int(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_float(mx_hash_int(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_float(mx_hash_int(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_float(mx_hash_int(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_float(mx_hash_int(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +vec3 mx_perlin_noise_vec3(vec2 p) +{ + int X, Y; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float u = mx_fade(fx); + float v = mx_fade(fy); + vec3 result = mx_bilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y ), fx , fy ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y ), fx-1.0, fy ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1), fx , fy-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1), fx-1.0, fy-1.0), + u, v); + return mx_gradient_scale2d(result); +} + +vec3 mx_perlin_noise_vec3(vec3 p) +{ + int X, Y, Z; + float fx = mx_floorfrac(p.x, X); + float fy = mx_floorfrac(p.y, Y); + float fz = mx_floorfrac(p.z, Z); + float u = mx_fade(fx); + float v = mx_fade(fy); + float w = mx_fade(fz); + vec3 result = mx_trilerp( + mx_gradient_vec3(mx_hash_vec3(X , Y , Z ), fx , fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z ), fx-1.0, fy , fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z ), fx , fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z ), fx-1.0, fy-1.0, fz ), + mx_gradient_vec3(mx_hash_vec3(X , Y , Z+1), fx , fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y , Z+1), fx-1.0, fy , fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X , Y+1, Z+1), fx , fy-1.0, fz-1.0), + mx_gradient_vec3(mx_hash_vec3(X+1, Y+1, Z+1), fx-1.0, fy-1.0, fz-1.0), + u, v, w); + return mx_gradient_scale3d(result); +} + +float mx_cell_noise_float(float p) +{ + int ix = mx_floor(p); + return mx_bits_to_01(mx_hash_int(ix)); +} + +float mx_cell_noise_float(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return mx_bits_to_01(mx_hash_int(ix, iy)); +} + +float mx_cell_noise_float(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + return mx_bits_to_01(mx_hash_int(ix, iy, iz)); +} + +float mx_cell_noise_float(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + return mx_bits_to_01(mx_hash_int(ix, iy, iz, iw)); +} + +vec3 mx_cell_noise_vec3(float p) +{ + int ix = mx_floor(p); + return vec3( + mx_bits_to_01(mx_hash_int(ix, 0)), + mx_bits_to_01(mx_hash_int(ix, 1)), + mx_bits_to_01(mx_hash_int(ix, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec2 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + return vec3( + mx_bits_to_01(mx_hash_int(ix, iy, 0)), + mx_bits_to_01(mx_hash_int(ix, iy, 1)), + mx_bits_to_01(mx_hash_int(ix, iy, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec3 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + return vec3( + mx_bits_to_01(mx_hash_int(ix, iy, iz, 0)), + mx_bits_to_01(mx_hash_int(ix, iy, iz, 1)), + mx_bits_to_01(mx_hash_int(ix, iy, iz, 2)) + ); +} + +vec3 mx_cell_noise_vec3(vec4 p) +{ + int ix = mx_floor(p.x); + int iy = mx_floor(p.y); + int iz = mx_floor(p.z); + int iw = mx_floor(p.w); + return vec3( + mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 0)), + mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 1)), + mx_bits_to_01(mx_hash_int(ix, iy, iz, iw, 2)) + ); +} + +float mx_fractal_noise_float(vec3 p, int octaves, float lacunarity, float diminish) +{ + float result = 0.0; + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_float(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec3 mx_fractal_noise_vec3(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 result = vec3(0.0); + float amplitude = 1.0; + for (int i = 0; i < octaves; ++i) + { + result += amplitude * mx_perlin_noise_vec3(p); + amplitude *= diminish; + p *= lacunarity; + } + return result; +} + +vec2 mx_fractal_noise_vec2(vec3 p, int octaves, float lacunarity, float diminish) +{ + return vec2(mx_fractal_noise_float(p, octaves, lacunarity, diminish), + mx_fractal_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish)); +} + +vec4 mx_fractal_noise_vec4(vec3 p, int octaves, float lacunarity, float diminish) +{ + vec3 c = mx_fractal_noise_vec3(p, octaves, lacunarity, diminish); + float f = mx_fractal_noise_float(p+vec3(19, 193, 17), octaves, lacunarity, diminish); + return vec4(c, f); +} + +float mx_worley_distance(vec2 p, int x, int y, int xoff, int yoff, float jitter, int metric) +{ + vec3 tmp = mx_cell_noise_vec3(vec2(x+xoff, y+yoff)); + vec2 off = vec2(tmp.x, tmp.y); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + vec2 cellpos = vec2(float(x), float(y)) + off; + vec2 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y); // Manhattan distance + if (metric == 3) + return max(abs(diff.x), abs(diff.y)); // Chebyshev distance + // Either Euclidian or Distance^2 + return dot(diff, diff); +} + +float mx_worley_distance(vec3 p, int x, int y, int z, int xoff, int yoff, int zoff, float jitter, int metric) +{ + vec3 off = mx_cell_noise_vec3(vec3(x+xoff, y+yoff, z+zoff)); + + off -= 0.5f; + off *= jitter; + off += 0.5f; + + vec3 cellpos = vec3(float(x), float(y), float(z)) + off; + vec3 diff = cellpos - p; + if (metric == 2) + return abs(diff.x) + abs(diff.y) + abs(diff.z); // Manhattan distance + if (metric == 3) + return max(max(abs(diff.x), abs(diff.y)), abs(diff.z)); // Chebyshev distance + // Either Euclidian or Distance^2 + return dot(diff, diff); +} + +float mx_worley_noise_float(vec2 p, float jitter, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + float sqdist = 1e6f; // Some big number for jitter > 1 (not all GPUs may be IEEE) + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + sqdist = min(sqdist, dist); + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +} + +vec2 mx_worley_noise_vec2(vec2 p, float jitter, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec2 sqdist = vec2(1e6f, 1e6f); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +} + +vec3 mx_worley_noise_vec3(vec2 p, float jitter, int metric) +{ + int X, Y; + vec2 localpos = vec2(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + float dist = mx_worley_distance(localpos, x, y, X, Y, jitter, metric); + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +} + +float mx_worley_noise_float(vec3 p, float jitter, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + float sqdist = 1e6f; + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + sqdist = min(sqdist, dist); + } + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +} + +vec2 mx_worley_noise_vec2(vec3 p, float jitter, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec2 sqdist = vec2(1e6f, 1e6f); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + if (dist < sqdist.x) + { + sqdist.y = sqdist.x; + sqdist.x = dist; + } + else if (dist < sqdist.y) + { + sqdist.y = dist; + } + } + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +} + +vec3 mx_worley_noise_vec3(vec3 p, float jitter, int metric) +{ + int X, Y, Z; + vec3 localpos = vec3(mx_floorfrac(p.x, X), mx_floorfrac(p.y, Y), mx_floorfrac(p.z, Z)); + vec3 sqdist = vec3(1e6f, 1e6f, 1e6f); + for (int x = -1; x <= 1; ++x) + { + for (int y = -1; y <= 1; ++y) + { + for (int z = -1; z <= 1; ++z) + { + float dist = mx_worley_distance(localpos, x, y, z, X, Y, Z, jitter, metric); + if (dist < sqdist.x) + { + sqdist.z = sqdist.y; + sqdist.y = sqdist.x; + sqdist.x = dist; + } + else if (dist < sqdist.y) + { + sqdist.z = sqdist.y; + sqdist.y = dist; + } + else if (dist < sqdist.z) + { + sqdist.z = dist; + } + } + } + } + if (metric == 0) + sqdist = sqrt(sqdist); + return sqdist; +}` ); + +const includes = [ mx_noise ]; + +export const mx_perlin_noise_float = fn( 'float mx_perlin_noise_float( vec3 p )', includes ); +export const mx_cell_noise_float = fn( 'float mx_cell_noise_float( vec3 p )', includes ); +export const mx_worley_noise_float = fn( 'float mx_worley_noise_float( vec3 p, float jitter, int metric )', includes ); +export const mx_fractal_noise_float = fn( 'float mx_fractal_noise_float( vec3 p, int octaves, float lacunarity, float diminish )', includes ); diff --git a/examples/screenshots/webgl_nodes_materialx_noise.jpg b/examples/screenshots/webgl_nodes_materialx_noise.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c0e209cfbbb9522cd32eed46816de11bbb115e1c GIT binary patch literal 38436 zcmbTdcTiJb)HWKW35ax%8kHtZI!KLzbOGs|Nbev>2@r^afb=FHU8HyEozRgk9YXIN z6Oa&E`0{(-neU(b&%JkN&Yon>*)yx0{p_`#wQ@Iqw+5h4Q&Lp|+`9(=+{1kUcZ+~8 zfcy9U8~@Gs{~P#t|IGyW_;~n)1cZeDa}g0gAS5CtA|!l3`hb|^zk&Pqkd)-%e?R_r z*?j^$JOUCTLZbh<{r_pY>jY3f09@UR$Gb-fxKDWxkMiDK@4cTm843PJG@PLSJMP`b z!zUml!ihjiffE}K4<{@EPEy>Hfw+4Bd`beUr$Vm@skJSMo_Wv+e@@7Kz$RbaMXNJ` zWEZjW3??R_qkqi6$id0=oSR2fOkConq?E!NMI~hwRW)5beFH-yV-sr|TRVFPN2iZo z-aft%KmU*~p<&@)BO()%z9pxmeossPnU`NsSX5k6T2otB-_Y39+|u3C+t)wvdvIuS zYIa|31AaA8mI(b zd4om_A4#u#IG0Ne^%|K#?skhW=Dpgz{#IIWH1SXT4&a_Jju}lpFEN@c2nDw)XGCIo zB{P2brk_OgJj=WT__ELGF?_4%9-0@MBJ`Z*F%zem(=#7a3zavHrBB}v4t&I2Q(5#r z72QAU(REHcK{qifnl5n%uw8z%GQ9CmP$Bji_Gd>(>LzEdbIHO)lt7$X+?QB3(c%p)zQLK7`R;?%Gn&|_`;_{B`y3A zJho)^_q(cJPSaN8{PQbXm}6B`39_s!@qn*~oOMN0YHnD^b^4vTmVsVizGN#fRbZ1? z#t|jb%eWP-g>W~&y1oatDZb{D72EotS24B}z)Um{pdZ^Sby4+WIPDa&%sx&e@~!O~ zxe5A;RmaeJGfUfe%jKb7Z?o(pQ{7otlan`RVXw=xccQFi4(JvKg(FR#Mxn3Y!YXOz z$*x^nnJA{#M{Vr6wYY?`K4J*yN-OqYi zpt%da7We6O%KY~}n z=JH@d7D1qm@REORe0P9#Rp2A21jruQUKi5lRm#2=Q0fV}Wc!YCX+2l9Xy=prHqjG- z6%n*^9eMq)a<4W_U8i6UFLFQbBd2ywtn*K%%qd0Eh(D4VOIL<(nIsE^5sFl6zbdb! zvt0wjENU*(2pbbGVr|PcbI?}WT>ZsiuE?!dS`sFS0v-f<6XNUvz1+NIr}hB z)ee(Gh02+AYmM9vvpH^~{>hkPNeW6dgJ=|3vyaTiS>-c5(l0Yp|M8ltyCCdz<-xx7@i?*5bUY}fi>)5CoO z#QQCYCx#8#;VCoG4ifCPUSupgd8`f>OL9>Mrqa$Nr58|I=s;CX}Dj%wIk(JS}2)nFUWo`aBVzFli zX?&L~Q_DoXpROTPKsVO99$lNIVm1=`G4ib1Yy0_LfMlS`R7yFTMZ~z#sMD|WYA$6@ ztNQrXF6qEgp~5)RZrwxo$bP=SB;&xvaZXhjkLf>F~7ZcQ8-mRlrtJ^A#8t>iY77##l2V*!@@aTXK9edMo^BxJ_emo7XnNn^5g5b`)akD;C8M5I--r`zp`m_NqMVM8ZmN%(Q@9JNbOQRV5QvZT?tk#>R7FX0P_bL+Jwn zL|t2`55PcJmQ1oc3PS3I;-SswOl5Ar-2sFw?B2KU`RAy1PdW=J_jHhHv2}?j?w0F| zSZv4zM|D`T#iE!O>luWdr+>hGV&7Wbo(UCxgcta{Sxeb=PQCQ2{C;Hp?Awvr?8Kkl zv;pU!Cs7*H#+B?OA?x5rmN$zIaiq@AEl2o+TeBlqTKa6sUT zAP=#>OhHCuk-nURk4{mOpK6#X-qB5id1V!OfBb5Fu#xUdt1pc=$H_r=XjRP+?w87ChOW%g)4*XLy}oSa+CfTif$U5W}V# z|GovQuNslh7X+B-u^%xp>z(I7K8o*QwVL6U#xtQ+?!IO6OC4tbnXneCFN=G%-yc`I zXX(+W{LHS@Qz*BIul~nzqV*UPO-2KI{Ey#HLmp zSEck^$XA2n@!}tsC7i<@!bwsh>0WYd%<>n;;CEn59aRqQ^(`yD1NbX~)>*(uJHvMX zk}Cq>GI-mpzJtvqfHm1geBkpO?PrapG-A90^`(MpzBikqVdZJIOdoR73uRUM5m5vg zl%2XNKP!K={%h8IRA#ykkB$~%obUztd=f(PcA8K(-G4nQo#dP&3hUB|yRkZH&bd6t z9rQV|zL~OGKi5-Tx`5OUbXcvPR>^j&pRjv>E$!|Abv7Ru?*OAgJMGNUw+NxW);T-9 zzai%FFWD=Hk{Z_hDvQ6X(iQ@$#M*o$cXK!4%pBfz-`{L8vxaqqJa24J9~viBz}41(4R1$mZ-=TbZQFKYg5_HycUy^@^H5atk*b4FPW3(&_K#5iBiO_^?&aOb zz;3s%fI_{D@3Hp#cYqLU;{4(POR!gV_^z&D!moFcu7!%B^MNHrKQ0wJnWvWwc$S?J zir;>cmSHBw6|MDt&IjaKp#;KrxQ1r=7b!-CdP8o_*oncn(|oycitP3b<=Yl9{2c5Z zcJa9;MLl#_rL2PXnd9}Tqw*KFXqn0EVMmj1hWEMi7CXd+su9D@o<#{w_Qe&} z2H&s@Tzl41`i?gq&NEC;>_3}Oye!K7L7+cilKr0d;7ec8+XG>FDjpu`uB^wtj)fkp zq~3w*2K6(!*)s`mYMygViQQcEQ+kZp(k|WBK65^Jmn0`~+xD{&W7o(yQ`eV$0+mXd zk}(94_w^TXH+Tz_Ya8xC$B_y;uIhSiEuaBzuG6Z#5igZ9LAAl$oVwkRBN_eN-c+j4 zg^)|;neEhX=aM2!@{GWj%Z>^AjbPiDQ_5ew2T$tc+}w4Qv@mGk$&|Xb#$I#=5P&)C zJ5|T+LZ&jOC?<;I!u`oHnrIuANRODFGuHZVd0aJOQ3kTo-EgFa*5YFS3SBL#F%%c# z<%VUv%F~snyc*`b_wwqGi6h0Zbjb8ZR`0~o2V-VgP< z)q;iH0ahna1^Lf_q2j`KfGObK^PKJg2sh}Mo7K9aNka4EN;?U#hmHQm$5wOUrmTjD z+T`0dmn?4~p~xF*)ziqmh+&a_tT^bTaJRZDcgW=+Z&xJrI>qURA&ZoBcm0bTcWLh-vJx7T@azj!#z+|1jqd3hro@29k4>lxTg=Afd=^(;gw>-2_DiksvF+c@Ay_ zvPXzj=Z*3@d00)JZ}Kzi{H%@_VJQVzlnX1HY*$4WDJzyq3u1VZ&;11st-GOM6zPWd zz*nyvdI)uwlznem9Fa3|0VeF~4+~z8gj7u52(PQJ*zL?6AdTYlcWQSR@DN$V))^aN zTO?*l(ROItc7b)~Asu5_br-eBFyzWgqL~%xoF#9NTh*Dq|#2;TuH9_IWq5vtoe){n^AQ z_i#6NSNAs6b!mZz1Epq&^2%ACD?eNE0Crts#vR25&jwFVYtn7I(Pv}hXa}6Z+0eYvv9Cb1UAc>nzcJuTv`T=^cPS4u(vPzy+0TNS};N(ux-w z-DGMK&K{m}#t&VnG-4)Z%#PWuvwyJiu5?=$Z_>B6?2Tvjzvq3Q1Fv1EfUhy8T=@8g zc-IYK4jWoo!|BR3;aj!Q0?znoipAb#kzuC%W2AXd=lM3+q|9CG0}`3)`O%bs?njKsqd|Gj3!jv>6jlmlI4*8L48 zUNO!RaUEP5?v_O>OCRq5tUgqIoD?+_>b>HI6{XALeuWTsqt@UvwHkII+u*Uc_pLvRhxN-By=&926Affp(-7#P4`N~E^qR73 zi-P5pEOvix1o$#XC$DWX?9Yke$@rqfF|M2Aj2M(RJRDZ1RP|$VXz43-%E;+RMsrJmGqyzLp=^ck-0- z=aaODZsiA*sXi;7!WH$-*?LLhEg)R(z4l`jsjP*dM*{<@nD(iaH$nG#TVJ#m4m9la zKaCb!hI7y-%1rY=?p(5dQR=r%M8_*_4rDj(SNOZ19=~VwM9t@&v{3={jh|vZnrsZL zOLWYqVQG9_WB}ZhRbHPC_4;~tY(b{)m!qwqX15z@OZKygurl%@8b!Xur@4x9U z-4aGdT@-%663=1B#^V65K>y)u@?3|jMu+a7bt{!)qnJj|?rP>gCNtE%yUcpB>S|kq zgM_(xMsY-#Kqs~K_%b>s4^c1t0gEIwPAA{=Me-Xx%ZS-1(8r57wae=olebFH*ynC* z$#LItDwpWE-F`p+em46Mw%Og}p?UuFAdrY0){(=pvcEC6)*gKT+YW=hHc_=8%KKbA z>&VuBZoe#T7)a|tAB`2UvpEhi7gT0FD&tF&G1QX~N#a@Z;*vcqjaX&NhXnMgm++YLI~8*!gI zz^{u){(l0o6srdkJdv)b=5ZhnXW!f8#RP>9ZEkFTt~m*+g-W4bBv(3AkGlpko!~KP z1Pc2q52@|X?+0HA?7w}ayiwJcMZT^X1KSXwhiLWEr*mffGSeOla_p`hJ@GN)w}$5ju*X4kn7DP0{+vxFEsSB#qs_^q z@-{Q5d%@~KYD;KmoqC!^F9or?+otw2$uL#dwMgl&>1M-1VFI*g=8YvMyvA(bG5pt0 zAc@!OK6#b8(waRcW2A z!uRBjqfxd}$?H{PM(s}r$BoQwvbVYV23I7jDq#XBGB>fCw~W`Ox~ZcfkyC=6 z(Z;32Q}hD8ccxj+s>}DZ+Ae&?8tsYMM}pT~2YSJDP{WL#Bn9LKm^eo1N({x?&cA(> zf<%mkMhh-3MTH~e)sTZbPZK`Hm`K|8m1TpG8J#dI`;^&ORpq>1$9x{v;qRoC=5UrB_v zNvu1Y3-qxPCc0{Apj>0BnMC!g`~4&kO?XWCbdbb4vvrP z&i`~G8;?Ruhp#=Hz+~S4#Q+RYN!tR&fKn&lynZ?f9p}WrxU{uM`$XxKX7TC=yJ6CP zwhO{<%Q!Oo^@$9=P3Psu9|Z9H@kpr-yaN<^0m+MvPli^#FCflcK;ZOL_H|W- zfaoAcu($g%)x0dPQ{1w{&=*(j$3XI`XGt0}(Vlp9gPDeFP<8Ab0HllNs}VT(1rqrW zW`GoQK>7p50LyBB!}NbOjLd(ueh)~ba)u{C37W6p_}1cGgs{pb@9j`(f72cf^$n5r zMZdp|l2O0bhrW&7)vrxi?3$&|cW%k$(Bt80{n176^?Zcpu7Cf4fp!4UtX)D=-|eT+w{n2Q!Owf8gPnt8rsQ* z|0bOqsEJWln37>wYgg#GVy$L2q;9KO6fcnq6&AHLdUSd z=UlKaZ^Yop!+B-5D_!Lu%O<3s`d_~=3G9m8-~+tAjI$U_sT1v>z41nEulC1LLO}hj zycp+lhhIiA2%p?_b5(;=Hs(WMvLESEYgy1)Dfg?_!`wVY;tq+`XF1Vu8x8A$tL-~L z49FUU2<`_lL*&(WSn+3{s{S)~n)Eq6DX+{6_Ik!m`&2L91!5r-t~311dZ=F9(;t|= z+E8>u9Wnr~9S8+(K1!U`*&BsS9Hfi2f)M|Fmgt51f49C_qB8fMzCzuHn>R=BKgMzlWEb;3Ze%7o|RQEk9u_u z+0eh0sqqb}Z_{)X>FE$P`)T%;@$CoaJ>jYiwq239wc0$4x)=MOr`o?abGloq$5-uh zQmed)H&wrxwIqEWH88^k;UOa6Ry$yr7-<>5H|MWbNG3U)>HS=hiD!&yA>^M`f#%4y z7Fz1I@`Wgi=TukA_VgH?(Dg#jlTEymssR2GYn|zW=5;$`dmeAAzz9@0Ive@7+x>In zDt+Ns3qRpS(?!#M%rf5@JCE@%`O?&tk@E5JaZAEQmZJ5jjsil*k0Y)HZ?rH3$cuhBX$QcW(LD`zo0AJ^K>x#po$MGch>p8j zGtUWwSK3k%YGjvO{(Lo%7om6^0vC^7c4pDuGzm*}zka*#d@Tx6laWFzxjPy^XfDDjd8T((B34s*|{sxMrc)6JJC82XMLn{*Xm=a^twBZqZBao z#=Ou;8*y;;CTZ}YM{1)HS$hxrPsy~AUqnLv+Ycwo<6fxo>ghx!)%Y|gqa?5-3P>$< z{B4mpzeG=}99>2ah_t9CeI?Mh*APL5Zsb*^9ZX-@b%;jrA(d#=R5&2Q?6DG;8}3=F zxgX+c4G#RqKXCBuR6JIcE*hJ9pK)jTwzk)L&X%mb(pXc8Y^TR5-8SS{x0T zj-4^v{2L8Y=%v>8@Jv4lic8s-7YrmHge{&Kr+_074-^8gQH~0WTF($mGQq@bEUO!-+rc~11rtn^w|EDc-zl^1@W?r` zTQM|*0d3VX1^-Rc{l4T$N_K2+U${_?2;wxtc<7q50_mxwA6q6bXvbT#6LzufanHZ_ zn1h5@wmEM!VHr&^?nl*2udxZ9c6N}V+@#NS519#eulth>NMkTvDBfNeKK215uTPEw zxp{!dj#?kSRoALbSy58mi6mxM`K^@}B23VI`f*yXCSezbd<#N^Z-yTSAkTWU1#Sz2 zsP}`Io2SGe6?L}t6K+S7J8Z1GF6Qb_p%M%_fITHAQfbg9AWMhLVaKx>mktT2U<0zR zj-qtITs40QQ82O?t8J66q$;P+C+@?rulg-f=DKT@=!SO<7>DJ>3>KO@b^ox6bvEt@dLs;IgVe{! z+UT!ngmH*p!$-2g-!k8xZdmu5a6Wk-*-h&f?equzv3lDRs%pTb!ce9!6WvV3tys{$?ld4*g%MQL>Xy14&zyH>0??&lm@(I0L5{QHy zm&9CYgEkp@Oo+6v<(jn!UJ2ds-jrofw4eD)z54ex|6$vlWZqlIHcIv2<&oCouATh+ z!K9SYXM>%Czl#+sC~j;*6s%lq_eb-heJY9tR`N)2@rlcAzXW<0Ybvk{7V|NQV6y01 zvAsEzbu+J%v%+Clfs;=)c9ij#Nafr2_j1sowk8?LCP78D3H8kC?$u|os5*4xZT68{ z6f={{IhuAsN=I*EB4zeVtpW6`SUoL*c1qRc!EwLnp)?IgDrd{jSn*1OtWFk1cYIq; z?Y11^=(#sOlKJOy-k7tp%d1SZDH<8%GS{BsC<;Zp+yQ*X^496#bXn`)tzR$!K4J{* zc$lYTmY6S};lP;*gPk8%NwcMleL-!hZXyHJksp3ef5OEKt`AAZr{Tj|DN{FsWzFuzS>0r+!AX zigdWb+-zwf53yuqgjilRyFW?Ao+|z>-?{#qXkXk&>EOSAyh9Ci1H)Dh-Ld>?14WpC z-a9~b)v@}u+99hLh6&|2^}4nJx$+%OZdo&02rsNJRV*(ULB)^TIS$162Xbm)$8o6ZO>EUhT*xZj4UoZG8zd@&2xY#1#x zv=u}C)8UFd{6^X~?=T7CdEzIU1=FUB+FDTMO2W}xl%Xb@M@l+eoE$GA;xFm!mZ3(d z#y*cV7y*E)dc@SsNjK6yi2w{jWN51$1f5g^4ontlw)r6zo?Kf7BI^QPX&+*duQrg?p{Jwk{ zOHn#-QQeoc)Vio=fFkdPlLmDI34^#WKGq(mS1k=(y-ZCc&95MXg3$=wWdW zGrAF|+-DW&GiMN{VbDLU6Yn(f`e6lop#wVso98%BeWiVTF_}!Fa8~6fXgGyl$(J(1 z?8KI9`1&0H??Cvitc)vTx-%09j%7m04PaD@IsSfj=P)D^ugDqdFs0?vUe5XuSCiE? z{(F3}N(5>(+brW$am#yhN`M^%D)fwJ?Zn}H5iAQ8iRzORnQ6244Rm$CO>#iDSg$mx zWMg-TQwWwId}^-x3>;Y=zpL_w_qeSJ^ly`G&+Y)9FLOZO4V=js)yv?^cL1VOkS0_* z&jJy&D94PkM*i(@Ov$F63SwS4Waa$R)(@#S?Qd3BdDz`vGPY4g`c!9Xl z!DyF4Rq7`bN9KDxV=U2eqJ)wBYjlYA*A_yZV&qCXGG%C?+k$gg+-@%%(Lzukj#i$( zf!C^y?)Y^CeQYh1slJ?iz6Dz=1lNzXB16`K(#jn>9@noPV3V| z9l!gjN_}tZSLiv;vLqQz%#8yIRXUY4Egk$k<`qE=V@cvRl`yDv0YXfzA?mGEV>FcW zg{V8lusg$a#?Rq9=s2 zUy5z&JN~}nQTro)^Ui>U}i2U3XtlC$4BY+;^MwOX!G$DtVycs(^sP4 zr&j`}l_of}7tbrF+@t8AC;TPmPn~xx`<$S}ifxBwq1bJk!|MHqkLsSYy~qX+|_|nx(XFR^fJ6-npn&!jy zWctX(0kn!2b;h`D3e=EpHp}D1BDZFd)1yZQO-a!tD^d)q4C!A&-|aMh9+!3fQ&UhX#?WNu-$)k5Lh;q=`G{$SyLl(xJl6WkM&7{ zRZ9XyCaj2z^~;R!(n%0OLEm|%ke27-SD=v0Oyge$(3gMC8&^REXalP?7z@xrJ81pm z##k$B)LI;w5hQOzvmOTzPqGMv$HFW_XRE5#JeK}^z#HjB_ z)wthByd_D&2wJyZdjhkiEuPCX?f%L7Zs7}e>!T_JSHCcJ1dh~M_U-2Xx#F}+BExtE z?p0SG#{+kIvxr+-r65K7?F}f3YtkJJnA<+je9+G_;X)ml$+0|yGv8Q7^!a|0C|)}E@YNY+}Cs68+0@*T;gXHU!5GJ%tt?LZ$Q>aEHS;pP4^y2 zG!VDYv$@)rgDW^z)1#FK+`m{z;%XXhh@ z7n*NpxibyouK9zez>j1!))-)pf5R<+D8ZQ!$Xxd-v5V-jc(-%_6YuxQ0CNK-h)W%vXdLRlST-GWP`y$o<*_zouN|{IXX=o+= zMZtrwRITW3WtuuNEr;858Quy=MVkc5zIV|3j-$BQ3{ccn$q= z$&VY`+iIxsHJ9TZfX)lddcX({uWD0)+OCi0SO$|HKX_s;)&Qs(f1G7B%=)fGpS{WY z-RQH4)1m=bl!?F*ZWRFwitAW?^XrMXIa|*PThp~qR{qc1g2|nEgdIpISylHXlPR(U+W?4RDVqB)?CJRRS-1B8QYDwxogw?Do2+Y~k&-PD}^ zSRC^EH>zA^m?<$jGVMHj)~?d|PMT!BSFd3pH@wKJ5~_Rcc=HTHzNUU_GSE5e=vuB` zu-H&#?@_MqH8D;$B1HC6*++Z3ri#c-kPuLn-D~Bn*ZbPb@Fwjajo`Fpc*eo;WnQO? zjBKIk6Q-BgR;SD5uV@c*GHKvL$AF%|NYM38!D#zXG?m?P))%_{8c`BiK)KCAi-8h2 z_K0jJg8jj@DvP3*<+da9%VLX%*|QVna^&@`LRK^%G5T62Te=24EcTuHcYsJ%YV6P* zfM=%{YBvo$nOJ=j!s5(C8&JK;(fV0u;^&`QqTxO}gY8h4>~Gm$>&i74@OQ-sEP6w0 zJfA#B|EN_ptn60_%+Yhz@vmf71(%BE@Aa&EyItWHW z+0V0g zrBwgSk4Q(+ky_j!>pH}oQYdM9WP0bmNcswq%=kBugE+k$XSNtqEIBYHpoyqd?xX0! z{6Po3S)b$jOYQI6fDb{*`{M?XZ+g+8~D_tYiJZ*%x!~j;7?~*t#Y8S*)utx zo@b)7*PkCl!T&K5jUkgADZqwV? zHZ}0p=~7D}xDtp_4e|i0Fj;?Q%{*b+`O`tb?v;@upVRR6ucvLDN{=4!G$FQiHKbW^ zv>&b;m4FcmKVIC7BZT1fuGSddJiP-@{N1gK9T>o6c;-qhjI;9$HrYcCf?W$q!@Zvg z7d(eHpZnR&lza7VgB;w$hBtuW{zS*pKd=Kn>F!}Sx*JjI_^7%dKJiq<C680PMR<$lwm z+zTf>(3SBIN-Hz#yUlg=WqXjV?s?2+8R=?gULLCO(69Z>)Ff?d6+Z|cY6wT|#(3QU zSRmuQSQ2DT#0{H2{Ncug=V^!Jx#b$U6;*I=A zaeY(bvsDF$0J#DX^$i3W*9(gU5g{%HVp9fQcVH1S9I-pURVGdZwfLJZDJ+!nl4CcM z6`s5^v$fJvP$?7X>Ht7m-{2x7N}{ipQ1GRIl9G1;%F(aQTndbAaE+{wGtN*OW8)V zUfRBatIAF0ZP__(2d1iQiTih;>eqpF@K4(h+uh24E;IX~GadHr*a0|m)g8b-=L;5y z3CVZ-<>Ubg-{8zyYuEX$zAc`eTJcmWD%-d8GNG3`I%VugxxOO~FgH`NYuz(Kf34YG z8I*kh1d74PAl9#Dq0*2zme~Y+2^_G;6TcIu$wX?6eein{z<5wUCOR%NAr=GPto$Jg zj&n#K2qg_{e4R?_j(@=v-1AI^z&J#a{R^)MH`$m9VZpc9zg_tonC-E| zhOh}HPPIjx0u#hfh2gLJ{P@>dw45d_sgN}4lSk6$cjtU(z(w%JYL6=n{pA-m!f1H~ zv5!tcO9&M0sNf16r`#)t3E}aZEOKqr?UX8~u*L9ofn#daE|#+DC=ddM*#JV@Xt#5@APfvu)C;VI9Sf~%h5gFGyum)g z*lRUKYCJ>eJL}AeUr6wBN2sf&G`DCjy{G;}TreMpTen1PMu;yaH)tIU< zlbg}oDDi6lPuE8_neu7|!v~rVPV@LX_e2gYScPk&nNx;&T1I`}|23RJLoo82&*<3W@1+NYheC3V8Sy%a@m_ajY{Dua5 zL;gi%vFZk`30kv?=GEy_WbJ41oJcyAjElNLj9zmuyl%vrRZq*AV>}+Xl6HM5*2WUe!<)kcb!`bC zr_+G3+bQCmY|0)^bz^OBc^W{fJ;eqC3V`n!=G+s>pHZr(aU7_w*% zl)$s$p-?TYdp(;hF#RaCbPYOf#}ebd^^D?mqY6&Ge(ux7kis(xzz2F-#FDP>OR6Nb z0S%-zIuo^0zrnj2)#N!8OF&XmyHEJI<7_eT? zVStMM!mt#YK@8EgsGxf94QcP@xjGF`(l1jt?5IWr*>dT93N_B|-ctVtKS1PYdYRGr zI0?@AbWp`>`+YD47PNm=kR4YE1-a^KA&*Co;v1S>>4))Diq|izYP zA&Evw-x53e6WkCYzk@iiQ@FT>=y)7i)f0i5+ED&_^Sayt5weG+`19}Bb55&cvHrZsw9ZjffX0c+ znO=PCDx{RhjJDA>Ao*3zr-E)emuhJzzO8?vEs@j6Vyq}6T)nlX<~9#(Fz3}c@xoQ$ z1z+2te!?++f=OGbEw|U}CLVSY@ymgZ<7#P%lf5gLIoVUM@{>96VaXDX>Xq;!r(RuH zhFZ>U2S4|^{#>vhLGojPxr}AHy4ZqB&_Y6=0oX3dMZ0CEw{AklRg~i$2&){J*s8}? zX_`&UppTC309w7*-~m`2$s)%0NWAfjP$Obds~(yq!;3CF%c*Zw?gcXlFzKOaT0+D( z`TI9ujMr_oH5{YlqYUP|Y3S=qOt@2OSJV2xE5jk}KCEW%UxIRXWThIJ|Ym60V(My_t) zE$*j?)9uq9?^FTm8%@6_eU(so<-=jhmfLkWCYX%)v%=3=X^EWxGjPdc2xN^l*9L1gVM9pQ)fy_Zw(@X zh&VP_fwR^}GEpzx} zCOp=b=sM&F1}Jc&9e+!7S_#!cY3vCsXDzp8?)+*lv9uZYf6Eu~!xQ{iG|ht_;2V-Y zni@z-8Bd>}bHO+*lCAipnl2Z|!d^;Z8E4~AlrgaNTD0%De)NkKWvF3{w=+#rGg)us zGd^W&-C>V2;~Yv@*V}WB)J|O-^ElsY@H&PhjlIkQg`WbIqPtR z39lUd!yxADU(*2Mdv~iG2Fd6JI{OIz26-*xVMx1A!Y)Rs=DuVlwo>k05TgP1EJaiG+gr z%3jVi#ko2054fhd(nr(zwO-HRc9=Ar1~FK%mo3zBEuQo<&k^ApEp`~;c5DMUYOT$b z{yz4I1h4M&0fXe={GusyN;vAezpa=^Qu1So_vUik%*ZllHI`P{`%W& z-D;yv*;J1N3_BIMn@E0<(#cOBFs|2K-f^n@($RCdBPa33_)77b?*?xM%Y4Jah$9KU z2KTu-*{OqN)p`f;i)A%mnqBlk8=iR!(Pn5V964JFHrr9r(0HpG?s)jDQdFMbg0-jQ zW=HtByvF?3X4J`#wwbcMc{(Pk5?@w59^}|wyHxEt>kFi%by6NSz)GLXYN5Sa0_de; zDrd4+171G`in_cjv6a<3wqsykOIT?e+^`Mq?=Ibk=Pg~xRaSrJ);*n?arp?Y2lhIX zaj84!JjA$iW|K*+nEtNoC*~=b%FNmEPrYXOe|sOQj-?h%#xHhNZCV= z$E?`9Vm2_whJ|E#@#Gc9%Z{2a0=RQ=;8lbg21&zoBZ!l5* z--ozb43&8U<dY*AU}bD~JUMtXs-b<}PB6J*sf*`_O7pE!(JMq~Z3LP9-2;Wk7dbvI8H zzVjsbgR2^`De$MR84bk99gobftZsdyDAlvq(BtFl2#wxpqacO4UvZz<{T>B4P z-wP}KA1u+0TF3ySKy=~kx#Yi(v>kCQC9jL}BXji&1fKfnU&_0hB|hF{GEJg1Fp6Z3 z6*pXMo(eBu7K1qy_`0@2$JH?H8SphicWa;* z+ilv6cO&A>(uvjEF0g(K11w>H3F}6AT)(jT9k@TK#lUrS{Bx%xr zaXVW~|t;WUlx`)P9fux3|3Fm&`i=nX@wH>rg}8!Zql$ zxewy-r>a<~f8mpCjN^k~N9i0qSeJ^}lNR>b*v<{FP0%sPZf7BCcNzg&@D=QM?o>T| z{nGf&gF8T+`yOvuidxC8x@Ttd#{^TQe$OXq=tuvDqqA^p@_pMl z7KjQ6NSD&mjdZtwgrh?mM(1b&>6kQ(lJ4&Aj?qZ7QPLYZ^84=h{sGU9W6$p0_jRAw z=R7Zu&A7 zGJfZ=U~_8pN9n9?!$rpl&( z&|6Lo?95v_K_6)^4>RC8Jx4SvZd+dAh3$)fxS66Fj5ubD^>SIHI^+0ncRWO7BVKT0 zfrggWVHOVx@5F_5DGeGNZ!PWuJ-XJLn$|V`xiCtxl$vwZw%=NmhOyeP2T_cUf214k8V30$GT@FMlhrg5?1-c!-uSR zE(T*@ASS+Nip9ir$vg|85aZ}aQ59&jD#-{4%}Wp>#TfH>3?$dok%_4o4ZTB^IUSqE zujb5+d40!Y zv{hkEN9VR%z%5Z9*hD_yBi?FtE*sJ7@N2V813JMa*~26nKUWDHSM41W7JvNuSSZIp z##-*+kJs4sCa_nyi_eb&rJnoXgBpjav|MFb!7QgQIqQ^{1c;}?A8C*76NE!o$;e^@ zuF0aR$Kmx+q#fq{u+6q+e~ROd)PSz=SyN{sE|5oLbpaaStQOouH|4Yzor;hlAWtAr z4B%_}aRr%;HwSUAWU5UOC|ut;^$zck6+Tkwnx{V3q7$9c%jo8BV!?yZ|6mzj9wkqd za&n#}j;e~#!`JCTAB!8XA2{Jgf<+<&j-TH-%`Uw>?wI}|6!1H(V*TAxf(tgAg;STtX;^WPkhYTTqB_4 zq=u|}ywlkR-IVigK(kxGu0;3~OL(6+UQ1((b)x@3LVXF0#0+eh)1LjxQcSObkN5OR z7zLDTxu@qgTIbv_L5l`CEfe#=v7)j}C?ZRT{TKH!=Hh+rWpXUxi6O50?V{4& zGH%+*P`OU!$&W;3yiS@O7w;g8%wq;0PA#7K0BX52l&IOaHzSGfNTLdwG7;U|#@W=V zeCn+DdXlH2cvW(hwi=t#Urf36l{wh3LLtxrlEm(8>8nRGX@2=AStwSQkfZ^_z zsx(HI@6Df=`H%KRy5B6WWR{IFyp5Im(M7=fYS`6o&3oIlSZ7&VQ;fHtrjfC63$4pH zhx6sUPcy_I1mbeB?zyD1v;57rmAw-dn%`ED_iILOZw2Ha?e2~SeHe=!EGrBRDWW5m zn^xCar{LPwolBc8ii41hr>!@=wnKhX*e6Z8|Cl& z#tuLt6#vVKYWwtAm`k19Gb5Mj@)v)Dj2l>_figo`LUTU(*$wmiXb!WQPjR~;lUqJw zMDfAvT0*~*d_LLzlHxI=;*g*%mcwhAPBeku0GZt?_WE)!CE5TCs9@;u2}^b4pq^aR zF{2CQDt8zb{X8Xhz)yBC?cy5Osfw;La&WsC{gmeO=fo*(Aiw^MXnJqQC%hE3==c?? z75wFk=;HUonOthSSOcVB|8#XEB$oa(pg6D>-Db?#tUv2FQc*)SA~OIXL)jcnmZ_?9 zJ0av&U@l7!clp~YMu4VlbtpxP>KJu52Rwj&c+m+@T6~JiWF_^Mli}u4LTv=3gCh+Y z0HliE`zJp+K@o=m1*c1;enN}Ta`83MEye-@Lrs~F8A}{2Y z>9zw`px5*gxZCYW>WqroxNCq5HtR2(saO6*SbUlZF?oI|oNSIHn$|-#AP!a9^DA=6 z0mbEyVEt+DT-{*X9TyiO$T+^lYIM@a7kxTb(LQ zr6I|E$OcdJUvdk``pM=mK3`QW{f06qhU3MLzlId(T1Z7*eFFHhmZTHaOJyVzG`8Ow&{YlmRvI{Y)!;jZm!4Gf zGG@DbvB>1bvt<~3G3?gMprP70vi z>eN|X76?-BtvOiKFgUugy4GE5%l$?NU=pdpc-6AC9hbSycSgjTuB_#<+uF^d8#?@( zd3so*tf})QEu`jj)L6tl#QE2^zT?q*pF*S@DQT6@^{z0Y^dh@`i?!zNYhb9~l}XH9 z8BITbhxFEgeV~4s1X&7$plW)vk6h(`2-$>6OI&xTA=;Jwr`y>x@Kq&FPAEKl8V{YD zu+-tCpltnTB|EJGM*lk7zB;og@jD&e& z4y@AV!Dg%*v3%p0g@k=-R4nY=;S^oUxe^4D-`iXe*wHkwx9N>WpT;)_+PUMk&MNGlioKkzC0|lw72o1;6bdfAl z^n}p#@RFJiPkV4j@0ySJ`smili^|@QW zL@rYTGPao;CEiz+8GxTUJ($b?IV(H#oVjlj$^?FqrGpexkTR~Y_^Gy~%=MFy0A`6i zj7dG=RhVwp<89r8oMdu7=Bid-EtU*z`jk&7J%DO>@>;3z=Gd7hRXZsZAbSk*&-~=j z!|FebezZw3!wC67*s8X~KX1hpplc~PwmluvO9VB}G^ePXIu=u4Ue50KMR39}oBGa= zdIe^b&3k}K)bDvW?YK-Pbe<2I(G_zqT-gyWB}Jn-?fTSyk!m6Xn|lw^N=FL&>D5ir zh42=QNhbwDK*6jPQO$hmoNMG|ct{|cSzgxa{BKriZC%H zJP$fCZi}6{I4w8>X3)Inr(%`k($!m*d&&Jy?j8OwZR(%6uRwZ*LTU>0JKytPi(~|1 zcH58!(AaS`+rlY_{FF9iIvh zIm=gVKdvi1)!EWpF)alYS^hJTL?&h#?pPu&nxNq&`iBOCYLpqxsdzT z*G3%L!p0*M%yplc0aHgWKRO#89kQwA(cCO zp1zM7iTkTTI4);44OF7``79fL$1f(ns@Z1xGAZSvpCI4!Cd^)FspUh|S2-F%+MrD- ze$2`IptbK>vo=GOw`7Ynk!?ld21C_4e8P>JP_DKgh+=nJqpR+ap^)!tmc z-UfAJfTToAR3ukq#lLHLDm~>h&1(ruKWpiTh4krnVYR;BhD6sP2DEpOej8yhq-{)Q<@8sh+oN@MkWizfnUc5vX4PdW2T<>AH$ zTX3TtpQTJ_zy0{NQ#M`i=Sft^CtTl$G`h21 zP;%<(E+ahF`|Xfnzu^rjL)d&%iSP{T-e%Pt*i+KMztQw_%$ol&klajbOSw22z4|w- zU;F)S$4uS3-{^vgSKS`Ik4K>JWZpf_9U74FIu@YQGIU~Qt&6d8f&GN9kdu*6CD#0R zotHl%Q&06S8@#r3bFrTEIM1sCSY>wUAGaq1SPz4$->3Woj!w{d($-lc$C-jrA zLF_~|v#9y=8sh)i^GO(z&k$p}Hh*k%4-9WxC^K4b0Kol5UW>8rU34TAF$l>S<(T|- zAtq1ev<4_Fb-xd^13!Q8MwmQkHUl{m9Yy=_q%m>4$r#lm`?VeOYQ6W&e`Sg5D(_E- zlYJ+@`WGOxCU{X@F(LL>j)pt+%Yv&&CtY8gIdeyB<{q98*hcUgvztWR>Eo>lUU@O8Sr)6n z>F^N=hCSguobju7T8RPkQ`~42K)5@&M*(J&?2j(``2%A%!V&SCtL|0iI(h6xE|VB( zs5@<*g;NzW(mQPxbL~rp(pJ00_svrziz#=((k8>vR^kiVUG&yEDEma!bBmhTwRg!! z5VW+jUCt*}e*4+>)5pMa$ESr#ks{eyajmG=r{bK4GEGRMm)gtJ?Jx`cys|A*o%rba zoAZ8`0_INOl#15+-%57qO}T7^+|@^jnNEoQz?9mqt%Wns@R9z&eyJ}Fub;>7?r5u* z$he%yYCw1&2$U0Xg(fM_%Rr24zIf;b&KNzt9l&l#2gK$6yLcJrCl#o?(vA1l9IX|# zt?l?yqCWNRx?bXGX#RS%^=fsu&VSIY=gsei@JL{mL>irM@ z?hC7jp41OE6=YwH8yPcMVp;gB=gGL0vH=za&Q;h7HJS6ICyqfF&qnEyQRkU#Q>aed zkiNh-=*Dfp=fI}%_U8$3?l{4YHHmlOL0hK0!MHPu z>L@NFRUq6FG&IDv;u&r?xuehW+h?znLw37#+gESM_(&|{+8%;JSv{;yhQ3(~;GfjY z`T~`87gg0`*QOiq0A%okhGBA>; zkG44$Dgr^yMe;{MNjnJ8b!q*vmd&n*ipnI*wS%B$W6H|j3Lpx;;m(W{P9W1$XXy!k zEgH;R6NPB88dBI-D#sm6wm}BVeV>jdj(*d0Gra#bCBhmsu>a#jzdL>E8$w5zWEIMpp6t)xBISNHGe}DA)g1zJ*>s2b z*-7wse!6^Hm=u&Qi`|-WcxK2?7(wd$eGU+xYyzw2cb_!od!6WvRp{GB&88g_>$qwF zA^W6syP}|Ox01?gvCyHhMF7GY&<~6|y|T)QqzuGy=S$#Dbd3_@?0YL}Q_i~|h2)0h zNTsZcsfA3uyf6;@eCGZs6-a;e6hhw|TzUJ1|4^#7#9Qz<7lEo3Sohx+1Ns2C2kh;ZRqA2=`2Qr5 z?Nf?reJF2&EH+Dr{DFXUD3dLf$so4N)@uCIq#>eH?A!T={4k<@|6@gajD=IJxaS2oiyz=ef`LZ#8Q+cUO*(4(vXLi>pVBEv`FfucQ zYy_*xyX0@Xi99&F+tvg{M{}Hyyyf6T@55)20$t=txuHx)zDn_7O{L5BA!#q3@`UkB zSd;hyO9$sHOTf>4)*hG6{4wyTW=cGC!1o%;@nF@D$YiFy}GC&7QTq z6H1WFQujlNyA~%XljsweppaQ@;;{6)8i~T>%4xm_RqyiWp~EY)WN=RDXEz(Pvte+X z!e6BC2C*SAG4glxrpgYfrcXZWnt(<-1oQsG&}m6l$8-Zvb+B#bUZqp)MvH-!oSVj> zh$U!&Z|r(JP=&$yckZe$nhAHOH zw!m`Wwen+BpbdC6XE1O%2U8SJ6!N_hE>jMIAj#O+lvot4dwCRzLcBG?5}hU+nAyal zTs#Cs(|s!*H6Iftw$Mygy-pB1Cj(04XN%y!iEA9SA~ab!x=C2o`}>L^A9Hqug8P4++ z=N)=9)&2kYY_cepuX#mR=#LNL+ifnlEhG`@iN&Onf0zpmM?DP3)a9CLW5D!+OrQ1I z$uUl#!An1EL{40X5KXZ7XH=jRaw>bUkB0Q1DK%JuO*iuUbm_LuNBQDf@z$0in{*`J zi5yy;fBTq#_P_ef2V$XZ?=X_c+(-`dls@9tS;vXkkMGza0Npv(*mx!C>1Qj#f}*92 zm(vSkc*D?Dool|wLWv(HM2yKuH_50o>CVi-T-1{E?=@TDbc(w8$)LJ#nv&Ba1d`_F z4OOIY__R_%qbMH={&3!mMWbxDXE-wFKE?KYDGij=5mEU+-Ut-^+;|4 zed(9Pfah6hR;^G&go;_8@Hva0!t|_H6=rb#g=n5$A?g*}WRX8v(MCm{@J!do6GH@A7Jo{bhizxXyw}#kp zlWo2F#G9_G{l7Q2$q_O6o^JZgzt_iZbdY`6ZiBX@O;$VE;W+T_NPr6OfoB3-PTS*w8bp~V)Jw+R-Tun<|jMzhs`RwC)RqVM#L9zJ-?&A&Lv9tLoDkM zJ22UHy0?Ag$j_y~@MwcPL%l&lB#u>)OvN`=L41omJy#4QI&Pc03@^nh;sOd=F45qg@M*XI zy`&%S(wV4`gTMRrN?3aJK~&fY;h7;V@g|+1+y#vpr`$e2?&^mKJ||2lQvR&xiDOAz zNS%K_yo$rRqo%no%;wDT*#X^fi(DM$f)Kpk>Q@(GJ8F0l;6(>8AeSOJ{g_G*>Wc~yi(=%M z;RCUspG3SQ^(~LzpMLoV{7fNxxfyCqxOmx(i*ojRfq06ALEjol;aq3gy8UTMvUFk7 z`b-u%@^2eUOsd3-Rjv3lvbz6C2np`bLI)o-2nL^YDE+C94(RuFg0X6Nyj%IYEW&q0<=yh+HMBK}NyOouNPJZOUYjE0AZ%AW>kNDF2jMBr}KD2Z>W0paB%K}<2+ zeg42X%-uI*9?R*R$$o*Bh{=s?2&-~F-23hIQa6+h5=!Mr z`;nW~V(&;C2~}rJE)Fm5%&M_ncd|Gv_CK!Nt}bW)9X|;EWF>~hm*DVMC<#z(eb4sP z&wlTLx-4p^TLB67Ukp9bb%lLnN^`_Ip0=P=>^a|Ykh_gjTW~5JMG#T!r3{bnwX~VM z^O7*=5Xygon!FVMV2D!bY5O+a!47+*T&;?Sq3T8{K?Ehb_4EmZH-8f*d`{U^{lA)z zRe-Y{@3SO=pFVcSH5ky4{5|kFNsf$77*|hOB%@6y`#tD6tI+-N6@#==Z~|3NLc11# zoWFWMkQxL$c_LVX&AUIU5$t~pJ{oz`?ve(P2>6vPv@iA}DK4NNb`#;Qj(yNYjwY<4 zIDSF=tk^}q&GR#LgBX5An*eK!V8d!_+DWmhK$Wn+#bNwM>`a<*XHGe;ia`U} z#&2T;P9~&!4e{flE^G}@X2b+}_XCH6PMGGC1?ej2m*0Eq7-wdW)rs2R}-S5O%Y#`NrCd4Q~r6v0ZIqYb|*(x*5SuC6jD89?@ zsi-`~>yZRnBKw~@p9_E_9@e%0TLiCU(RYs@`cH!r#Eglsuw1uF5H2dWuCpbXp=EZ@ zVf#2$j!4peXit!(eV$s7E-1mvlQ)YA$A<>}Y#%{F(+HgG?z>)E`zJG$KkZ~{jQN3j z5}^)<9>|du`^J8Vg-Lake6B2?t`m`x>ll&pcr-Mikz@q@({Dz{T;Q&=@1MS`tA&aM zc013oDFl-#?bFOg27b^$2LcGw{AxivV>~5{S#$7_8R%N*mk(|>UJAG2qv~7amPfuu zu3ne@8+07dR|wY!@<>LzbUtOpkrLaw(@#?{Eh~|=1WU$saHBR&m-Y96le9Lchzj=O z8I!ri&Le6X7AuozQS(9tvu!c$oAO^qqm5vU*((tmlrD*mh4U%5k%`5ALc5qNl{9{V z0zDHM(H`7%MXaJtnTI}VC+$}ps9J2+miibd|258_@QLs{>975wa8{(2c6&Wyd$PD| z+1a})irermeF36<+AKPU&Xo z==$AZdgDXxmG6}pfk4#al7;#6s>zW;o1XFZn&$S@6M`aOU6zn8yj+unuC?LkD(TN# zJiEF0N;T^*D69e#oQH zdIJ3Li#!DdzH;krq1$bUPi@R?Hf#4I0$zdI2dEjEP~+a{FE29;aM542i#NbNxlEfjWf{U-6R%9* zUCfh@IDWvYMB9Ggv73=k#OPcAj;Bw}2!{eMVUoyG(R|`u&-j=I;%SKt$;y9g7Q{}y!MFEU8UvKXF zkFmR)xVD_WN8es*k!}Py;$&?7z{^VD3v8)OkxPAS?0dKvsg7F%93pB-qU^|a-5or; zb_=Aez5x+kcz6A~TZ`qig1VyX$cm0((U+5cXPmrZqkN5@5P55UTByi^2R1~jRtZq> z07y8pNiUfL(GiO$ajQKpQ@6WBfZjCP(YIv-cxja1TOWrX-)y0=>bm0Kiic+~c1)Fa zX8RMq5f3&-CwkAdQ%ty$EqzP+)br{IOk&Zc4XuJw&2M0tZ6=NRlAXJ(JCs(>2Hotb zAAS)^MLtoo&4Pr(95*rV{bZ}+%08VVwiu5qh;LPT&8i&^CF}KzwGJ#g=%SdDSvgE4 zaZb$n{hMU(`?nB`)-`N1uGghxp~Vk&CvcLE+xIt|X}RF3XR6%!ff~(WbNv||dLGxEoNk=U`SMDXk81?K97mX9J3L5F(yeI< z17-xpMN#!GTRC_SeCeG2e%owMcRWr z_l8t}to~|T77dV%^@1iV!#&aZa%D_c9-S(zuZym&WwpJ2R>+Avi6B!{PN{8^&Rq&P z5D0W=e1h_y3`~_%HTc$<@{FGZdZ9z+CdcPIA6}mkEu?hfkv2!|B%xf+ z!%0x9vfbaZep&3P(zILt+36<PdufOmkm;zPv?wU(Nxp^l7f6y_LszDI1Zf*(PRE zCGCDPe*jEa9mqr|hf5@uL z&E+KNUQ~XhB+0xfSh1NElsy>RikhsKR-D3|(KPg=#8iD}k-$pfd8ZjZAg6H3i+9gB z2xp1EBs#ML#r}n%Ij)Q%g-;##e<5q79`PQ zSD_btwNpSRT5XQpSNno&RJ3XGceN=dMkUq6Vz|wdL@mk%352EgNrZL3SZ^>m5<0u0 zvYOfjY>d>5$*a6e*v5D^4^TIk^>NH9vEATCc~zq1hhYmzZlfP^>=9YDuSt2G&zdtK zqYz5-Y+( zX7UCo1Bkj9uXP9COR_$n;T4d4=`v|er)Y=-#|6H5@IrfxyU0;42$8KdECXaw1thz= zR1J;ahA4O4Z`j7)iTC)LDKzmWqiyKYa25`rEp1H zOm&cQf^L``0lr=j1UfLQWOyJrn+cU(ad2JF7@a%%qe#j3t*GaXm&^E5e9+JDv{AD5 zHN)9|TzkMxqX!~xUEzIuS~qLzGh)gVP!f=@%%Z3Z@;Q8V@QiP@W{65zf^R zH8PcLOX|`0LGLv>Re5+tbgl(S50RTHe^~?aFK(}^5x8S>+#}7mmTB=W!=0A?NkIl( zpHgGejNyFyfQ8`f=Oo;C03gE$vwXGd+c4CN4)5+q3s;rT<$DwGlE21mnTITyVYF+j zczw37%vhsg$uiQqy|Bu!V{4FVURfze*!E{*VLXu0g7GSB!g=%J`s<+@`rL zdH8psb#RC7AOF*V>W>0~R(b^k_5uQ2?OQSw?U8CKf!_>r4@jUTUu%tAVeSKJX-h9Gn#hIg~8X)IWVL$Ypw!8 zTaR*a`93Zsof0D`@*_BP_Q5$6y4bD_=1tfQM5(%8lU)ei&9>ZVm52$uT6gGukt4W_SBWP z1~@^NT$94qHUEy^*#SedFmuxXeP%Fa0DpXLi_YZwn@(!ZPw=;}1>wr8x2g5r1*%p;@#(NzhbTN1dZ+H!7 zQ9AYB@5K>V{f2y8ljF%9l3>|$2J@mxHr=c0NMjn|z;I#^A*Bvmk{MJ5cW*HqyYMh2 zWi|lW<@hk$c`YnXIGPXwZellNA>)Xi{k1bU3Xa9~6Zu_yr~ zVGZQlxBV627*bhdB%%X3WZvB%L@f(s?n}(({?qqTu!dC!(GW?XD@mFMPE^qL+fg?A zF6!Js0*+L=)yV36Lz*OKr1{U+CwgNev%* zurlh4hHrOlHVX!cbBu525I#X6G%@Uj3$#rrklb&Ae;TAy2YPouDQt!pb0Gujzr
    xUT9Lf!~{ivo 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 skE!cXEzOF)AS6gIX+4XE + + + three.js webgl - materials - materialx nodes + + + + + +
    + three.js webgl - MaterialX - Noise +
    + + + + + + + + + + From 52231716df36dee61963ef78a142c2158e91e02b Mon Sep 17 00:00:00 2001 From: sunag Date: Tue, 16 Aug 2022 14:45:10 -0300 Subject: [PATCH 7/7] adjust scale to better visual --- .../webgl_nodes_materialx_noise.jpg | Bin 38436 -> 37486 bytes examples/webgl_nodes_materialx_noise.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/screenshots/webgl_nodes_materialx_noise.jpg b/examples/screenshots/webgl_nodes_materialx_noise.jpg index c0e209cfbbb9522cd32eed46816de11bbb115e1c..99ee561e76257606660a833c044c0b46782750c5 100644 GIT binary patch delta 14170 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 Tk~$@^+FYEf=li0Z$UpztB!+DL diff --git a/examples/webgl_nodes_materialx_noise.html b/examples/webgl_nodes_materialx_noise.html index 7ae950b4ec0fc5..c3729e36056808 100644 --- a/examples/webgl_nodes_materialx_noise.html +++ b/examples/webgl_nodes_materialx_noise.html @@ -109,7 +109,7 @@ // right bottom material = new MeshPhysicalNodeMaterial(); - material.colorNode = saturate( mul( add( mx_fractal_noise_float( customUV, 7, 2, .7 ), 1 ), .5 ) ); + material.colorNode = saturate( mul( add( mx_fractal_noise_float( mul( customUV, .2 ), 7, 2, .7 ), 1 ), .5 ) ); mesh = new THREE.Mesh( geometry, material ); mesh.position.x = 100;