troika-three-utils
Advanced tools
Comparing version 0.15.0 to 0.15.3
@@ -1,2 +0,2 @@ | ||
import { ShaderChunk, UniformsUtils, ShaderLib, DataTexture } from 'three'; | ||
import { ShaderChunk, UniformsUtils, MeshDepthMaterial, RGBADepthPacking, MeshDistanceMaterial, ShaderLib, DataTexture } from 'three'; | ||
@@ -45,2 +45,3 @@ /** | ||
var idCtr = 0; | ||
var epoch = Date.now(); | ||
var CACHE = new WeakMap(); //threejs requires WeakMap internally so should be safe to assume support | ||
@@ -62,2 +63,6 @@ | ||
* in a ShaderMaterial. You do not need to repeat the base material's own uniforms here. | ||
* @param {String} options.timeUniform - If specified, a uniform of this name will be injected into | ||
* both shaders, and it will automatically be updated on each render frame with a number of | ||
* elapsed milliseconds. The "zero" epoch time is not significant so don't rely on this as a | ||
* true calendar time. | ||
* @param {String} options.vertexDefs - Custom GLSL code to inject into the vertex shader's top-level | ||
@@ -79,2 +84,11 @@ * definitions, above the `void main()` function. | ||
* @return {THREE.Material} | ||
* | ||
* The returned material will also have two new methods, `getDepthMaterial()` and `getDistanceMaterial()`, | ||
* which can be called to get a variant of the derived material for use in shadow casting. If the | ||
* target mesh is expected to cast shadows, then you can assign these to the mesh's `customDepthMaterial` | ||
* (for directional and spot lights) and/or `customDistanceMaterial` (for point lights) properties to | ||
* allow the cast shadow to honor your derived shader's vertex transforms and discarded fragments. These | ||
* will also set a custom `#define IS_DEPTH_MATERIAL` or `#define IS_DISTANCE_MATERIAL` that you can look | ||
* for in your derived shaders with `#ifdef` to customize their behavior for the depth or distance | ||
* scenarios, e.g. skipping antialiasing or expensive shader logic. | ||
*/ | ||
@@ -98,2 +112,3 @@ function createDerivedMaterial(baseMaterial, options) { | ||
var privateBeforeCompileProp = "_onBeforeCompile" + id; | ||
var depthMaterial, distanceMaterial; | ||
@@ -122,2 +137,9 @@ // Private onBeforeCompile handler that injects the modified shaders and uniforms when | ||
// Inject auto-updating time uniform if requested | ||
if (options.timeUniform) { | ||
shaderInfo.uniforms[options.timeUniform] = { | ||
get value() {return Date.now() - epoch} | ||
}; | ||
} | ||
// Users can still add their own handlers on top of ours | ||
@@ -131,2 +153,3 @@ if (this[privateBeforeCompileProp]) { | ||
baseMaterial.constructor.apply(this, arguments); | ||
this._listeners = undefined; //don't inherit EventDispatcher listeners | ||
} | ||
@@ -157,3 +180,46 @@ DerivedMaterial.prototype = Object.create(baseMaterial, { | ||
} | ||
} | ||
}, | ||
/** | ||
* Utility to get a MeshDepthMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDepthMaterial: {value: function value() { | ||
if (!depthMaterial) { | ||
depthMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDepthMaterial() | ||
: new MeshDepthMaterial({depthPacking: RGBADepthPacking}), | ||
options | ||
); | ||
depthMaterial.defines.IS_DEPTH_MATERIAL = ''; | ||
} | ||
return depthMaterial | ||
}}, | ||
/** | ||
* Utility to get a MeshDistanceMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDistanceMaterial: {value: function value() { | ||
if (!distanceMaterial) { | ||
distanceMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDistanceMaterial() | ||
: new MeshDistanceMaterial(), | ||
options | ||
); | ||
distanceMaterial.defines.IS_DISTANCE_MATERIAL = ''; | ||
} | ||
return distanceMaterial | ||
}}, | ||
dispose: {value: function value() { | ||
var ref = this; | ||
var _depthMaterial = ref._depthMaterial; | ||
var _distanceMaterial = ref._distanceMaterial; | ||
if (_depthMaterial) { _depthMaterial.dispose(); } | ||
if (_distanceMaterial) { _distanceMaterial.dispose(); } | ||
baseMaterial.dispose.call(this); | ||
}} | ||
}); | ||
@@ -185,3 +251,11 @@ | ||
var fragmentColorTransform = options.fragmentColorTransform; | ||
var timeUniform = options.timeUniform; | ||
// Inject auto-updating time uniform if requested | ||
if (timeUniform) { | ||
var code = "\nuniform float " + timeUniform + ";\n"; | ||
vertexDefs = (vertexDefs || '') + code; | ||
fragmentDefs = (fragmentDefs || '') + code; | ||
} | ||
// Modify vertex shader | ||
@@ -188,0 +262,0 @@ if (vertexDefs || vertexMainIntro || vertexTransform) { |
@@ -49,2 +49,3 @@ (function (global, factory) { | ||
var idCtr = 0; | ||
var epoch = Date.now(); | ||
var CACHE = new WeakMap(); //threejs requires WeakMap internally so should be safe to assume support | ||
@@ -66,2 +67,6 @@ | ||
* in a ShaderMaterial. You do not need to repeat the base material's own uniforms here. | ||
* @param {String} options.timeUniform - If specified, a uniform of this name will be injected into | ||
* both shaders, and it will automatically be updated on each render frame with a number of | ||
* elapsed milliseconds. The "zero" epoch time is not significant so don't rely on this as a | ||
* true calendar time. | ||
* @param {String} options.vertexDefs - Custom GLSL code to inject into the vertex shader's top-level | ||
@@ -83,2 +88,11 @@ * definitions, above the `void main()` function. | ||
* @return {THREE.Material} | ||
* | ||
* The returned material will also have two new methods, `getDepthMaterial()` and `getDistanceMaterial()`, | ||
* which can be called to get a variant of the derived material for use in shadow casting. If the | ||
* target mesh is expected to cast shadows, then you can assign these to the mesh's `customDepthMaterial` | ||
* (for directional and spot lights) and/or `customDistanceMaterial` (for point lights) properties to | ||
* allow the cast shadow to honor your derived shader's vertex transforms and discarded fragments. These | ||
* will also set a custom `#define IS_DEPTH_MATERIAL` or `#define IS_DISTANCE_MATERIAL` that you can look | ||
* for in your derived shaders with `#ifdef` to customize their behavior for the depth or distance | ||
* scenarios, e.g. skipping antialiasing or expensive shader logic. | ||
*/ | ||
@@ -102,2 +116,3 @@ function createDerivedMaterial(baseMaterial, options) { | ||
var privateBeforeCompileProp = "_onBeforeCompile" + id; | ||
var depthMaterial, distanceMaterial; | ||
@@ -126,2 +141,9 @@ // Private onBeforeCompile handler that injects the modified shaders and uniforms when | ||
// Inject auto-updating time uniform if requested | ||
if (options.timeUniform) { | ||
shaderInfo.uniforms[options.timeUniform] = { | ||
get value() {return Date.now() - epoch} | ||
}; | ||
} | ||
// Users can still add their own handlers on top of ours | ||
@@ -135,2 +157,3 @@ if (this[privateBeforeCompileProp]) { | ||
baseMaterial.constructor.apply(this, arguments); | ||
this._listeners = undefined; //don't inherit EventDispatcher listeners | ||
} | ||
@@ -161,3 +184,46 @@ DerivedMaterial.prototype = Object.create(baseMaterial, { | ||
} | ||
} | ||
}, | ||
/** | ||
* Utility to get a MeshDepthMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDepthMaterial: {value: function value() { | ||
if (!depthMaterial) { | ||
depthMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDepthMaterial() | ||
: new three.MeshDepthMaterial({depthPacking: three.RGBADepthPacking}), | ||
options | ||
); | ||
depthMaterial.defines.IS_DEPTH_MATERIAL = ''; | ||
} | ||
return depthMaterial | ||
}}, | ||
/** | ||
* Utility to get a MeshDistanceMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDistanceMaterial: {value: function value() { | ||
if (!distanceMaterial) { | ||
distanceMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDistanceMaterial() | ||
: new three.MeshDistanceMaterial(), | ||
options | ||
); | ||
distanceMaterial.defines.IS_DISTANCE_MATERIAL = ''; | ||
} | ||
return distanceMaterial | ||
}}, | ||
dispose: {value: function value() { | ||
var ref = this; | ||
var _depthMaterial = ref._depthMaterial; | ||
var _distanceMaterial = ref._distanceMaterial; | ||
if (_depthMaterial) { _depthMaterial.dispose(); } | ||
if (_distanceMaterial) { _distanceMaterial.dispose(); } | ||
baseMaterial.dispose.call(this); | ||
}} | ||
}); | ||
@@ -189,3 +255,11 @@ | ||
var fragmentColorTransform = options.fragmentColorTransform; | ||
var timeUniform = options.timeUniform; | ||
// Inject auto-updating time uniform if requested | ||
if (timeUniform) { | ||
var code = "\nuniform float " + timeUniform + ";\n"; | ||
vertexDefs = (vertexDefs || '') + code; | ||
fragmentDefs = (fragmentDefs || '') + code; | ||
} | ||
// Modify vertex shader | ||
@@ -192,0 +266,0 @@ if (vertexDefs || vertexMainIntro || vertexTransform) { |
@@ -1,13 +0,14 @@ | ||
'use strict';(function(f,k){"object"===typeof exports&&"undefined"!==typeof module?k(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],k):(f=f||self,k(f.troika_three_utils={},f.THREE))})(this,function(f,k){function l(a){return a.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(a,c){return(c=k.ShaderChunk[c])?l(c):a})}function u(a,b,c){var d=a.vertexShader;a=a.fragmentShader;var g=b.vertexDefs,e=b.vertexMainIntro,f=b.vertexTransform,h=b.fragmentDefs,k=b.fragmentMainIntro; | ||
b=b.fragmentColorTransform;if(g||e||f)f&&(d=l(d),g=(g||"")+"\nvoid troikaVertexTransform"+c+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+f+"\n}\n",d=d.replace(/\b(position|normal|uv)\b/g,function(a,b,d,e){return/\battribute\s+vec3\s+$/.test(e.substr(0,d))?b:"troika_"+b+"_"+c}),e="\nvec3 troika_position_"+c+" = vec3(position);\nvec3 troika_normal_"+c+" = vec3(normal);\nvec2 troika_uv_"+c+" = vec2(uv);\ntroikaVertexTransform"+c+"(troika_position_"+c+", troika_normal_"+c+", troika_uv_"+ | ||
c+");\n"+(e||"")+"\n"),d=d.replace(p,(g||"")+"\n\n$&\n\n"+(e||""));if(h||k||b)a=l(a),a=a.replace(p,"\n"+(h||"")+"\nvoid troikaOrigMain"+c+"() {\n"+(k||"")+"\n"),a+="\nvoid main() {\n troikaOrigMain"+c+"();\n "+(b||"")+"\n}";return{vertexShader:d,fragmentShader:a}}function v(a,b){return"uniforms"===a?void 0:b}function r(a,b,c){a*=255;var d=a%1*255,g=d%1*255;var e=Math.round(g%1*255)&255;b[c]=a&255;b[c+1]=d&255;b[c+2]=g&255;b[c+3]=e;return b}var p=/\bvoid\s+main\s*\(\s*\)\s*{/g,n=Object.assign||function(){for(var a= | ||
arguments,b=arguments[0],c=1,d=arguments.length;c<d;c++){var g=a[c];if(g)for(var e in g)g.hasOwnProperty(e)&&(b[e]=g[e])}return b},w=0,t=new WeakMap,x={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"phong",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points", | ||
ShadowMaterial:"shadow",SpriteMaterial:"sprite"},h=function(a){this.name=a;this.textureUniform="dataTex_"+a;this.textureSizeUniform="dataTexSize_"+a;this.multiplierUniform="dataMultiplier_"+a;this.dataSizeUniform="dataSize_"+a;this.readFunction="readData_"+a;this._raw=new Float32Array(0);this._texture=new k.DataTexture(new Uint8Array(0),0,1);this._length=0;this._multiplier=1},q={length:{configurable:!0}};q.length.set=function(a){if(a!==this._length){var b=Math.pow(2,Math.ceil(Math.log2(a))),c=this._raw; | ||
b<c.length?this._raw=c.subarray(0,b):b>c.length&&(this._raw=new Float32Array(b),this._raw.set(c));this._length=a}};q.length.get=function(){return this._length};h.prototype.push=function(a){return this.set(this.length++,a)};h.prototype.setArray=function(a){this.length=a.length;this._raw.set(a);this._needsRepack=!0};h.prototype.get=function(a){return this._raw[a]};h.prototype.set=function(a,b){a+1>this._length&&(this.length=a+1);b!==this._raw[a]&&(this._raw[a]=b,r(b/this._multiplier,this._texture.image.data, | ||
4*a),this._needsMultCheck=!0)};h.prototype.clone=function(){var a=new h(this.name);a.setArray(this._raw);return a};h.prototype.getShaderUniforms=function(){var a,b=this;return a={},a[this.textureUniform]={get value(){b._sync();return b._texture}},a[this.textureSizeUniform]={get value(){b._sync();return b._texture.image.width}},a[this.dataSizeUniform]={get value(){b._sync();return b.length}},a[this.multiplierUniform]={get value(){b._sync();return b._multiplier}},a};h.prototype.getShaderHeaderCode= | ||
function(){var a=this.textureUniform,b=this.textureSizeUniform,c=this.multiplierUniform;return"\nuniform sampler2D "+a+";\nuniform float "+b+";\nuniform float "+this.dataSizeUniform+";\nuniform float "+c+";\n\nfloat "+this.readFunction+"(float index) {\n vec2 texUV = vec2((index + 0.5) / "+b+", 0.5);\n vec4 pixel = texture2D("+a+", texUV);\n return dot(pixel, 1.0 / vec4(1.0, 255.0, 65025.0, 16581375.0)) * "+c+";\n}\n"};h.prototype._sync=function(){var a=this._texture,b=this._raw,c=this._needsRepack; | ||
b.length!==a.image.width&&(a.image={data:new Uint8Array(4*b.length),width:b.length,height:1},c=!0);if(c||this._needsMultCheck){var d=this._raw.reduce(function(a,b){return Math.max(a,b)},0);d=Math.pow(2,Math.ceil(Math.log2(d)));d!==this._multiplier&&(this._multiplier=d,c=!0);a.needsUpdate=!0;this._needsMultCheck=!1}if(c){c=0;d=b.length;for(var g=this._multiplier;c<d;c++)r(b[c]/g,a.image.data,4*c);this._needsRepack=!1}};Object.defineProperties(h.prototype,q);f.ShaderFloatArray=h;f.createDerivedMaterial= | ||
function(a,b){function c(c){a.onBeforeCompile.call(this,c);var d=this[h]||(this[h]={vertex:{},fragment:{}}),e=d.vertex;d=d.fragment;if(e.source!==c.vertexShader||d.source!==c.fragmentShader){var g=u(c,b,f);e.source=c.vertexShader;e.result=g.vertexShader;d.source=c.fragmentShader;d.result=g.fragmentShader}c.vertexShader=e.result;c.fragmentShader=d.result;n(c.uniforms,this.uniforms);if(this[l])this[l](c)}function d(){a.constructor.apply(this,arguments)}var g=JSON.stringify(b,v),e=t.get(a);e||(e=Object.create(null), | ||
t.set(a,e));if(e[g])return e[g].clone();var f=++w,h="_derivedShaders"+f,l="_onBeforeCompile"+f;d.prototype=Object.create(a,{constructor:{value:d},isDerivedMaterial:{value:!0},baseMaterial:{value:a},onBeforeCompile:{get:function(){return c},set:function(a){this[l]=a}},copy:{value:function(b){a.copy.call(this,b);a.isShaderMaterial||a.isDerivedMaterial||(this.extensions=b.extensions,this.defines=n({},b.defines),this.uniforms=k.UniformsUtils.clone(b.uniforms));return this}}});var m=new d;m.copy(a);m.uniforms= | ||
n(k.UniformsUtils.clone(a.uniforms||{}),b.uniforms);m.defines=n({},a.defines,b.defines);m.defines.TROIKA_DERIVED_MATERIAL=f;m.extensions=n({},a.extensions,b.extensions);e[g]=m;return m.clone()};f.expandShaderIncludes=l;f.getShaderUniformTypes=function(a){for(var b=/\buniform\s+(int|float|vec[234])\s+([A-Za-z_][\w]*)/g,c=Object.create(null),d;null!==(d=b.exec(a));)c[d[2]]=d[1];return c};f.getShadersForMaterial=function(a){var b=x[a.type];return b?k.ShaderLib[b]:a};f.voidMainRegExp=p;Object.defineProperty(f, | ||
"__esModule",{value:!0})}); | ||
'use strict';(function(f,k){"object"===typeof exports&&"undefined"!==typeof module?k(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],k):(f=f||self,k(f.troika_three_utils={},f.THREE))})(this,function(f,k){function p(a){return a.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(a,c){return(c=k.ShaderChunk[c])?p(c):a})}function r(a,b){function c(c){a.onBeforeCompile.call(this,c);var d=this[h]||(this[h]={vertex:{},fragment:{}}),e=d.vertex;d=d.fragment;if(e.source!== | ||
c.vertexShader||d.source!==c.fragmentShader){var g=y(c,b,f);e.source=c.vertexShader;e.result=g.vertexShader;d.source=c.fragmentShader;d.result=g.fragmentShader}c.vertexShader=e.result;c.fragmentShader=d.result;n(c.uniforms,this.uniforms);b.timeUniform&&(c.uniforms[b.timeUniform]={get value(){return Date.now()-z}});if(this[t])this[t](c)}function d(){a.constructor.apply(this,arguments);this._listeners=void 0}var e=JSON.stringify(b,A),g=w.get(a);g||(g=Object.create(null),w.set(a,g));if(g[e])return g[e].clone(); | ||
var f=++B,h="_derivedShaders"+f,t="_onBeforeCompile"+f,l,q;d.prototype=Object.create(a,{constructor:{value:d},isDerivedMaterial:{value:!0},baseMaterial:{value:a},onBeforeCompile:{get:function(){return c},set:function(a){this[t]=a}},copy:{value:function(b){a.copy.call(this,b);a.isShaderMaterial||a.isDerivedMaterial||(this.extensions=b.extensions,this.defines=n({},b.defines),this.uniforms=k.UniformsUtils.clone(b.uniforms));return this}},getDepthMaterial:{value:function(){l||(l=r(a.isDerivedMaterial? | ||
a.getDepthMaterial():new k.MeshDepthMaterial({depthPacking:k.RGBADepthPacking}),b),l.defines.IS_DEPTH_MATERIAL="");return l}},getDistanceMaterial:{value:function(){q||(q=r(a.isDerivedMaterial?a.getDistanceMaterial():new k.MeshDistanceMaterial,b),q.defines.IS_DISTANCE_MATERIAL="");return q}},dispose:{value:function(){var b=this._depthMaterial,c=this._distanceMaterial;b&&b.dispose();c&&c.dispose();a.dispose.call(this)}}});var m=new d;m.copy(a);m.uniforms=n(k.UniformsUtils.clone(a.uniforms||{}),b.uniforms); | ||
m.defines=n({},a.defines,b.defines);m.defines.TROIKA_DERIVED_MATERIAL=f;m.extensions=n({},a.extensions,b.extensions);g[e]=m;return m.clone()}function y(a,b,c){var d=a.vertexShader;a=a.fragmentShader;var e=b.vertexDefs,g=b.vertexMainIntro,f=b.vertexTransform,h=b.fragmentDefs,k=b.fragmentMainIntro,l=b.fragmentColorTransform;if(b=b.timeUniform)b="\nuniform float "+b+";\n",e=(e||"")+b,h=(h||"")+b;if(e||g||f)f&&(d=p(d),e=(e||"")+"\nvoid troikaVertexTransform"+c+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+ | ||
f+"\n}\n",d=d.replace(/\b(position|normal|uv)\b/g,function(a,b,d,e){return/\battribute\s+vec3\s+$/.test(e.substr(0,d))?b:"troika_"+b+"_"+c}),g="\nvec3 troika_position_"+c+" = vec3(position);\nvec3 troika_normal_"+c+" = vec3(normal);\nvec2 troika_uv_"+c+" = vec2(uv);\ntroikaVertexTransform"+c+"(troika_position_"+c+", troika_normal_"+c+", troika_uv_"+c+");\n"+(g||"")+"\n"),d=d.replace(u,(e||"")+"\n\n$&\n\n"+(g||""));if(h||k||l)a=p(a),a=a.replace(u,"\n"+(h||"")+"\nvoid troikaOrigMain"+c+"() {\n"+(k|| | ||
"")+"\n"),a+="\nvoid main() {\n troikaOrigMain"+c+"();\n "+(l||"")+"\n}";return{vertexShader:d,fragmentShader:a}}function A(a,b){return"uniforms"===a?void 0:b}function x(a,b,c){a*=255;var d=a%1*255,e=d%1*255;var g=Math.round(e%1*255)&255;b[c]=a&255;b[c+1]=d&255;b[c+2]=e&255;b[c+3]=g;return b}var u=/\bvoid\s+main\s*\(\s*\)\s*{/g,n=Object.assign||function(){for(var a=arguments,b=arguments[0],c=1,d=arguments.length;c<d;c++){var e=a[c];if(e)for(var g in e)e.hasOwnProperty(g)&&(b[g]=e[g])}return b}, | ||
B=0,z=Date.now(),w=new WeakMap,C={MeshDepthMaterial:"depth",MeshDistanceMaterial:"distanceRGBA",MeshNormalMaterial:"normal",MeshBasicMaterial:"basic",MeshLambertMaterial:"lambert",MeshPhongMaterial:"phong",MeshToonMaterial:"phong",MeshStandardMaterial:"physical",MeshPhysicalMaterial:"physical",MeshMatcapMaterial:"matcap",LineBasicMaterial:"basic",LineDashedMaterial:"dashed",PointsMaterial:"points",ShadowMaterial:"shadow",SpriteMaterial:"sprite"},h=function(a){this.name=a;this.textureUniform="dataTex_"+ | ||
a;this.textureSizeUniform="dataTexSize_"+a;this.multiplierUniform="dataMultiplier_"+a;this.dataSizeUniform="dataSize_"+a;this.readFunction="readData_"+a;this._raw=new Float32Array(0);this._texture=new k.DataTexture(new Uint8Array(0),0,1);this._length=0;this._multiplier=1},v={length:{configurable:!0}};v.length.set=function(a){if(a!==this._length){var b=Math.pow(2,Math.ceil(Math.log2(a))),c=this._raw;b<c.length?this._raw=c.subarray(0,b):b>c.length&&(this._raw=new Float32Array(b),this._raw.set(c));this._length= | ||
a}};v.length.get=function(){return this._length};h.prototype.push=function(a){return this.set(this.length++,a)};h.prototype.setArray=function(a){this.length=a.length;this._raw.set(a);this._needsRepack=!0};h.prototype.get=function(a){return this._raw[a]};h.prototype.set=function(a,b){a+1>this._length&&(this.length=a+1);b!==this._raw[a]&&(this._raw[a]=b,x(b/this._multiplier,this._texture.image.data,4*a),this._needsMultCheck=!0)};h.prototype.clone=function(){var a=new h(this.name);a.setArray(this._raw); | ||
return a};h.prototype.getShaderUniforms=function(){var a,b=this;return a={},a[this.textureUniform]={get value(){b._sync();return b._texture}},a[this.textureSizeUniform]={get value(){b._sync();return b._texture.image.width}},a[this.dataSizeUniform]={get value(){b._sync();return b.length}},a[this.multiplierUniform]={get value(){b._sync();return b._multiplier}},a};h.prototype.getShaderHeaderCode=function(){var a=this.textureUniform,b=this.textureSizeUniform,c=this.multiplierUniform;return"\nuniform sampler2D "+ | ||
a+";\nuniform float "+b+";\nuniform float "+this.dataSizeUniform+";\nuniform float "+c+";\n\nfloat "+this.readFunction+"(float index) {\n vec2 texUV = vec2((index + 0.5) / "+b+", 0.5);\n vec4 pixel = texture2D("+a+", texUV);\n return dot(pixel, 1.0 / vec4(1.0, 255.0, 65025.0, 16581375.0)) * "+c+";\n}\n"};h.prototype._sync=function(){var a=this._texture,b=this._raw,c=this._needsRepack;b.length!==a.image.width&&(a.image={data:new Uint8Array(4*b.length),width:b.length,height:1},c=!0);if(c||this._needsMultCheck){var d= | ||
this._raw.reduce(function(a,b){return Math.max(a,b)},0);d=Math.pow(2,Math.ceil(Math.log2(d)));d!==this._multiplier&&(this._multiplier=d,c=!0);a.needsUpdate=!0;this._needsMultCheck=!1}if(c){c=0;d=b.length;for(var e=this._multiplier;c<d;c++)x(b[c]/e,a.image.data,4*c);this._needsRepack=!1}};Object.defineProperties(h.prototype,v);f.ShaderFloatArray=h;f.createDerivedMaterial=r;f.expandShaderIncludes=p;f.getShaderUniformTypes=function(a){for(var b=/\buniform\s+(int|float|vec[234])\s+([A-Za-z_][\w]*)/g, | ||
c=Object.create(null),d;null!==(d=b.exec(a));)c[d[2]]=d[1];return c};f.getShadersForMaterial=function(a){var b=C[a.type];return b?k.ShaderLib[b]:a};f.voidMainRegExp=u;Object.defineProperty(f,"__esModule",{value:!0})}); |
{ | ||
"name": "troika-three-utils", | ||
"version": "0.15.0", | ||
"version": "0.15.3", | ||
"description": "Various utilities related to Three.js", | ||
@@ -17,3 +17,3 @@ "author": "Jason Johnston <jason.johnston@protectwise.com>", | ||
"module:es2015": "src/index.js", | ||
"gitHead": "ed0883f7a7093a15de489ce750c042f8112a94d4" | ||
"gitHead": "5286e414c66aa8c471091aaaea28c08b86bed0f6" | ||
} |
import { voidMainRegExp } from './voidMainRegExp.js' | ||
import { expandShaderIncludes } from './expandShaderIncludes.js' | ||
import { UniformsUtils } from 'three' | ||
import { MeshDepthMaterial, MeshDistanceMaterial, RGBADepthPacking, UniformsUtils } from 'three' | ||
@@ -24,2 +24,3 @@ | ||
let idCtr = 0 | ||
const epoch = Date.now() | ||
const CACHE = new WeakMap() //threejs requires WeakMap internally so should be safe to assume support | ||
@@ -41,2 +42,6 @@ | ||
* in a ShaderMaterial. You do not need to repeat the base material's own uniforms here. | ||
* @param {String} options.timeUniform - If specified, a uniform of this name will be injected into | ||
* both shaders, and it will automatically be updated on each render frame with a number of | ||
* elapsed milliseconds. The "zero" epoch time is not significant so don't rely on this as a | ||
* true calendar time. | ||
* @param {String} options.vertexDefs - Custom GLSL code to inject into the vertex shader's top-level | ||
@@ -58,2 +63,11 @@ * definitions, above the `void main()` function. | ||
* @return {THREE.Material} | ||
* | ||
* The returned material will also have two new methods, `getDepthMaterial()` and `getDistanceMaterial()`, | ||
* which can be called to get a variant of the derived material for use in shadow casting. If the | ||
* target mesh is expected to cast shadows, then you can assign these to the mesh's `customDepthMaterial` | ||
* (for directional and spot lights) and/or `customDistanceMaterial` (for point lights) properties to | ||
* allow the cast shadow to honor your derived shader's vertex transforms and discarded fragments. These | ||
* will also set a custom `#define IS_DEPTH_MATERIAL` or `#define IS_DISTANCE_MATERIAL` that you can look | ||
* for in your derived shaders with `#ifdef` to customize their behavior for the depth or distance | ||
* scenarios, e.g. skipping antialiasing or expensive shader logic. | ||
*/ | ||
@@ -77,2 +91,3 @@ export function createDerivedMaterial(baseMaterial, options) { | ||
const privateBeforeCompileProp = `_onBeforeCompile${id}` | ||
let depthMaterial, distanceMaterial | ||
@@ -99,2 +114,9 @@ // Private onBeforeCompile handler that injects the modified shaders and uniforms when | ||
// Inject auto-updating time uniform if requested | ||
if (options.timeUniform) { | ||
shaderInfo.uniforms[options.timeUniform] = { | ||
get value() {return Date.now() - epoch} | ||
} | ||
} | ||
// Users can still add their own handlers on top of ours | ||
@@ -108,2 +130,3 @@ if (this[privateBeforeCompileProp]) { | ||
baseMaterial.constructor.apply(this, arguments) | ||
this._listeners = undefined //don't inherit EventDispatcher listeners | ||
} | ||
@@ -134,3 +157,44 @@ DerivedMaterial.prototype = Object.create(baseMaterial, { | ||
} | ||
} | ||
}, | ||
/** | ||
* Utility to get a MeshDepthMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDepthMaterial: {value() { | ||
if (!depthMaterial) { | ||
depthMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDepthMaterial() | ||
: new MeshDepthMaterial({depthPacking: RGBADepthPacking}), | ||
options | ||
) | ||
depthMaterial.defines.IS_DEPTH_MATERIAL = '' | ||
} | ||
return depthMaterial | ||
}}, | ||
/** | ||
* Utility to get a MeshDistanceMaterial that will honor this derived material's vertex | ||
* transformations and discarded fragments. | ||
*/ | ||
getDistanceMaterial: {value() { | ||
if (!distanceMaterial) { | ||
distanceMaterial = createDerivedMaterial( | ||
baseMaterial.isDerivedMaterial | ||
? baseMaterial.getDistanceMaterial() | ||
: new MeshDistanceMaterial(), | ||
options | ||
) | ||
distanceMaterial.defines.IS_DISTANCE_MATERIAL = '' | ||
} | ||
return distanceMaterial | ||
}}, | ||
dispose: {value() { | ||
const {_depthMaterial, _distanceMaterial} = this | ||
if (_depthMaterial) _depthMaterial.dispose() | ||
if (_distanceMaterial) _distanceMaterial.dispose() | ||
baseMaterial.dispose.call(this) | ||
}} | ||
}) | ||
@@ -159,5 +223,13 @@ | ||
fragmentMainIntro, | ||
fragmentColorTransform | ||
fragmentColorTransform, | ||
timeUniform | ||
} = options | ||
// Inject auto-updating time uniform if requested | ||
if (timeUniform) { | ||
const code = `\nuniform float ${timeUniform};\n` | ||
vertexDefs = (vertexDefs || '') + code | ||
fragmentDefs = (fragmentDefs || '') + code | ||
} | ||
// Modify vertex shader | ||
@@ -164,0 +236,0 @@ if (vertexDefs || vertexMainIntro || vertexTransform) { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
80804
1754