diff --git a/index.js b/index.js index 9711418..4b6dbb1 100644 --- a/index.js +++ b/index.js @@ -42,6 +42,10 @@ function minifier(safe_words, mutate_storages) { if(node.parent && is_redundant_vector_literal(node.parent) && node.parent.children.indexOf(node) > 1) return if(is_redundant_vector_literal(node)) node.children = node.children.slice(0, 2) + // mat2(1.0, 0.0, 0.0, 1.0) => mat2(1.0) + if(node.parent && is_redundant_matrix_literal(node.parent) && node.parent.children.indexOf(node) > 1) return + if(is_redundant_matrix_literal(node)) node.children = node.children.slice(0, 2) + if(should_mutate(node)) { var t = node.parent.parent.children[1] if(mutate_storages || (t.type === 'placeholder' || t.token.data === 'const')) { @@ -91,4 +95,28 @@ function minifier(safe_words, mutate_storages) { } return false } + + function is_redundant_matrix_literal(node) { + if(node.type === 'call' && /^mat[234]$/.test(node.children[0].data) && + (node.children[1].type === 'literal' || node.children[1].type === 'ident')) { + var rows = Math.sqrt(node.children.length - 1); + var first = node.children[1].data; + + for(var i = 2; i < node.children.length; i++) { + var diagonalPosition = !((i - 1) % (rows + 1)); + var data = node.children[i].data; + + if (diagonalPosition) { + if (data !== first) { + return false; + } + } else if (!(node.children[i].type === 'literal' || node.children[i].type === 'ident') || parseFloat(data) !== 0) { + return false; + } + } + + return true + } + return false + } } diff --git a/tap-snapshots/test-basic.js-TAP.test.js b/tap-snapshots/test-basic.js-TAP.test.js index 3272e44..b32e7f1 100644 --- a/tap-snapshots/test-basic.js-TAP.test.js +++ b/tap-snapshots/test-basic.js-TAP.test.js @@ -744,6 +744,25 @@ bool c = 1. && true && true; bool d = 0. || false || true; ` +exports[`test/basic.js TAP mat shorthand > output 1`] = ` + +mat2 mat2Long = mat2(1., 1., 1., 1.); +mat2 mat2Short = mat2(1.); +mat3 mat3Long = mat3(1., 1., 1., 1., 1., 1., 1., 1., 1.); +mat3 mat3Short = mat3(1.); +mat4 mat4Long = mat4(1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.); +mat4 mat4Short = mat4(1.); +mat2 a = mat2(1., .0, .0, .0); +float b = 1.; +float c = .0; +mat2 d = mat2(b, c, c, b); +vec3 e = vec3(1, 0, 0); +vec3 f = vec3(0, 1, 0); +vec3 g = vec3(0, 0, 1); +mat3 h = mat3(e, f, g); +mat3 i = mat3(mat3(1)); +` + exports[`test/basic.js TAP vec shorthand > output 1`] = ` vec2 vec2Long = vec2(.0, 1.); diff --git a/test/basic.js b/test/basic.js index 63da188..6ec591e 100644 --- a/test/basic.js +++ b/test/basic.js @@ -12,6 +12,7 @@ const zeroGLSL = path.resolve(__dirname, "./zero-decimals.glsl"); const commutativeGLSL = path.resolve(__dirname, "./commutative-operators.glsl"); const workingGLSL = path.resolve(__dirname, "./working.glsl"); const vecGLSL = path.resolve(__dirname, "./vec-shorthand.glsl"); +const matGLSL = path.resolve(__dirname, "./mat-shorthand.glsl"); tap.test("basic", t => { let output = ""; @@ -157,3 +158,47 @@ tap.test("grouping removal test", t => { .pipe(endStream); }); +tap.test("mat shorthand", t => { + const types = [2,3,4].map(size => `mat${size}`); + + const variableNames = types + .map(type => ["Short", "Long"].map(suffix => `${type}${suffix}`)) + .reduce((a, b) => a.concat(b)); + + const safewords = [ + "main", + ...variableNames, + ]; + + let output = ""; + + const endStream = through((data) => { + output += data; + }, () => { + t.matchSnapshot(output, "output"); + + t.ok( + variableNames + .filter(name => name.endsWith("Long")) + .every(name => output.includes(`${name} = ${name.replace("Long", "")}(1., 1.`)), + "does not retain differing scalars" + ); + + t.ok( + variableNames + .filter(name => name.endsWith("Short")) + .every(name => output.includes(`${name} = ${name.replace("Short", "")}(1.)`)), + "does not shorten identical scalars" + ); + + t.end(); + }); + + fs.createReadStream(matGLSL) + .pipe(tokenizer()) + .pipe(parser()) + .pipe(minify(safewords)) + .pipe(deparser()) + .pipe(endStream); +}); + diff --git a/test/mat-shorthand.glsl b/test/mat-shorthand.glsl new file mode 100644 index 0000000..5f6db4f --- /dev/null +++ b/test/mat-shorthand.glsl @@ -0,0 +1,62 @@ +mat2 mat2Long = mat2( + 1.0, 1.0, + 1.0, 1.0 +); + +mat2 mat2Short = mat2( + 1.0, 0.0, + 0.0, 1.0 +); + +mat3 mat3Long = mat3( + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0 +); + +mat3 mat3Short = mat3( + 1.0, 0.0, 0.0, + 0.0, 1.0, 0.0, + 0.0, 0.0, 1.0 +); + + +mat4 mat4Long = mat4( + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0 +); + +mat4 mat4Short = mat4( + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0 +); + +mat2 mat2NotQuiteShort = mat2( + 1.0, 0.0, + 0.0, 0.0 +); + +float one = 1.0; +float zero = 0.0; + +mat2 mat2WithIdentShort = mat2( + one, zero, + zero, one +); + +vec3 vec3one = vec3(1,0,0); +vec3 vec3two = vec3(0,1,0); +vec3 vec3three = vec3(0,0,1); + +mat3 mat3WithVecIdent = mat3( + vec3one, + vec3two, + vec3three +); + +mat3 mat3WithMat = mat3(mat3(1, 0, 0, 0, 1, 0, 0, 0, 1)); +