diff --git a/editor/index.html b/editor/index.html
index cbbae21ea2dc2e..29775ed72887a9 100644
--- a/editor/index.html
+++ b/editor/index.html
@@ -23,7 +23,7 @@
-
+
diff --git a/editor/js/Sidebar.Geometry.CircleGeometry.js b/editor/js/Sidebar.Geometry.CircleGeometry.js
index c8537f8d044947..a68316ba8a58e6 100644
--- a/editor/js/Sidebar.Geometry.CircleGeometry.js
+++ b/editor/js/Sidebar.Geometry.CircleGeometry.js
@@ -36,7 +36,7 @@ function GeometryParametersPanel( editor, object ) {
// thetaStart
const thetaStartRow = new UIRow();
- const thetaStart = new UINumber( parameters.thetaStart * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
+ const thetaStart = new UINumber( parameters.thetaStart * THREE.MathUtils.RAD2DEG ).setUnit( '°' ).setStep( 10 ).onChange( update );
thetaStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetastart' ) ).setClass( 'Label' ) );
thetaStartRow.add( thetaStart );
@@ -46,7 +46,7 @@ function GeometryParametersPanel( editor, object ) {
// thetaLength
const thetaLengthRow = new UIRow();
- const thetaLength = new UINumber( parameters.thetaLength * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
+ const thetaLength = new UINumber( parameters.thetaLength * THREE.MathUtils.RAD2DEG ).setUnit( '°' ).setStep( 10 ).onChange( update );
thetaLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/circle_geometry/thetalength' ) ).setClass( 'Label' ) );
thetaLengthRow.add( thetaLength );
diff --git a/editor/js/Sidebar.Geometry.RingGeometry.js b/editor/js/Sidebar.Geometry.RingGeometry.js
index 73d5dbf63b6582..33b83e098ae665 100644
--- a/editor/js/Sidebar.Geometry.RingGeometry.js
+++ b/editor/js/Sidebar.Geometry.RingGeometry.js
@@ -56,7 +56,7 @@ function GeometryParametersPanel( editor, object ) {
// thetaStart
const thetaStartRow = new UIRow();
- const thetaStart = new UINumber( parameters.thetaStart * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
+ const thetaStart = new UINumber( parameters.thetaStart * THREE.MathUtils.RAD2DEG ).setUnit( '°' ).setStep( 10 ).onChange( update );
thetaStartRow.add( new UIText( strings.getKey( 'sidebar/geometry/ring_geometry/thetastart' ) ).setClass( 'Label' ) );
thetaStartRow.add( thetaStart );
@@ -66,7 +66,7 @@ function GeometryParametersPanel( editor, object ) {
// thetaLength
const thetaLengthRow = new UIRow();
- const thetaLength = new UINumber( parameters.thetaLength * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
+ const thetaLength = new UINumber( parameters.thetaLength * THREE.MathUtils.RAD2DEG ).setUnit( '°' ).setStep( 10 ).onChange( update );
thetaLengthRow.add( new UIText( strings.getKey( 'sidebar/geometry/ring_geometry/thetalength' ) ).setClass( 'Label' ) );
thetaLengthRow.add( thetaLength );
diff --git a/editor/js/Sidebar.Geometry.TorusGeometry.js b/editor/js/Sidebar.Geometry.TorusGeometry.js
index ce96c00815ccf4..9a5eef26008019 100644
--- a/editor/js/Sidebar.Geometry.TorusGeometry.js
+++ b/editor/js/Sidebar.Geometry.TorusGeometry.js
@@ -56,7 +56,7 @@ function GeometryParametersPanel( editor, object ) {
// arc
const arcRow = new UIRow();
- const arc = new UINumber( parameters.arc * THREE.MathUtils.RAD2DEG ).setStep( 10 ).onChange( update );
+ const arc = new UINumber( parameters.arc * THREE.MathUtils.RAD2DEG ).setUnit( '°' ).setStep( 10 ).onChange( update );
arcRow.add( new UIText( strings.getKey( 'sidebar/geometry/torus_geometry/arc' ) ).setClass( 'Label' ) );
arcRow.add( arc );
diff --git a/editor/js/Sidebar.Project.Video.js b/editor/js/Sidebar.Project.Video.js
index 1766d9ab1655ca..6590ed5932d963 100644
--- a/editor/js/Sidebar.Project.Video.js
+++ b/editor/js/Sidebar.Project.Video.js
@@ -16,17 +16,25 @@ function SidebarProjectVideo( editor ) {
// Resolution
+ function toDiv2() {
+
+ // Make sure dimensions are divisible by 2 (requirement of libx264)
+
+ this.setValue( 2 * Math.floor( this.getValue() / 2 ) );
+
+ }
+
const resolutionRow = new UIRow();
container.add( resolutionRow );
resolutionRow.add( new UIText( strings.getKey( 'sidebar/project/resolution' ) ).setClass( 'Label' ) );
- const videoWidth = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+ const videoWidth = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' ).setStep( 2 ).onChange( toDiv2 );
resolutionRow.add( videoWidth );
resolutionRow.add( new UIText( '×' ).setTextAlign( 'center' ).setFontSize( '12px' ).setWidth( '12px' ) );
- const videoHeight = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+ const videoHeight = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' ).setStep( 2 ).onChange( toDiv2 );
resolutionRow.add( videoHeight );
const videoFPS = new UIInteger( 30 ).setTextAlign( 'center' ).setWidth( '20px' );
diff --git a/editor/js/libs/ffmpeg.min.js b/editor/js/libs/ffmpeg.min.js
deleted file mode 100644
index 1c8795e1174ca3..00000000000000
--- a/editor/js/libs/ffmpeg.min.js
+++ /dev/null
@@ -1,2 +0,0 @@
-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.FFmpeg=t():e.FFmpeg=t()}(self,(function(){return e={497:(e,t,r)=>{r(72);var n=r(306).devDependencies;e.exports={corePath:"https://unpkg.com/@ffmpeg/core@".concat(n["@ffmpeg/core"].substring(1),"/dist/ffmpeg-core.js")}},663:(e,t,r)=>{function n(e,t,r,n,o,i,a){try{var c=e[i](a),s=c.value}catch(e){return void r(e)}c.done?t(s):Promise.resolve(s).then(n,o)}var o=r(72),i=function(e){return new Promise((function(t,r){var n=new FileReader;n.onload=function(){t(n.result)},n.onerror=function(e){var t=e.target.error.code;r(Error("File could not be read! Code=".concat(t)))},n.readAsArrayBuffer(e)}))};e.exports=function(){var e,t=(e=regeneratorRuntime.mark((function e(t){var r,n;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(r=t,void 0!==t){e.next=3;break}return e.abrupt("return",new Uint8Array);case 3:if("string"!=typeof t){e.next=16;break}if(!/data:_data\/([a-zA-Z]*);base64,([^"]*)/.test(t)){e.next=8;break}r=atob(t.split(",")[1]).split("").map((function(e){return e.charCodeAt(0)})),e.next=14;break;case 8:return e.next=10,fetch(o(t));case 10:return n=e.sent,e.next=13,n.arrayBuffer();case 13:r=e.sent;case 14:e.next=20;break;case 16:if(!(t instanceof File||t instanceof Blob)){e.next=20;break}return e.next=19,i(t);case 19:r=e.sent;case 20:return e.abrupt("return",new Uint8Array(r));case 21:case"end":return e.stop()}}),e)})),function(){var t=this,r=arguments;return new Promise((function(o,i){var a=e.apply(t,r);function c(e){n(a,o,i,c,s,"next",e)}function s(e){n(a,o,i,c,s,"throw",e)}c(void 0)}))});return function(e){return t.apply(this,arguments)}}()},452:(e,t,r)=>{function n(e,t,r,n,o,i,a){try{var c=e[i](a),s=c.value}catch(e){return void r(e)}c.done?t(s):Promise.resolve(s).then(n,o)}function o(e){return function(){var t=this,r=arguments;return new Promise((function(o,i){var a=e.apply(t,r);function c(e){n(a,o,i,c,s,"next",e)}function s(e){n(a,o,i,c,s,"throw",e)}c(void 0)}))}}var i=r(72),a=r(185).log,c=function(){var e=o(regeneratorRuntime.mark((function e(t,r){var n,o,i;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:return a("info","fetch ".concat(t)),e.next=3,fetch(t);case 3:return e.next=5,e.sent.arrayBuffer();case 5:return n=e.sent,a("info","".concat(t," file size = ").concat(n.byteLength," bytes")),o=new Blob([n],{type:r}),i=URL.createObjectURL(o),a("info","".concat(t," blob URL = ").concat(i)),e.abrupt("return",i);case 11:case"end":return e.stop()}}),e)})));return function(t,r){return e.apply(this,arguments)}}();e.exports=function(){var e=o(regeneratorRuntime.mark((function e(t){var r,n,o,s,u;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if("string"==typeof(r=t.corePath)){e.next=3;break}throw Error("corePath should be a string!");case 3:return n=i(r),e.next=6,c(n,"application/javascript");case 6:return o=e.sent,e.next=9,c(n.replace("ffmpeg-core.js","ffmpeg-core.wasm"),"application/wasm");case 9:return s=e.sent,e.next=12,c(n.replace("ffmpeg-core.js","ffmpeg-core.worker.js"),"application/javascript");case 12:if(u=e.sent,"undefined"!=typeof createFFmpegCore){e.next=15;break}return e.abrupt("return",new Promise((function(e){var t=document.createElement("script");t.src=o,t.type="text/javascript",t.addEventListener("load",(function r(){t.removeEventListener("load",r),a("info","ffmpeg-core.js script loaded"),e({createFFmpegCore,corePath:o,wasmPath:s,workerPath:u})})),document.getElementsByTagName("head")[0].appendChild(t)})));case 15:return a("info","ffmpeg-core.js script is loaded already"),e.abrupt("return",Promise.resolve({createFFmpegCore,corePath:o,wasmPath:s,workerPath:u}));case 17:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()},698:(e,t,r)=>{var n=r(497),o=r(452),i=r(663);e.exports={defaultOptions:n,getCreateFFmpegCore:o,fetchFile:i}},500:e=>{e.exports={defaultArgs:["./ffmpeg","-nostdin","-y"],baseOptions:{log:!1,logger:function(){},progress:function(){},corePath:""}}},906:(e,t,r)=>{function n(e){return function(e){if(Array.isArray(e))return o(e)}(e)||function(e){if("undefined"!=typeof Symbol&&Symbol.iterator in Object(e))return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return o(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function o(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);r=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=r(500),p=l.defaultArgs,h=l.baseOptions,m=r(185),g=m.setLogging,d=m.setCustomLogger,y=m.log,v=r(583),b=r(319),w=r(698),x=w.defaultOptions,j=w.getCreateFFmpegCore,E=r(306).version,O=Error("ffmpeg.wasm is not ready, make sure you have completed load().");e.exports=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=s(s(s({},h),x),e),r=t.log,o=t.logger,i=t.progress,c=f(t,["log","logger","progress"]),u=null,l=null,m=null,w=!1,F=i,L=function(e){"FFMPEG_END"===e&&null!==m&&(m(),m=null,w=!1)},P=function(e){var t=e.type,r=e.message;y(t,r),v(r,F),L(r)},k=function(){var e=a(regeneratorRuntime.mark((function e(){var t,r,n,o,i;return regeneratorRuntime.wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(y("info","load ffmpeg-core"),null!==u){e.next=17;break}return y("info","loading ffmpeg-core"),e.next=5,j(c);case 5:return t=e.sent,r=t.createFFmpegCore,n=t.corePath,o=t.workerPath,i=t.wasmPath,e.next=12,r({mainScriptUrlOrBlob:n,printErr:function(e){return P({type:"fferr",message:e})},print:function(e){return P({type:"ffout",message:e})},locateFile:function(e,t){if("undefined"!=typeof window){if(void 0!==i&&e.endsWith("ffmpeg-core.wasm"))return i;if(void 0!==o&&e.endsWith("ffmpeg-core.worker.js"))return o}return t+e}});case 12:u=e.sent,l=u.cwrap("proxy_main","number",["number","number"]),y("info","ffmpeg-core loaded"),e.next=18;break;case 17:throw Error("ffmpeg.wasm was loaded, you should not load it again, use ffmpeg.isLoaded() to check next time.");case 18:case"end":return e.stop()}}),e)})));return function(){return e.apply(this,arguments)}}(),S=function(){return null!==u},A=function(){for(var e=arguments.length,t=new Array(e),r=0;r1?t-1:0),n=1;n")})).join(" "))),null===u)throw O;var o=null;try{var i;o=(i=u.FS)[e].apply(i,r)}catch(t){throw"readdir"===e?Error("ffmpeg.FS('readdir', '".concat(r[0],"') error. Check if the path exists, ex: ffmpeg.FS('readdir', '/')")):"readFile"===e?Error("ffmpeg.FS('readFile', '".concat(r[0],"') error. Check if the path exists")):Error("Oops, something went wrong in FS operation.")}return o},C=function(){if(null===u)throw O;w=!1,u.exit(1),u=null,l=null,m=null},R=function(e){F=e},T=function(e){d(e)};return g(r),d(o),y("info","use ffmpeg.wasm v".concat(E)),{setProgress:R,setLogger:T,setLogging:g,load:k,isLoaded:S,run:A,exit:C,FS:_}}},352:(e,t,r)=>{r(666);var n=r(906),o=r(698).fetchFile;e.exports={createFFmpeg:n,fetchFile:o}},185:e=>{var t=!1,r=function(){};e.exports={logging:t,setLogging:function(e){t=e},setCustomLogger:function(e){r=e},log:function(e,n){r({type:e,message:n}),t&&console.log("[".concat(e,"] ").concat(n))}}},319:e=>{e.exports=function(e,t){var r=e._malloc(t.length*Uint32Array.BYTES_PER_ELEMENT);return t.forEach((function(t,n){var o=e._malloc(t.length+1);e.writeAsciiToMemory(t,o),e.setValue(r+Uint32Array.BYTES_PER_ELEMENT*n,o,"i32")})),[t.length,r]}},583:e=>{function t(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=new Array(t);ra)&&(r=a)}else if(e.startsWith("frame")||e.startsWith("size")){var c=e.split("time=")[1].split(" ")[0],s=o(c);t({ratio:n=s/r,time:s})}else e.startsWith("video:")&&(t({ratio:1}),r=0)}},666:e=>{var t=function(e){"use strict";var t,r=Object.prototype,n=r.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",c=o.toStringTag||"@@toStringTag";function s(e,t,r){return Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{s({},"")}catch(e){s=function(e,t,r){return e[t]=r}}function u(e,t,r,n){var o=t&&t.prototype instanceof d?t:d,i=Object.create(o.prototype),a=new k(n||[]);return i._invoke=function(e,t,r){var n=l;return function(o,i){if(n===h)throw new Error("Generator is already running");if(n===m){if("throw"===o)throw i;return A()}for(r.method=o,r.arg=i;;){var a=r.delegate;if(a){var c=F(a,r);if(c){if(c===g)continue;return c}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===l)throw n=m,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=h;var s=f(e,t,r);if("normal"===s.type){if(n=r.done?m:p,s.arg===g)continue;return{value:s.arg,done:r.done}}"throw"===s.type&&(n=m,r.method="throw",r.arg=s.arg)}}}(e,r,a),i}function f(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}e.wrap=u;var l="suspendedStart",p="suspendedYield",h="executing",m="completed",g={};function d(){}function y(){}function v(){}var b={};b[i]=function(){return this};var w=Object.getPrototypeOf,x=w&&w(w(S([])));x&&x!==r&&n.call(x,i)&&(b=x);var j=v.prototype=d.prototype=Object.create(b);function E(e){["next","throw","return"].forEach((function(t){s(e,t,(function(e){return this._invoke(t,e)}))}))}function O(e,t){function r(o,i,a,c){var s=f(e[o],e,i);if("throw"!==s.type){var u=s.arg,l=u.value;return l&&"object"==typeof l&&n.call(l,"__await")?t.resolve(l.__await).then((function(e){r("next",e,a,c)}),(function(e){r("throw",e,a,c)})):t.resolve(l).then((function(e){u.value=e,a(u)}),(function(e){return r("throw",e,a,c)}))}c(s.arg)}var o;this._invoke=function(e,n){function i(){return new t((function(t,o){r(e,n,t,o)}))}return o=o?o.then(i,i):i()}}function F(e,r){var n=e.iterator[r.method];if(n===t){if(r.delegate=null,"throw"===r.method){if(e.iterator.return&&(r.method="return",r.arg=t,F(e,r),"throw"===r.method))return g;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return g}var o=f(n,e.iterator,r.arg);if("throw"===o.type)return r.method="throw",r.arg=o.arg,r.delegate=null,g;var i=o.arg;return i?i.done?(r[e.resultName]=i.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,g):i:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,g)}function L(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function P(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function k(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(L,this),this.reset(!0)}function S(e){if(e){var r=e[i];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,a=function r(){for(;++o=0;--i){var a=this.tryEntries[i],c=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var s=n.call(a,"catchLoc"),u=n.call(a,"finallyLoc");if(s&&u){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),P(r),g}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;P(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,r,n){return this.delegate={iterator:S(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),g}},e}(e.exports);try{regeneratorRuntime=t}catch(e){Function("r","regeneratorRuntime = r")(t)}},72:function(e,t,r){var n,o;void 0===(o="function"==typeof(n=function(){return function(){var e=arguments.length;if(0===e)throw new Error("resolveUrl requires at least one argument; got none.");var t=document.createElement("base");if(t.href=arguments[0],1===e)return t.href;var r=document.getElementsByTagName("head")[0];r.insertBefore(t,r.firstChild);for(var n,o=document.createElement("a"),i=1;i{"use strict";e.exports=JSON.parse('{"name":"@ffmpeg/ffmpeg","version":"0.10.1","description":"FFmpeg WebAssembly version","main":"src/index.js","types":"src/index.d.ts","directories":{"example":"examples"},"scripts":{"start":"node scripts/server.js","build":"rimraf dist && webpack --config scripts/webpack.config.prod.js","prepublishOnly":"npm run build","lint":"eslint src","wait":"rimraf dist && wait-on http://localhost:3000/dist/ffmpeg.dev.js","test":"npm-run-all -p -r start test:all","test:all":"npm-run-all wait test:browser:ffmpeg test:node:all","test:node":"node --experimental-wasm-threads --experimental-wasm-bulk-memory node_modules/.bin/_mocha --exit --bail --require ./scripts/test-helper.js","test:node:all":"npm run test:node -- ./tests/*.test.js","test:browser":"mocha-headless-chrome -a allow-file-access-from-files -a incognito -a no-sandbox -a disable-setuid-sandbox -a disable-logging -t 300000","test:browser:ffmpeg":"npm run test:browser -- -f ./tests/ffmpeg.test.html"},"browser":{"./src/node/index.js":"./src/browser/index.js"},"repository":{"type":"git","url":"git+https://github.com/ffmpegwasm/ffmpeg.wasm.git"},"keywords":["ffmpeg","WebAssembly","video"],"author":"Jerome Wu ","license":"MIT","bugs":{"url":"https://github.com/ffmpegwasm/ffmpeg.wasm/issues"},"engines":{"node":">=12.16.1"},"homepage":"https://github.com/ffmpegwasm/ffmpeg.wasm#readme","dependencies":{"is-url":"^1.2.4","node-fetch":"^2.6.1","regenerator-runtime":"^0.13.7","resolve-url":"^0.2.1"},"devDependencies":{"@babel/core":"^7.12.3","@babel/preset-env":"^7.12.1","@ffmpeg/core":"^0.10.0","@types/emscripten":"^1.39.4","babel-loader":"^8.1.0","chai":"^4.2.0","cors":"^2.8.5","eslint":"^7.12.1","eslint-config-airbnb-base":"^14.1.0","eslint-plugin-import":"^2.22.1","express":"^4.17.1","mocha":"^8.2.1","mocha-headless-chrome":"^2.0.3","npm-run-all":"^4.1.5","wait-on":"^5.3.0","webpack":"^5.3.2","webpack-cli":"^4.1.0","webpack-dev-middleware":"^4.0.0"}}')}},t={},function r(n){if(t[n])return t[n].exports;var o=t[n]={exports:{}};return e[n].call(o.exports,o,o.exports,r),o.exports}(352);var e,t}));
-//# sourceMappingURL=ffmpeg.min.js.map
\ No newline at end of file
diff --git a/editor/sw.js b/editor/sw.js
index 7553e8287e58da..3cec06c472b139 100644
--- a/editor/sw.js
+++ b/editor/sw.js
@@ -91,7 +91,6 @@ const assets = [
'./js/libs/codemirror/mode/glsl.js',
'./js/libs/esprima.js',
- './js/libs/ffmpeg.min.js',
'./js/libs/jsonlint.js',
'./js/libs/codemirror/addon/dialog.css',
diff --git a/examples/jsm/nodes/Nodes.js b/examples/jsm/nodes/Nodes.js
index bac1a3e9c4aea8..bdee9f3f6b045e 100644
--- a/examples/jsm/nodes/Nodes.js
+++ b/examples/jsm/nodes/Nodes.js
@@ -95,9 +95,9 @@ export { default as ModelViewProjectionNode, modelViewProjection } from './acces
export * from './accessors/NormalNode.js';
export { default as Object3DNode, objectDirection, objectViewMatrix, objectNormalMatrix, objectWorldMatrix, objectPosition, objectScale, objectViewPosition } from './accessors/Object3DNode.js';
export { default as PointUVNode, pointUV } from './accessors/PointUVNode.js';
-export { default as PositionNode, positionGeometry, positionLocal, positionWorld, positionWorldDirection, positionView, positionViewDirection } from './accessors/PositionNode.js';
+export * from './accessors/PositionNode.js';
export { default as ReferenceNode, reference, referenceBuffer } from './accessors/ReferenceNode.js';
-export { default as ReflectVectorNode, reflectVector } from './accessors/ReflectVectorNode.js';
+export * from './accessors/ReflectVectorNode.js';
export { default as SkinningNode, skinning } from './accessors/SkinningNode.js';
export { default as SceneNode, backgroundBlurriness, backgroundIntensity } from './accessors/SceneNode.js';
export { default as StorageBufferNode, storage, storageObject } from './accessors/StorageBufferNode.js';
@@ -105,7 +105,7 @@ export * from './accessors/TangentNode.js';
export { default as TextureNode, texture, textureLoad, /*textureLevel,*/ sampler } from './accessors/TextureNode.js';
export { default as TextureStoreNode, textureStore } from './accessors/TextureStoreNode.js';
export { default as Texture3DNode, texture3D } from './accessors/Texture3DNode.js';
-export { default as UVNode, uv } from './accessors/UVNode.js';
+export * from './accessors/UVNode.js';
export { default as UserDataNode, userData } from './accessors/UserDataNode.js';
// display
diff --git a/examples/jsm/nodes/accessors/BitangentNode.js b/examples/jsm/nodes/accessors/BitangentNode.js
index 03f10bdc77dfe4..877b9efe73c89e 100644
--- a/examples/jsm/nodes/accessors/BitangentNode.js
+++ b/examples/jsm/nodes/accessors/BitangentNode.js
@@ -5,9 +5,9 @@ import { tangentGeometry, tangentLocal, tangentView, tangentWorld, transformedTa
const getBitangent = ( crossNormalTangent ) => crossNormalTangent.mul( tangentGeometry.w ).xyz;
-export const bitangentGeometry = varying( getBitangent( normalGeometry.cross( tangentGeometry ) ) ).normalize();
-export const bitangentLocal = varying( getBitangent( normalLocal.cross( tangentLocal ) ) ).normalize();
-export const bitangentView = varying( getBitangent( normalView.cross( tangentView ) ) ).normalize();
-export const bitangentWorld = varying( getBitangent( normalWorld.cross( tangentWorld ) ) ).normalize();
-export const transformedBitangentView = getBitangent( transformedNormalView.cross( transformedTangentView ) ).normalize();
-export const transformedBitangentWorld = transformedBitangentView.transformDirection( cameraViewMatrix ).normalize();
+export const bitangentGeometry = /*#__PURE__*/ varying( getBitangent( normalGeometry.cross( tangentGeometry ) ), 'v_bitangentGeometry' ).normalize().toVar( 'bitangentGeometry' );
+export const bitangentLocal = /*#__PURE__*/ varying( getBitangent( normalLocal.cross( tangentLocal ) ), 'v_bitangentLocal' ).normalize().toVar( 'bitangentLocal' );
+export const bitangentView = /*#__PURE__*/ varying( getBitangent( normalView.cross( tangentView ) ), 'v_bitangentView' ).normalize().toVar( 'bitangentView' );
+export const bitangentWorld = /*#__PURE__*/ varying( getBitangent( normalWorld.cross( tangentWorld ) ), 'v_bitangentWorld' ).normalize().toVar( 'bitangentWorld' );
+export const transformedBitangentView = /*#__PURE__*/ getBitangent( transformedNormalView.cross( transformedTangentView ) ).normalize().toVar( 'transformedBitangentView' );
+export const transformedBitangentWorld = /*#__PURE__*/ transformedBitangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedBitangentWorld' );
diff --git a/examples/jsm/nodes/accessors/NormalNode.js b/examples/jsm/nodes/accessors/NormalNode.js
index 2f1c3ca14217dd..a9c99ff27d1973 100644
--- a/examples/jsm/nodes/accessors/NormalNode.js
+++ b/examples/jsm/nodes/accessors/NormalNode.js
@@ -6,9 +6,9 @@ import { modelNormalMatrix } from './ModelNode.js';
import { vec3 } from '../shadernode/ShaderNode.js';
export const normalGeometry = /*#__PURE__*/ attribute( 'normal', 'vec3', vec3( 0, 1, 0 ) );
-export const normalLocal = /*#__PURE__*/ varying( normalGeometry ).toVar( 'normalLocal' );
-export const normalView = /*#__PURE__*/ varying( modelNormalMatrix.mul( normalLocal ), 'normalView' ).normalize();
-export const normalWorld = /*#__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'normalWorld' ).normalize();
+export const normalLocal = /*#__PURE__*/ normalGeometry.toVar( 'normalLocal' );
+export const normalView = /*#__PURE__*/ varying( modelNormalMatrix.mul( normalLocal ), 'v_normalView' ).normalize().toVar( 'normalView' );
+export const normalWorld = /*#__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'v_normalWorld' ).normalize().toVar( 'transformedNormalWorld' );
export const transformedNormalView = /*#__PURE__*/ property( 'vec3', 'transformedNormalView' );
-export const transformedNormalWorld = /*#__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).normalize();
+export const transformedNormalWorld = /*#__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedNormalWorld' );
export const transformedClearcoatNormalView = /*#__PURE__*/ property( 'vec3', 'transformedClearcoatNormalView' );
diff --git a/examples/jsm/nodes/accessors/PositionNode.js b/examples/jsm/nodes/accessors/PositionNode.js
index 89dc162e2fd4ad..f77d84563b01af 100644
--- a/examples/jsm/nodes/accessors/PositionNode.js
+++ b/examples/jsm/nodes/accessors/PositionNode.js
@@ -1,104 +1,10 @@
-import Node, { addNodeClass } from '../core/Node.js';
import { attribute } from '../core/AttributeNode.js';
import { varying } from '../core/VaryingNode.js';
-import { normalize } from '../math/MathNode.js';
import { modelWorldMatrix, modelViewMatrix } from './ModelNode.js';
-import { nodeImmutable } from '../shadernode/ShaderNode.js';
-class PositionNode extends Node {
-
- constructor( scope = PositionNode.LOCAL ) {
-
- super( 'vec3' );
-
- this.scope = scope;
-
- }
-
- isGlobal() {
-
- return true;
-
- }
-
- getHash( /*builder*/ ) {
-
- return `position-${this.scope}`;
-
- }
-
- generate( builder ) {
-
- const scope = this.scope;
-
- let outputNode = null;
-
- if ( scope === PositionNode.GEOMETRY ) {
-
- outputNode = attribute( 'position', 'vec3' );
-
- } else if ( scope === PositionNode.LOCAL ) {
-
- outputNode = varying( positionGeometry );
-
- } else if ( scope === PositionNode.WORLD ) {
-
- const vertexPositionNode = modelWorldMatrix.mul( positionLocal );
- outputNode = varying( vertexPositionNode );
-
- } else if ( scope === PositionNode.VIEW ) {
-
- const vertexPositionNode = modelViewMatrix.mul( positionLocal );
- outputNode = varying( vertexPositionNode );
-
- } else if ( scope === PositionNode.VIEW_DIRECTION ) {
-
- const vertexPositionNode = positionView.negate();
- outputNode = normalize( varying( vertexPositionNode ) );
-
- } else if ( scope === PositionNode.WORLD_DIRECTION ) {
-
- const vertexPositionNode = positionLocal.transformDirection( modelWorldMatrix );
- outputNode = normalize( varying( vertexPositionNode ) );
-
- }
-
- return outputNode.build( builder, this.getNodeType( builder ) );
-
- }
-
- serialize( data ) {
-
- super.serialize( data );
-
- data.scope = this.scope;
-
- }
-
- deserialize( data ) {
-
- super.deserialize( data );
-
- this.scope = data.scope;
-
- }
-
-}
-
-PositionNode.GEOMETRY = 'geometry';
-PositionNode.LOCAL = 'local';
-PositionNode.WORLD = 'world';
-PositionNode.WORLD_DIRECTION = 'worldDirection';
-PositionNode.VIEW = 'view';
-PositionNode.VIEW_DIRECTION = 'viewDirection';
-
-export default PositionNode;
-
-export const positionGeometry = nodeImmutable( PositionNode, PositionNode.GEOMETRY );
-export const positionLocal = nodeImmutable( PositionNode, PositionNode.LOCAL ).temp( 'Position' );
-export const positionWorld = nodeImmutable( PositionNode, PositionNode.WORLD );
-export const positionWorldDirection = nodeImmutable( PositionNode, PositionNode.WORLD_DIRECTION );
-export const positionView = nodeImmutable( PositionNode, PositionNode.VIEW );
-export const positionViewDirection = nodeImmutable( PositionNode, PositionNode.VIEW_DIRECTION );
-
-addNodeClass( 'PositionNode', PositionNode );
+export const positionGeometry = /*#__PURE__*/ attribute( 'position', 'vec3' );
+export const positionLocal = /*#__PURE__*/ positionGeometry.toVar( 'positionLocal' );
+export const positionWorld = /*#__PURE__*/ varying( modelWorldMatrix.mul( positionLocal ).xyz, 'v_positionWorld' );
+export const positionWorldDirection = /*#__PURE__*/ varying( positionLocal.transformDirection( modelWorldMatrix ), 'v_positionWorldDirection' ).normalize().toVar( 'positionWorldDirection' );
+export const positionView = /*#__PURE__*/ varying( modelViewMatrix.mul( positionLocal ).xyz, 'v_positionView' );
+export const positionViewDirection = /*#__PURE__*/ varying( positionView.negate(), 'v_positionViewDirection' ).normalize().toVar( 'positionViewDirection' );
diff --git a/examples/jsm/nodes/accessors/ReflectVectorNode.js b/examples/jsm/nodes/accessors/ReflectVectorNode.js
index b552b268e91704..ced16b3993b5c1 100644
--- a/examples/jsm/nodes/accessors/ReflectVectorNode.js
+++ b/examples/jsm/nodes/accessors/ReflectVectorNode.js
@@ -1,35 +1,6 @@
-import Node, { addNodeClass } from '../core/Node.js';
import { cameraViewMatrix } from './CameraNode.js';
import { transformedNormalView } from './NormalNode.js';
import { positionViewDirection } from './PositionNode.js';
-import { nodeImmutable } from '../shadernode/ShaderNode.js';
-class ReflectVectorNode extends Node {
-
- constructor() {
-
- super( 'vec3' );
-
- }
-
- getHash( /*builder*/ ) {
-
- return 'reflectVector';
-
- }
-
- setup() {
-
- const reflectView = positionViewDirection.negate().reflect( transformedNormalView );
-
- return reflectView.transformDirection( cameraViewMatrix );
-
- }
-
-}
-
-export default ReflectVectorNode;
-
-export const reflectVector = nodeImmutable( ReflectVectorNode );
-
-addNodeClass( 'ReflectVectorNode', ReflectVectorNode );
+export const reflectView = /*#__PURE__*/ positionViewDirection.negate().reflect( transformedNormalView );
+export const reflectVector = /*#__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' );
diff --git a/examples/jsm/nodes/accessors/TangentNode.js b/examples/jsm/nodes/accessors/TangentNode.js
index e8f85e69a3e813..f2e5726d258b89 100644
--- a/examples/jsm/nodes/accessors/TangentNode.js
+++ b/examples/jsm/nodes/accessors/TangentNode.js
@@ -16,8 +16,8 @@ export const tangentGeometry = /*#__PURE__*/ tslFn( ( stack, builder ) => {
} )();
-export const tangentLocal = /*#__PURE__*/ varying( tangentGeometry.xyz, 'tangentLocal' );
-export const tangentView = /*#__PURE__*/ varying( modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz, 'tangentView' ).normalize();
-export const tangentWorld = /*#__PURE__*/ varying( tangentView.transformDirection( cameraViewMatrix ), 'tangentWorld' ).normalize();
+export const tangentLocal = /*#__PURE__*/ tangentGeometry.xyz.toVar( 'tangentLocal' );
+export const tangentView = /*#__PURE__*/ varying( modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz, 'v_tangentView' ).normalize().toVar( 'tangentView' );
+export const tangentWorld = /*#__PURE__*/ varying( tangentView.transformDirection( cameraViewMatrix ), 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' );
export const transformedTangentView = /*#__PURE__*/ tangentView.toVar( 'transformedTangentView' );
-export const transformedTangentWorld = /*#__PURE__*/ transformedTangentView.transformDirection( cameraViewMatrix ).normalize();
+export const transformedTangentWorld = /*#__PURE__*/ transformedTangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedTangentWorld' );
diff --git a/examples/jsm/nodes/accessors/UVNode.js b/examples/jsm/nodes/accessors/UVNode.js
index 473545eb081582..4789a74bc36d67 100644
--- a/examples/jsm/nodes/accessors/UVNode.js
+++ b/examples/jsm/nodes/accessors/UVNode.js
@@ -1,47 +1,3 @@
-import { addNodeClass } from '../core/Node.js';
-import AttributeNode from '../core/AttributeNode.js';
-import { nodeObject } from '../shadernode/ShaderNode.js';
+import { attribute } from '../core/AttributeNode.js';
-class UVNode extends AttributeNode {
-
- constructor( index = 0 ) {
-
- super( null, 'vec2' );
-
- this.isUVNode = true;
-
- this.index = index;
-
- }
-
- getAttributeName( /*builder*/ ) {
-
- const index = this.index;
-
- return 'uv' + ( index > 0 ? index : '' );
-
- }
-
- serialize( data ) {
-
- super.serialize( data );
-
- data.index = this.index;
-
- }
-
- deserialize( data ) {
-
- super.deserialize( data );
-
- this.index = data.index;
-
- }
-
-}
-
-export default UVNode;
-
-export const uv = ( ...params ) => nodeObject( new UVNode( ...params ) );
-
-addNodeClass( 'UVNode', UVNode );
+export const uv = ( index ) => attribute( 'uv' + ( index > 0 ? index : '' ), 'vec2' );
diff --git a/examples/jsm/nodes/core/ContextNode.js b/examples/jsm/nodes/core/ContextNode.js
index b776b9644d2861..d2873507d6bbc9 100644
--- a/examples/jsm/nodes/core/ContextNode.js
+++ b/examples/jsm/nodes/core/ContextNode.js
@@ -20,6 +20,12 @@ class ContextNode extends Node {
}
+ analyze( builder ) {
+
+ this.node.build( builder );
+
+ }
+
setup( builder ) {
const previousContext = builder.getContext();
diff --git a/examples/jsm/nodes/core/Node.js b/examples/jsm/nodes/core/Node.js
index 79ad31a86324f4..007186bef09f20 100644
--- a/examples/jsm/nodes/core/Node.js
+++ b/examples/jsm/nodes/core/Node.js
@@ -25,6 +25,8 @@ class Node extends EventDispatcher {
this._cacheKey = null;
this._cacheKeyVersion = 0;
+ this.global = false;
+
this.isNode = true;
Object.defineProperty( this, 'id', { value: _nodeId ++ } );
@@ -98,7 +100,7 @@ class Node extends EventDispatcher {
isGlobal( /*builder*/ ) {
- return false;
+ return this.global;
}
@@ -199,9 +201,11 @@ class Node extends EventDispatcher {
const nodeProperties = builder.getNodeProperties( this );
+ let index = 0;
+
for ( const childNode of this.getChildren() ) {
- nodeProperties[ '_node' + childNode.id ] = childNode;
+ nodeProperties[ 'node' + index ++ ] = childNode;
}
diff --git a/examples/jsm/nodes/core/NodeBuilder.js b/examples/jsm/nodes/core/NodeBuilder.js
index a496c6d6152c0c..08aedc074008b7 100644
--- a/examples/jsm/nodes/core/NodeBuilder.js
+++ b/examples/jsm/nodes/core/NodeBuilder.js
@@ -80,7 +80,7 @@ class NodeBuilder {
this.computeShader = null;
this.flowNodes = { vertex: [], fragment: [], compute: [] };
- this.flowCode = { vertex: '', fragment: '', compute: [] };
+ this.flowCode = { vertex: '', fragment: '', compute: '' };
this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 };
this.structs = { vertex: [], fragment: [], compute: [], index: 0 };
this.bindings = { vertex: [], fragment: [], compute: [] };
@@ -415,12 +415,6 @@ class NodeBuilder {
}
- generateMethod( method ) {
-
- return method;
-
- }
-
hasGeometryAttribute( name ) {
return this.geometry && this.geometry.getAttribute( name ) !== undefined;
@@ -917,7 +911,9 @@ class NodeBuilder {
const previousFlow = this.flow;
const previousVars = this.vars;
+ const previousCache = this.cache;
const previousBuildStage = this.buildStage;
+ const previousStack = this.stack;
const flow = {
code: ''
@@ -925,6 +921,8 @@ class NodeBuilder {
this.flow = flow;
this.vars = {};
+ this.cache = new NodeCache();
+ this.stack = stack();
for ( const buildStage of defaultBuildStages ) {
@@ -938,6 +936,9 @@ class NodeBuilder {
this.flow = previousFlow;
this.vars = previousVars;
+ this.cache = previousCache;
+ this.stack = previousStack;
+
this.setBuildStage( previousBuildStage );
return flow;
diff --git a/examples/jsm/nodes/core/VaryingNode.js b/examples/jsm/nodes/core/VaryingNode.js
index ceac05cf35b73b..2bcff5398d8534 100644
--- a/examples/jsm/nodes/core/VaryingNode.js
+++ b/examples/jsm/nodes/core/VaryingNode.js
@@ -66,13 +66,20 @@ class VaryingNode extends Node {
generate( builder ) {
- const type = this.getNodeType( builder );
+ const properties = builder.getNodeProperties( this );
const varying = this.setupVarying( builder );
- const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX );
+ if ( properties.propertyName === undefined ) {
+
+ const type = this.getNodeType( builder );
+ const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX );
+
+ // force node run in vertex stage
+ builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName );
+
+ properties.propertyName = propertyName;
- // force node run in vertex stage
- builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName );
+ }
return builder.getPropertyName( varying );
diff --git a/examples/jsm/nodes/display/PassNode.js b/examples/jsm/nodes/display/PassNode.js
index cd9e440a4d1422..acfdd502651ab0 100644
--- a/examples/jsm/nodes/display/PassNode.js
+++ b/examples/jsm/nodes/display/PassNode.js
@@ -7,6 +7,8 @@ import { uniform } from '../core/UniformNode.js';
import { viewZToOrthographicDepth, perspectiveDepthToViewZ } from './ViewportDepthNode.js';
import { RenderTarget, Vector2, HalfFloatType, DepthTexture, NoToneMapping/*, FloatType*/ } from 'three';
+const _size = new Vector2();
+
class PassTextureNode extends TextureNode {
constructor( passNode, texture ) {
@@ -135,7 +137,7 @@ class PassNode extends TempNode {
this._pixelRatio = renderer.getPixelRatio();
- const size = renderer.getSize( new Vector2() );
+ const size = renderer.getSize( _size );
this.setSize( size.width, size.height );
diff --git a/examples/jsm/nodes/functions/PhysicalLightingModel.js b/examples/jsm/nodes/functions/PhysicalLightingModel.js
index 3a4d332b527707..ecfc0085bc7901 100644
--- a/examples/jsm/nodes/functions/PhysicalLightingModel.js
+++ b/examples/jsm/nodes/functions/PhysicalLightingModel.js
@@ -331,7 +331,7 @@ const IBLSheenBRDF = tslFn( ( { normal, viewDir, roughness } ) => {
} );
const clearcoatF0 = vec3( 0.04 );
-const clearcoatF90 = vec3( 1 );
+const clearcoatF90 = float( 1 );
//
diff --git a/examples/jsm/nodes/lighting/LightsNode.js b/examples/jsm/nodes/lighting/LightsNode.js
index d8f88251317987..57b058967e8526 100644
--- a/examples/jsm/nodes/lighting/LightsNode.js
+++ b/examples/jsm/nodes/lighting/LightsNode.js
@@ -53,6 +53,18 @@ class LightsNode extends Node {
}
+ analyze( builder ) {
+
+ const properties = builder.getDataFromNode( this );
+
+ for ( const node of properties.nodes ) {
+
+ node.build( builder );
+
+ }
+
+ }
+
setup( builder ) {
const context = builder.context;
@@ -70,6 +82,11 @@ class LightsNode extends Node {
//
+ const properties = builder.getDataFromNode( this );
+ properties.nodes = stack.nodes;
+
+ //
+
lightingModel.start( context, stack, builder );
// lights
diff --git a/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js b/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js
index 91495702d2fc48..e42b658b5f9642 100644
--- a/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js
+++ b/examples/jsm/nodes/materials/MeshPhysicalNodeMaterial.js
@@ -3,6 +3,7 @@ import { transformedClearcoatNormalView } from '../accessors/NormalNode.js';
import { clearcoat, clearcoatRoughness, sheen, sheenRoughness, iridescence, iridescenceIOR, iridescenceThickness, specularColor, specularF90, diffuseColor, metalness, roughness, anisotropy, alphaT, anisotropyT, anisotropyB, ior, transmission, thickness, attenuationDistance, attenuationColor, dispersion } from '../core/PropertyNode.js';
import { materialClearcoat, materialClearcoatRoughness, materialClearcoatNormal, materialSheen, materialSheenRoughness, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialSpecularIntensity, materialSpecularColor, materialAnisotropy, materialIOR, materialTransmission, materialThickness, materialAttenuationDistance, materialAttenuationColor, materialDispersion } from '../accessors/MaterialNode.js';
import { float, vec2, vec3, If } from '../shadernode/ShaderNode.js';
+import getRoughness from '../functions/material/getRoughness.js';
import { TBNViewMatrix } from '../accessors/AccessorsUtils.js';
import PhysicalLightingModel from '../functions/PhysicalLightingModel.js';
import MeshStandardNodeMaterial from './MeshStandardNodeMaterial.js';
@@ -112,7 +113,7 @@ class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial {
const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness;
clearcoat.assign( clearcoatNode );
- clearcoatRoughness.assign( clearcoatRoughnessNode );
+ clearcoatRoughness.assign( getRoughness( { roughness: clearcoatRoughnessNode } ) );
}
diff --git a/examples/jsm/nodes/shadernode/ShaderNode.js b/examples/jsm/nodes/shadernode/ShaderNode.js
index 6daedb977d5c0b..39054ee312bac9 100644
--- a/examples/jsm/nodes/shadernode/ShaderNode.js
+++ b/examples/jsm/nodes/shadernode/ShaderNode.js
@@ -531,6 +531,16 @@ addNodeClass( 'ShaderNode', ShaderNode );
//
+addNodeElement( 'toGlobal', ( node ) => {
+
+ node.global = true;
+
+ return node;
+
+} );
+
+//
+
export const setCurrentStack = ( stack ) => {
if ( currentStack === stack ) {
diff --git a/examples/jsm/renderers/common/Attributes.js b/examples/jsm/renderers/common/Attributes.js
index afb3467cf66ed5..b1330ba66be168 100644
--- a/examples/jsm/renderers/common/Attributes.js
+++ b/examples/jsm/renderers/common/Attributes.js
@@ -22,6 +22,8 @@ class Attributes extends DataMap {
}
+ return attributeData;
+
}
update( attribute, type ) {
diff --git a/examples/jsm/renderers/common/Pipelines.js b/examples/jsm/renderers/common/Pipelines.js
index afb176f1b7ee93..4cae37d1260006 100644
--- a/examples/jsm/renderers/common/Pipelines.js
+++ b/examples/jsm/renderers/common/Pipelines.js
@@ -67,7 +67,7 @@ class Pipelines extends DataMap {
if ( pipeline === undefined ) {
- if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( computeNode );
+ if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline );
pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings );
@@ -205,7 +205,7 @@ class Pipelines extends DataMap {
}
- super.delete( object );
+ return super.delete( object );
}
diff --git a/examples/jsm/renderers/common/Uniform.js b/examples/jsm/renderers/common/Uniform.js
index 4386d3e755e025..23bcf5ad382cfb 100644
--- a/examples/jsm/renderers/common/Uniform.js
+++ b/examples/jsm/renderers/common/Uniform.js
@@ -2,7 +2,7 @@ import { Color, Matrix3, Matrix4, Vector2, Vector3, Vector4 } from 'three';
class Uniform {
- constructor( name, value = null ) {
+ constructor( name, value ) {
this.name = name;
this.value = value;
diff --git a/examples/screenshots/webgpu_clearcoat.jpg b/examples/screenshots/webgpu_clearcoat.jpg
index 19bd4024d71182..7dfb0d565f2ea0 100644
Binary files a/examples/screenshots/webgpu_clearcoat.jpg and b/examples/screenshots/webgpu_clearcoat.jpg differ
diff --git a/examples/webgpu_clearcoat.html b/examples/webgpu_clearcoat.html
index 0f8c37c5589944..1f8551e2db2207 100644
--- a/examples/webgpu_clearcoat.html
+++ b/examples/webgpu_clearcoat.html
@@ -24,7 +24,6 @@
import * as THREE from 'three';
- import WebGPU from 'three/addons/capabilities/WebGPU.js';
import WebGPURenderer from 'three/addons/renderers/webgpu/WebGPURenderer.js';
import Stats from 'three/addons/libs/stats.module.js';
@@ -45,14 +44,6 @@
function init() {
- if ( WebGPU.isAvailable() === false ) {
-
- document.body.appendChild( WebGPU.getErrorMessage() );
-
- throw new Error( 'No WebGPU support' );
-
- }
-
container = document.createElement( 'div' );
document.body.appendChild( container );