Last active
June 14, 2019 02:15
-
-
Save postspectacular/43f3424aa9716fde1b84bfef70081e02 to your computer and use it in GitHub Desktop.
@thi.ng/shader-ast WIP codegen example w/ multiple output targets (GLSL & JS)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// // // // | |
// ///// // //// // //// ///// //// ///// ////// | |
// // ///// // ///// // // // // ////// // // // | |
// //// // // ///// // // ////// // ///// //// // | |
// // // // // // // // // // // // // // | |
// ///// // // ///// ///// //// // ///// ///// /// | |
// | |
// Head over to thi.ng/shader-ast for more details | |
const ast = require("@thi.ng/shader-ast"); | |
const v = require("@thi.ng/vectors"); | |
// define function using AST DSL | |
// (looks more verbose due to `ast.` prefixes) | |
// every node carries type information (both at runtime & authoring time) | |
// the latter provides realtime feedback about type mismatches | |
// e.g. the built-in `dot` function returns a float, which too is | |
// the return value of the entire `phong` function. | |
// when `defn` executes the function body is also checked for correct | |
// return types... | |
const phong = ast.defn( | |
"f32", "phong", | |
[["vec3", "ldir"], ["vec3", "edir"], ["vec3", "n"]], | |
(ld, ed, n) => [ | |
ast.ret(ast.dot(ast.reflect(ast.neg(ld), n), ed)) | |
]); | |
// resulting AST | |
// [Function: $] { | |
// tag: 'fn', | |
// type: 'f32', | |
// id: 'phong', | |
// args: [ | |
// { tag: 'arg', type: 'vec3', id: 'ldir', q: 'in' }, | |
// { tag: 'arg', type: 'vec3', id: 'edir', q: 'in' }, | |
// { tag: 'arg', type: 'vec3', id: 'n', q: 'in' } | |
// ], | |
// scope: { tag: 'scope', type: 'void', body: [ [Object] ], global: false } | |
// } | |
// note `phong` is a callable JS function | |
// when called it returns a function-call AST node. | |
// in TypeScript the arguments are type checked | |
// see api.ts & ast.ts for details | |
phong(ast.vec3(1,-1,0),ast.vec3(0,-1,0),ast.vec3(0,1,0)) | |
// { | |
// tag: 'call', | |
// type: 'f32', | |
// id: 'phong', | |
// args: [ | |
// { tag: 'lit', type: 'vec3', val: [Array] }, | |
// { tag: 'lit', type: 'vec3', val: [Array] }, | |
// { tag: 'lit', type: 'vec3', val: [Array] } | |
// ] | |
// } | |
// emit function as GLSL | |
const gl = ast.targetGLSL(); | |
console.log(gl(phong)); | |
// float phong(in vec3 ldir, in vec3 edir, in vec3 n) { | |
// return dot(reflect(-ldir, n), edir); | |
// } | |
// emit as JS | |
// for JS all built-in fns are delegated to an environment object | |
// provided by the user | |
const js = ast.targetJS(); | |
console.log(js(phong)) | |
// /** | |
// * @param ldir vec3 | |
// * @param edir vec3 | |
// * @param n vec3 | |
// */ | |
// function phong(ldir, edir, n) { | |
// return env.vec3_dot(env.vec3_reflect(env.vec3_sub1(ldir), n), edir); | |
// }; | |
// now compile as actual JS function | |
const compile = new Function("env", js(phong) + "\nreturn phong"); | |
// then instantiate with given test environment | |
// here the env is used to delegate built-in fns to @thi.ng/vectors | |
const phong2 = compile({ | |
vec3_dot: v.dot3, | |
vec3_reflect: (a,b) => v.reflect([], a, b), | |
vec3_sub1: (a) => v.neg([], a) | |
}); | |
phong2([1,-1,0], [0,-1,0], [0,1,0]); | |
// 1 | |
// tada :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment