New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

troika-three-utils

Package Overview
Dependencies
Maintainers
1
Versions
46
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

troika-three-utils - npm Package Compare versions

Comparing version 0.20.0 to 0.21.0

13

CHANGELOG.md

@@ -6,2 +6,15 @@ # Change Log

# [0.21.0](https://github.com/protectwise/troika/compare/v0.20.0...v0.21.0) (2020-03-27)
### Features
* **examples:** beziers: add instanceable version of the beziers, and add point light option ([0739f4d](https://github.com/protectwise/troika/commit/0739f4d6ebcdd13be46b6371c95504b290c86359))
* **troika-three-utils:** added new options for createDerivedMaterial ([d67bb4a](https://github.com/protectwise/troika/commit/d67bb4a569e151efad87a047e845607226f02027))
* **troika-three-utils:** derived shadow material uniforms are now synced automatically ([7843f23](https://github.com/protectwise/troika/commit/7843f2314caf9463262a16b15de948931b4b6511))
# [0.20.0](https://github.com/protectwise/troika/compare/v0.19.0...v0.20.0) (2020-03-16)

@@ -8,0 +21,0 @@

140

dist/troika-three-utils.esm.js

@@ -68,2 +68,4 @@ import { ShaderChunk, UniformsUtils, MeshDepthMaterial, RGBADepthPacking, MeshDistanceMaterial, ShaderLib, DataTexture, Vector3, MeshStandardMaterial, DoubleSide, Mesh, CylinderBufferGeometry, Vector2 } from 'three';

* shader's `void main` function.
* @param {String} options.vertexMainOutro - Custom GLSL code to inject at the end of the vertex
* shader's `void main` function.
* @param {String} options.vertexTransform - Custom GLSL code to manipulate the `position`, `normal`,

@@ -76,5 +78,11 @@ * and/or `uv` vertex attributes. This code will be wrapped within a standalone function with

* shader's `void main` function.
* @param {String} options.fragmentMainOutro - Custom GLSL code to inject at the end of the fragment
* shader's `void main` function.
* @param {String} options.fragmentColorTransform - Custom GLSL code to manipulate the `gl_FragColor`
* output value. Will be injected after all other `void main` logic has executed.
* TODO allow injecting before base shader logic or elsewhere?
* output value. Will be injected after all other `void main` logic has executed but just before
* the `fragmentMainOutro`. TODO allow injecting in other places?
* @param {function<{vertexShader,fragmentShader}>:{vertexShader,fragmentShader}} options.customRewriter - A function
* for performing custom rewrites of the full shader code. Useful if you need to do something
* special that's not covered by the other builtin options. This function will be executed before
* any other transforms are applied.
*

@@ -191,2 +199,3 @@ * @return {THREE.Material}

depthMaterial = this._depthMaterial = depthMaterialTpl.clone();
depthMaterial.uniforms = this.uniforms; //automatically recieve same uniform values
}

@@ -213,2 +222,3 @@ return depthMaterial

distanceMaterial = this._distanceMaterial = distanceMaterialTpl.clone();
distanceMaterial.uniforms = this.uniforms; //automatically recieve same uniform values
}

@@ -244,25 +254,52 @@ return distanceMaterial

vertexMainIntro,
vertexMainOutro,
vertexTransform,
fragmentDefs,
fragmentMainIntro,
fragmentMainOutro,
fragmentColorTransform,
customRewriter,
timeUniform
} = options;
vertexDefs = vertexDefs || '';
vertexMainIntro = vertexMainIntro || '';
vertexMainOutro = vertexMainOutro || '';
fragmentDefs = fragmentDefs || '';
fragmentMainIntro = fragmentMainIntro || '';
fragmentMainOutro = fragmentMainOutro || '';
// Expand includes if needed
if (vertexTransform || customRewriter) {
vertexShader = expandShaderIncludes(vertexShader);
}
if (fragmentColorTransform || customRewriter) {
fragmentShader = expandShaderIncludes(fragmentShader);
}
// Apply custom rewriter function
if (customRewriter) {
let res = customRewriter({vertexShader, fragmentShader});
vertexShader = res.vertexShader;
fragmentShader = res.fragmentShader;
}
// Treat fragmentColorTransform as an outro
if (fragmentColorTransform) {
fragmentMainOutro = `${fragmentColorTransform}\n${fragmentMainOutro}`;
}
// Inject auto-updating time uniform if requested
if (timeUniform) {
const code = `\nuniform float ${timeUniform};\n`;
vertexDefs = (vertexDefs || '') + code;
fragmentDefs = (fragmentDefs || '') + code;
vertexDefs += code;
fragmentDefs += code;
}
// Modify vertex shader
if (vertexDefs || vertexMainIntro || vertexTransform) {
// If there's a position transform, we need to:
// - expand all include statements
// - replace all usages of the `position` attribute with a mutable variable
// - inject the transform code into a function and call it to transform the position
if (vertexTransform) {
vertexShader = expandShaderIncludes(vertexShader);
vertexDefs = `${vertexDefs || ''}
// Inject a function for the vertexTransform and rename all usages of position/normal/uv
if (vertexTransform) {
vertexDefs = `${vertexDefs}
vec3 troika_position_${id};
vec3 troika_normal_${id};
vec2 troika_uv_${id};
void troikaVertexTransform${id}(inout vec3 position, inout vec3 normal, inout vec2 uv) {

@@ -272,33 +309,17 @@ ${vertexTransform}

`;
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, (match, match1, index, fullStr) => {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : `troika_${match1}_${id}`
});
vertexMainIntro = `
vec3 troika_position_${id} = vec3(position);
vec3 troika_normal_${id} = vec3(normal);
vec2 troika_uv_${id} = vec2(uv);
vertexMainIntro = `
troika_position_${id} = vec3(position);
troika_normal_${id} = vec3(normal);
troika_uv_${id} = vec2(uv);
troikaVertexTransform${id}(troika_position_${id}, troika_normal_${id}, troika_uv_${id});
${vertexMainIntro || ''}
${vertexMainIntro}
`;
}
vertexShader = vertexShader.replace(
voidMainRegExp,
`${vertexDefs || ''}\n\n$&\n\n${vertexMainIntro || ''}`);
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, (match, match1, index, fullStr) => {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : `troika_${match1}_${id}`
});
}
// Modify fragment shader
if (fragmentDefs || fragmentMainIntro || fragmentColorTransform) {
fragmentShader = expandShaderIncludes(fragmentShader);
fragmentShader = fragmentShader.replace(voidMainRegExp, `
${fragmentDefs || ''}
void troikaOrigMain${id}() {
${fragmentMainIntro || ''}
`);
fragmentShader += `
void main() {
troikaOrigMain${id}();
${fragmentColorTransform || ''}
}`;
}
// Inject defs and intro/outro snippets
vertexShader = injectIntoShaderCode(vertexShader, id, vertexDefs, vertexMainIntro, vertexMainOutro);
fragmentShader = injectIntoShaderCode(fragmentShader, id, fragmentDefs, fragmentMainIntro, fragmentMainOutro);

@@ -311,2 +332,17 @@ return {

function injectIntoShaderCode(shaderCode, id, defs, intro, outro) {
if (intro || outro || defs) {
shaderCode = shaderCode.replace(voidMainRegExp, `
${defs}
void troikaOrigMain${id}() {`
);
shaderCode += `
void main() {
${intro}
troikaOrigMain${id}();
${outro}
}`;
}
return shaderCode
}

@@ -316,4 +352,5 @@ function getOptionsHash(options) {

}
function optionsJsonReplacer(key, value) {
return key === 'uniforms' ? undefined : value
return key === 'uniforms' ? undefined : typeof value === 'function' ? value.toString() : value
}

@@ -769,7 +806,11 @@

class BezierMesh extends Mesh {
static getGeometry() {
return geometry || (geometry =
new CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
)
}
constructor() {
super(
geometry || (geometry =
new CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
),
BezierMesh.getGeometry(),
defaultBaseMaterial

@@ -815,14 +856,10 @@ );

get customDepthMaterial() {
return this._updateBezierUniforms(this.material.getDepthMaterial())
return this.material.getDepthMaterial()
}
get customDistanceMaterial() {
return this._updateBezierUniforms(this.material.getDistanceMaterial())
return this.material.getDistanceMaterial()
}
onBeforeRender(shaderInfo) {
this._updateBezierUniforms(this.material);
}
_updateBezierUniforms(material) {
const {uniforms} = material;
const {uniforms} = this.material;
const {pointA, controlA, controlB, pointB, radius, dashArray, dashOffset} = this;

@@ -835,3 +872,2 @@ uniforms.pointA.value.copy(pointA);

uniforms.dashing.value.set(dashArray.x, dashArray.y, dashOffset || 0);
return material
}

@@ -838,0 +874,0 @@

@@ -74,2 +74,4 @@ (function (global, factory) {

* shader's `void main` function.
* @param {String} options.vertexMainOutro - Custom GLSL code to inject at the end of the vertex
* shader's `void main` function.
* @param {String} options.vertexTransform - Custom GLSL code to manipulate the `position`, `normal`,

@@ -82,5 +84,11 @@ * and/or `uv` vertex attributes. This code will be wrapped within a standalone function with

* shader's `void main` function.
* @param {String} options.fragmentMainOutro - Custom GLSL code to inject at the end of the fragment
* shader's `void main` function.
* @param {String} options.fragmentColorTransform - Custom GLSL code to manipulate the `gl_FragColor`
* output value. Will be injected after all other `void main` logic has executed.
* TODO allow injecting before base shader logic or elsewhere?
* output value. Will be injected after all other `void main` logic has executed but just before
* the `fragmentMainOutro`. TODO allow injecting in other places?
* @param {function<{vertexShader,fragmentShader}>:{vertexShader,fragmentShader}} options.customRewriter - A function
* for performing custom rewrites of the full shader code. Useful if you need to do something
* special that's not covered by the other builtin options. This function will be executed before
* any other transforms are applied.
*

@@ -199,2 +207,3 @@ * @return {THREE.Material}

depthMaterial = this._depthMaterial = depthMaterialTpl.clone();
depthMaterial.uniforms = this.uniforms; //automatically recieve same uniform values
}

@@ -221,2 +230,3 @@ return depthMaterial

distanceMaterial = this._distanceMaterial = distanceMaterialTpl.clone();
distanceMaterial.uniforms = this.uniforms; //automatically recieve same uniform values
}

@@ -256,41 +266,57 @@ return distanceMaterial

var vertexMainIntro = options.vertexMainIntro;
var vertexMainOutro = options.vertexMainOutro;
var vertexTransform = options.vertexTransform;
var fragmentDefs = options.fragmentDefs;
var fragmentMainIntro = options.fragmentMainIntro;
var fragmentMainOutro = options.fragmentMainOutro;
var fragmentColorTransform = options.fragmentColorTransform;
var customRewriter = options.customRewriter;
var timeUniform = options.timeUniform;
vertexDefs = vertexDefs || '';
vertexMainIntro = vertexMainIntro || '';
vertexMainOutro = vertexMainOutro || '';
fragmentDefs = fragmentDefs || '';
fragmentMainIntro = fragmentMainIntro || '';
fragmentMainOutro = fragmentMainOutro || '';
// Expand includes if needed
if (vertexTransform || customRewriter) {
vertexShader = expandShaderIncludes(vertexShader);
}
if (fragmentColorTransform || customRewriter) {
fragmentShader = expandShaderIncludes(fragmentShader);
}
// Apply custom rewriter function
if (customRewriter) {
var res = customRewriter({vertexShader: vertexShader, fragmentShader: fragmentShader});
vertexShader = res.vertexShader;
fragmentShader = res.fragmentShader;
}
// Treat fragmentColorTransform as an outro
if (fragmentColorTransform) {
fragmentMainOutro = fragmentColorTransform + "\n" + fragmentMainOutro;
}
// Inject auto-updating time uniform if requested
if (timeUniform) {
var code = "\nuniform float " + timeUniform + ";\n";
vertexDefs = (vertexDefs || '') + code;
fragmentDefs = (fragmentDefs || '') + code;
vertexDefs += code;
fragmentDefs += code;
}
// Modify vertex shader
if (vertexDefs || vertexMainIntro || vertexTransform) {
// If there's a position transform, we need to:
// - expand all include statements
// - replace all usages of the `position` attribute with a mutable variable
// - inject the transform code into a function and call it to transform the position
if (vertexTransform) {
vertexShader = expandShaderIncludes(vertexShader);
vertexDefs = (vertexDefs || '') + "\nvoid troikaVertexTransform" + id + "(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n " + vertexTransform + "\n}\n";
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, function (match, match1, index, fullStr) {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : ("troika_" + match1 + "_" + id)
});
vertexMainIntro = "\nvec3 troika_position_" + id + " = vec3(position);\nvec3 troika_normal_" + id + " = vec3(normal);\nvec2 troika_uv_" + id + " = vec2(uv);\ntroikaVertexTransform" + id + "(troika_position_" + id + ", troika_normal_" + id + ", troika_uv_" + id + ");\n" + (vertexMainIntro || '') + "\n";
}
vertexShader = vertexShader.replace(
voidMainRegExp,
((vertexDefs || '') + "\n\n$&\n\n" + (vertexMainIntro || '')));
// Inject a function for the vertexTransform and rename all usages of position/normal/uv
if (vertexTransform) {
vertexDefs = vertexDefs + "\nvec3 troika_position_" + id + ";\nvec3 troika_normal_" + id + ";\nvec2 troika_uv_" + id + ";\nvoid troikaVertexTransform" + id + "(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n " + vertexTransform + "\n}\n";
vertexMainIntro = "\ntroika_position_" + id + " = vec3(position);\ntroika_normal_" + id + " = vec3(normal);\ntroika_uv_" + id + " = vec2(uv);\ntroikaVertexTransform" + id + "(troika_position_" + id + ", troika_normal_" + id + ", troika_uv_" + id + ");\n" + vertexMainIntro + "\n";
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, function (match, match1, index, fullStr) {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : ("troika_" + match1 + "_" + id)
});
}
// Modify fragment shader
if (fragmentDefs || fragmentMainIntro || fragmentColorTransform) {
fragmentShader = expandShaderIncludes(fragmentShader);
fragmentShader = fragmentShader.replace(voidMainRegExp, ("\n" + (fragmentDefs || '') + "\nvoid troikaOrigMain" + id + "() {\n" + (fragmentMainIntro || '') + "\n"));
fragmentShader += "\nvoid main() {\n troikaOrigMain" + id + "();\n " + (fragmentColorTransform || '') + "\n}";
}
// Inject defs and intro/outro snippets
vertexShader = injectIntoShaderCode(vertexShader, id, vertexDefs, vertexMainIntro, vertexMainOutro);
fragmentShader = injectIntoShaderCode(fragmentShader, id, fragmentDefs, fragmentMainIntro, fragmentMainOutro);

@@ -303,2 +329,10 @@ return {

function injectIntoShaderCode(shaderCode, id, defs, intro, outro) {
if (intro || outro || defs) {
shaderCode = shaderCode.replace(voidMainRegExp, ("\n" + defs + "\nvoid troikaOrigMain" + id + "() {")
);
shaderCode += "\nvoid main() {\n " + intro + "\n troikaOrigMain" + id + "();\n " + outro + "\n}";
}
return shaderCode
}

@@ -308,4 +342,5 @@ function getOptionsHash(options) {

}
function optionsJsonReplacer(key, value) {
return key === 'uniforms' ? undefined : value
return key === 'uniforms' ? undefined : typeof value === 'function' ? value.toString() : value
}

@@ -696,5 +731,3 @@

Mesh.call(
this, geometry || (geometry =
new three.CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
),
this, BezierMesh.getGeometry(),
defaultBaseMaterial

@@ -724,2 +757,8 @@ );

// lazily on _read_ rather than write to avoid unnecessary wrapping on transient values.
BezierMesh.getGeometry = function getGeometry () {
return geometry || (geometry =
new three.CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
)
};
prototypeAccessors.material.get = function () {

@@ -747,22 +786,19 @@ var derivedMaterial = this._derivedMaterial;

prototypeAccessors.customDepthMaterial.get = function () {
return this._updateBezierUniforms(this.material.getDepthMaterial())
return this.material.getDepthMaterial()
};
prototypeAccessors.customDistanceMaterial.get = function () {
return this._updateBezierUniforms(this.material.getDistanceMaterial())
return this.material.getDistanceMaterial()
};
BezierMesh.prototype.onBeforeRender = function onBeforeRender (shaderInfo) {
this._updateBezierUniforms(this.material);
};
BezierMesh.prototype._updateBezierUniforms = function _updateBezierUniforms (material) {
var uniforms = material.uniforms;
var ref = this;
var pointA = ref.pointA;
var controlA = ref.controlA;
var controlB = ref.controlB;
var pointB = ref.pointB;
var radius = ref.radius;
var dashArray = ref.dashArray;
var dashOffset = ref.dashOffset;
var ref = this.material;
var uniforms = ref.uniforms;
var ref$1 = this;
var pointA = ref$1.pointA;
var controlA = ref$1.controlA;
var controlB = ref$1.controlB;
var pointB = ref$1.pointB;
var radius = ref$1.radius;
var dashArray = ref$1.dashArray;
var dashOffset = ref$1.dashOffset;
uniforms.pointA.value.copy(pointA);

@@ -774,3 +810,2 @@ uniforms.controlA.value.copy(controlA);

uniforms.dashing.value.set(dashArray.x, dashArray.y, dashOffset || 0);
return material
};

@@ -777,0 +812,0 @@

@@ -1,20 +0,20 @@

'use strict';(function(h,d){"object"===typeof exports&&"undefined"!==typeof module?d(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],d):(h=h||self,d(h.troika_three_utils={},h.THREE))})(this,function(h,d){function r(a){return a.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(a,c){return(c=d.ShaderChunk[c])?r(c):a})}function t(a,b){function c(c){a.onBeforeCompile.call(this,c);var e=this[h]||(this[h]={vertex:{},fragment:{}}),f=e.vertex;e=e.fragment;if(f.source!==
c.vertexShader||e.source!==c.fragmentShader){var d=A(c,b,n);f.source=c.vertexShader;f.result=d.vertexShader;e.source=c.fragmentShader;e.result=d.fragmentShader}c.vertexShader=f.result;c.fragmentShader=e.result;k(c.uniforms,this.uniforms);b.timeUniform&&(c.uniforms[b.timeUniform]={get value(){return Date.now()-B}});if(this[g])this[g](c)}function e(){a.constructor.apply(this,arguments);this._listeners=void 0}var f=JSON.stringify(b,C),p=w.get(a);p||(p=Object.create(null),w.set(a,p));if(p[f])return p[f].clone();
var n=++D,h="_derivedShaders"+n,g="_onBeforeCompile"+n,l,u;e.prototype=Object.create(a,{constructor:{value:e},isDerivedMaterial:{value:!0},baseMaterial:{value:a},onBeforeCompile:{get:function(){return c},set:function(a){this[g]=a}},copy:{value:function(b){a.copy.call(this,b);a.isShaderMaterial||a.isDerivedMaterial||(this.extensions=k({},b.extensions),this.defines=k({},b.defines),this.uniforms=d.UniformsUtils.clone(b.uniforms));return this}},getDepthMaterial:{value:function(){var c=this._depthMaterial;
c||(u||(u=t(a.isDerivedMaterial?a.getDepthMaterial():new d.MeshDepthMaterial({depthPacking:d.RGBADepthPacking}),b),u.defines.IS_DEPTH_MATERIAL=""),c=this._depthMaterial=u.clone());return c}},getDistanceMaterial:{value:function(){var c=this._distanceMaterial;c||(l||(l=t(a.isDerivedMaterial?a.getDistanceMaterial():new d.MeshDistanceMaterial,b),l.defines.IS_DISTANCE_MATERIAL=""),c=this._distanceMaterial=l.clone());return c}},dispose:{value:function(){var b=this._depthMaterial,c=this._distanceMaterial;
b&&b.dispose();c&&c.dispose();a.dispose.call(this)}}});var m=new e;m.copy(a);m.uniforms=k(d.UniformsUtils.clone(a.uniforms||{}),b.uniforms);m.defines=k({},a.defines,b.defines);m.defines.TROIKA_DERIVED_MATERIAL=n;m.extensions=k({},a.extensions,b.extensions);p[f]=m;return m.clone()}function A(a,b,c){var e=a.vertexShader;a=a.fragmentShader;var f=b.vertexDefs,d=b.vertexMainIntro,h=b.vertexTransform,g=b.fragmentDefs,k=b.fragmentMainIntro,l=b.fragmentColorTransform;if(b=b.timeUniform)b="\nuniform float "+
b+";\n",f=(f||"")+b,g=(g||"")+b;if(f||d||h)h&&(e=r(e),f=(f||"")+"\nvoid troikaVertexTransform"+c+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+h+"\n}\n",e=e.replace(/\b(position|normal|uv)\b/g,function(a,b,e,f){return/\battribute\s+vec[23]\s+$/.test(f.substr(0,e))?b:"troika_"+b+"_"+c}),d="\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"+(d||"")+"\n"),e=e.replace(v,(f||"")+"\n\n$&\n\n"+(d||""));if(g||k||l)a=r(a),a=a.replace(v,"\n"+(g||"")+"\nvoid troikaOrigMain"+c+"() {\n"+(k||"")+"\n"),a+="\nvoid main() {\n troikaOrigMain"+c+"();\n "+(l||"")+"\n}";return{vertexShader:e,fragmentShader:a}}function C(a,b){return"uniforms"===a?void 0:b}function x(a,b,c){a*=255;var e=a%1*255,f=e%1*255;var d=Math.round(f%1*255)&255;b[c]=a&255;b[c+1]=e&255;b[c+2]=f&255;b[c+3]=d;return b}var v=/\bvoid\s+main\s*\(\s*\)\s*{/g,k=Object.assign||function(){for(var a=
arguments,b=arguments[0],c=1,e=arguments.length;c<e;c++){var f=a[c];if(f)for(var d in f)f.hasOwnProperty(d)&&(b[d]=f[d])}return b},D=0,B=Date.now(),w=new WeakMap,E={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"},g=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 d.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};g.prototype.push=function(a){return this.set(this.length++,a)};g.prototype.setArray=function(a){this.length=a.length;this._raw.set(a);this._needsRepack=!0};g.prototype.get=function(a){return this._raw[a]};g.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)};g.prototype.clone=function(){var a=new g(this.name);a.setArray(this._raw);return a};g.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};g.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"};g.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 e=this._raw.reduce(function(a,b){return Math.max(a,b)},0);e=Math.pow(2,Math.ceil(Math.log2(e)));e!==this._multiplier&&(this._multiplier=e,c=!0);a.needsUpdate=!0;this._needsMultCheck=!1}if(c){c=0;e=b.length;for(var d=this._multiplier;c<e;c++)x(b[c]/d,a.image.data,4*c);this._needsRepack=!1}};Object.defineProperties(g.prototype,q);var y=null,z=new d.MeshStandardMaterial({color:16777215,
side:d.DoubleSide});q=function(a){function b(){a.call(this,y||(y=(new d.CylinderBufferGeometry(1,1,1,6,64)).translate(0,.5,0)),z);this.pointA=new d.Vector3;this.controlA=new d.Vector3;this.controlB=new d.Vector3;this.pointB=new d.Vector3;this.radius=.01;this.dashArray=new d.Vector2;this.dashOffset=0;this.frustumCulled=!1}a&&(b.__proto__=a);b.prototype=Object.create(a&&a.prototype);b.prototype.constructor=b;var c={material:{configurable:!0},customDepthMaterial:{configurable:!0},customDistanceMaterial:{configurable:!0}};
c.material.get=function(){var a=this._derivedMaterial,b=this._baseMaterial||z;a&&a.baseMaterial===b||(a&&a.dispose(),a=this._derivedMaterial=t(b,{uniforms:{pointA:{value:new d.Vector3},controlA:{value:new d.Vector3},controlB:{value:new d.Vector3},pointB:{value:new d.Vector3},radius:{value:.01},dashing:{value:new d.Vector3}},vertexDefs:"\nuniform vec3 pointA;\nuniform vec3 controlA;\nuniform vec3 controlB;\nuniform vec3 pointB;\nuniform float radius;\nvarying float bezierT;\n\nvec3 cubicBezier(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n float b0 = t2 * t2 * t2;\n float b1 = 3.0 * t * t2 * t2;\n float b2 = 3.0 * t * t * t2;\n float b3 = t * t * t;\n return b0 * p1 + b1 * c1 + b2 * c2 + b3 * p2;\n}\n\nvec3 cubicBezierDerivative(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n return -3.0 * p1 * t2 * t2 +\n c1 * (3.0 * t2 * t2 - 6.0 * t2 * t) +\n c2 * (6.0 * t2 * t - 3.0 * t * t) +\n 3.0 * p2 * t * t;\n}\n",
'use strict';(function(g,e){"object"===typeof exports&&"undefined"!==typeof module?e(exports,require("three")):"function"===typeof define&&define.amd?define(["exports","three"],e):(g=g||self,e(g.troika_three_utils={},g.THREE))})(this,function(g,e){function t(a){return a.replace(/^[ \t]*#include +<([\w\d./]+)>/gm,function(a,c){return(c=e.ShaderChunk[c])?t(c):a})}function u(a,b){function c(c){a.onBeforeCompile.call(this,c);var d=this[g]||(this[g]={vertex:{},fragment:{}}),f=d.vertex;d=d.fragment;if(f.source!==
c.vertexShader||d.source!==c.fragmentShader){var e=C(c,b,p);f.source=c.vertexShader;f.result=e.vertexShader;d.source=c.fragmentShader;d.result=e.fragmentShader}c.vertexShader=f.result;c.fragmentShader=d.result;l(c.uniforms,this.uniforms);b.timeUniform&&(c.uniforms[b.timeUniform]={get value(){return Date.now()-D}});if(this[h])this[h](c)}function d(){a.constructor.apply(this,arguments);this._listeners=void 0}var f=JSON.stringify(b,E),q=w.get(a);q||(q=Object.create(null),w.set(a,q));if(q[f])return q[f].clone();
var p=++F,g="_derivedShaders"+p,h="_onBeforeCompile"+p,n,m;d.prototype=Object.create(a,{constructor:{value:d},isDerivedMaterial:{value:!0},baseMaterial:{value:a},onBeforeCompile:{get:function(){return c},set:function(a){this[h]=a}},copy:{value:function(b){a.copy.call(this,b);a.isShaderMaterial||a.isDerivedMaterial||(this.extensions=l({},b.extensions),this.defines=l({},b.defines),this.uniforms=e.UniformsUtils.clone(b.uniforms));return this}},getDepthMaterial:{value:function(){var c=this._depthMaterial;
c||(m||(m=u(a.isDerivedMaterial?a.getDepthMaterial():new e.MeshDepthMaterial({depthPacking:e.RGBADepthPacking}),b),m.defines.IS_DEPTH_MATERIAL=""),c=this._depthMaterial=m.clone(),c.uniforms=this.uniforms);return c}},getDistanceMaterial:{value:function(){var c=this._distanceMaterial;c||(n||(n=u(a.isDerivedMaterial?a.getDistanceMaterial():new e.MeshDistanceMaterial,b),n.defines.IS_DISTANCE_MATERIAL=""),c=this._distanceMaterial=n.clone(),c.uniforms=this.uniforms);return c}},dispose:{value:function(){var b=
this._depthMaterial,c=this._distanceMaterial;b&&b.dispose();c&&c.dispose();a.dispose.call(this)}}});var k=new d;k.copy(a);k.uniforms=l(e.UniformsUtils.clone(a.uniforms||{}),b.uniforms);k.defines=l({},a.defines,b.defines);k.defines.TROIKA_DERIVED_MATERIAL=p;k.extensions=l({},a.extensions,b.extensions);q[f]=k;return k.clone()}function C(a,b,c){var d=a.vertexShader,f=a.fragmentShader;a=b.vertexDefs;var e=b.vertexMainIntro,g=b.vertexMainOutro,h=b.vertexTransform,v=b.fragmentDefs,n=b.fragmentMainIntro,
m=b.fragmentMainOutro,k=b.fragmentColorTransform,l=b.customRewriter;b=b.timeUniform;a=a||"";e=e||"";g=g||"";v=v||"";n=n||"";m=m||"";if(h||l)d=t(d);if(k||l)f=t(f);l&&(f=l({vertexShader:d,fragmentShader:f}),d=f.vertexShader,f=f.fragmentShader);k&&(m=k+"\n"+m);b&&(k="\nuniform float "+b+";\n",a+=k,v+=k);h&&(a=a+"\nvec3 troika_position_"+c+";\nvec3 troika_normal_"+c+";\nvec2 troika_uv_"+c+";\nvoid troikaVertexTransform"+c+"(inout vec3 position, inout vec3 normal, inout vec2 uv) {\n "+h+"\n}\n",e="\ntroika_position_"+
c+" = vec3(position);\ntroika_normal_"+c+" = vec3(normal);\ntroika_uv_"+c+" = vec2(uv);\ntroikaVertexTransform"+c+"(troika_position_"+c+", troika_normal_"+c+", troika_uv_"+c+");\n"+e+"\n",d=d.replace(/\b(position|normal|uv)\b/g,function(a,b,d,f){return/\battribute\s+vec[23]\s+$/.test(f.substr(0,d))?b:"troika_"+b+"_"+c}));d=x(d,c,a,e,g);f=x(f,c,v,n,m);return{vertexShader:d,fragmentShader:f}}function x(a,b,c,d,f){if(d||f||c)a=a.replace(y,"\n"+c+"\nvoid troikaOrigMain"+b+"() {"),a+="\nvoid main() {\n "+
d+"\n troikaOrigMain"+b+"();\n "+f+"\n}";return a}function E(a,b){return"uniforms"===a?void 0:"function"===typeof b?b.toString():b}function z(a,b,c){a*=255;var d=a%1*255,f=d%1*255;var e=Math.round(f%1*255)&255;b[c]=a&255;b[c+1]=d&255;b[c+2]=f&255;b[c+3]=e;return b}var y=/\bvoid\s+main\s*\(\s*\)\s*{/g,l=Object.assign||function(){for(var a=arguments,b=arguments[0],c=1,d=arguments.length;c<d;c++){var f=a[c];if(f)for(var e in f)f.hasOwnProperty(e)&&(b[e]=f[e])}return b},F=0,D=Date.now(),w=new WeakMap,
G={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 e.DataTexture(new Uint8Array(0),0,1);this._length=0;this._multiplier=1},r={length:{configurable:!0}};r.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}};r.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,z(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 f=this._multiplier;c<d;c++)z(b[c]/f,a.image.data,4*c);this._needsRepack=!1}};Object.defineProperties(h.prototype,r);var A=null,B=new e.MeshStandardMaterial({color:16777215,side:e.DoubleSide});r=function(a){function b(){a.call(this,b.getGeometry(),B);this.pointA=new e.Vector3;this.controlA=new e.Vector3;this.controlB=
new e.Vector3;this.pointB=new e.Vector3;this.radius=.01;this.dashArray=new e.Vector2;this.dashOffset=0;this.frustumCulled=!1}a&&(b.__proto__=a);b.prototype=Object.create(a&&a.prototype);b.prototype.constructor=b;var c={material:{configurable:!0},customDepthMaterial:{configurable:!0},customDistanceMaterial:{configurable:!0}};b.getGeometry=function(){return A||(A=(new e.CylinderBufferGeometry(1,1,1,6,64)).translate(0,.5,0))};c.material.get=function(){var a=this._derivedMaterial,b=this._baseMaterial||
B;a&&a.baseMaterial===b||(a&&a.dispose(),a=this._derivedMaterial=u(b,{uniforms:{pointA:{value:new e.Vector3},controlA:{value:new e.Vector3},controlB:{value:new e.Vector3},pointB:{value:new e.Vector3},radius:{value:.01},dashing:{value:new e.Vector3}},vertexDefs:"\nuniform vec3 pointA;\nuniform vec3 controlA;\nuniform vec3 controlB;\nuniform vec3 pointB;\nuniform float radius;\nvarying float bezierT;\n\nvec3 cubicBezier(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n float b0 = t2 * t2 * t2;\n float b1 = 3.0 * t * t2 * t2;\n float b2 = 3.0 * t * t * t2;\n float b3 = t * t * t;\n return b0 * p1 + b1 * c1 + b2 * c2 + b3 * p2;\n}\n\nvec3 cubicBezierDerivative(vec3 p1, vec3 c1, vec3 c2, vec3 p2, float t) {\n float t2 = 1.0 - t;\n return -3.0 * p1 * t2 * t2 +\n c1 * (3.0 * t2 * t2 - 6.0 * t2 * t) +\n c2 * (6.0 * t2 * t - 3.0 * t * t) +\n 3.0 * p2 * t * t;\n}\n",
vertexTransform:'\nfloat t = position.y;\nbezierT = t;\nvec3 bezierCenterPos = cubicBezier(pointA, controlA, controlB, pointB, t);\nvec3 bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t));\n\n// Make "sideways" always perpendicular to the camera ray; this ensures that any twists\n// in the cylinder occur where you won\'t see them: \nvec3 viewDirection = normalMatrix * vec3(0.0, 0.0, 1.0);\nif (bezierDir == viewDirection) {\n bezierDir = normalize(cubicBezierDerivative(pointA, controlA, controlB, pointB, t == 1.0 ? t - 0.0001 : t + 0.0001));\n}\nvec3 sideways = normalize(cross(bezierDir, viewDirection));\nvec3 upish = normalize(cross(sideways, bezierDir));\n\n// Build a matrix for transforming this disc in the cylinder:\nmat4 discTx;\ndiscTx[0].xyz = sideways * radius;\ndiscTx[1].xyz = bezierDir * radius;\ndiscTx[2].xyz = upish * radius;\ndiscTx[3].xyz = bezierCenterPos;\ndiscTx[3][3] = 1.0;\n\n// Apply transform, ignoring original y\nposition = (discTx * vec4(position.x, 0.0, position.z, 1.0)).xyz;\nnormal = normalize(mat3(discTx) * normal);\n',
fragmentDefs:"\nuniform vec3 dashing;\nvarying float bezierT;\n",fragmentMainIntro:"\nif (dashing.x + dashing.y > 0.0) {\n float dashFrac = mod(bezierT - dashing.z, dashing.x + dashing.y);\n if (dashFrac > dashing.x) {\n discard;\n }\n}\n"}),b.addEventListener("dispose",function n(){b.removeEventListener("dispose",n);a.dispose()}));return a};c.material.set=function(a){this._baseMaterial=a};c.customDepthMaterial.get=function(){return this._updateBezierUniforms(this.material.getDepthMaterial())};
c.customDistanceMaterial.get=function(){return this._updateBezierUniforms(this.material.getDistanceMaterial())};b.prototype.onBeforeRender=function(a){this._updateBezierUniforms(this.material)};b.prototype._updateBezierUniforms=function(a){var b=a.uniforms,c=this.controlA,d=this.controlB,e=this.pointB,h=this.radius,g=this.dashArray,k=this.dashOffset;b.pointA.value.copy(this.pointA);b.controlA.value.copy(c);b.controlB.value.copy(d);b.pointB.value.copy(e);b.radius.value=h;b.dashing.value.set(g.x,g.y,
k||0);return a};b.prototype.raycast=function(a,b){};Object.defineProperties(b.prototype,c);return b}(d.Mesh);h.BezierMesh=q;h.ShaderFloatArray=g;h.createDerivedMaterial=t;h.expandShaderIncludes=r;h.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};h.getShadersForMaterial=function(a){var b=E[a.type];return b?d.ShaderLib[b]:a};h.voidMainRegExp=v;Object.defineProperty(h,"__esModule",
{value:!0})});
fragmentDefs:"\nuniform vec3 dashing;\nvarying float bezierT;\n",fragmentMainIntro:"\nif (dashing.x + dashing.y > 0.0) {\n float dashFrac = mod(bezierT - dashing.z, dashing.x + dashing.y);\n if (dashFrac > dashing.x) {\n discard;\n }\n}\n"}),b.addEventListener("dispose",function p(){b.removeEventListener("dispose",p);a.dispose()}));return a};c.material.set=function(a){this._baseMaterial=a};c.customDepthMaterial.get=function(){return this.material.getDepthMaterial()};c.customDistanceMaterial.get=
function(){return this.material.getDistanceMaterial()};b.prototype.onBeforeRender=function(a){a=this.material.uniforms;var b=this.controlA,c=this.controlB,d=this.pointB,e=this.radius,g=this.dashArray,h=this.dashOffset;a.pointA.value.copy(this.pointA);a.controlA.value.copy(b);a.controlB.value.copy(c);a.pointB.value.copy(d);a.radius.value=e;a.dashing.value.set(g.x,g.y,h||0)};b.prototype.raycast=function(a,b){};Object.defineProperties(b.prototype,c);return b}(e.Mesh);g.BezierMesh=r;g.ShaderFloatArray=
h;g.createDerivedMaterial=u;g.expandShaderIncludes=t;g.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};g.getShadersForMaterial=function(a){var b=G[a.type];return b?e.ShaderLib[b]:a};g.voidMainRegExp=y;Object.defineProperty(g,"__esModule",{value:!0})})
{
"name": "troika-three-utils",
"version": "0.20.0",
"version": "0.21.0",
"description": "Various utilities related to Three.js",

@@ -17,3 +17,3 @@ "author": "Jason Johnston <jason.johnston@protectwise.com>",

"module:src": "src/index.js",
"gitHead": "c97a9f97c30cd4ddfba068430d02d7c0a73c2e08"
"gitHead": "0a7527c90b55f0cd09192ad2f71c62f287702186"
}

@@ -37,7 +37,11 @@ import { CylinderBufferGeometry, DoubleSide, Mesh, MeshStandardMaterial, Vector2, Vector3 } from 'three'

class BezierMesh extends Mesh {
static getGeometry() {
return geometry || (geometry =
new CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
)
}
constructor() {
super(
geometry || (geometry =
new CylinderBufferGeometry(1, 1, 1, 6, 64).translate(0, 0.5, 0)
),
BezierMesh.getGeometry(),
defaultBaseMaterial

@@ -83,14 +87,10 @@ )

get customDepthMaterial() {
return this._updateBezierUniforms(this.material.getDepthMaterial())
return this.material.getDepthMaterial()
}
get customDistanceMaterial() {
return this._updateBezierUniforms(this.material.getDistanceMaterial())
return this.material.getDistanceMaterial()
}
onBeforeRender(shaderInfo) {
this._updateBezierUniforms(this.material)
}
_updateBezierUniforms(material) {
const {uniforms} = material
const {uniforms} = this.material
const {pointA, controlA, controlB, pointB, radius, dashArray, dashOffset} = this

@@ -103,3 +103,2 @@ uniforms.pointA.value.copy(pointA)

uniforms.dashing.value.set(dashArray.x, dashArray.y, dashOffset || 0)
return material
}

@@ -106,0 +105,0 @@

@@ -49,2 +49,4 @@ import { voidMainRegExp } from './voidMainRegExp.js'

* shader's `void main` function.
* @param {String} options.vertexMainOutro - Custom GLSL code to inject at the end of the vertex
* shader's `void main` function.
* @param {String} options.vertexTransform - Custom GLSL code to manipulate the `position`, `normal`,

@@ -57,5 +59,11 @@ * and/or `uv` vertex attributes. This code will be wrapped within a standalone function with

* shader's `void main` function.
* @param {String} options.fragmentMainOutro - Custom GLSL code to inject at the end of the fragment
* shader's `void main` function.
* @param {String} options.fragmentColorTransform - Custom GLSL code to manipulate the `gl_FragColor`
* output value. Will be injected after all other `void main` logic has executed.
* TODO allow injecting before base shader logic or elsewhere?
* output value. Will be injected after all other `void main` logic has executed but just before
* the `fragmentMainOutro`. TODO allow injecting in other places?
* @param {function<{vertexShader,fragmentShader}>:{vertexShader,fragmentShader}} options.customRewriter - A function
* for performing custom rewrites of the full shader code. Useful if you need to do something
* special that's not covered by the other builtin options. This function will be executed before
* any other transforms are applied.
*

@@ -172,2 +180,3 @@ * @return {THREE.Material}

depthMaterial = this._depthMaterial = depthMaterialTpl.clone()
depthMaterial.uniforms = this.uniforms //automatically recieve same uniform values
}

@@ -194,2 +203,3 @@ return depthMaterial

distanceMaterial = this._distanceMaterial = distanceMaterialTpl.clone()
distanceMaterial.uniforms = this.uniforms //automatically recieve same uniform values
}

@@ -225,25 +235,52 @@ return distanceMaterial

vertexMainIntro,
vertexMainOutro,
vertexTransform,
fragmentDefs,
fragmentMainIntro,
fragmentMainOutro,
fragmentColorTransform,
customRewriter,
timeUniform
} = options
vertexDefs = vertexDefs || ''
vertexMainIntro = vertexMainIntro || ''
vertexMainOutro = vertexMainOutro || ''
fragmentDefs = fragmentDefs || ''
fragmentMainIntro = fragmentMainIntro || ''
fragmentMainOutro = fragmentMainOutro || ''
// Expand includes if needed
if (vertexTransform || customRewriter) {
vertexShader = expandShaderIncludes(vertexShader)
}
if (fragmentColorTransform || customRewriter) {
fragmentShader = expandShaderIncludes(fragmentShader)
}
// Apply custom rewriter function
if (customRewriter) {
let res = customRewriter({vertexShader, fragmentShader})
vertexShader = res.vertexShader
fragmentShader = res.fragmentShader
}
// Treat fragmentColorTransform as an outro
if (fragmentColorTransform) {
fragmentMainOutro = `${fragmentColorTransform}\n${fragmentMainOutro}`
}
// Inject auto-updating time uniform if requested
if (timeUniform) {
const code = `\nuniform float ${timeUniform};\n`
vertexDefs = (vertexDefs || '') + code
fragmentDefs = (fragmentDefs || '') + code
vertexDefs += code
fragmentDefs += code
}
// Modify vertex shader
if (vertexDefs || vertexMainIntro || vertexTransform) {
// If there's a position transform, we need to:
// - expand all include statements
// - replace all usages of the `position` attribute with a mutable variable
// - inject the transform code into a function and call it to transform the position
if (vertexTransform) {
vertexShader = expandShaderIncludes(vertexShader)
vertexDefs = `${vertexDefs || ''}
// Inject a function for the vertexTransform and rename all usages of position/normal/uv
if (vertexTransform) {
vertexDefs = `${vertexDefs}
vec3 troika_position_${id};
vec3 troika_normal_${id};
vec2 troika_uv_${id};
void troikaVertexTransform${id}(inout vec3 position, inout vec3 normal, inout vec2 uv) {

@@ -253,33 +290,17 @@ ${vertexTransform}

`
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, (match, match1, index, fullStr) => {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : `troika_${match1}_${id}`
})
vertexMainIntro = `
vec3 troika_position_${id} = vec3(position);
vec3 troika_normal_${id} = vec3(normal);
vec2 troika_uv_${id} = vec2(uv);
vertexMainIntro = `
troika_position_${id} = vec3(position);
troika_normal_${id} = vec3(normal);
troika_uv_${id} = vec2(uv);
troikaVertexTransform${id}(troika_position_${id}, troika_normal_${id}, troika_uv_${id});
${vertexMainIntro || ''}
${vertexMainIntro}
`
}
vertexShader = vertexShader.replace(
voidMainRegExp,
`${vertexDefs || ''}\n\n$&\n\n${vertexMainIntro || ''}`)
vertexShader = vertexShader.replace(/\b(position|normal|uv)\b/g, (match, match1, index, fullStr) => {
return /\battribute\s+vec[23]\s+$/.test(fullStr.substr(0, index)) ? match1 : `troika_${match1}_${id}`
})
}
// Modify fragment shader
if (fragmentDefs || fragmentMainIntro || fragmentColorTransform) {
fragmentShader = expandShaderIncludes(fragmentShader)
fragmentShader = fragmentShader.replace(voidMainRegExp, `
${fragmentDefs || ''}
void troikaOrigMain${id}() {
${fragmentMainIntro || ''}
`)
fragmentShader += `
void main() {
troikaOrigMain${id}();
${fragmentColorTransform || ''}
}`
}
// Inject defs and intro/outro snippets
vertexShader = injectIntoShaderCode(vertexShader, id, vertexDefs, vertexMainIntro, vertexMainOutro)
fragmentShader = injectIntoShaderCode(fragmentShader, id, fragmentDefs, fragmentMainIntro, fragmentMainOutro)

@@ -292,2 +313,17 @@ return {

function injectIntoShaderCode(shaderCode, id, defs, intro, outro) {
if (intro || outro || defs) {
shaderCode = shaderCode.replace(voidMainRegExp, `
${defs}
void troikaOrigMain${id}() {`
)
shaderCode += `
void main() {
${intro}
troikaOrigMain${id}();
${outro}
}`
}
return shaderCode
}

@@ -297,4 +333,5 @@ function getOptionsHash(options) {

}
function optionsJsonReplacer(key, value) {
return key === 'uniforms' ? undefined : value
return key === 'uniforms' ? undefined : typeof value === 'function' ? value.toString() : value
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc