trimill.xyz/flaskr/templates/projects/complex_grapher/main.js
2022-06-23 02:23:38 -04:00

234 lines
7.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

var shaderBase;
var dpi = 1;
const BASE_CTX = {
"*$2": "cmul",
"/$2": "cdiv",
"^$2": "cpow",
"root$2": "croot",
"root$2_o": "croot_o",
"recip$1": "crecip",
"re$1": "cre",
"im$1": "cim",
"abs$1": "cabs",
"arg$1": "carg",
"arg$1_i": "carg_o",
"norm$1": "cnorm",
"conj$1": "cconj",
"sqrt$1": "csqrt",
"sqrt$1_o": "csqrt_o",
"√$1": "csqrt",
"√$1_o": "csqrt_o",
"sinh$1": "csinh",
"cosh$1": "ccosh",
"tanh$1": "ctanh",
"asinh$1": "casinh",
"asinh$1_o": "casinh_o",
"acosh$1_o": "cacosh_o",
"sin$1": "csin",
"cos$1": "ccos",
"tan$1": "ctan",
"asin$1": "casin",
"acos$1": "cacos",
"atan$1": "catan",
"asin$1_o": "casin_o",
"acos$1_o": "cacos_o",
"exp$1": "cexp",
"log$1": "clog",
"log$2": "clogbase",
"log$1_o": "clog_o",
"log$2_o": "clogbase_o",
"ln$1": "clog",
"ln$1_o": "clog_o",
"gamma$1": "cgamma",
"Γ$1": "cgamma",
"unitcircle$1": "cunitcircle",
"signre$1": "csignre",
"signim$1": "csignim",
"lambertw$1": "clambertw",
// CONSTANTS
"e": "CONST_E",
"pi": "CONST_PI",
"π": "CONST_PI",
"tau": "CONST_TAU",
"τ": "CONST_TAU",
"emg": "CONST_EMGAMMA",
"γ": "CONST_EMGAMMA",
// NOT OFFICIALLY SUPPORTED YET
"digamma$1": "cdigamma",
"loggamma$1": "cloggamma",
"erf$1": "cerf",
"eulerfn$1": "ceulerfn",
"ti$1": "cti",
"weierp$3": "cweierp",
};
const FZ_CTX = {
...BASE_CTX,
"z": "z",
"c": "c",
"n": "n",
}
const INIT_CTX = {
...BASE_CTX,
"z": "z",
}
function expr2source(expr, ctx) {
let ast = peg$parse(expr);
console.log(ast);
const reduced = ast.reduce();
if(reduced !== null) {
ast = reduced;
}
return ast.gen(ctx);
}
function graph() {
const shadingRaw = document.getElementById("shading").value
try {
const options = {
rmin: parseFloat(document.getElementById("rmin").value),
rmax: parseFloat(document.getElementById("rmax").value),
imin: parseFloat(document.getElementById("imin").value),
imax: parseFloat(document.getElementById("imax").value),
drawcontours: document.getElementById("drawcontours").checked,
smoothcolor: document.getElementById("smoothcolor").checked,
shading: 15/(4-4*shadingRaw**4) - 15/4,
swapbw: document.getElementById("swapbw").checked,
iterations: parseInt(document.getElementById("iterations").value),
}
console.log(options);
console.log("=== PRINTING GENERATED GLSL ===");
const fz = document.getElementById("fz").value;
const fzSource = expr2source(fz, FZ_CTX);
console.log("fz: " + fzSource);
const initZ = document.getElementById("init_z").value;
const initZSource = expr2source(initZ, INIT_CTX);
console.log("z_init: " + initZSource);
const initC = document.getElementById("init_c").value;
const initCSource = expr2source(initC, INIT_CTX);
console.log("c_init: " + initCSource);
const fsSource = shaderBase
+ "vec2 f(vec2 z, vec2 c, vec2 n) { return "
+ fzSource
+ ";}"
+ "vec2 z_init(vec2 z) { return "
+ initZSource
+ ";}"
+ "vec2 c_init(vec2 z) { return "
+ initCSource
+ ";}";
runShader(fsSource, options);
} catch(e) {
document.getElementById("errors").textContent = e.toString();
console.log(e);
return;
}
document.getElementById("errors").textContent = "";
}
function decodeURLParams() {
const canvas = document.getElementById("canvas");
var params = new URLSearchParams(window.location.search);
if(!params.has("dpi") || params.get("dpi") == "1") {
dpi = 1;
canvas.width = 640;
canvas.height = 640;
} else if(params.get("dpi") == "2") {
dpi = 2;
canvas.width = 640*2;
canvas.height = 640*2;
} else if(params.get("dpi") == "4") {
dpi = 4;
canvas.width = 640*4;
canvas.height = 640*4;
}
if(params.has("src")) {
const src = JSON.parse(atob(params.get("src")));
document.getElementById("fz").value = src.expr;
document.getElementById("rmin").value = src.axes[0];
document.getElementById("rmax").value = src.axes[1];
document.getElementById("imin").value = src.axes[2];
document.getElementById("imax").value = src.axes[3];
document.getElementById("shading").value = src.shading;
document.getElementById("swapbw").checked = src.swapbw;
document.getElementById("drawcontours").checked = src.contours;
if(src.itermode !== false) {
document.getElementById("enable_iters").checked = true;
document.getElementById("iterations").value = src.itermode.iters;
document.getElementById("init_z").value = src.itermode.zinit;
document.getElementById("init_c").value = src.itermode.cinit;
} else {
document.getElementById("enable_iters").checked = false;
}
}
}
function encodeURLParams() {
const itermode = document.getElementById("enable_iters").checked;
let params = {
expr: document.getElementById("fz").value,
axes: [
document.getElementById("rmin").value,
document.getElementById("rmax").value,
document.getElementById("imin").value,
document.getElementById("imax").value,
],
shading: document.getElementById("shading").value,
swapbw: document.getElementById("swapbw").checked,
contours: document.getElementById("drawcontours").checked,
};
if(itermode) {
params.itermode = {
iters: document.getElementById("iterations").value,
zinit: document.getElementById("init_z").value,
cinit: document.getElementById("init_c").value,
}
} else {
params.itermode = false;
}
const src = btoa(JSON.stringify(params));
const url = window.location.origin + window.location.pathname + "?src=" + src + "&dpi=" + dpi;
document.location.href = url;
}
function changeIterationMode() {
const checked = document.getElementById('enable_iters').checked;
document.getElementById('iteration_mode').hidden = !checked;
if(!checked) {
document.getElementById('iterations').value = 1;
document.getElementById('init_z').value = "z";
document.getElementById('init_c').value = "0";
}
}
//const constantHtml = `<span class="constant">
//<input type="button" class="const-del" value="[-]" style="color: #ff4444" onclick="this.parentElement.remove()"/>
//<input type="text" class="const-label" style="width: 30px" /> =
//<input type="text" class="const-re" style="width: 80px" /> +
//<input type="text" class="const-im" style="width: 80px" /> i
//</span>`
//
//function addConstant() {
// const parse = Range.prototype.createContextualFragment.bind(document.createRange());
// const constWrapper = document.getElementById("constants-wrapper");
// constWrapper.appendChild(parse(constantHtml));
//}
window.onload = () => {
decodeURLParams();
fetch('shaderbase.glsl')
.then(response => response.text())
.then((data) => {
shaderBase = data;
graph();
});
changeIterationMode();
};