Animate
Depth
The HTML file:
<html> <head> <script id="vertex-shader" type="x-shader/x-vertex" > attribute vec4 vStartPosition; attribute vec4 vEndPosition; attribute vec4 vColor; uniform float percent; varying vec4 f_Color; void main() { float fixedPct; fixedPct = clamp(percent, 0.0, 1.0); gl_Position = mix(vStartPosition, vEndPosition, fixedPct); f_Color = vColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 f_Color; void main() { gl_FragColor = f_Color; } </script> <script type="text/javascript" src="../Common/webgl-utils.js"></script> <script type="text/javascript" src="../Common/initShaders.js"></script> <script type="text/javascript" src="../Common/MV.js"></script> <script type="text/javascript" src="AniSepTriCanvas.js"></script> <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> <style> input { text-align: right; } </style> </head> <body> <h1>A Sierpinski Gasket With Triangles</h1> <script> var WIDTH = 500; var HEIGHT = 500; var canvas = new Canvas(WIDTH, HEIGHT); window.addEventListener("load", function(event){ document.getElementById('DepthBox').value = canvas.GetDepth(); }); </script> <p> <button type="button" onclick=" canvas.AnimationStep()">Animate 1</button> <p> Animate <label class="switch"> <input type="checkbox" onclick="canvas.ChangeAnimation()"> </label> <p> Depth <input type="text" name="Depth" maxLength = "5" size = "5" value = "" id="DepthBox", onchange="canvas.ChangeDepth(this.value)"> <p> </body>
The Javascript File
function MakeCanvas(width, height, locID) { if (width == undefined || width < 0) { width = 300; } if (height == undefined || height < 0) { height = 300; } var canvas = document.createElement('canvas') canvas.height = height; canvas.width = width; if(locID == undefined) { document.body.appendChild(canvas); } else { div = document.getElementById(locID); if (null == div) { document.body.appendChild(canvas); } else { div.appendChild(canvas); } } document.body.appendChild(canvas); return canvas; } function Canvas(width, height, locID) { var canvas = MakeCanvas(width, height, locID); var gl = WebGLUtils.setupWebGL(canvas); if (!gl) { alert ("WebGL isn't available"); } this.gl = gl; gl.viewport(0,0, width, height); program = initShaders(gl, "vertex-shader","fragment-shader"); gl.useProgram(program); // somewhat new code, two vertex buffers. this.vStartBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vStartBuffer); var vPosition = gl.getAttribLocation(program, "vStartPosition"); gl.vertexAttribPointer(vPosition,2,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(vPosition); this.vEndBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vEndBuffer); vPosition = gl.getAttribLocation(program, "vEndPosition"); gl.vertexAttribPointer(vPosition,2,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(vPosition); // a buffer for the colors this.cBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.cBuffer); var colorAttribute = gl.getAttribLocation(program, "vColor"); gl.vertexAttribPointer(colorAttribute,3,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(colorAttribute); // this is new. Get the location to send pct this.pctLoc = gl.getUniformLocation(program, "percent"); this.pct = 0; this.pctStep = 0.01; gl.uniform1f(this.pctLoc, this.pct); this.maxDepth = 1; this.Init(); return this; } Canvas.prototype = { Init: function() { this.animationState = false; this.gl.clearColor(1.0, 1.0, 1.0, 1.0); this.RestartList(); }, RestartList: function() { this.currentDepth = 0; var p1 = vec2(-0.8, -0.8); var p2 = vec2(0, .8); var p3 = vec2(0.8, -0.8); this.verts= [p1, p2, p3] ; var c1 = vec3(Math.random(), Math.random(),Math.random()) var c2 = vec3(Math.random(), Math.random(),Math.random()) var c3 = vec3(Math.random(), Math.random(),Math.random()) this.colors = [c1, c2, c3]; this.MakePoints(); this.MakeOld(); this.UpdateBuffers(); this.Redisplay(); }, UpdateBuffers: function() { gl = this.gl; // change the vertex data gl.bindBuffer(gl.ARRAY_BUFFER, this.vStartBuffer); gl.bufferData(gl.ARRAY_BUFFER,flatten(this.startV),gl.DYNAMIC_DRAW); gl.bindBuffer(gl.ARRAY_BUFFER, this.vEndBuffer); gl.bufferData(gl.ARRAY_BUFFER,flatten(this.verts),gl.DYNAMIC_DRAW); // change the color data gl.bindBuffer(this.gl.ARRAY_BUFFER, this.cBuffer); gl.bufferData(gl.ARRAY_BUFFER,flatten(this.colors),gl.DYNAMIC_DRAW); }, GetDepth: function() { return this.maxDepth; }, ChangeDepth: function(newDepth) { var depth = parseInt(newDepth); if (depth < 1 ) { alert("depth must be positive"); return; } if (depth > 11) { alert ("Depth has a max value of 11"); depth = 10; } if (depth < this.maxDepth) { this.maxDepth = depth; this.RestartList(); } else { this.maxDepth = depth; this.MakePoints(); this.MakeOld(); var gl = this.gl; this.UpdateBuffers(); } this.Redisplay(); }, Interp: function(a,b,s) { return a*(1-s) + b*s; }, HalfPoint: function(p1,p2) { var x = this.Interp(p1[0],p2[0],.5); var y = this.Interp(p1[1],p2[1],.5); return vec2(x,y); }, AddTri: function(p1, p2, p3, vert, c1, colors) { vert.push(p1); colors.push(c1); vert.push(p2); var c2 = vec3(Math.random(), Math.random(),Math.random()) colors.push(c2); vert.push(p3); var c3 = vec3(Math.random(), Math.random(),Math.random()) colors.push(c3); }, MakePoints: function(){ var newVertex = []; var newColors = []; var a,b,c; var p1, p2, p3; if (this.currentDepth < this.maxDepth) { this.currentDepth++; for(i =0; i < this.verts.length;i+=3) { a = this.verts[i]; b = this.verts[i+1] c = this.verts[i+2]; ap = this.HalfPoint(a,b,.5); bp = this.HalfPoint(b,c,.5); cp = this.HalfPoint(c,a,.5); this.AddTri(a,ap,cp, newVertex, this.colors[i], newColors); this.AddTri(b,bp,ap, newVertex, this.colors[i+1], newColors); this.AddTri(c,cp,bp, newVertex, this.colors[i+2], newColors); } this.verts = newVertex; this.colors = newColors; this.MakePoints(); } return; }, MakeOld: function() { this.startV = []; var mid; var tris = this.verts.length/3; for(var i =0; i < this.verts.length; i+= 9) { this.startV.push(this.verts[i]); this.startV.push(this.verts[i+2]); this.startV.push(this.verts[i+1]); this.startV.push(this.verts[i+3]); this.startV.push(this.verts[i+5]); this.startV.push(this.verts[i+4]); this.startV.push(this.verts[i+6]); this.startV.push(this.verts[i+8]); this.startV.push(this.verts[i+7]); } return; }, Midpoint: function(p1, p2, p3) { var x = (p1[0]+p2[0]+p3[0])/3; var y = (p1[1]+p2[1]+p3[1])/3; return vec2(x,y); }, ChangeAnimation: function() { this.animationState = !this.animationState; if (this.animationState) { setTimeout(canvas.FakeAnimationStep,20,this); } }, IsAnimating: function() { return this.animationState; }, FakeAnimationStep: function(me) { me.AnimationStep(); }, AnimationStep: function() { this.pct += this.pctStep; if (this.pct >= 1.0) { this.pct = 1.0; this.pctStep *= -1; } if (this.pct <= 0.0) { this.pct = 0.0; this.pctStep *= -1; } if (this.animationState) { setTimeout(canvas.FakeAnimationStep,20,this); } this.gl.uniform1f(this.pctLoc, this.pct); this.Redisplay(); }, Redisplay: function() { this.gl.clear(this.gl.COLOR_BUFFER_BIT); this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length); return; } };