- <!DOCTYPE html>
- <html>
- <head>
- <title>WebGL Shader Lab</title>
- <script id="shader-vs" type="x-shader/x-vertex">
- attribute vec3 aPos;
- attribute vec2 aTexCoord;
- varying vec2 pixel;
- void main(void) {
- gl_Position = vec4(aPos, 1.);
- pixel = aTexCoord;
- }
- </script>
- <script id="shader-fs-blur-horizontal" type="x-shader/x-fragment">
- #ifdef GL_ES
- precision highp float;
- #endif
- // original shader from http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
- // horizontal blur fragment shader
- uniform sampler2D src_tex;
- varying vec2 pixel;
- uniform vec2 pixelSize;
- void main(void) // fragment
- {
- float h = pixelSize.x;
- vec4 sum = vec4(0.0);
- sum += texture2D(src_tex, vec2(pixel.x - 4.0*h, pixel.y) ) * 0.05;
- sum += texture2D(src_tex, vec2(pixel.x - 3.0*h, pixel.y) ) * 0.09;
- sum += texture2D(src_tex, vec2(pixel.x - 2.0*h, pixel.y) ) * 0.12;
- sum += texture2D(src_tex, vec2(pixel.x - 1.0*h, pixel.y) ) * 0.15;
- sum += texture2D(src_tex, vec2(pixel.x + 0.0*h, pixel.y) ) * 0.16;
- sum += texture2D(src_tex, vec2(pixel.x + 1.0*h, pixel.y) ) * 0.15;
- sum += texture2D(src_tex, vec2(pixel.x + 2.0*h, pixel.y) ) * 0.12;
- sum += texture2D(src_tex, vec2(pixel.x + 3.0*h, pixel.y) ) * 0.09;
- sum += texture2D(src_tex, vec2(pixel.x + 4.0*h, pixel.y) ) * 0.05;
- gl_FragColor.xyz = sum.xyz/0.98; // normalize
- gl_FragColor.a = 1.;
- }
- </script>
- <script id="shader-fs-blur-vertical" type="x-shader/x-fragment">
- #ifdef GL_ES
- precision highp float;
- #endif
- // original shader from http://www.gamerendering.com/2008/10/11/gaussian-blur-filter-shader/
- // vertical blur fragment shader
- uniform sampler2D src_tex;
- varying vec2 pixel;
- uniform vec2 pixelSize;
- void main(void) // fragment
- {
- float v = pixelSize.y;
- vec4 sum = vec4(0.0);
- sum += texture2D(src_tex, vec2(pixel.x, - 4.0*v + pixel.y) ) * 0.05;
- sum += texture2D(src_tex, vec2(pixel.x, - 3.0*v + pixel.y) ) * 0.09;
- sum += texture2D(src_tex, vec2(pixel.x, - 2.0*v + pixel.y) ) * 0.12;
- sum += texture2D(src_tex, vec2(pixel.x, - 1.0*v + pixel.y) ) * 0.15;
- sum += texture2D(src_tex, vec2(pixel.x, + 0.0*v + pixel.y) ) * 0.16;
- sum += texture2D(src_tex, vec2(pixel.x, + 1.0*v + pixel.y) ) * 0.15;
- sum += texture2D(src_tex, vec2(pixel.x, + 2.0*v + pixel.y) ) * 0.12;
- sum += texture2D(src_tex, vec2(pixel.x, + 3.0*v + pixel.y) ) * 0.09;
- sum += texture2D(src_tex, vec2(pixel.x, + 4.0*v + pixel.y) ) * 0.05;
- gl_FragColor.xyz = sum.xyz/0.98;
- gl_FragColor.a = 1.;
- }
- </script>
- <script id="shader-fs-advance" type="x-shader/x-fragment">
- #ifdef GL_ES
- precision highp float;
- #endif
- uniform sampler2D sampler_prev;
- uniform sampler2D sampler_prev_n;
- uniform sampler2D sampler_blur;
- uniform sampler2D sampler_blur2;
- uniform sampler2D sampler_blur3;
- uniform sampler2D sampler_blur4;
- uniform sampler2D sampler_noise;
- uniform sampler2D sampler_noise_n;
- varying vec2 pixel;
- uniform vec2 pixelSize;
- uniform vec4 rnd;
- uniform vec2 mouse;
- uniform float time;
- uniform float fps;
- uniform float x1;
- uniform float y1;
- uniform float d1;
- uniform float x2;
- uniform float y2;
- uniform float d2;
- float line_segment(vec2 domain, vec2 p1, float d1, vec2 p2, float d2){
- float h = 1./(p2.x-p1.x); // helper registers
- float h1 = (p2.y-p1.y)*h;
- float h2 = 1./h1;
- float xs = (-p1.y+h1*p1.x+h2*domain.x+domain.y)/(h2+h1);// coordinates of the point on the line between p1 and p2,
- float ys = -h2*(xs-domain.x)+domain.y; // ^ orthogonally to the given point in the domain
- float d = length(domain-vec2(xs,ys)); // the orthogonal distance from the domain point to the line (unlimited)
- float s = 0.; // distance from domain point to p1 relative to p2
- if(p2.x == p1.x){ // division by zero fix
- d = abs(domain.x - p1.x);
- s = (p1.y-ys)/(p1.y-p2.y);
- }else{
- s = (xs-p1.x)*h;
- }
- d = clamp(d*(d1*(1.-s)+d2*s),0., 1.); // adjusting the line thickness using a linear interpolation with s
- float m1 = 0.; if(s > 0.) m1 = 1.; // masking out the segment between p1 and p2
- float m2 = 0.; if(s < 1.) m2 = 1.;
- float result = clamp( m1*m2-d, 0., 1.); // return result as 1-distance in the range [0..1]
- result = clamp(1.-length(domain-vec2(p1.x,p1.y))*d1-m1, result, 1.); // round corners if you will (half circles)
- //result = clamp(1.-length(domain-vec2(p2.x,p2.y))*d2-m2, result, 1.);
- return result;
- }
- uniform float sin1;
- uniform float cos1;
- uniform float scale1;
- uniform float sin2;
- uniform float cos2;
- uniform float scale2;
- uniform float sin3;
- uniform float cos3;
- vec2 complex_mul(vec2 factorA, vec2 factorB){
- return vec2( factorA.x*factorB.x - factorA.y*factorB.y, factorA.x*factorB.y + factorA.y*factorB.x);
- }
- float square_mask(vec2 domain){
- return (domain.x <= 1. && domain.x >= 0. && domain.y <= 1. && domain.y >= 0.) ? 1. : 0.;
- }
- void main(void) {
- vec3 color_increment =vec3(0.004,0.008,0.);
- vec2 pos1 = vec2(x1,y1);
- vec2 pos2 = vec2(x2,y2);
- vec2 c = vec2(0.5);
- gl_FragColor.xyz = vec3(1.-line_segment(pixel, pos1, d1, pos2, d2));
- // complex multiplication to rotate
- vec2 uv_stem_feedback = complex_mul((pixel-pos2),vec2(cos1,sin1)*vec2(scale1)) + pos1;
- vec3 stem_feedback = texture2D( sampler_prev, uv_stem_feedback).xyz + color_increment;
- vec3 stem_feedback_mask = vec3(square_mask(uv_stem_feedback));
- stem_feedback *= stem_feedback_mask;
- stem_feedback += vec3(1.)-stem_feedback_mask;
- vec2 uv_left_arm_feedback = complex_mul((pixel-pos2),vec2(cos2,sin2)*vec2(scale2)) + pos1;
- vec3 left_arm_feedback = texture2D( sampler_prev, uv_left_arm_feedback).xyz + color_increment;
- vec3 left_arm_feedback_mask = vec3(square_mask(uv_left_arm_feedback));
- left_arm_feedback *= left_arm_feedback_mask;
- left_arm_feedback += vec3(1.)-left_arm_feedback_mask;
- vec2 uv_right_arm_feedback = complex_mul((pixel-pos2),vec2(cos3,sin3)*vec2(scale2)) + pos1;
- vec3 right_arm_feedback = texture2D( sampler_prev, uv_right_arm_feedback).xyz + color_increment;
- vec3 right_arm_feedback_mask = vec3(square_mask(uv_right_arm_feedback));
- right_arm_feedback *= right_arm_feedback_mask;
- right_arm_feedback += vec3(1.)-right_arm_feedback_mask;
- gl_FragColor.xyz = min( gl_FragColor.xyz, min(stem_feedback, min(left_arm_feedback, right_arm_feedback)));
- gl_FragColor.xyz = mix( gl_FragColor.xyz, texture2D(sampler_prev, pixel).xyz, vec3(0.42)); // sort of a motion blur
- gl_FragColor.a = 1.;
- }
- </script>
- <script id="shader-fs-composite" type="x-shader/x-fragment">
- #ifdef GL_ES
- precision highp float;
- #endif
- uniform sampler2D sampler_prev;
- uniform sampler2D sampler_prev_n;
- uniform sampler2D sampler_blur;
- uniform sampler2D sampler_blur2;
- uniform sampler2D sampler_blur3;
- uniform sampler2D sampler_blur4;
- uniform sampler2D sampler_noise;
- uniform sampler2D sampler_noise_n;
- varying vec2 pixel;
- uniform vec2 pixelSize;
- uniform vec4 rnd;
- uniform vec2 mouse;
- uniform float time;
- uniform float fps;
- void main(void) {
- gl_FragColor = texture2D(sampler_prev, pixel); // copy
- gl_FragColor.a = 1.;
- }
- </script>
- <script id="shader-fs-copy" type="x-shader/x-fragment">
- #ifdef GL_ES
- precision highp float;
- #endif
- uniform sampler2D sampler_prev;
- varying vec2 pixel;
- void main(void) {
- gl_FragColor = texture2D(sampler_prev, pixel);
- gl_FragColor.a = 1.;
- }
- </script>
- <script type="text/javascript">
- function BrowserSize() {
- if (typeof (window.innerWidth) == 'number') {
- //Non-IE
- this.width = window.innerWidth;
- this.height = window.innerHeight;
- } else if (document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
- //IE 6+ in 'standards compliant mode'
- this.width = document.documentElement.clientWidth;
- this.height = document.documentElement.clientHeight;
- } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
- //IE 4 compatible
- this.width = document.body.clientWidth;
- this.height = document.body.clientHeight;
- }
- }
- BrowserSize.prototype.width;
- BrowserSize.prototype.height;
- function getShader(gl, id) {
- var shaderScript = document.getElementById(id);
- var str = "";
- var k = shaderScript.firstChild;
- while (k) {
- if (k.nodeType == 3)
- str += k.textContent;
- k = k.nextSibling;
- }
- var shader;
- if (shaderScript.type == "x-shader/x-fragment")
- shader = gl.createShader(gl.FRAGMENT_SHADER);
- else if (shaderScript.type == "x-shader/x-vertex")
- shader = gl.createShader(gl.VERTEX_SHADER);
- else
- return null;
- gl.shaderSource(shader, str);
- gl.compileShader(shader);
- if (gl.getShaderParameter(shader, gl.COMPILE_STATUS) == 0)
- alert(gl.getShaderInfoLog(shader));
- return shader;
- }
- requestAnimFrame = (function() {
- return window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback, element) {
- setTimeout(callback, 1000 / 60);
- };
- })();
- var gl;
- var prog_copy;
- var prog_advance;
- var prog_composite;
- var prog_blur_horizontal;
- var prog_blur_vertical;
- var FBO_main;
- var FBO_main2;
- var FBO_noise;
- var FBO_blur;
- var FBO_blur2;
- var FBO_blur3;
- var FBO_blur4;
- var FBO_helper;
- var FBO_helper2;
- var FBO_helper3;
- var FBO_helper4;
- var texture_main_l; // main, linear
- var texture_main_n; // main, nearest (accurate pixel access on the same buffer)
- var texture_main2_l; // main double buffer, linear
- var texture_main2_n; // main double buffer, nearest (accurate pixel access on the same buffer)
- var texture_helper; // needed for multi-pass shader programs (2-pass Gaussian blur)
- var texture_helper2; // (1/4 resolution )
- var texture_helper3; // (1/16 resolution )
- var texture_helper4; // (1/256 resolution )
- var texture_blur; // full resolution blur result
- var texture_blur2; // double blur
- var texture_blur3; // quad blur
- var texture_blur4; // really low resolution - use wisely ^^
- var texture_noise_n; // noise pixel accurate
- var texture_noise_l; // noise interpolated pixel access
- var halted = false;
- var delay = 3;
- var it = 1;
- var frames = 0;
- var fps = 60; // no hurdle for DX10 graphics cards
- var time = 0;
- var mouseX = 0.5;
- var mouseY = 0.5;
- var animation;
- var timer;
- // texture size (must be powers of two, remember 2048x1024 flat could also be a 128x128x128 voxel)
- var sizeX = 2048;
- var sizeY = 1024; // 2048x1024 flat or 128x128x128 cube
- // viewport size
- var viewX = 1024;
- var viewY = 1024;
- var basetime = new Date().getTime();
- var c;
- function setMaximalSize() {
- browserSize = new BrowserSize();
- c.width = viewX = browserSize.width;
- c.height = viewY = browserSize.height;
- }
- function load() {
- clearInterval(timer);
- c = document.getElementById("c");
- try {
- gl = c.getContext("experimental-webgl", { depth : false });
- } catch (e) {
- }
- if (!gl) {
- alert("Your browser does not support WebGL");
- return;
- }
- document.onmousemove = function(evt) {
- mouseX = evt.pageX / viewX;
- mouseY = 1 - evt.pageY / viewY;
- };
- document.onclick = function(evt) {
- // halted = !halted;
- };
- window.onresize = setMaximalSize;
- setMaximalSize();
- c.width = viewX;
- c.height = viewY;
- prog_copy = gl.createProgram();
- gl.attachShader(prog_copy, getShader(gl, "shader-vs"));
- gl.attachShader(prog_copy, getShader(gl, "shader-fs-copy"));
- gl.linkProgram(prog_copy);
- prog_advance = gl.createProgram();
- gl.attachShader(prog_advance, getShader(gl, "shader-vs"));
- gl.attachShader(prog_advance, getShader(gl, "shader-fs-advance"));
- gl.linkProgram(prog_advance);
- prog_composite = gl.createProgram();
- gl.attachShader(prog_composite, getShader(gl, "shader-vs"));
- gl.attachShader(prog_composite, getShader(gl, "shader-fs-composite"));
- gl.linkProgram(prog_composite);
- prog_blur_horizontal = gl.createProgram();
- gl.attachShader(prog_blur_horizontal, getShader(gl, "shader-vs"));
- gl.attachShader(prog_blur_horizontal, getShader(gl, "shader-fs-blur-horizontal"));
- gl.linkProgram(prog_blur_horizontal);
- prog_blur_vertical = gl.createProgram();
- gl.attachShader(prog_blur_vertical, getShader(gl, "shader-vs"));
- gl.attachShader(prog_blur_vertical, getShader(gl, "shader-fs-blur-vertical"));
- gl.linkProgram(prog_blur_vertical);
- var posBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
- var vertices = new Float32Array([ -1, -1, 0, 1, -1, 0, -1, 1, 0, 1, 1, 0 ]);
- var aPosLoc = gl.getAttribLocation(prog_advance, "aPos");
- gl.enableVertexAttribArray(aPosLoc);
- var aTexLoc = gl.getAttribLocation(prog_advance, "aTexCoord");
- gl.enableVertexAttribArray(aTexLoc);
- var texCoords = new Float32Array([ 0, 0, 1, 0, 0, 1, 1, 1 ]);
- var texCoordOffset = vertices.byteLength;
- gl.bufferData(gl.ARRAY_BUFFER, texCoordOffset + texCoords.byteLength, gl.STATIC_DRAW);
- gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices);
- gl.bufferSubData(gl.ARRAY_BUFFER, texCoordOffset, texCoords);
- gl.vertexAttribPointer(aPosLoc, 3, gl.FLOAT, gl.FALSE, 0, 0);
- gl.vertexAttribPointer(aTexLoc, 2, gl.FLOAT, gl.FALSE, 0, texCoordOffset);
- var noisepixels = [];
- var pixels = [];
- for ( var i = 0; i < sizeX; i++) {
- for ( var j = 0; j < sizeY; j++) {
- noisepixels.push(Math.random() * 255, Math.random() * 255, Math.random() * 255, 255);
- pixels.push(0, 0, 0, 255);
- }
- }
- var pixels2 = [];
- for ( var i = 0; i < sizeX / 2; i++) {
- for ( var j = 0; j < sizeY / 2; j++) {
- pixels2.push(0, 0, 0, 255);
- }
- }
- var pixels3 = [];
- for ( var i = 0; i < sizeX / 4; i++) {
- for ( var j = 0; j < sizeY / 4; j++) {
- pixels3.push(0, 0, 0, 255);
- }
- }
- var pixels4 = [];
- for ( var i = 0; i < sizeX / 8; i++) {
- for ( var j = 0; j < sizeY / 8; j++) {
- pixels4.push(0, 0, 0, 255);
- }
- }
- var rawData = new Uint8Array(noisepixels);
- texture_main_l = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_main_l);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(noisepixels);
- texture_main_n = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_main_n);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- rawData = new Uint8Array(noisepixels);
- texture_main2_l = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_l);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(noisepixels);
- texture_main2_n = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_n);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- rawData = new Uint8Array(pixels);
- texture_helper = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_helper);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels2);
- texture_helper2 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_helper2);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 2, sizeY / 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels3);
- texture_helper3 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_helper3);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 4, sizeY / 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels4);
- texture_helper4 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_helper4);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 8, sizeY / 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels);
- texture_blur = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_blur);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels2);
- texture_blur2 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_blur2);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 2, sizeY / 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels3);
- texture_blur3 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_blur3);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 4, sizeY / 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(pixels4);
- texture_blur4 = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_blur4);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX / 8, sizeY / 8, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- rawData = new Uint8Array(noisepixels);
- texture_noise_l = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_noise_l);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
- texture_noise_n = gl.createTexture();
- gl.bindTexture(gl.TEXTURE_2D, texture_noise_n);
- gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
- gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, sizeX, sizeY, 0, gl.RGBA, gl.UNSIGNED_BYTE, rawData);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
- FBO_main = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_main);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_main_l, 0);
- FBO_main2 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_main2);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_main2_l, 0);
- FBO_helper = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_helper, 0);
- FBO_helper2 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper2);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_helper2, 0);
- FBO_helper3 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper3);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_helper3, 0);
- FBO_helper4 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper4);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_helper4, 0);
- FBO_blur = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_blur, 0);
- FBO_blur2 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur2);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_blur2, 0);
- FBO_blur3 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur3);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_blur3, 0);
- FBO_blur4 = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur4);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_blur4, 0);
- FBO_noise = gl.createFramebuffer();
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_noise);
- gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture_noise_l, 0);
- gl.activeTexture(gl.TEXTURE2);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur);
- gl.activeTexture(gl.TEXTURE3);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur2);
- gl.activeTexture(gl.TEXTURE4);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur3);
- gl.activeTexture(gl.TEXTURE5);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur4);
- gl.activeTexture(gl.TEXTURE6);
- gl.bindTexture(gl.TEXTURE_2D, texture_noise_l);
- gl.activeTexture(gl.TEXTURE7);
- gl.bindTexture(gl.TEXTURE_2D, texture_noise_n);
- calculateBlurTexture();
- posX1 = 0.5;
- posY1 = 0.4;
- scale1 = 1.23;
- var w1 = 0;
- sinW1 = Math.sin(w1);
- cosW1 = Math.cos(w1);
- posX2 = 0.5;
- posY2 = 0.6;
- scale2 = 2.5;
- var w2 = 0.1;
- w2 *= Math.PI;
- sinW2 = Math.sin(w2);
- cosW2 = Math.cos(w2);
- timer = setInterval(fr, 500);
- time = new Date().getTime();
- animation = "animate";
- anim();
- }
- var x1 = 0.5;
- var y1 = 0.03;
- var x2 = 0.5;
- var y2 = 0.15;
- var thickness = 1. / 0.01; // inverse actually, keeping the shader calculation low
- var w1 = 0.2;
- var w2 = 0.9;
- var scale1 = 1.23;
- var scale2 = 2.5;
- function setUniforms(program) {
- gl.uniform2f(gl.getUniformLocation(program, "pixelSize"), 1. / sizeX, 1. / sizeY);
- gl.uniform4f(gl.getUniformLocation(program, "rnd"), Math.random(), Math.random(), Math.random(), Math.random());
- gl.uniform1f(gl.getUniformLocation(program, "fps"), fps);
- gl.uniform1f(gl.getUniformLocation(program, "time"), (new Date().getTime() - basetime) / 1000);
- gl.uniform2f(gl.getUniformLocation(program, "aspect"), Math.max(1, viewX / viewY), Math.max(1, viewY / viewX));
- gl.uniform2f(gl.getUniformLocation(program, "mouse"), mouseX, mouseY);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_prev"), 0);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_prev_n"), 1);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_blur"), 2);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_blur2"), 3);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_blur3"), 4);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_blur4"), 5);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_noise"), 6);
- gl.uniform1i(gl.getUniformLocation(program, "sampler_noise_n"), 7);
- gl.uniform1f(gl.getUniformLocation(program, "x1"), x1);
- gl.uniform1f(gl.getUniformLocation(program, "y1"), y1);
- gl.uniform1f(gl.getUniformLocation(program, "d1"), thickness);
- gl.uniform1f(gl.getUniformLocation(program, "x2"), x2);
- gl.uniform1f(gl.getUniformLocation(program, "y2"), y2);
- gl.uniform1f(gl.getUniformLocation(program, "d2"), thickness * scale1);
- gl.uniform1f(gl.getUniformLocation(program, "sin1"), Math.sin(w1));
- gl.uniform1f(gl.getUniformLocation(program, "cos1"), Math.cos(w1));
- gl.uniform1f(gl.getUniformLocation(program, "sin2"), Math.sin(w1 - w2));
- gl.uniform1f(gl.getUniformLocation(program, "cos2"), Math.cos(w1 - w2));
- gl.uniform1f(gl.getUniformLocation(program, "sin3"), Math.sin(w1 + w2));
- gl.uniform1f(gl.getUniformLocation(program, "cos3"), Math.cos(w1 + w2));
- gl.uniform1f(gl.getUniformLocation(program, "scale1"), scale1);
- gl.uniform1f(gl.getUniformLocation(program, "scale2"), scale2);
- }
- function calculateBlurTexture() {
- // simple blur
- // horizontal
- gl.viewport(0, 0, sizeX, sizeY);
- gl.useProgram(prog_blur_horizontal);
- gl.uniform2f(gl.getUniformLocation(prog_blur_horizontal, "pixelSize"), 1. / sizeX, 1. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- if (it < 0) {
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_l);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper);
- } else {
- gl.bindTexture(gl.TEXTURE_2D, texture_main_l);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper);
- }
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // vertical
- gl.viewport(0, 0, sizeX, sizeY);
- gl.useProgram(prog_blur_vertical);
- gl.uniform2f(gl.getUniformLocation(prog_blur_vertical, "pixelSize"), 1. / sizeX, 1. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_helper);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // double blur
- // copy previous blur level to lower resolution texture
- gl.viewport(0, 0, sizeX / 2, sizeY / 2);
- gl.useProgram(prog_copy);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur2);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur2 vertical
- gl.viewport(0, 0, sizeX / 2, sizeY / 2);
- gl.useProgram(prog_blur_vertical);
- gl.uniform2f(gl.getUniformLocation(prog_blur_vertical, "pixelSize"), 2. / sizeX, 2. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur2);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper2);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur2 horizontal
- gl.viewport(0, 0, sizeX / 2, sizeY / 2);
- gl.useProgram(prog_blur_horizontal);
- gl.uniform2f(gl.getUniformLocation(prog_blur_horizontal, "pixelSize"), 2. / sizeX, 2. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_helper2);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur2);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur3
- // copy previous blur level to lower resolution texture
- gl.viewport(0, 0, sizeX / 4, sizeY / 4);
- gl.useProgram(prog_copy);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur2);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur3);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur3 vertical
- gl.viewport(0, 0, sizeX / 4, sizeY / 4);
- gl.useProgram(prog_blur_vertical);
- gl.uniform2f(gl.getUniformLocation(prog_blur_vertical, "pixelSize"), 4. / sizeX, 4. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur3);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper3);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur3 horizontal
- gl.viewport(0, 0, sizeX / 4, sizeY / 4);
- gl.useProgram(prog_blur_horizontal);
- gl.uniform2f(gl.getUniformLocation(prog_blur_horizontal, "pixelSize"), 4. / sizeX, 4. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_helper3);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur3);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur4
- // copy previous blur level to lower resolution texture
- gl.viewport(0, 0, sizeX / 8, sizeY / 8);
- gl.useProgram(prog_copy);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur3);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur4);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur4 vertical
- gl.viewport(0, 0, sizeX / 8, sizeY / 8);
- gl.useProgram(prog_blur_vertical);
- gl.uniform2f(gl.getUniformLocation(prog_blur_vertical, "pixelSize"), 8. / sizeX, 8. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_blur4);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_helper4);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- // blur4 horizontal
- gl.viewport(0, 0, sizeX / 8, sizeY / 8);
- gl.useProgram(prog_blur_horizontal);
- gl.uniform2f(gl.getUniformLocation(prog_blur_horizontal, "pixelSize"), 8. / sizeX, 8. / sizeY);
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_helper4);
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_blur4);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- }
- function advance() {
- x1 = 0.5;
- thickness = (2 - mouseY * 1.) / 0.025;
- y1 = 0.035;
- x2 = 0.5 + (mouseX - 0.5) * 0.25;
- y2 = 0.07 + mouseY * 0.14;
- w1 = (0.5 - mouseX) * 0.15;
- gl.viewport(0, 0, sizeX, sizeY);
- gl.useProgram(prog_advance);
- setUniforms(prog_advance);
- if (it > 0) {
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_main_l); // interpolated input
- gl.activeTexture(gl.TEXTURE1);
- gl.bindTexture(gl.TEXTURE_2D, texture_main_n); // "nearest" input
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_main2); // write to buffer
- } else {
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_l); // interpolated
- gl.activeTexture(gl.TEXTURE1);
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_n); // "nearest"
- gl.bindFramebuffer(gl.FRAMEBUFFER, FBO_main); // write to buffer
- }
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- calculateBlurTexture();
- it = -it;
- }
- function composite() {
- gl.viewport(0, 0, viewX, viewY);
- gl.useProgram(prog_composite);
- setUniforms(prog_composite);
- if (it < 0) {
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_main_l);
- gl.activeTexture(gl.TEXTURE1);
- gl.bindTexture(gl.TEXTURE_2D, texture_main_n);
- } else {
- gl.activeTexture(gl.TEXTURE0);
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_l);
- gl.activeTexture(gl.TEXTURE1);
- gl.bindTexture(gl.TEXTURE_2D, texture_main2_n);
- }
- gl.bindFramebuffer(gl.FRAMEBUFFER, null);
- gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
- gl.flush();
- frames++;
- }
- function anim() {
- if (!halted)
- advance();
- composite();
- switch (animation) {
- case "animate":
- setTimeout("requestAnimFrame(anim)", delay);
- break;
- case "reset":
- load();
- break;
- }
- }
- function setDelay(v) {
- delay = parseInt(v);
- }
- function fr() {
- var ti = new Date().getTime();
- fps = Math.round(1000 * frames / (ti - time));
- document.getElementById("fps").textContent = fps;
- frames = 0;
- time = ti;
- }
- </script>
- <style type="text/css">
- body {
- background-color: #FFFFFF;
- color: #000000;
- }
- a {
- color: #666666;
- text-decoration: none;
- }
- #c {
- position: absolute;
- top: 0;
- left: 0;
- z-index: -1;
- }
- #desc {
- background-color: rgba(255, 255, 255, 0.2);
- }
- </style>
- </head>
- <body onload="load()">
- <div id="desc">
- <b><i>Progressive <a href="http://en.wikipedia.org/wiki/L-system" target=new>Lindenmayer</a> tree fractal</i> </b><br />
- Fps: <span id="fps"></span>
- </div>
- <canvas id="c"></canvas>
- </body>
- </html>