package;
import js.Browser;
import js.html.Float32Array;
import js.html.CanvasElement;
import js.html.InputElement;
import js.html.webgl.Program;
import js.html.webgl.RenderingContext;
import js.html.webgl.GL;
import js.html.webgl.Shader;
import Formula;
/**
* simple webgl starter for Formula
* by Sylvio Sell, Rostock 2017
*
**/
class Main
{
static var canvas:CanvasElement;
static var input:InputElement;
static var width:Int;
static var height:Int;
static var gl:RenderingContext;
static var formula:Formula = "x^2 + y^2";
static function main()
{
width = Browser.window.innerWidth;
height = Browser.window.innerHeight;
canvas = Browser.document.createCanvasElement();
canvas.width = width;
canvas.height = height;
canvas.style.position = "absolute";
canvas.style.top = "0px";
canvas.style.left = "0px";
canvas.style.zIndex = "-1024";
Browser.document.body.appendChild(canvas);
try {
gl = canvas.getContext("experimental-webgl");
if (gl == null) { throw "x"; }
} catch (err:Dynamic) {
throw "Your web browser does not support WebGL!";
}
input = Browser.document.createInputElement();
input.value = formula;
Browser.document.body.appendChild(input);
input.onchange = function(event) {
updateFormula(input.value);
}
//Browser.window.setTimeout(draw, 500);
draw();
}
static public function updateFormula (_formula:String):Void
{
if (_formula != null && _formula != '')
{
try {
var f:Formula = new Formula(_formula);
var p:Array = f.params();
if ((p.indexOf("x") >-1) && (p.indexOf("y") >-1) ) {
formula = f;
input.style.backgroundColor = "#ffffff";
draw();
} else {
trace('Error: wrong params, need x and y');
input.style.backgroundColor = "#ffddcc";
}
}
catch (msg:String)
{
trace('Error: $msg');
input.style.backgroundColor = "#ffddcc";
}
}
}
static function draw()
{
gl.clearColor(0.0, 0.0, 0.0, 1);
gl.clear(GL.COLOR_BUFFER_BIT);
var prog:Program = shaderProgram(gl,
'
attribute vec2 pos;
varying vec2 vTexCoord;
void main() {
vTexCoord = pos;
gl_Position = vec4(pos, 0.0, 1.0);
}
',
'
precision highp float;
varying vec2 vTexCoord;
void main() {
float x = vTexCoord.x;
float y = vTexCoord.y;
/*
if ( y > sin(x*2.0*3.14) ) {
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
*/
if ( ${formula.toString('glsl')} < 1.0 ) {
gl_FragColor = vec4(1.0, 1.0, 0.0, 1.0);
}
else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
}
'
);
gl.useProgram(prog);
attributeSetFloats(gl, prog, "pos", 2, new Float32Array([
-1, 1,
-1, -1,
1, 1,
1, -1
]));
gl.drawArrays(GL.TRIANGLE_STRIP, 0, 4);
}
static function shaderProgram(gl:RenderingContext, vs:String, fs:String):Program
{
var prog = gl.createProgram();
var addshader = function(type:Int, source:String) {
var shader:Shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, GL.COMPILE_STATUS)) {
throw "Could not compile shader:\n\n"+gl.getShaderInfoLog(shader);
}
gl.attachShader(prog, shader);
};
addshader(GL.VERTEX_SHADER, vs);
addshader(GL.FRAGMENT_SHADER, fs);
gl.linkProgram(prog);
if (!gl.getProgramParameter(prog, GL.LINK_STATUS)) {
throw "Could not link the shader program!";
}
return prog;
}
static function attributeSetFloats(gl:RenderingContext, prog:Program, attr_name:String, rsize:Int, arr:Float32Array) {
gl.bindBuffer(GL.ARRAY_BUFFER, gl.createBuffer());
gl.bufferData(GL.ARRAY_BUFFER, arr, GL.STATIC_DRAW);
var attr:Int = gl.getAttribLocation(prog, attr_name);
gl.enableVertexAttribArray(attr);
gl.vertexAttribPointer(attr, rsize, GL.FLOAT, false, 0, 0);
}
}