提交 cc5ffd81 编写于 作者: S sunag

NodeMaterialLoader + example + tests

上级 76e0ef80
{"nodes":{"0C853FCD-3CB8-4144-B7A3-F49CED812B61":{"uuid":"0C853FCD-3CB8-4144-B7A3-F49CED812B61","type":"StandardNode","color":"69ACB125-2EAB-4F1C-9A30-C8A2E886BBFB","roughness":"6C740750-9287-47E1-9A13-6A5DE38EF80C","metalness":"290C6194-C8F5-4CAD-8790-098E506DA454","ambient":"E9EC29E0-A9F3-4046-BB0A-C743D5A60528"},"69ACB125-2EAB-4F1C-9A30-C8A2E886BBFB":{"uuid":"69ACB125-2EAB-4F1C-9A30-C8A2E886BBFB","type":"Math3Node","a":"C051EF5D-5269-4A12-AC20-4102377D5D57","b":"02ED8121-2961-4074-ACA7-F386EB1290A1","c":"6C7A71AD-A8CC-4E19-9F26-F9C3B2CD0B8F","method":"mix"},"C051EF5D-5269-4A12-AC20-4102377D5D57":{"uuid":"C051EF5D-5269-4A12-AC20-4102377D5D57","type":"ColorNode","r":1,"g":1,"b":1},"02ED8121-2961-4074-ACA7-F386EB1290A1":{"uuid":"02ED8121-2961-4074-ACA7-F386EB1290A1","type":"Math3Node","a":"8D184736-20DD-4EFB-8BDE-657B0B7E0374","b":"C187F032-F8B4-475F-9317-305998EDA247","c":"962F8B0A-B3DA-4789-AF1B-C47B8FE5A01B","method":"mix"},"8D184736-20DD-4EFB-8BDE-657B0B7E0374":{"uuid":"8D184736-20DD-4EFB-8BDE-657B0B7E0374","type":"ColorNode","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"C187F032-F8B4-475F-9317-305998EDA247":{"uuid":"C187F032-F8B4-475F-9317-305998EDA247","type":"ColorNode","r":1,"g":1,"b":1},"962F8B0A-B3DA-4789-AF1B-C47B8FE5A01B":{"uuid":"962F8B0A-B3DA-4789-AF1B-C47B8FE5A01B","type":"Math1Node","a":"025D9840-CC59-4345-9ECF-58F30EA1BC18","method":"saturate"},"025D9840-CC59-4345-9ECF-58F30EA1BC18":{"uuid":"025D9840-CC59-4345-9ECF-58F30EA1BC18","type":"OperatorNode","a":"F33136D1-4646-46A9-8168-B5F3A7F0E6E7","b":"C1E4ED63-76C4-454E-8042-3FEB65265365","op":"*"},"F33136D1-4646-46A9-8168-B5F3A7F0E6E7":{"uuid":"F33136D1-4646-46A9-8168-B5F3A7F0E6E7","type":"FunctionCallNode","value":"34DE7BBF-67F0-42AE-A92F-E41A88065E2C","inputs":{"p":"29DDBD3C-E348-4E25-B79A-3D75D5576E47","time":"91645353-F838-4ECB-A54F-0B0BD81EF0CE"}},"34DE7BBF-67F0-42AE-A92F-E41A88065E2C":{"uuid":"34DE7BBF-67F0-42AE-A92F-E41A88065E2C","type":"FunctionNode","name":"voronoiLayers","src":"float voronoiLayers(vec2 p, in float time) {\n\tfloat v = 0.0;\n\tfloat a = 0.4;\n\tfor (int i = 0; i < 3; i++) {\n\t\tv += voronoi(p, time) * a;\n\t\tp *= 2.0;\n\t\ta *= 0.5;\n\t}\n\treturn v;\n}","isMethod":true,"useKeywords":true,"extensions":{},"keywords":{},"includes":["3E1A3E00-4D57-4363-B4E8-9AC7FFFD1162"]},"3E1A3E00-4D57-4363-B4E8-9AC7FFFD1162":{"uuid":"3E1A3E00-4D57-4363-B4E8-9AC7FFFD1162","type":"FunctionNode","name":"voronoi","src":"float voronoi(vec2 p, in float time) {\n\tvec2 n = floor(p);\n\tvec2 f = fract(p);\n\tfloat md = 5.0;\n\tvec2 m = vec2(0.0);\n\tfor (int i = -1; i <= 1; i++) {\n\t\tfor (int j = -1; j <= 1; j++) {\n\t\t\tvec2 g = vec2(i, j);\n\t\t\tvec2 o = hash2(n + g);\n\t\t\to = 0.5 + 0.5 * sin(time + 5.038 * o);\n\t\t\tvec2 r = g + o - f;\n\t\t\tfloat d = dot(r, r);\n\t\t\tif (d < md) {\n\t\t\t\tmd = d;\n\t\t\t\tm = n+g+o;\n\t\t\t}\n\t\t}\n\t}\n\treturn md;\n}","isMethod":true,"useKeywords":true,"extensions":{},"keywords":{},"includes":["DFB9B6EF-EAD5-4CA4-B491-CED3B14BDCF3"]},"DFB9B6EF-EAD5-4CA4-B491-CED3B14BDCF3":{"uuid":"DFB9B6EF-EAD5-4CA4-B491-CED3B14BDCF3","type":"FunctionNode","name":"hash2","src":"vec2 hash2(vec2 p) {\n\treturn fract(sin(vec2(dot(p, vec2(123.4, 748.6)), dot(p, vec2(547.3, 659.3))))*5232.85324);\n}","isMethod":true,"useKeywords":true,"extensions":{},"keywords":{}},"29DDBD3C-E348-4E25-B79A-3D75D5576E47":{"uuid":"29DDBD3C-E348-4E25-B79A-3D75D5576E47","type":"OperatorNode","a":"37FCB5FB-D6C5-4D51-B6C9-D65CFF8E56F5","b":"C2939E11-9118-412E-8656-687BDEE7F259","op":"*"},"37FCB5FB-D6C5-4D51-B6C9-D65CFF8E56F5":{"uuid":"37FCB5FB-D6C5-4D51-B6C9-D65CFF8E56F5","type":"SwitchNode","node":"B5FE994F-6069-45C5-87D0-E5BBB5DDAA9B","components":"xz"},"B5FE994F-6069-45C5-87D0-E5BBB5DDAA9B":{"uuid":"B5FE994F-6069-45C5-87D0-E5BBB5DDAA9B","type":"PositionNode","scope":"world"},"C2939E11-9118-412E-8656-687BDEE7F259":{"uuid":"C2939E11-9118-412E-8656-687BDEE7F259","type":"FloatNode","number":0.1},"91645353-F838-4ECB-A54F-0B0BD81EF0CE":{"uuid":"91645353-F838-4ECB-A54F-0B0BD81EF0CE","type":"OperatorNode","a":"4301B6EC-D918-4C2C-A8A4-BDA39B67FC88","b":"2BD5D8FE-FA0F-4B6F-A15D-1C6341A2A49A","op":"*"},"4301B6EC-D918-4C2C-A8A4-BDA39B67FC88":{"uuid":"4301B6EC-D918-4C2C-A8A4-BDA39B67FC88","type":"TimerNode","name":"time","scale":1},"2BD5D8FE-FA0F-4B6F-A15D-1C6341A2A49A":{"uuid":"2BD5D8FE-FA0F-4B6F-A15D-1C6341A2A49A","type":"FloatNode","name":"speed","number":2},"C1E4ED63-76C4-454E-8042-3FEB65265365":{"uuid":"C1E4ED63-76C4-454E-8042-3FEB65265365","type":"FloatNode","number":1.5},"6C7A71AD-A8CC-4E19-9F26-F9C3B2CD0B8F":{"uuid":"6C7A71AD-A8CC-4E19-9F26-F9C3B2CD0B8F","type":"OperatorNode","a":"484155DB-1D71-4C53-BD67-8C7F0D39DFAF","b":"E26C242B-22E1-4CF0-8E6A-9D3EE3009DDF","op":"*"},"484155DB-1D71-4C53-BD67-8C7F0D39DFAF":{"uuid":"484155DB-1D71-4C53-BD67-8C7F0D39DFAF","type":"FloatNode","number":1},"E26C242B-22E1-4CF0-8E6A-9D3EE3009DDF":{"uuid":"E26C242B-22E1-4CF0-8E6A-9D3EE3009DDF","type":"Math1Node","a":"4E7D0932-B617-4DC8-B3EE-CB2F2D0C71D3","method":"saturate"},"4E7D0932-B617-4DC8-B3EE-CB2F2D0C71D3":{"uuid":"4E7D0932-B617-4DC8-B3EE-CB2F2D0C71D3","type":"SwitchNode","node":"121C70CA-F385-46EA-85DF-8803A8DFA94A","components":"y"},"121C70CA-F385-46EA-85DF-8803A8DFA94A":{"uuid":"121C70CA-F385-46EA-85DF-8803A8DFA94A","type":"NormalNode","scope":"world"},"6C740750-9287-47E1-9A13-6A5DE38EF80C":{"uuid":"6C740750-9287-47E1-9A13-6A5DE38EF80C","type":"FloatNode","number":0.5},"290C6194-C8F5-4CAD-8790-098E506DA454":{"uuid":"290C6194-C8F5-4CAD-8790-098E506DA454","type":"FloatNode","number":0.5},"E9EC29E0-A9F3-4046-BB0A-C743D5A60528":{"uuid":"E9EC29E0-A9F3-4046-BB0A-C743D5A60528","type":"OperatorNode","a":"025D9840-CC59-4345-9ECF-58F30EA1BC18","b":"6C7A71AD-A8CC-4E19-9F26-F9C3B2CD0B8F","op":"*"}},"materials":{"F60E153B-B020-448B-8309-FA32A7387B37":{"uuid":"F60E153B-B020-448B-8309-FA32A7387B37","type":"StandardNodeMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"fog":false,"lights":true,"vertex":"0C853FCD-3CB8-4144-B7A3-F49CED812B61","fragment":"0C853FCD-3CB8-4144-B7A3-F49CED812B61"}},"material":"F60E153B-B020-448B-8309-FA32A7387B37"}
\ No newline at end of file
{"nodes":{"159F7363-B727-4F3E-AF62-BE65DFF91C79":{"uuid":"159F7363-B727-4F3E-AF62-BE65DFF91C79","type":"PhongNode","transform":"5C02A7EF-E3B5-45F1-A51D-30FE5FDC7AD5","color":"C2D6FC53-4F88-4C10-9381-922F370FA2E9","specular":"C2D6FC53-4F88-4C10-9381-922F370FA2E9","shininess":"9E2B0686-3575-468B-A490-29AF12C00E18","emissive":"7F1D8D17-7EFB-4C01-A394-B273EE8DE569"},"5C02A7EF-E3B5-45F1-A51D-30FE5FDC7AD5":{"uuid":"5C02A7EF-E3B5-45F1-A51D-30FE5FDC7AD5","type":"OperatorNode","a":"2C5D1792-66CE-4357-BE14-781E4C84DAEB","b":"A7759D0E-31BA-48DB-BF71-9BAACF2D93E4","op":"+"},"2C5D1792-66CE-4357-BE14-781E4C84DAEB":{"uuid":"2C5D1792-66CE-4357-BE14-781E4C84DAEB","type":"PositionNode","scope":"local"},"A7759D0E-31BA-48DB-BF71-9BAACF2D93E4":{"uuid":"A7759D0E-31BA-48DB-BF71-9BAACF2D93E4","type":"OperatorNode","a":"506BDB3C-153F-47A8-89BA-88516F94021B","b":"2DF083C9-1D7F-4366-B2F0-6AB7EDE61F06","op":"*"},"506BDB3C-153F-47A8-89BA-88516F94021B":{"uuid":"506BDB3C-153F-47A8-89BA-88516F94021B","type":"OperatorNode","a":"10F05EC7-E04C-4237-BA21-7F83824C2C0F","b":"CA0D7D12-8386-49B1-AB77-5C8E8A1F7119","op":"*"},"10F05EC7-E04C-4237-BA21-7F83824C2C0F":{"uuid":"10F05EC7-E04C-4237-BA21-7F83824C2C0F","type":"NormalNode","scope":"local"},"CA0D7D12-8386-49B1-AB77-5C8E8A1F7119":{"uuid":"CA0D7D12-8386-49B1-AB77-5C8E8A1F7119","type":"SwitchNode","node":"63E59FC4-8B59-41F5-AD42-46E6DAA7AE22","components":"w"},"63E59FC4-8B59-41F5-AD42-46E6DAA7AE22":{"uuid":"63E59FC4-8B59-41F5-AD42-46E6DAA7AE22","type":"TextureNode","value":"cloud","coord":"BD7395C2-2C5D-42A4-BBED-2CC216067727","project":false},"BD7395C2-2C5D-42A4-BBED-2CC216067727":{"uuid":"BD7395C2-2C5D-42A4-BBED-2CC216067727","type":"OperatorNode","a":"C4DD00B6-A40C-48E2-AA8E-2760F18C3606","b":"65A19E19-D02F-4025-843B-D646F83E5A9D","op":"+"},"C4DD00B6-A40C-48E2-AA8E-2760F18C3606":{"uuid":"C4DD00B6-A40C-48E2-AA8E-2760F18C3606","type":"OperatorNode","a":"1F9A12DF-7D69-41C6-90D5-042E2E53E6CE","b":"D838BBDF-50BF-4572-B8DB-54F7FCB77680","op":"*"},"1F9A12DF-7D69-41C6-90D5-042E2E53E6CE":{"uuid":"1F9A12DF-7D69-41C6-90D5-042E2E53E6CE","type":"TimerNode","name":"time","scale":1},"D838BBDF-50BF-4572-B8DB-54F7FCB77680":{"uuid":"D838BBDF-50BF-4572-B8DB-54F7FCB77680","type":"FloatNode","name":"speed","number":0.2},"65A19E19-D02F-4025-843B-D646F83E5A9D":{"uuid":"65A19E19-D02F-4025-843B-D646F83E5A9D","type":"UVNode","index":0},"2DF083C9-1D7F-4366-B2F0-6AB7EDE61F06":{"uuid":"2DF083C9-1D7F-4366-B2F0-6AB7EDE61F06","type":"FloatNode","number":2},"C2D6FC53-4F88-4C10-9381-922F370FA2E9":{"uuid":"C2D6FC53-4F88-4C10-9381-922F370FA2E9","type":"ColorNode","r":0,"g":0,"b":0},"9E2B0686-3575-468B-A490-29AF12C00E18":{"uuid":"9E2B0686-3575-468B-A490-29AF12C00E18","type":"FloatNode","number":30},"7F1D8D17-7EFB-4C01-A394-B273EE8DE569":{"uuid":"7F1D8D17-7EFB-4C01-A394-B273EE8DE569","type":"Math3Node","a":"769EDCC2-F6E9-424F-AE93-7517F343CFE0","b":"F24EB80D-E7AC-4CFE-83B3-8E6EFA270470","c":"CA0D7D12-8386-49B1-AB77-5C8E8A1F7119","method":"mix"},"769EDCC2-F6E9-424F-AE93-7517F343CFE0":{"uuid":"769EDCC2-F6E9-424F-AE93-7517F343CFE0","type":"ColorNode","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"F24EB80D-E7AC-4CFE-83B3-8E6EFA270470":{"uuid":"F24EB80D-E7AC-4CFE-83B3-8E6EFA270470","type":"ColorNode","r":1,"g":1,"b":1}},"materials":{"A6680195-B61F-4159-903A-8D2C09E56F59":{"uuid":"A6680195-B61F-4159-903A-8D2C09E56F59","type":"PhongNodeMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"fog":false,"lights":true,"vertex":"159F7363-B727-4F3E-AF62-BE65DFF91C79","fragment":"159F7363-B727-4F3E-AF62-BE65DFF91C79"}},"material":"A6680195-B61F-4159-903A-8D2C09E56F59"}
\ No newline at end of file
{"nodes":{"3EE87473-C714-4386-8F5C-B500C9AA1D1A":{"uuid":"3EE87473-C714-4386-8F5C-B500C9AA1D1A","type":"PhongNode","transform":"6FB5A984-1B5D-453E-8840-A7543930894C","color":"81AD4AB3-680C-48A0-978F-3EFB95F86605","specular":"2CCE835E-048F-4338-B634-E2139469B32F","shininess":"5EC6AACA-7A31-4D60-9159-DFAA089D22C9"},"6FB5A984-1B5D-453E-8840-A7543930894C":{"uuid":"6FB5A984-1B5D-453E-8840-A7543930894C","type":"OperatorNode","a":"05C8BE9A-F710-4224-BA9E-CEA5BB40F9B4","b":"1EEC92B8-2C62-4AFF-8069-E9854B0BE4D8","op":"+"},"05C8BE9A-F710-4224-BA9E-CEA5BB40F9B4":{"uuid":"05C8BE9A-F710-4224-BA9E-CEA5BB40F9B4","type":"PositionNode","scope":"local"},"1EEC92B8-2C62-4AFF-8069-E9854B0BE4D8":{"uuid":"1EEC92B8-2C62-4AFF-8069-E9854B0BE4D8","type":"JoinNode","inputs":{"x":"6B70F504-DC84-4C7B-90B2-803F8090A207","y":"B0FA37D3-3719-440D-8483-D0D9B6E84720","z":"03769BCB-952D-4D88-BCA5-2BD5B47746A3"}},"6B70F504-DC84-4C7B-90B2-803F8090A207":{"uuid":"6B70F504-DC84-4C7B-90B2-803F8090A207","type":"FloatNode","number":0},"B0FA37D3-3719-440D-8483-D0D9B6E84720":{"uuid":"B0FA37D3-3719-440D-8483-D0D9B6E84720","type":"OperatorNode","a":"9500D1CB-5406-4045-A243-4247983DBCD1","b":"98D9C3B8-E78E-4DA8-B2FD-0284BCC1D4FC","op":"*"},"9500D1CB-5406-4045-A243-4247983DBCD1":{"uuid":"9500D1CB-5406-4045-A243-4247983DBCD1","type":"SwitchNode","node":"3F4C7A4F-04DC-4545-992B-F08941C80C1F","components":"x"},"3F4C7A4F-04DC-4545-992B-F08941C80C1F":{"uuid":"3F4C7A4F-04DC-4545-992B-F08941C80C1F","type":"Math1Node","a":"CF0B79AB-CCA9-407A-9224-FB94CB21BE05","method":"sin"},"CF0B79AB-CCA9-407A-9224-FB94CB21BE05":{"uuid":"CF0B79AB-CCA9-407A-9224-FB94CB21BE05","type":"OperatorNode","a":"E76CF5B1-1491-4825-8AC1-0794D1B29415","b":"4568D710-E298-4D99-9C20-0A8C05A236F8","op":"+"},"E76CF5B1-1491-4825-8AC1-0794D1B29415":{"uuid":"E76CF5B1-1491-4825-8AC1-0794D1B29415","type":"OperatorNode","a":"99F6A1F9-D304-4A6B-83A3-66D14EBA8218","b":"0D75A0EB-8497-432F-AAAF-08EB1206B9A8","op":"*"},"99F6A1F9-D304-4A6B-83A3-66D14EBA8218":{"uuid":"99F6A1F9-D304-4A6B-83A3-66D14EBA8218","type":"PositionNode","scope":"local"},"0D75A0EB-8497-432F-AAAF-08EB1206B9A8":{"uuid":"0D75A0EB-8497-432F-AAAF-08EB1206B9A8","type":"FloatNode","number":0.4},"4568D710-E298-4D99-9C20-0A8C05A236F8":{"uuid":"4568D710-E298-4D99-9C20-0A8C05A236F8","type":"OperatorNode","a":"0B71AD7A-4526-4178-850A-D8DF269CA68C","b":"EF53D89A-0511-4E8A-A344-241D77B66B9B","op":"*"},"0B71AD7A-4526-4178-850A-D8DF269CA68C":{"uuid":"0B71AD7A-4526-4178-850A-D8DF269CA68C","type":"TimerNode","name":"time","scale":1},"EF53D89A-0511-4E8A-A344-241D77B66B9B":{"uuid":"EF53D89A-0511-4E8A-A344-241D77B66B9B","type":"FloatNode","name":"speed","number":5},"98D9C3B8-E78E-4DA8-B2FD-0284BCC1D4FC":{"uuid":"98D9C3B8-E78E-4DA8-B2FD-0284BCC1D4FC","type":"FloatNode","number":1},"03769BCB-952D-4D88-BCA5-2BD5B47746A3":{"uuid":"03769BCB-952D-4D88-BCA5-2BD5B47746A3","type":"FloatNode","number":0},"81AD4AB3-680C-48A0-978F-3EFB95F86605":{"uuid":"81AD4AB3-680C-48A0-978F-3EFB95F86605","type":"Math3Node","a":"BA150D88-7DFE-4637-A3AE-2A9DFA06E8E7","b":"986A69F3-890D-4AA5-920B-0DE8D583BF09","c":"9500D1CB-5406-4045-A243-4247983DBCD1","method":"mix"},"BA150D88-7DFE-4637-A3AE-2A9DFA06E8E7":{"uuid":"BA150D88-7DFE-4637-A3AE-2A9DFA06E8E7","type":"ColorNode","r":0,"g":0.32941176470588235,"b":0.8745098039215686},"986A69F3-890D-4AA5-920B-0DE8D583BF09":{"uuid":"986A69F3-890D-4AA5-920B-0DE8D583BF09","type":"ColorNode","r":1,"g":1,"b":1},"2CCE835E-048F-4338-B634-E2139469B32F":{"uuid":"2CCE835E-048F-4338-B634-E2139469B32F","type":"ColorNode","r":0.06666666666666667,"g":0.06666666666666667,"b":0.06666666666666667},"5EC6AACA-7A31-4D60-9159-DFAA089D22C9":{"uuid":"5EC6AACA-7A31-4D60-9159-DFAA089D22C9","type":"FloatNode","number":30}},"materials":{"B13AD55D-3685-4737-B4BF-88DEA97128E0":{"uuid":"B13AD55D-3685-4737-B4BF-88DEA97128E0","type":"PhongNodeMaterial","depthFunc":3,"depthTest":true,"depthWrite":true,"fog":false,"lights":true,"vertex":"3EE87473-C714-4386-8F5C-B500C9AA1D1A","fragment":"3EE87473-C714-4386-8F5C-B500C9AA1D1A"}},"material":"B13AD55D-3685-4737-B4BF-88DEA97128E0"}
\ No newline at end of file
{"material":"8101BA5D-02FD-44AD-BD7F-78509B5ABCF3","nodes":{"DB73F154-FC47-451B-AC3A-9950333B66FD":{"uuid":"DB73F154-FC47-451B-AC3A-9950333B66FD","type":"PhongNode","color":"A7CF9848-5F11-42D7-9728-85D4B563C7D0","specular":"EE5B0CB1-AC58-4776-A522-EA80EBD9C60E","shininess":"987F1F9E-7FFA-43CE-88F2-098FDFD6F22D","alpha":"CFA8CCDE-B065-4C88-AC42-204536C5A020","emissive":"01A6AE98-69DA-47A9-AE1D-D6039B9FCE7B"},"A7CF9848-5F11-42D7-9728-85D4B563C7D0":{"uuid":"A7CF9848-5F11-42D7-9728-85D4B563C7D0","type":"ColorNode","r":0.06666666666666667,"g":0.06666666666666667,"b":0.06666666666666667},"EE5B0CB1-AC58-4776-A522-EA80EBD9C60E":{"uuid":"EE5B0CB1-AC58-4776-A522-EA80EBD9C60E","type":"ColorNode","r":0.06666666666666667,"g":0.06666666666666667,"b":0.06666666666666667},"987F1F9E-7FFA-43CE-88F2-098FDFD6F22D":{"uuid":"987F1F9E-7FFA-43CE-88F2-098FDFD6F22D","type":"FloatNode","number":30},"CFA8CCDE-B065-4C88-AC42-204536C5A020":{"uuid":"CFA8CCDE-B065-4C88-AC42-204536C5A020","type":"Math2Node","a":"955B8AA7-A5B2-49D2-9CA6-6CF880B52A68","b":"03349DA1-C72E-4313-9D93-0F20AB9FCAB9","method":"pow"},"955B8AA7-A5B2-49D2-9CA6-6CF880B52A68":{"uuid":"955B8AA7-A5B2-49D2-9CA6-6CF880B52A68","type":"OperatorNode","a":"0A5469D3-4E04-4019-B5B9-C29ECC723568","b":"6016CBD4-8301-4D33-A3A1-3C5997FE20F3","op":"+"},"0A5469D3-4E04-4019-B5B9-C29ECC723568":{"uuid":"0A5469D3-4E04-4019-B5B9-C29ECC723568","type":"Math2Node","a":"D6A4B70C-D75D-4885-83E4-E634F18815E6","b":"E42952FC-5B06-4BE8-9631-573D7845D313","method":"dot"},"D6A4B70C-D75D-4885-83E4-E634F18815E6":{"uuid":"D6A4B70C-D75D-4885-83E4-E634F18815E6","type":"NormalNode","scope":"view"},"E42952FC-5B06-4BE8-9631-573D7845D313":{"uuid":"E42952FC-5B06-4BE8-9631-573D7845D313","type":"Vector3Node","x":0,"y":0,"z":-1.3},"6016CBD4-8301-4D33-A3A1-3C5997FE20F3":{"uuid":"6016CBD4-8301-4D33-A3A1-3C5997FE20F3","type":"FloatNode","number":1.3},"03349DA1-C72E-4313-9D93-0F20AB9FCAB9":{"uuid":"03349DA1-C72E-4313-9D93-0F20AB9FCAB9","type":"FloatNode","number":3},"01A6AE98-69DA-47A9-AE1D-D6039B9FCE7B":{"uuid":"01A6AE98-69DA-47A9-AE1D-D6039B9FCE7B","type":"ColorNode","r":1,"g":1,"b":1}},"materials":{"8101BA5D-02FD-44AD-BD7F-78509B5ABCF3":{"uuid":"8101BA5D-02FD-44AD-BD7F-78509B5ABCF3","type":"PhongNodeMaterial","blending":2,"transparent":true,"depthFunc":3,"depthTest":true,"depthWrite":false,"fog":false,"lights":true,"vertex":"DB73F154-FC47-451B-AC3A-9950333B66FD","fragment":"DB73F154-FC47-451B-AC3A-9950333B66FD"}}}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<title>three.js webgl - node material</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
body {
color: #fff;
font-family:Monospace;
font-size:13px;
margin: 0px;
text-align:center;
overflow: hidden;
}
#info {
color: #fff;
position: absolute;
top: 10px;
width: 100%;
text-align: center;
display:block;
}
a { color: white }
</style>
</head>
<body>
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Node-Based Material</br>
Serialized using <a href="webgl_materials_nodes.html">webgl_materials_nodes.html</a>
</div>
<script src="../build/three.js"></script>
<script src='js/geometries/TeapotBufferGeometry.js'></script>
<script src="js/controls/OrbitControls.js"></script>
<script src="js/libs/dat.gui.min.js"></script>
<!-- NodeLibrary -->
<script src="js/nodes/GLNode.js"></script>
<script src="js/nodes/RawNode.js"></script>
<script src="js/nodes/TempNode.js"></script>
<script src="js/nodes/InputNode.js"></script>
<script src="js/nodes/ConstNode.js"></script>
<script src="js/nodes/VarNode.js"></script>
<script src="js/nodes/FunctionNode.js"></script>
<script src="js/nodes/FunctionCallNode.js"></script>
<script src="js/nodes/AttributeNode.js"></script>
<script src="js/nodes/NodeBuilder.js"></script>
<script src="js/nodes/NodeLib.js"></script>
<script src="js/nodes/NodeMaterial.js"></script>
<!-- Accessors -->
<script src="js/nodes/accessors/PositionNode.js"></script>
<script src="js/nodes/accessors/NormalNode.js"></script>
<script src="js/nodes/accessors/UVNode.js"></script>
<script src="js/nodes/accessors/ScreenUVNode.js"></script>
<script src="js/nodes/accessors/ColorsNode.js"></script>
<script src="js/nodes/accessors/CameraNode.js"></script>
<script src="js/nodes/accessors/ReflectNode.js"></script>
<script src="js/nodes/accessors/LightNode.js"></script>
<!-- Inputs -->
<script src="js/nodes/inputs/IntNode.js"></script>
<script src="js/nodes/inputs/FloatNode.js"></script>
<script src="js/nodes/inputs/ColorNode.js"></script>
<script src="js/nodes/inputs/Vector2Node.js"></script>
<script src="js/nodes/inputs/Vector3Node.js"></script>
<script src="js/nodes/inputs/Vector4Node.js"></script>
<script src="js/nodes/inputs/TextureNode.js"></script>
<script src="js/nodes/inputs/Matrix4Node.js"></script>
<script src="js/nodes/inputs/CubeTextureNode.js"></script>
<!-- Math -->
<script src="js/nodes/math/Math1Node.js"></script>
<script src="js/nodes/math/Math2Node.js"></script>
<script src="js/nodes/math/Math3Node.js"></script>
<script src="js/nodes/math/OperatorNode.js"></script>
<!-- Utils -->
<script src="js/nodes/utils/SwitchNode.js"></script>
<script src="js/nodes/utils/JoinNode.js"></script>
<script src="js/nodes/utils/TimerNode.js"></script>
<script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
<script src="js/nodes/utils/VelocityNode.js"></script>
<script src="js/nodes/utils/LuminanceNode.js"></script>
<script src="js/nodes/utils/ColorAdjustmentNode.js"></script>
<script src="js/nodes/utils/NoiseNode.js"></script>
<script src="js/nodes/utils/ResolutionNode.js"></script>
<script src="js/nodes/utils/BumpNode.js"></script>
<script src="js/nodes/utils/BlurNode.js"></script>
<script src="js/nodes/utils/UVTransformNode.js"></script>
<!-- Phong Material -->
<script src="js/nodes/materials/PhongNode.js"></script>
<script src="js/nodes/materials/PhongNodeMaterial.js"></script>
<!-- Standard Material -->
<script src="js/nodes/materials/StandardNode.js"></script>
<script src="js/nodes/materials/StandardNodeMaterial.js"></script>
<!-- NodeMaterial Loader -->
<script src="js/loaders/NodeMaterialLoader.js"></script>
<script>
var container = document.getElementById( 'container' );
var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
var teapot, mesh, cloud;
var controls;
var gui;
var param = { load: 'caustic' };
window.addEventListener( 'load', init );
function init() {
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
camera.position.x = 50;
camera.position.z = - 50;
camera.position.y = 30;
camera.target = new THREE.Vector3();
cloud = new THREE.TextureLoader().load( 'textures/lava/cloud.png' );
cloud.wrapS = cloud.wrapT = THREE.RepeatWrapping;
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minDistance = 50;
controls.maxDistance = 200;
scene.add( new THREE.AmbientLight( 0x464646 ) );
var light = new THREE.DirectionalLight( 0xffddcc, 1 );
light.position.set( 1, 0.75, 0.5 );
scene.add( light );
var light = new THREE.DirectionalLight( 0xccccff, 1 );
light.position.set( - 1, 0.75, - 0.5 );
scene.add( light );
teapot = new THREE.TeapotBufferGeometry( 15, 18 );
mesh = new THREE.Mesh( teapot );
scene.add( mesh );
window.addEventListener( 'resize', onWindowResize, false );
updateMaterial();
onWindowResize();
animate();
}
function clearGui() {
if ( gui ) gui.destroy();
gui = new dat.GUI();
var example = gui.add( param, 'load', {
'caustic': 'caustic',
'displace': 'displace',
'wave': 'wave',
'xray': 'xray'
} ).onFinishChange( function () {
updateMaterial();
} );
gui.open();
}
function addGui( name, value, callback, isColor, min, max ) {
var node;
param[ name ] = value;
if ( isColor ) {
node = gui.addColor( param, name ).onChange( function () {
callback( param[ name ] );
} );
} else if ( typeof value == 'object' ) {
node = gui.add( param, name, value ).onChange( function () {
callback( param[ name ] );
} );
} else {
node = gui.add( param, name, min, max ).onChange( function () {
callback( param[ name ] );
} );
}
return node;
}
function updateMaterial() {
if ( mesh.material ) mesh.material.dispose();
clearGui();
var url = "nodes/" + param.load + ".json";
var library = {
"cloud" : cloud
};
var loader = new THREE.NodeMaterialLoader( undefined, library ).load( url, function () {
var time = loader.getObjectByName("time");
if (time) {
addGui( 'timeScale', time.scale, function ( val ) {
time.scale = val;
}, false, -2, 2 );
}
// set material
mesh.material = loader.material;
} );
}
function onWindowResize() {
var width = window.innerWidth, height = window.innerHeight;
camera.aspect = width / height;
camera.updateProjectionMatrix();
renderer.setSize( width, height );
}
function animate() {
var delta = clock.getDelta();
// update material animation and/or gpu calcs (pre-renderer)
if ( mesh.material instanceof THREE.NodeMaterial ) mesh.material.updateFrame( delta );
renderer.render( scene, camera );
requestAnimationFrame( animate );
}
</script>
</body>
</html>
......@@ -30,7 +30,8 @@
<div id="container"></div>
<div id="info">
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Node-Based Material
<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - Node-Based Material</br>
<a id="serialize" onclick="toggleSerialize()" href="javascript:void(0);">Serialize and apply</a>
</div>
<script src="../build/three.js"></script>
......@@ -102,6 +103,9 @@
<script src="js/nodes/materials/StandardNode.js"></script>
<script src="js/nodes/materials/StandardNodeMaterial.js"></script>
<!-- NodeMaterial Loader -->
<script src="js/loaders/NodeMaterialLoader.js"></script>
<script>
var container = document.getElementById( 'container' );
......@@ -112,6 +116,8 @@
var move = false;
var rtTexture, rtMaterial;
var gui, guiElements = [];
var library = {};
var serialized = false;
var textures = {
brick: { url: 'textures/brick_diffuse.jpg' },
grass: { url: 'textures/terrain/grasslight-big.jpg' },
......@@ -132,6 +138,8 @@
texture = textures[ name ].texture = new THREE.TextureLoader().load( textures[ name ].url );
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
library[ texture.uuid ] = texture;
}
return texture;
......@@ -151,6 +159,8 @@
var textureCube = new THREE.CubeTextureLoader().load( urls );
textureCube.format = THREE.RGBFormat;
library[ textureCube.uuid ] = textureCube;
return textureCube;
}();
......@@ -162,6 +172,7 @@
renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.uuid = THREE.Math.generateUUID(); // generate to library
container.appendChild( renderer.domElement );
scene = new THREE.Scene();
......@@ -172,6 +183,7 @@
camera.position.y = 30;
camera.target = new THREE.Vector3();
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.minDistance = 50;
controls.maxDistance = 200;
......@@ -191,6 +203,10 @@
mesh = new THREE.Mesh( teapot );
scene.add( mesh );
library[ renderer.uuid ] = renderer;
library[ camera.uuid ] = camera;
library[ mesh.uuid ] = mesh;
window.addEventListener( 'resize', onWindowResize, false );
updateMaterial();
......@@ -292,6 +308,8 @@
if ( rtTexture ) {
delete library[ rtTexture.uuid ];
rtTexture.dispose();
rtTexture = null;
......@@ -412,7 +430,7 @@
addGui( 'roughnessA', roughnessA.number, function ( val ) {
roughnessA.number = val;
roughnessA.number = val;
}, false, 0, 1 );
......@@ -424,7 +442,7 @@
addGui( 'roughnessB', roughnessB.number, function ( val ) {
roughnessB.number = val;
roughnessB.number = val;
}, false, 0, 1 );
......@@ -444,26 +462,26 @@
case 'physical':
// MATERIAL
// MATERIAL
mtl = new THREE.StandardNodeMaterial();
//mtl.color = // albedo (vec3)
//mtl.alpha = // opacity (float)
//mtl.roughness = // roughness (float)
//mtl.metalness = // metalness (float)
//mtl.reflectivity = // reflectivity (float)
//mtl.clearCoat = // clearCoat (float)
//mtl.clearCoatRoughness = // clearCoatRoughness (float)
//mtl.normal = // normalmap (vec3)
//mtl.normalScale = // normalmap scale (vec2)
//mtl.emissive = // emissive color (vec3)
//mtl.ambient = // ambient color (vec3)
//mtl.shadow = // shadowmap (vec3)
//mtl.light = // custom-light (vec3)
//mtl.ao = // ambient occlusion (float)
//mtl.environment = // reflection/refraction (vec3)
//mtl.transform = // vertex transformation (vec3)
//mtl.color = // albedo (vec3)
//mtl.alpha = // opacity (float)
//mtl.roughness = // roughness (float)
//mtl.metalness = // metalness (float)
//mtl.reflectivity = // reflectivity (float)
//mtl.clearCoat = // clearCoat (float)
//mtl.clearCoatRoughness = // clearCoatRoughness (float)
//mtl.normal = // normalmap (vec3)
//mtl.normalScale = // normalmap scale (vec2)
//mtl.emissive = // emissive color (vec3)
//mtl.ambient = // ambient color (vec3)
//mtl.shadow = // shadowmap (vec3)
//mtl.light = // custom-light (vec3)
//mtl.ao = // ambient occlusion (float)
//mtl.environment = // reflection/refraction (vec3)
//mtl.transform = // vertex transformation (vec3)
var mask = new THREE.SwitchNode( new THREE.TextureNode( getTexture( "decalDiffuse" ) ), 'w' );
......@@ -480,24 +498,24 @@
var clearCoatRoughness = new THREE.FloatNode( 1 );
var roughness = new THREE.Math3Node(
roughnessA,
roughnessB,
mask,
THREE.Math3Node.MIX
);
roughnessA,
roughnessB,
mask,
THREE.Math3Node.MIX
);
var metalness = new THREE.Math3Node(
metalnessA,
metalnessB,
mask,
THREE.Math3Node.MIX
);
metalnessA,
metalnessB,
mask,
THREE.Math3Node.MIX
);
var normalMask = new THREE.OperatorNode(
new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
normalScale,
THREE.OperatorNode.MUL
);
new THREE.Math1Node( mask, THREE.Math1Node.INVERT ),
normalScale,
THREE.OperatorNode.MUL
);
mtl.color = new THREE.ColorNode( 0xEEEEEE );
mtl.roughness = roughness;
......@@ -509,7 +527,7 @@
mtl.normal = new THREE.TextureNode( getTexture( "grassNormal" ) );
mtl.normalScale = normalMask;
// GUI
// GUI
addGui( 'color', mtl.color.value.getHex(), function ( val ) {
......@@ -519,25 +537,25 @@
addGui( 'reflectivity', reflectivity.number, function ( val ) {
reflectivity.number = val;
reflectivity.number = val;
}, false, 0, 1 );
addGui( 'clearCoat', clearCoat.number, function ( val ) {
clearCoat.number = val;
clearCoat.number = val;
}, false, 0, 1 );
addGui( 'clearCoatRoughness', clearCoatRoughness.number, function ( val ) {
clearCoatRoughness.number = val;
clearCoatRoughness.number = val;
}, false, 0, 1 );
addGui( 'roughnessA', roughnessA.number, function ( val ) {
roughnessA.number = val;
roughnessA.number = val;
}, false, 0, 1 );
......@@ -549,7 +567,7 @@
addGui( 'roughnessB', roughnessB.number, function ( val ) {
roughnessB.number = val;
roughnessB.number = val;
}, false, 0, 1 );
......@@ -580,6 +598,10 @@
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
// used for serialization only
time.name = "time";
speed.name = "speed";
var timeScale = new THREE.OperatorNode(
time,
speed,
......@@ -1078,7 +1100,7 @@
var satrgb = new THREE.FunctionNode( [
"vec3 satrgb(vec3 rgb, float adjustment) {",
//" const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
//" const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
" vec3 intensity = vec3(dot(rgb, LUMA));",
" return mix(intensity, rgb, adjustment);",
"}"
......@@ -1166,6 +1188,10 @@
var colorA = new THREE.ColorNode( 0xFFFFFF );
var colorB = new THREE.ColorNode( 0x0054df );
// used for serialization only
time.name = "time";
speed.name = "speed";
var uv = new THREE.UVNode();
var timeScl = new THREE.OperatorNode(
......@@ -1357,7 +1383,7 @@
].join( "\n" ) );
var voronoi = new THREE.FunctionNode( [
// Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
// Based off of iq's described here: http://www.iquilezles.org/www/articles/voronoili
"float voronoi(vec2 p, in float time) {",
" vec2 n = floor(p);",
" vec2 f = fract(p);",
......@@ -1381,7 +1407,7 @@
].join( "\n" ), [ hash2 ] ); // define hash2 as dependencies
var voronoiLayers = new THREE.FunctionNode( [
// based on https://www.shadertoy.com/view/4tXSDf
// based on https://www.shadertoy.com/view/4tXSDf
"float voronoiLayers(vec2 p, in float time) {",
" float v = 0.0;",
" float a = 0.4;",
......@@ -1397,6 +1423,10 @@
var time = new THREE.TimerNode();
var timeScale = new THREE.FloatNode( 2 );
// used for serialization only
time.name = "time";
timeScale.name = "speed";
var alpha = new THREE.FloatNode( 1 );
var scale = new THREE.FloatNode( .1 );
var intensity = new THREE.FloatNode( 1.5 );
......@@ -1928,7 +1958,7 @@
mtl = new THREE.PhongNodeMaterial();
var keywordsexample = new THREE.FunctionNode( [
// use "uv" reserved keyword
// use "uv" reserved keyword
"vec4 keywordsexample( sampler2D texture ) {",
" return texture2D( texture, myUV ) + vec4( position * myAlpha, 0.0 );",
"}"
......@@ -1967,10 +1997,10 @@
var setMyVar = new THREE.FunctionNode( [
"float setMyVar( vec3 pos ) {",
// set "myVar" in vertex shader in this example,
// can be used in fragment shader too or in rest of the current shader
// set "myVar" in vertex shader in this example,
// can be used in fragment shader too or in rest of the current shader
" myVar = pos;",
// it is not accept "void" functions for now!
// it is not accept "void" functions for now!
" return 0.;",
"}"
].join( "\n" ) );
......@@ -1996,11 +2026,11 @@
var alpha = new THREE.FloatNode( 1 );
var blurtexture = new THREE.FunctionNode( [
// Reference: TriangleBlurShader.js
// Reference: TriangleBlurShader.js
"vec4 blurtexture(sampler2D texture, vec2 uv, vec2 delta) {",
" vec4 color = vec4( 0.0 );",
" float total = 0.0;",
// randomize the lookup values to hide the fixed number of samples
// randomize the lookup values to hide the fixed number of samples
" float offset = rand( uv );",
" for ( float t = -BLUR_ITERATIONS; t <= BLUR_ITERATIONS; t ++ ) {",
" float percent = ( t + offset - 0.5 ) / BLUR_ITERATIONS;",
......@@ -2136,6 +2166,8 @@
rtTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter, format: THREE.RGBFormat } );
library[ rtTexture.uuid ] = rtTexture;
var distanceMtl = new THREE.PhongNodeMaterial();
distanceMtl.environment = objectDepth;
distanceMtl.side = THREE.BackSide;
......@@ -2269,6 +2301,56 @@
}
function toggleSerialize() {
if ( serialized ) reset();
else serialize();
serialized = ! serialized;
}
function reset() {
updateMaterial();
// gui
var div = document.getElementById( 'serialize' );
div.textContent = "Serialize and apply";
}
function serialize() {
var json = mesh.material.toJSON(),
loader = new THREE.NodeMaterialLoader( null, library ),
material = loader.parse( json );
mesh.material = material;
// replace uuid to url (facilitates the load of textures using url otherside uuid)
// example:
THREE.NodeMaterialLoaderUtils.replaceUUID( json, getTexture( "cloud" ), "cloud" );
// get source
var jsonStr = JSON.stringify( json );
console.log( jsonStr );
// gui
var div = document.getElementById( 'serialize' );
div.textContent = "Click to reset - JSON Generate: " + ( jsonStr.length / 1024 ).toFixed( 3 ) + "kB";
if ( gui ) gui.destroy();
gui = null;
}
function animate() {
var delta = clock.getDelta();
......
......@@ -96,223 +96,242 @@
<script src="js/nodes/materials/PhongNode.js"></script>
<script src="js/nodes/materials/PhongNodeMaterial.js"></script>
<!-- NodeMaterial Loader -->
<script src="js/loaders/NodeMaterialLoader.js"></script>
<script>
// scene size
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
// scene size
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
// camera
var VIEW_ANGLE = 45;
var ASPECT = WIDTH / HEIGHT;
var NEAR = 1;
var FAR = 500;
var decalNormal = new THREE.TextureLoader().load( 'textures/decal/decal-normal.jpg' );
var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
var camera, scene, renderer;
var clock = new THREE.Clock();
var cameraControls;
var gui = new dat.GUI();
var sphereGroup, smallSphere;
var groundMirrorMaterial;
function init() {
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
// scene
scene = new THREE.Scene();
// camera
var VIEW_ANGLE = 45;
var ASPECT = WIDTH / HEIGHT;
var NEAR = 1;
var FAR = 500;
camera = new THREE.PerspectiveCamera( VIEW_ANGLE, ASPECT, NEAR, FAR );
camera.position.set( 0, 75, 160 );
cameraControls = new THREE.OrbitControls( camera, renderer.domElement );
cameraControls.target.set( 0, 40, 0 );
cameraControls.maxDistance = 400;
cameraControls.minDistance = 10;
cameraControls.update();
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
}
function fillScene() {
var planeGeo = new THREE.PlaneBufferGeometry( 100.1, 100.1 );
// reflector/mirror plane
var geometry = new THREE.PlaneBufferGeometry( 100, 100 );
var groundMirror = new THREE.ReflectorRTT( geometry, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT } );
var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
var maskFlip = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
var mirror = new THREE.ReflectorNode( groundMirror );
var normal = new THREE.TextureNode( decalNormal );
var normalXY = new THREE.SwitchNode( normal, 'xy' );
var normalXYFlip = new THREE.Math1Node(
normalXY,
THREE.Math1Node.INVERT
);
var offsetNormal = new THREE.OperatorNode(
normalXYFlip,
new THREE.FloatNode( .5 ),
THREE.OperatorNode.SUB
);
mirror.offset = new THREE.OperatorNode(
offsetNormal, // normal
new THREE.FloatNode( 6 ), // scale
THREE.OperatorNode.MUL
);
var clr = new THREE.Math3Node(
mirror,
new THREE.ColorNode( 0xFFFFFF ),
mask,
THREE.Math3Node.MIX
);
var blurMirror = new THREE.BlurNode( mirror );
blurMirror.size = new THREE.Vector2( WIDTH, HEIGHT );
blurMirror.coord = new THREE.FunctionNode( "projCoord.xyz / projCoord.q", "vec3" );
blurMirror.coord.keywords[ "projCoord" ] = new THREE.OperatorNode( mirror.offset, mirror.coord, THREE.OperatorNode.ADD );
blurMirror.radius.x = blurMirror.radius.y = 0;
gui.add( { blur: blurMirror.radius.x }, "blur", 0, 25 ).onChange( function ( v ) {
blurMirror.radius.x = blurMirror.radius.y = v;
} );
groundMirrorMaterial = new THREE.PhongNodeMaterial();
groundMirrorMaterial.environment = blurMirror; // or add "mirror" variable to disable blur
groundMirrorMaterial.environmentAlpha = mask;
groundMirrorMaterial.normal = normal;
//groundMirrorMaterial.normalScale = new THREE.FloatNode( 1 );
groundMirrorMaterial.build();
// test serialization
/*
var library = {};
library[ groundMirror.uuid ] = groundMirror;
library[ decalDiffuse.uuid ] = decalDiffuse;
library[ decalNormal.uuid ] = decalNormal;
library[ mirror.textureMatrix.uuid ] = mirror.textureMatrix; // use textureMatrix to projection
var json = groundMirrorMaterial.toJSON();
groundMirrorMaterial = new THREE.NodeMaterialLoader( null, library ).parse( json );
*/
//--
var mirrorMesh = new THREE.Mesh( planeGeo, groundMirrorMaterial );
mirrorMesh.add( groundMirror );
mirrorMesh.rotateX( - Math.PI / 2 );
scene.add( mirrorMesh );
var decalNormal = new THREE.TextureLoader().load( 'textures/decal/decal-normal.jpg' );
sphereGroup = new THREE.Object3D();
scene.add( sphereGroup );
var decalDiffuse = new THREE.TextureLoader().load( 'textures/decal/decal-diffuse.png' );
decalDiffuse.wrapS = decalDiffuse.wrapT = THREE.RepeatWrapping;
var geometry = new THREE.CylinderGeometry( 0.1, 15 * Math.cos( Math.PI / 180 * 30 ), 0.1, 24, 1 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x444444 } );
var sphereCap = new THREE.Mesh( geometry, material );
sphereCap.position.y = - 15 * Math.sin( Math.PI / 180 * 30 ) - 0.05;
sphereCap.rotateX( - Math.PI );
var camera, scene, renderer;
var clock = new THREE.Clock();
var geometry = new THREE.SphereGeometry( 15, 24, 24, Math.PI / 2, Math.PI * 2, 0, Math.PI / 180 * 120 );
var halfSphere = new THREE.Mesh( geometry, material );
halfSphere.add( sphereCap );
halfSphere.rotateX( - Math.PI / 180 * 135 );
halfSphere.rotateZ( - Math.PI / 180 * 20 );
halfSphere.position.y = 7.5 + 15 * Math.sin( Math.PI / 180 * 30 );
var cameraControls;
sphereGroup.add( halfSphere );
var gui = new dat.GUI();
var geometry = new THREE.IcosahedronGeometry( 5, 0 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x333333, flatShading: true } );
smallSphere = new THREE.Mesh( geometry, material );
scene.add( smallSphere );
var sphereGroup, smallSphere;
var groundMirrorMaterial;
// walls
var planeTop = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeTop.position.y = 100;
planeTop.rotateX( Math.PI / 2 );
scene.add( planeTop );
var planeBack = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeBack.position.z = - 50;
planeBack.position.y = 50;
scene.add( planeBack );
function init() {
var planeFront = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x7f7fff } ) );
planeFront.position.z = 50;
planeFront.position.y = 50;
planeFront.rotateY( Math.PI );
scene.add( planeFront );
var planeRight = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
planeRight.position.x = 50;
planeRight.position.y = 50;
planeRight.rotateY( - Math.PI / 2 );
scene.add( planeRight );
// renderer
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
var planeLeft = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xff0000 } ) );
planeLeft.position.x = - 50;
planeLeft.position.y = 50;
planeLeft.rotateY( Math.PI / 2 );
scene.add( planeLeft );
// scene
scene = new THREE.Scene();
// lights
var mainLight = new THREE.PointLight( 0xcccccc, 1.5, 250 );
mainLight.position.y = 60;
scene.add( mainLight );
// camera
camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.position.set( 0, 75, 160 );
var greenLight = new THREE.PointLight( 0x00ff00, 0.25, 1000 );
greenLight.position.set( 550, 50, 0 );
scene.add( greenLight );
cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
cameraControls.target.set( 0, 40, 0);
cameraControls.maxDistance = 400;
cameraControls.minDistance = 10;
cameraControls.update();
var redLight = new THREE.PointLight( 0xff0000, 0.25, 1000 );
redLight.position.set( - 550, 50, 0 );
scene.add( redLight );
var container = document.getElementById( 'container' );
container.appendChild( renderer.domElement );
var blueLight = new THREE.PointLight( 0x7f7fff, 0.25, 1000 );
blueLight.position.set( 0, 50, 550 );
scene.add( blueLight );
}
}
function fillScene() {
var planeGeo = new THREE.PlaneBufferGeometry( 100.1, 100.1 );
// reflector/mirror plane
var geometry = new THREE.PlaneBufferGeometry( 100, 100 );
var groundMirror = new THREE.ReflectorRTT( geometry, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT } );
var mask = new THREE.SwitchNode( new THREE.TextureNode( decalDiffuse ), 'w' );
var maskFlip = new THREE.Math1Node( mask, THREE.Math1Node.INVERT );
var mirror = new THREE.ReflectorNode( groundMirror );
var normal = new THREE.TextureNode( decalNormal );
var normalXY = new THREE.SwitchNode( normal, 'xy' );
var normalXYFlip = new THREE.Math1Node(
normalXY,
THREE.Math1Node.INVERT
);
var offsetNormal = new THREE.OperatorNode(
normalXYFlip,
new THREE.FloatNode( .5 ),
THREE.OperatorNode.SUB
);
mirror.offset = new THREE.OperatorNode(
offsetNormal, // normal
new THREE.FloatNode( 6 ),// scale
THREE.OperatorNode.MUL
);
var clr = new THREE.Math3Node(
mirror,
new THREE.ColorNode( 0xFFFFFF ),
mask,
THREE.Math3Node.MIX
);
var blurMirror = new THREE.BlurNode( mirror );
blurMirror.size = new THREE.Vector2( WIDTH, HEIGHT );
blurMirror.coord = new THREE.FunctionNode( "projCoord.xyz / projCoord.q", "vec3" );
blurMirror.coord.keywords[ "projCoord" ] = new THREE.OperatorNode( mirror.offset, mirror.coord, THREE.OperatorNode.ADD );
blurMirror.radius.x = blurMirror.radius.y = 0;
gui.add( { blur : blurMirror.radius.x }, "blur", 0, 25 ).onChange( function(v) {
blurMirror.radius.x = blurMirror.radius.y = v;
} );
groundMirrorMaterial = new THREE.PhongNodeMaterial();
groundMirrorMaterial.environment = blurMirror; // or add "mirror" variable to disable blur
groundMirrorMaterial.environmentAlpha = mask;
groundMirrorMaterial.normal = normal;
//groundMirrorMaterial.normalScale = new THREE.FloatNode( 1 );
groundMirrorMaterial.build();
var mirrorMesh = new THREE.Mesh( planeGeo, groundMirrorMaterial );
mirrorMesh.add( groundMirror );
mirrorMesh.rotateX( - Math.PI / 2 );
scene.add( mirrorMesh );
sphereGroup = new THREE.Object3D();
scene.add( sphereGroup );
var geometry = new THREE.CylinderGeometry( 0.1, 15 * Math.cos( Math.PI / 180 * 30 ), 0.1, 24, 1 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x444444 } );
var sphereCap = new THREE.Mesh( geometry, material );
sphereCap.position.y = -15 * Math.sin( Math.PI / 180 * 30 ) - 0.05;
sphereCap.rotateX(-Math.PI);
var geometry = new THREE.SphereGeometry( 15, 24, 24, Math.PI / 2, Math.PI * 2, 0, Math.PI / 180 * 120 );
var halfSphere = new THREE.Mesh( geometry, material );
halfSphere.add( sphereCap );
halfSphere.rotateX( - Math.PI / 180 * 135 );
halfSphere.rotateZ( - Math.PI / 180 * 20 );
halfSphere.position.y = 7.5 + 15 * Math.sin( Math.PI / 180 * 30 );
sphereGroup.add( halfSphere );
var geometry = new THREE.IcosahedronGeometry( 5, 0 );
var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x333333, flatShading: true } );
smallSphere = new THREE.Mesh( geometry, material );
scene.add(smallSphere);
// walls
var planeTop = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeTop.position.y = 100;
planeTop.rotateX( Math.PI / 2 );
scene.add( planeTop );
var planeBack = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
planeBack.position.z = -50;
planeBack.position.y = 50;
scene.add( planeBack );
var planeFront = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x7f7fff } ) );
planeFront.position.z = 50;
planeFront.position.y = 50;
planeFront.rotateY( Math.PI );
scene.add( planeFront );
var planeRight = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
planeRight.position.x = 50;
planeRight.position.y = 50;
planeRight.rotateY( - Math.PI / 2 );
scene.add( planeRight );
var planeLeft = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xff0000 } ) );
planeLeft.position.x = -50;
planeLeft.position.y = 50;
planeLeft.rotateY( Math.PI / 2 );
scene.add( planeLeft );
// lights
var mainLight = new THREE.PointLight( 0xcccccc, 1.5, 250 );
mainLight.position.y = 60;
scene.add( mainLight );
var greenLight = new THREE.PointLight( 0x00ff00, 0.25, 1000 );
greenLight.position.set( 550, 50, 0 );
scene.add( greenLight );
var redLight = new THREE.PointLight( 0xff0000, 0.25, 1000 );
redLight.position.set( - 550, 50, 0 );
scene.add( redLight );
var blueLight = new THREE.PointLight( 0x7f7fff, 0.25, 1000 );
blueLight.position.set( 0, 50, 550 );
scene.add( blueLight );
function render() {
}
renderer.render( scene, camera );
function render() {
}
renderer.render(scene, camera);
function update() {
}
requestAnimationFrame( update );
function update() {
var delta = clock.getDelta();
var timer = Date.now() * 0.01;
requestAnimationFrame( update );
sphereGroup.rotation.y -= 0.002;
var delta = clock.getDelta();
var timer = Date.now() * 0.01;
smallSphere.position.set(
Math.cos( timer * 0.1 ) * 30,
Math.abs( Math.cos( timer * 0.2 ) ) * 20 + 5,
Math.sin( timer * 0.1 ) * 30
);
smallSphere.rotation.y = ( Math.PI / 2 ) - timer * 0.1;
smallSphere.rotation.z = timer * 0.8;
sphereGroup.rotation.y -= 0.002;
groundMirrorMaterial.updateFrame( delta );
smallSphere.position.set(
Math.cos( timer * 0.1 ) * 30,
Math.abs( Math.cos( timer * 0.2 ) ) * 20 + 5,
Math.sin( timer * 0.1 ) * 30
);
smallSphere.rotation.y = ( Math.PI / 2 ) - timer * 0.1;
smallSphere.rotation.z = timer * 0.8;
render();
groundMirrorMaterial.updateFrame( delta );
}
render();
}
init();
fillScene();
update();
init();
fillScene();
update();
</script>
</body>
......
......@@ -86,6 +86,9 @@
<!-- Post-Processing -->
<script src="js/nodes/postprocessing/NodePass.js"></script>
<!-- NodeMaterial Loader -->
<script src="js/loaders/NodeMaterialLoader.js"></script>
<script>
var camera, scene, renderer, composer;
......@@ -121,7 +124,7 @@
'adv / saturation': 'saturation',
'adv / refraction': 'refraction',
'adv / mosaic': 'mosaic'
} ).onFinishChange( function() {
} ).onFinishChange( function () {
updateMaterial();
......@@ -139,7 +142,7 @@
if ( isColor ) {
node = gui.addColor( param, name ).onChange( function() {
node = gui.addColor( param, name ).onChange( function () {
callback( param[ name ] );
......@@ -147,7 +150,7 @@
} else if ( typeof value == 'object' ) {
node = gui.add( param, name, value ).onChange( function() {
node = gui.add( param, name, value ).onChange( function () {
callback( param[ name ] );
......@@ -155,7 +158,7 @@
} else {
node = gui.add( param, name, min, max ).onChange( function() {
node = gui.add( param, name, min, max ).onChange( function () {
callback( param[ name ] );
......@@ -195,31 +198,31 @@
// GUI
addGui( 'hue', hue.number, function( val ) {
addGui( 'hue', hue.number, function ( val ) {
hue.number = val;
}, false, 0, Math.PI * 2 );
addGui( 'saturation', sataturation.number, function( val ) {
addGui( 'saturation', sataturation.number, function ( val ) {
sataturation.number = val;
}, false, 0, 2 );
addGui( 'vibrance', vibrance.number, function( val ) {
addGui( 'vibrance', vibrance.number, function ( val ) {
vibrance.number = val;
}, false, - 1, 1 );
addGui( 'brightness', brightness.number, function( val ) {
addGui( 'brightness', brightness.number, function ( val ) {
brightness.number = val;
}, false, 0, .5 );
addGui( 'contrast', contrast.number, function( val ) {
addGui( 'contrast', contrast.number, function ( val ) {
contrast.number = val;
......@@ -245,13 +248,13 @@
// GUI
addGui( 'color', color.value.getHex(), function( val ) {
addGui( 'color', color.value.getHex(), function ( val ) {
color.value.setHex( val );
}, true );
addGui( 'fade', percent.number, function( val ) {
addGui( 'fade', percent.number, function ( val ) {
percent.number = val;
......@@ -279,7 +282,7 @@
// GUI
addGui( 'alpha', alpha.number, function( val ) {
addGui( 'alpha', alpha.number, function ( val ) {
alpha.number = val;
......@@ -302,11 +305,11 @@
// GUI
addGui( 'blend', {
'addition' : THREE.OperatorNode.ADD,
'subtract' : THREE.OperatorNode.SUB,
'multiply' : THREE.OperatorNode.MUL,
'division' : THREE.OperatorNode.DIV
}, function( val ) {
'addition': THREE.OperatorNode.ADD,
'subtract': THREE.OperatorNode.SUB,
'multiply': THREE.OperatorNode.MUL,
'division': THREE.OperatorNode.DIV
}, function ( val ) {
multiply.op = val;
......@@ -324,11 +327,11 @@
var sat = new THREE.FloatNode( 0 );
var satrgb = new THREE.FunctionNode( [
"vec3 satrgb(vec3 rgb, float adjustment) {",
//" const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
" vec3 intensity = vec3(dot(rgb, LUMA));",
" return mix(intensity, rgb, adjustment);",
"}"
"vec3 satrgb(vec3 rgb, float adjustment) {",
//" const vec3 W = vec3(0.2125, 0.7154, 0.0721);", // LUMA
" vec3 intensity = vec3(dot(rgb, LUMA));",
" return mix(intensity, rgb, adjustment);",
"}"
].join( "\n" ) );
var saturation = new THREE.FunctionCallNode( satrgb );
......@@ -339,7 +342,7 @@
// GUI
addGui( 'saturation', sat.number, function( val ) {
addGui( 'saturation', sat.number, function ( val ) {
sat.number = val;
......@@ -392,13 +395,13 @@
// GUI
addGui( 'scale', scale.number, function( val ) {
addGui( 'scale', scale.number, function ( val ) {
scale.number = val;
}, false, 0, 1 );
addGui( 'invert', false, function( val ) {
addGui( 'invert', false, function ( val ) {
offsetNormal.a = val ? normalXYFlip : normalXY;
......@@ -444,19 +447,19 @@
// GUI
addGui( 'scale', scale.number, function( val ) {
addGui( 'scale', scale.number, function ( val ) {
scale.number = val;
}, false, 16, 1024 );
addGui( 'fade', fade.number, function( val ) {
addGui( 'fade', fade.number, function ( val ) {
fade.number = val;
}, false, 0, 1 );
addGui( 'mask', true, function( val ) {
addGui( 'mask', true, function ( val ) {
fadeCoord.c = val ? maskAlpha : fade;
......@@ -479,13 +482,13 @@
// GUI
addGui( 'blurX', blurScreen.radius.x, function( val ) {
addGui( 'blurX', blurScreen.radius.x, function ( val ) {
blurScreen.radius.x = val;
}, false, 0, 15 );
addGui( 'blurY', blurScreen.radius.y, function( val ) {
addGui( 'blurY', blurScreen.radius.y, function ( val ) {
blurScreen.radius.y = val;
......@@ -497,6 +500,17 @@
nodepass.build();
// test serialization
/*
var library = {};
library[ lensflare2.uuid ] = lensflare2;
library[ decalNormal.uuid ] = decalNormal;
var json = nodepass.toJSON();
nodepass.value = new THREE.NodeMaterialLoader( null, library ).parse( json ).value;
nodepass.build();
*/
}
function init() {
......
......@@ -97,13 +97,18 @@
<!-- Sprite Material -->
<script src="js/nodes/materials/SpriteNode.js"></script>
<script src="js/nodes/materials/SpriteNodeMaterial.js"></script>
<!-- NodeMaterial Loader -->
<script src="js/loaders/NodeMaterialLoader.js"></script>
<script>
var container = document.getElementById( 'container' );
var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
var plane, sprite1, sprite2, sprite3;
var walkingManTexture, walkingManTextureURL;
var library = {};
var controls;
window.addEventListener( 'load', init );
......@@ -138,9 +143,13 @@
plane = new THREE.PlaneBufferGeometry( 1, 1 );
// https://openclipart.org/detail/239883/walking-man-sprite-sheet
var walkingManTexture = new THREE.TextureLoader().load( "textures/WalkingManSpriteSheet.png" );
walkingManTextureURL = "textures/WalkingManSpriteSheet.png";
walkingManTexture = new THREE.TextureLoader().load( walkingManTextureURL );
walkingManTexture.wrapS = walkingManTexture.wrapT = THREE.RepeatWrapping;
library[ walkingManTextureURL ] = walkingManTexture;
// horizontal sprite-sheet animator
function createHorizontalSpriteSheetNode( hCount, speed ) {
......@@ -203,7 +212,7 @@
sprite2.material.spherical = false; // look at camera horizontally only, very used to vegetation
// horizontal zigzag sprite
sprite2.material.transform = new THREE.OperatorNode(
new THREE.OperatorNode(
new THREE.OperatorNode(
new THREE.Math1Node( new THREE.TimerNode( 0, 3 ), THREE.Math1Node.SIN ), // 3 is speed (time scale)
new THREE.Vector2Node( .3, 0 ), // horizontal scale (position)
THREE.OperatorNode.MUL
......@@ -227,14 +236,22 @@
sprite3.position.x = - 30;
sprite3.scale.x = spriteWidth;
sprite3.scale.y = spriteHeight;
sprite3.material.fog = true;
sprite3.material.color = new THREE.TextureNode( walkingManTexture );
sprite3.material.color.coord = new THREE.FunctionCallNode( sineWaveFunction, {
"uv": createHorizontalSpriteSheetNode( 8, 0 ),
"phase": new THREE.TimerNode()
} );
sprite3.material.fog = true;
sprite3.material.build();
//
// Test serialization
//
spriteToJSON( sprite1 );
spriteToJSON( sprite2 );
spriteToJSON( sprite3 );
//
// Events
//
......@@ -246,6 +263,26 @@
}
function spriteToJSON( sprite ) {
// serialize
var json = sprite.material.toJSON();
// replace uuid to url (facilitates the load of textures using url otherside uuid)
THREE.NodeMaterialLoaderUtils.replaceUUID( json, walkingManTexture, walkingManTextureURL );
// unserialize
var material = new THREE.NodeMaterialLoader( null, library ).parse( json );
// replace material
sprite.material = material;
}
function onWindowResize() {
var width = window.innerWidth, height = window.innerHeight;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册