glsl-transpiler
Advanced tools
Comparing version
143
lib/index.js
@@ -26,4 +26,4 @@ 'use strict' | ||
var floatRE = /^-?[0-9]*(?:.[0-9]+)?(?:e-?[0-9]+)?$/i | ||
var swizzleRE = /^[xyzwstpdrgba]{1,4}$/ | ||
/** | ||
@@ -404,2 +404,18 @@ * Create GLSL codegen instance | ||
//sort arguments by qualifier | ||
var inArgs = [] | ||
var outArgs = [] | ||
args.components.forEach(function (arg, index) { | ||
arg.index = index | ||
if (arg.qualifier.slice(0, 2) === 'in') { | ||
inArgs.push(arg) | ||
} | ||
if (arg.qualifier.slice(-3) === 'out') { | ||
outArgs.push(arg) | ||
} | ||
}) | ||
if (outArgs.length === 0) { | ||
outArgs = null | ||
} | ||
//if main name is registered - provide type-scoped name of function | ||
@@ -415,3 +431,24 @@ if (this.functions[name] && argTypesSfx) { | ||
result += `function ${name} (${args}) {\n` | ||
//guard input parameters from being mutated | ||
inArgs.forEach(function (arg) { | ||
if (/^(vec|mat)/.test(arg.type)) { | ||
result += `${arg} = ${arg}.slice();\n` | ||
} | ||
}) | ||
//populate current scope information | ||
//this is used by the `return` transform | ||
var scope = this.scopes[this.currentScope] | ||
scope.callName = name | ||
scope.outArgs = outArgs | ||
result += this.process(node.children[2]) | ||
if (outArgs && outType === 'void') { | ||
//the output list is usually created when transforming the `return` statement | ||
//but this function does not have a `return` at the end | ||
result += `\n${name}.__out__ = [${outArgs.join(', ')}];` | ||
} | ||
result = result.replace(/\n/g, '\n\t') | ||
@@ -429,2 +466,6 @@ result += '\n}' | ||
//save the output arguments list | ||
//this is used by the `call` transform | ||
result.outArgs = outArgs | ||
//register function descriptor | ||
@@ -487,2 +528,11 @@ this.functions[name] = result | ||
result = this.process(decllist) | ||
// in/out/inout | ||
var qualifier = node.token.data | ||
if (qualifier === result.type) { | ||
result.qualifier = 'in' | ||
} else { | ||
result.qualifier = qualifier | ||
} | ||
return result | ||
@@ -651,3 +701,3 @@ } | ||
//ab.xyz for example | ||
if (/^[xyzwstpdrgba]{1,4}$/.test(prop)) { | ||
if (swizzleRE.test(prop)) { | ||
return this.unswizzle(node) | ||
@@ -732,3 +782,22 @@ } | ||
var expr = this.process(node.children[0]) | ||
return Descriptor('return' + (expr.visible ? ' ' + expr : ''), {type: expr.type}) | ||
var result | ||
var scope = this.scopes[this.currentScope] | ||
if (scope.outArgs) { | ||
var outStmt = `${scope.callName}.__out__ = [${scope.outArgs.join(', ')}]` | ||
if (expr.visible) { | ||
// func.__return__ = <expression>; | ||
// func.__out__ = [outArg1, outArg2, ...]; | ||
// return func.__return__; | ||
result = `${scope.callName}.__return__ = ${expr};\n${outStmt};\nreturn ${scope.callName}.__return__` | ||
} else { | ||
// func.__out__ = [outArg1, outArg2, ...]; | ||
// return; | ||
result = `${outStmt};\nreturn` | ||
} | ||
} else { | ||
// return <expression>; | ||
result = 'return' + (expr.visible ? ' ' + expr : '') | ||
} | ||
return Descriptor(result, {type: expr.type}) | ||
}, | ||
@@ -821,3 +890,3 @@ | ||
return Descriptor(`${left}[${right}]`, { | ||
type: type, | ||
type: type || null, | ||
complexity: left.complexity + right.complexity + 1 | ||
@@ -847,4 +916,8 @@ }) | ||
var target = left | ||
var isSwizzle = node.children[0].type === 'operator' && /^[xyzwstpdrgba]{1,4}$/.test(node.children[0].children[1].data) | ||
// here some targets may be unswizzled already, eg. | ||
// [a[0], a[1]], a[0][0], etc. | ||
var isSwizzle = node.children[0].type === 'operator' && | ||
swizzleRE.test(node.children[0].children[1].data) | ||
//a *= b.x | ||
@@ -860,3 +933,3 @@ if (!isSwizzle && this.types[right.type].length == 1 && this.types[target.type].length == 1) { | ||
//in cases of setting swizzle - we gotta drop left unswizzle to the right | ||
//in cases of setting swizzle - we have to place left unswizzle to the right | ||
if (isSwizzle) { | ||
@@ -871,7 +944,12 @@ var positions = this.swizzlePositions(node.children[0].children[1].data) | ||
target = Descriptor(node.children[0].children[0].data, { | ||
type: right.type, | ||
optimize: false | ||
}) | ||
var targetType = node.children[0].children[0].type | ||
// a.x = ... | ||
if ((targetType === 'ident' || targetType === 'builtin')) { | ||
target = Descriptor(node.children[0].children[0].data, { | ||
type: right.type, | ||
optimize: false | ||
}) | ||
} | ||
//a.wy *= a.zx → | ||
@@ -917,6 +995,13 @@ //a = [null, 1, null, 0].map(function (idx, i) { | ||
else { | ||
return Descriptor(`${target}[${positions[0]}] ${operator} ${right}`, { | ||
type: right.type, | ||
optimize: false | ||
}) | ||
if (targetType === 'builtin' || targetType === 'ident') { | ||
return Descriptor(`${target}[${positions[0]}] ${operator} ${right}`, { | ||
type: right.type, | ||
optimize: false | ||
}) | ||
} else { | ||
return Descriptor(`${target} ${operator} ${right}`, { | ||
type: right.type, | ||
optimize: false | ||
}) | ||
} | ||
} | ||
@@ -1063,9 +1148,12 @@ } | ||
else { | ||
var type, optimize = true | ||
var type, optimize = true, outArgs = null | ||
//registered fn() | ||
if (this.functions[callName]) { | ||
var fn = this.functions[callName] | ||
if (fn) { | ||
var sfx = argTypes.join('_') | ||
if (sfx && this.functions[`${callName}_${sfx}`]) { | ||
type = this.functions[`${callName}_${sfx}`].type | ||
fn = this.functions[`${callName}_${sfx}`] | ||
type = fn.type | ||
outArgs = fn.outArgs | ||
callName = Descriptor(`${callName}_${sfx}`, { | ||
@@ -1075,4 +1163,5 @@ complexity: callName.complexity | ||
} | ||
else if (this.functions[callName]) { | ||
type = this.functions[callName].type | ||
else { | ||
type = fn.type | ||
outArgs = fn.outArgs | ||
} | ||
@@ -1105,3 +1194,14 @@ } | ||
} | ||
var res = Descriptor(`${callName}(${argValues.join(', ')})`, { | ||
var res = `${callName}(${argValues.join(', ')})` | ||
if (outArgs) { | ||
// calling func(in a, out b, out c): | ||
// (func(a, b, c), [b, c] = func.__out__, func.__return__) | ||
var outList = outArgs.map(function (arg) { | ||
return argValues[arg.index] | ||
}) | ||
res = `(${res}, [${outList.join(', ')}] = ${callName}.__out__, ${callName}.__return__)` | ||
} | ||
return Descriptor(res, { | ||
type: type || callName.type, | ||
@@ -1114,3 +1214,2 @@ complexity: 999 /* argValues.reduce(function (prev, curr) { | ||
return res | ||
} | ||
@@ -1231,2 +1330,3 @@ } | ||
if (args[0] == null) console.warn(`Cannot unswizzle '${ident.type}(${ident}).${prop}': ${prop} is outside the type range.`) | ||
result = Descriptor(args[0] || `undefined`, { | ||
@@ -1237,2 +1337,3 @@ type: 'float', | ||
} | ||
return result | ||
@@ -1239,0 +1340,0 @@ } |
{ | ||
"name": "glsl-transpiler", | ||
"version": "1.7.2", | ||
"version": "1.8.0", | ||
"description": "Transpile GLSL to JS", | ||
@@ -9,5 +9,5 @@ "main": "index.js", | ||
"glsl-parser": "^2.0.1", | ||
"glsl-tokenizer": "^2.1.4", | ||
"glsl-tokenizer": "^2.1.5", | ||
"inherits": "^2.0.1", | ||
"prepr": "^1.1.0", | ||
"prepr": "^1.1.2", | ||
"xtend": "^4.0.1" | ||
@@ -65,3 +65,6 @@ }, | ||
], | ||
"author": "Deema Yvanow <dfcreative@gmail.com>", | ||
"author": "Dmitry Yv <df.creative@gmail.com>", | ||
"contributors": [ | ||
"Xiaoji Chen (http://pessimistress.github.io/)" | ||
], | ||
"license": "MIT", | ||
@@ -68,0 +71,0 @@ "bugs": { |
@@ -1,3 +0,5 @@ | ||
_glsl-transpiler_ transforms [glsl](https://www.opengl.org/documentation/glsl/) source to optimized js code. It converts vectors and matrices to arrays, expands swizzles, applies expressions optimizations and provides stdlib for environment compatibility. | ||
# glsl-transpiler [](https://travis-ci.org/stackgl/glsl-transpiler) | ||
Transforms [glsl](https://www.opengl.org/documentation/glsl/) source to optimized js code. It converts vectors and matrices to arrays, expands swizzles, applies expressions optimizations and provides stdlib for environment compatibility. | ||
## Usage | ||
@@ -4,0 +6,0 @@ |
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
101982
2.95%3074
2.88%131
1.55%3
50%Updated
Updated